MRPT  2.0.4
CFBORender.cpp
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | https://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2020, Individual contributors, see AUTHORS file |
6  | See: https://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See: https://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 
10 #include "opengl-precomp.h" // Precompiled header
11 
12 #include <mrpt/opengl/CFBORender.h>
13 #include <mrpt/opengl/opengl_api.h>
14 
15 using namespace std;
16 using namespace mrpt;
17 using namespace mrpt::opengl;
18 using mrpt::img::CImage;
19 
20 /*---------------------------------------------------------------
21  Constructor
22 ---------------------------------------------------------------*/
23 CFBORender::CFBORender(
24  unsigned int width, unsigned int height, const bool skip_glut_window)
25  : m_width(width),
26  m_height(height),
27  m_win_used(!skip_glut_window),
28  m_default_bk_color(.6f, .6f, .6f, 1)
29 {
30 #if MRPT_HAS_OPENCV && MRPT_HAS_OPENGL_GLUT
31 
33 
34  if (m_win_used)
35  {
36  // check a previous initialization of the GLUT
37  if (!glutGet(GLUT_INIT_STATE))
38  {
39  // create the context (a little trick)
40  int argc = 1;
41  char* argv[1] = {nullptr};
42  glutInit(&argc, argv);
43  }
44 
45  // create a hidden window
46  m_win = glutCreateWindow("CFBORender");
47  glutHideWindow();
48  }
49 
50  // call after creating the hidden window
51  if (!isExtensionSupported("GL_EXT_framebuffer_object"))
52  THROW_EXCEPTION("Framebuffer Object extension unsupported");
53 
54 // In win32 we have to load the pointers to the functions:
55 #ifdef _WIN32
56  glGenFramebuffersEXT =
57  (PFNGLGENFRAMEBUFFERSEXTPROC)wglGetProcAddress("glGenFramebuffersEXT");
58  glDeleteFramebuffersEXT = (PFNGLDELETEFRAMEBUFFERSEXTPROC)wglGetProcAddress(
59  "glDeleteFramebuffersEXT");
60  glBindFramebufferEXT =
61  (PFNGLBINDFRAMEBUFFEREXTPROC)wglGetProcAddress("glBindFramebufferEXT");
62  glFramebufferTexture2DEXT =
63  (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)wglGetProcAddress(
64  "glFramebufferTexture2DEXT");
65 
66  ASSERT_(glGenFramebuffersEXT != nullptr);
67  ASSERT_(glDeleteFramebuffersEXT != nullptr);
68  ASSERT_(glBindFramebufferEXT != nullptr);
69  ASSERT_(glFramebufferTexture2DEXT != nullptr);
70 #endif
71 
72  // gen the frambuffer object (FBO), similar manner as a texture
73  glGenFramebuffersEXT(1, &m_fbo);
74 
75  // bind the framebuffer, fbo, so operations will now occur on it
76  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
77 
78  // change viewport size (in pixels)
79  glViewport(0, 0, m_width, m_height);
80 
81  // make a texture
82  glGenTextures(1, &m_tex);
83 
84  // initialize texture that will store the framebuffer image
85  const GLenum texTarget =
86 #if defined(GL_TEXTURE_RECTANGLE_NV)
87  GL_TEXTURE_RECTANGLE_NV;
88 #elif defined(GL_TEXTURE_RECTANGLE_ARB)
89  GL_TEXTURE_RECTANGLE_ARB;
90 #else
91  GL_TEXTURE_RECTANGLE_EXT;
92 #endif
93 
94  glBindTexture(texTarget, m_tex);
95  glTexImage2D(
96  texTarget, 0, GL_RGB, m_width, m_height, 0, GL_RGB, GL_UNSIGNED_BYTE,
97  nullptr);
98 
99  // bind this texture to the current framebuffer obj. as color_attachement_0
100  glFramebufferTexture2DEXT(
101  GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, texTarget, m_tex, 0);
102 
103  //'unbind' the frambuffer object, so subsequent drawing ops are not drawn
104  // into the FBO.
105  // '0' means "windowing system provided framebuffer
106  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
107 
108  MRPT_END
109 
110 //#else
111 // THROW_EXCEPTION("MRPT compiled without OpenCV and/or OpenGL support!!");
112 #endif
113 }
114 
115 /*---------------------------------------------------------------
116  Destructor:
117  ---------------------------------------------------------------*/
119 {
120 #if MRPT_HAS_OPENGL_GLUT
121  // delete the current texture, the framebuffer object and the GLUT window
122  glDeleteTextures(1, &m_tex);
123  glDeleteFramebuffersEXT(1, &m_fbo);
124  if (m_win_used) glutDestroyWindow(m_win);
125 #endif
126 }
127 
128 /*---------------------------------------------------------------
129  Set the scene camera
130  ---------------------------------------------------------------*/
131 void CFBORender::setCamera(const COpenGLScene& scene, const CCamera& camera)
132 {
133  MRPT_START
134 
135  scene.getViewport("main")->getCamera() = camera;
136 
137  MRPT_END
138 }
139 
140 /*---------------------------------------------------------------
141  Get the scene camera
142  ---------------------------------------------------------------*/
144 {
145  MRPT_START
146 
147  return scene.getViewport("main")->getCamera();
148 
149  MRPT_END
150 }
151 
152 /*---------------------------------------------------------------
153  Render the scene and get the rendered rgb image. This
154  function resizes the image buffer if it is necessary
155  ---------------------------------------------------------------*/
157  [[maybe_unused]] const COpenGLScene& scene, [[maybe_unused]] CImage& buffer)
158 {
159 #if MRPT_HAS_OPENCV && MRPT_HAS_OPENGL_GLUT
160 
161  MRPT_START
162 
163  // resize the buffer if it is necessary
164  if (buffer.getWidth() != static_cast<size_t>(m_width) ||
165  buffer.getHeight() != static_cast<size_t>(m_height) ||
166  buffer.getChannelCount() != 3 || buffer.isOriginTopLeft() != false)
167  {
168  buffer.resize(m_width, m_height, mrpt::img::CH_RGB);
169  }
170 
171  // Go on.
172  getFrame2(scene, buffer);
173  ;
174 
175  MRPT_END
176 #endif
177 }
178 
179 /*---------------------------------------------------------------
180  Render the scene and get the rendered rgb image. This
181  function does not resize the image buffer.
182  ---------------------------------------------------------------*/
184  [[maybe_unused]] const COpenGLScene& scene, [[maybe_unused]] CImage& buffer)
185 {
186 #if MRPT_HAS_OPENGL_GLUT
187 
188  MRPT_START
189 
190  // check the buffer size
191  ASSERT_EQUAL_(buffer.getWidth(), static_cast<size_t>(m_width));
192  ASSERT_EQUAL_(buffer.getHeight(), static_cast<size_t>(m_height));
193  ASSERT_EQUAL_(buffer.getChannelCount(), 3);
194  ASSERT_EQUAL_(buffer.isOriginTopLeft(), false);
195  // bind the framebuffer, fbo, so operations will now occur on it
196  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
197 
198  glClearColor(
201 
202  // Render opengl objects:
203  // ---------------------------
204  scene.render();
205 
206  // TODO NOTE: This should fail if the image has padding bytes. See
207  // glPixelStore() etc.
208  glReadPixels(
209  0, 0, m_width, m_height, GL_BGR_EXT, GL_UNSIGNED_BYTE, buffer(0, 0));
210 
211  //'unbind' the frambuffer object, so subsequent drawing ops are not drawn
212  // into the FBO.
213  // '0' means "windowing system provided framebuffer
214  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
215 
216  MRPT_END
217 #endif
218 }
219 
220 /*---------------------------------------------------------------
221  Resize the image size
222  ---------------------------------------------------------------*/
224  [[maybe_unused]] unsigned int width, [[maybe_unused]] unsigned int height)
225 {
226 #if MRPT_HAS_OPENCV && MRPT_HAS_OPENGL_GLUT
227 
228  MRPT_START
229 
230  // update members
231  m_width = width;
232  m_height = height;
233 
234  // bind the framebuffer, fbo, so operations will now occur on it
235  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
236 
237  // change viewport size (in pixels)
238  glViewport(0, 0, m_width, m_height);
239 
240  // change texture size
241  const GLenum texTarget =
242 #if defined(GL_TEXTURE_RECTANGLE_NV)
243  GL_TEXTURE_RECTANGLE_NV;
244 #elif defined(GL_TEXTURE_RECTANGLE_ARB)
245  GL_TEXTURE_RECTANGLE_ARB;
246 #else
247  GL_TEXTURE_RECTANGLE_EXT;
248 #endif
249 
250  glBindTexture(texTarget, m_tex);
251  glTexImage2D(
252  texTarget, 0, GL_RGB, m_width, m_height, 0, GL_RGB, GL_UNSIGNED_BYTE,
253  nullptr);
254 
255  //'unbind' the frambuffer object, so subsequent drawing ops are not drawn
256  // into the FBO.
257  // '0' means "windowing system provided framebuffer
258  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
259 
260  MRPT_END
261 
262 //#else
263 // THROW_EXCEPTION("MRPT compiled without OpenCV and/or OpenGL support!!");
264 #endif
265 }
266 
267 /*---------------------------------------------------------------
268  Provide information on Framebuffer object extension
269  ---------------------------------------------------------------*/
270 int CFBORender::isExtensionSupported([[maybe_unused]] const char* extension)
271 {
272 #if MRPT_HAS_OPENGL_GLUT
273 
274  MRPT_START
275 
276  /* Extension names should not have spaces. */
277  auto where = strchr(extension, ' ');
278  if (where || *extension == '\0') return 0;
279  const auto extensions = glGetString(GL_EXTENSIONS);
280 
281  /* It takes a bit of care to be fool-proof about parsing the
282  OpenGL extensions string. Don't be fooled by sub-strings,
283  etc. */
284  auto start = reinterpret_cast<const char*>(extensions);
285  for (;;)
286  {
287  where = strstr(start, extension);
288  if (!where) break;
289  auto terminator = where + strlen(extension);
290  if (where == start || *(where - 1) == ' ')
291  if (*terminator == ' ' || *terminator == '\0') return 1;
292  start = terminator;
293  }
294 
295  MRPT_END
296 #endif
297 
298  return 0;
299 }
#define MRPT_START
Definition: exceptions.h:241
int isExtensionSupported(const char *extension)
Provide information on Framebuffer object extension.
Definition: CFBORender.cpp:270
#define THROW_EXCEPTION(msg)
Definition: exceptions.h:67
void getFrame(const COpenGLScene &scene, mrpt::img::CImage &image)
Render the scene and get the rendered rgb image.
Definition: CFBORender.cpp:156
STL namespace.
#define ASSERT_(f)
Defines an assertion mechanism.
Definition: exceptions.h:120
mrpt::img::CImage CImage
Definition: utils/CImage.h:5
#define ASSERT_EQUAL_(__A, __B)
Assert comparing two values, reporting their actual values upon failure.
Definition: exceptions.h:137
CCamera & getCamera(const COpenGLScene &scene)
Get a reference to the scene camera.
Definition: CFBORender.cpp:143
virtual ~CFBORender()
Destructor.
Definition: CFBORender.cpp:118
void getFrame2(const COpenGLScene &scene, mrpt::img::CImage &image)
Render the scene and get the rendered rgb image.
Definition: CFBORender.cpp:183
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
const char * argv[]
COpenGLViewport::Ptr getViewport(const std::string &viewportName=std::string("main")) const
Returns the viewport with the given name, or nullptr if it does not exist; note that the default view...
void setCamera(const COpenGLScene &scene, const CCamera &camera)
Change the scene camera.
Definition: CFBORender.cpp:131
void resize(unsigned int width, unsigned int height)
Resize the rendering canvas size.
Definition: CFBORender.cpp:223
#define MRPT_END
Definition: exceptions.h:245
The namespace for 3D scene representation and rendering.
Definition: CGlCanvasBase.h:13
This class allows the user to create, load, save, and render 3D scenes using OpenGL primitives...
Definition: COpenGLScene.h:56
const int argc
mrpt::img::TColorf m_default_bk_color
Definition: CFBORender.h:82
A camera: if added to a scene, the viewpoint defined by this camera will be used instead of the camer...
Definition: CCamera.h:33
A class for storing images as grayscale or RGB bitmaps.
Definition: img/CImage.h:148



Page generated by Doxygen 1.8.14 for MRPT 2.0.4 Git: 3e8ecd670 Mon May 18 14:23:19 2020 +0200 at lun may 18 14:30:11 CEST 2020