Main MRPT website > C++ reference for MRPT 1.9.9
CTexturedObject.cpp
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | http://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2017, Individual contributors, see AUTHORS file |
6  | See: http://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See details in http://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 
10 #include "opengl-precomp.h" // Precompiled header
11 
13 #include <mrpt/utils/CTimeLogger.h>
14 #include <mrpt/utils/CStream.h>
15 #include "opengl_internals.h"
16 
17 using namespace mrpt;
18 using namespace mrpt::opengl;
19 using namespace mrpt::poses;
20 using namespace mrpt::utils;
21 using namespace mrpt::math;
22 using namespace std;
23 
26 
27 // Whether to profile memory allocations:
28 //#define TEXTUREOBJ_PROFILE_MEM_ALLOC
29 
30 // Whether to use a memory pool for the texture buffer:
31 #define TEXTUREOBJ_USE_MEMPOOL
32 
33 // Data types for memory pooling CTexturedObject:
34 #ifdef TEXTUREOBJ_USE_MEMPOOL
35 
37 
38 struct CTexturedObject_MemPoolParams
39 {
40  /** size of the vector<unsigned char> */
41  size_t len;
42 
43  inline bool isSuitable(const CTexturedObject_MemPoolParams& req) const
44  {
45  return len == req.len;
46  }
47 };
49 {
50  vector<unsigned char> data;
51 };
52 
53 typedef mrpt::system::CGenericMemoryPool<CTexturedObject_MemPoolParams,
56 #endif
57 
58 /*---------------------------------------------------------------
59  CTexturedObject
60  ---------------------------------------------------------------*/
62  : m_glTextureName(0),
63  m_texture_is_loaded(false),
64  m_enableTransparency(false)
65 {
66 }
67 
68 /*---------------------------------------------------------------
69  assignImage
70  ---------------------------------------------------------------*/
71 void CTexturedObject::assignImage(const CImage& img, const CImage& imgAlpha)
72 {
74 
76 
77  unloadTexture();
78 
79  // Make a copy:
81  m_textureImageAlpha = imgAlpha;
82 
83  m_enableTransparency = true;
84 
85  MRPT_END
86 }
87 
88 /*---------------------------------------------------------------
89  assignImage
90  ---------------------------------------------------------------*/
92 {
94 
96 
97  unloadTexture();
98 
99  // Make a copy:
101 
102  m_enableTransparency = false;
103 
104  MRPT_END
105 }
106 
107 /*---------------------------------------------------------------
108  assignImage
109  ---------------------------------------------------------------*/
111 {
112  MRPT_START
113 
115 
116  unloadTexture();
117 
118  // Make a copy:
121 
122  m_enableTransparency = true;
123 
124  MRPT_END
125 }
126 
127 /*---------------------------------------------------------------
128  assignImage
129  ---------------------------------------------------------------*/
131 {
132  MRPT_START
133 
135 
136  unloadTexture();
137 
138  // Make a copy:
140 
141  m_enableTransparency = false;
142 
143  MRPT_END
144 }
145 
146 // Auxiliary function for loadTextureInOpenGL(): reserve memory and return
147 // 16byte aligned starting point within it:
148 unsigned char* reserveDataBuffer(const size_t len, vector<unsigned char>& data)
149 {
150 #ifdef TEXTUREOBJ_USE_MEMPOOL
152  if (pool)
153  {
154  CTexturedObject_MemPoolParams mem_params;
155  mem_params.len = len;
156 
157  CTexturedObject_MemPoolData* mem_block =
158  pool->request_memory(mem_params);
159  if (mem_block)
160  {
161  // Recover the memory block via a swap:
162  data.swap(mem_block->data);
163  delete mem_block;
164  }
165  }
166 #endif
167  data.resize(len);
168  return ((unsigned char*)(((POINTER_TYPE)&data[0]) & (~((POINTER_TYPE)0x0F)))) +
169  0x10;
170 }
171 
172 /*---------------------------------------------------------------
173  loadTextureInOpenGL
174  ---------------------------------------------------------------*/
176 {
177 #if MRPT_HAS_OPENGL_GLUT
178  unsigned char* dataAligned = nullptr;
179  vector<unsigned char> data;
180 
181 #ifdef TEXTUREOBJ_PROFILE_MEM_ALLOC
182  static mrpt::utils::CTimeLogger tim;
183 #endif
184 
185  try
186  {
188  {
191  return;
192  }
193 
194  // Reserve the new one --------------------------
195 
196  // allocate texture names:
198 
199  // select our current texture
202 
203  // when texture area is small, linear interpolation. Default is
204  // GL_LINEAR_MIPMAP_NEAREST but we
205  // are not building mipmaps.
206  // See also:
207  // http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=133116&page=1
210 
211  // when texture area is large, NEAREST: this is mainly thinking of
212  // rendering
213  // occupancy grid maps, such as we want those "big pixels" to be
214  // clearly visible ;-)
217 
218  // if wrap is true, the texture wraps over at the edges (repeat)
219  // ... false, the texture ends at the edges (clamp)
222 
225 
226  // Assure that the images do not overpass the maximum dimensions allowed
227  // by OpenGL:
228  // ------------------------------------------------------------------------------------
229  GLint texSize;
231  while (m_textureImage.getHeight() > (unsigned int)texSize ||
232  m_textureImage.getWidth() > (unsigned int)texSize)
233  {
236  }
237 
238  const int width = m_textureImage.getWidth();
239  const int height = m_textureImage.getHeight();
240 
241 #ifdef TEXTUREOBJ_PROFILE_MEM_ALLOC
242  {
243  const std::string sSec = mrpt::format(
244  "opengl_texture: load %ix%i %s %stransp", width, height,
245  m_textureImage.isColor() ? "RGB" : "BW",
246  m_enableTransparency ? "" : "no ");
247  tim.enter(sSec.c_str());
248  }
249 #endif
250 
251  r_width = width; // round2up( width );
252  r_height = height; // round2up( height );
253 
254  // Padding pixels:
257 
259  {
261  ASSERT_(
263  ASSERT_(
265  }
266 
267  if (m_textureImage.isColor())
268  {
269  // Color texture:
271  {
272 // Color texture WITH trans.
273 // --------------------------------------
274 #ifdef TEXTUREOBJ_PROFILE_MEM_ALLOC
275  const std::string sSec = mrpt::format(
276  "opengl_texture_alloc %ix%i (color,trans)", width, height);
277  tim.enter(sSec.c_str());
278 #endif
279 
280  dataAligned = reserveDataBuffer(height * width * 4 + 512, data);
281 
282 #ifdef TEXTUREOBJ_PROFILE_MEM_ALLOC
283  tim.leave(sSec.c_str());
284 #endif
285 
286  for (int y = 0; y < height; y++)
287  {
288  unsigned char* ptrSrcCol = m_textureImage(0, y, 0);
289  unsigned char* ptrSrcAlfa = m_textureImageAlpha(0, y);
290  unsigned char* ptr = dataAligned + y * width * 4;
291 
292  for (int x = 0; x < width; x++)
293  {
294  *ptr++ = *ptrSrcCol++;
295  *ptr++ = *ptrSrcCol++;
296  *ptr++ = *ptrSrcCol++;
297  *ptr++ = *ptrSrcAlfa++;
298  }
299  }
300 
301  // Prepare image data types:
302  const GLenum img_type = GL_UNSIGNED_BYTE;
303  const bool is_RGB_order =
304  (!::strcmp(
306  "RGB")); // Reverse RGB <-> BGR order?
307  const GLenum img_format = (is_RGB_order ? GL_RGBA : GL_BGRA);
308 
309  // Send image data to OpenGL:
312  glTexImage2D(
313  GL_TEXTURE_2D, 0 /*level*/, 4 /* RGB components */, width,
314  height, 0 /*border*/, img_format, img_type, dataAligned);
316  glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); // Reset
317 
318  // No need to hide a fill border:
319  m_pad_x_right = 0;
320  m_pad_y_bottom = 0;
321 
322  } // End of color texture WITH trans.
323  else
324  {
325  // Color texture WITHOUT trans.
326  // --------------------------------------
327  // Prepare image data types:
328  const GLenum img_type = GL_UNSIGNED_BYTE;
329  const int nBytesPerPixel = m_textureImage.isColor() ? 3 : 1;
330  const bool is_RGB_order =
331  (!::strcmp(
333  "RGB")); // Reverse RGB <-> BGR order?
334  const GLenum img_format = nBytesPerPixel == 3
335  ? (is_RGB_order ? GL_RGB : GL_BGR)
336  : GL_LUMINANCE;
337 
338  // Send image data to OpenGL:
342  m_textureImage.getRowStride() / nBytesPerPixel);
343  glTexImage2D(
344  GL_TEXTURE_2D, 0 /*level*/, 3 /* RGB components */, width,
345  height, 0 /*border*/, img_format, img_type,
346  m_textureImage.get_unsafe(0, 0));
347  glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); // Reset
348 
349  // No need to hide a fill border:
350  m_pad_x_right = 0;
351  m_pad_y_bottom = 0;
352 
353  } // End of color texture WITHOUT trans.
354  }
355  else
356  {
357  // Gray-scale texture:
359  {
360 #ifdef TEXTUREOBJ_PROFILE_MEM_ALLOC
361  const std::string sSec = mrpt::format(
362  "opengl_texture_alloc %ix%i (gray,transp)", width, height);
363  tim.enter(sSec.c_str());
364 #endif
365 
366  dataAligned =
367  reserveDataBuffer(height * width * 2 + 1024, data);
368 
369 #ifdef TEXTUREOBJ_PROFILE_MEM_ALLOC
370  tim.leave(sSec.c_str());
371 #endif
372 
373  for (int y = 0; y < height; y++)
374  {
375  unsigned char* ptrSrcCol = m_textureImage(0, y);
376  unsigned char* ptrSrcAlfa = m_textureImageAlpha(0, y);
377  unsigned char* ptr = dataAligned + y * width * 2;
378  for (int x = 0; x < width; x++)
379  {
380  *ptr++ = *ptrSrcCol++;
381  *ptr++ = *ptrSrcAlfa++;
382  }
383  }
384 
385  // Prepare image data types:
386  const GLenum img_type = GL_UNSIGNED_BYTE;
387  const GLenum img_format = GL_LUMINANCE_ALPHA;
388 
389  // Send image data to OpenGL:
392  glTexImage2D(
393  GL_TEXTURE_2D, 0 /*level*/, 2 /* RGB components */, width,
394  height, 0 /*border*/, img_format, img_type, dataAligned);
396  glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); // Reset
397 
398  // No need to hide a fill border:
399  m_pad_x_right = 0;
400  m_pad_y_bottom = 0;
401 
402  } // End of gray-scale texture WITH trans.
403  else
404  {
405  // Prepare image data types:
406  const GLenum img_type = GL_UNSIGNED_BYTE;
407  const GLenum img_format = GL_LUMINANCE;
408 
409  // Send image data to OpenGL:
413  glTexImage2D(
414  GL_TEXTURE_2D, 0 /*level*/, 1 /* RGB components */, width,
415  height, 0 /*border*/, img_format, img_type,
416  m_textureImage(0, 0));
418  glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); // Reset
419 
420  // No need to hide a fill border:
421  m_pad_x_right = 0;
422  m_pad_y_bottom = 0;
423 
424  } // End of gray-scale texture WITHOUT trans.
425  }
426 
427  m_texture_is_loaded = true;
428 
429 #ifdef TEXTUREOBJ_PROFILE_MEM_ALLOC
430  {
431  const std::string sSec = mrpt::format(
432  "opengl_texture: load %ix%i %s %stransp", width, height,
433  m_textureImage.isColor() ? "RGB" : "BW",
434  m_enableTransparency ? "" : "no ");
435  tim.leave(sSec.c_str());
436  }
437 #endif
438 
439 #ifdef TEXTUREOBJ_USE_MEMPOOL
440  // Before freeing the buffer in "data", donate my memory to the pool:
441  if (!data.empty())
442  {
444  if (pool)
445  {
446  CTexturedObject_MemPoolParams mem_params;
447  mem_params.len = data.size();
448 
449  CTexturedObject_MemPoolData* mem_block =
451  data.swap(mem_block->data);
452 
453  pool->dump_to_pool(mem_params, mem_block);
454  }
455  }
456 #endif
457  }
458  catch (exception& e)
459  {
461  format("m_glTextureName=%i\n%s", m_glTextureName, e.what()));
462  }
463  catch (...)
464  {
465  THROW_EXCEPTION("Runtime error!");
466  }
467 #endif
468 }
469 
470 /*---------------------------------------------------------------
471  ~CTexturedObject
472  ---------------------------------------------------------------*/
474 /*---------------------------------------------------------------
475  unloadTexture
476  ---------------------------------------------------------------*/
478 {
480  {
481  m_texture_is_loaded = false;
483  m_glTextureName = 0;
484  }
485 }
486 
487 /*---------------------------------------------------------------
488  Implements the writing to a CStream capability of
489  CSerializable objects
490  ---------------------------------------------------------------*/
492  mrpt::utils::CStream& out) const
493 {
494  uint8_t ver = 0;
495 
496  out << ver;
497  out << m_enableTransparency;
498  out << m_textureImage;
500 }
501 
503 {
504 #if MRPT_HAS_OPENGL_GLUT
505  render_pre();
506  if (glGetError() != GL_NO_ERROR)
507  std::cerr << "render_pre: Error" << std::endl;
509  if (glGetError() != GL_NO_ERROR)
510  std::cerr << "render_texturedobj: Error" << std::endl;
511  render_post();
512  if (glGetError() != GL_NO_ERROR)
513  std::cerr << "render_post: Error" << std::endl;
514 #endif
515 }
516 
518 {
519 #if MRPT_HAS_OPENGL_GLUT
520  MRPT_START
523 
524  if (m_enableTransparency || m_color.A != 255)
525  {
529  }
530  else
531  {
534  }
535 
536  // This will load and/or select our texture, only if "m_texture_is_loaded"
537  // is false
539  MRPT_END
540 #endif
541 }
542 
544 {
545 #if MRPT_HAS_OPENGL_GLUT
546  MRPT_START
547 
548  if (m_enableTransparency || m_color.A != 255)
549  {
552 
554 
557  }
558 
561 
562  MRPT_END
563 #endif
564 }
565 
566 /*---------------------------------------------------------------
567  Implements the reading from a CStream capability of
568  CSerializable objects
569  ---------------------------------------------------------------*/
571 {
572  uint8_t version;
573  in >> version;
574 
576 
577  switch (version)
578  {
579  case 0:
580  {
582  in >> m_textureImage;
584  {
587  }
588  else
589  {
591  }
592  }
593  break;
594  default:
596  };
598 }
mrpt::system::CGenericMemoryPool< CTexturedObject_MemPoolParams, CTexturedObject_MemPoolData > TMyMemPool
IMPLEMENTS_VIRTUAL_SERIALIZABLE(CTexturedObject, CRenderizableDisplayList, mrpt::opengl) struct CTexturedObject_MemPoolParams
unsigned char * reserveDataBuffer(const size_t len, vector< unsigned char > &data)
A renderizable object suitable for rendering with OpenGL's display lists.
EIGEN_STRONG_INLINE void notifyChange() const
Must be called to notify that the object has changed (so, the display list must be updated)
static void releaseTextureName(unsigned int i)
static unsigned int getNewTextureNumber()
Returns the lowest next free texture name (avoid using OpenGL's own function since we may call them f...
static void checkOpenGLError()
Checks glGetError and throws an exception if an error situation is found.
mrpt::utils::TColor m_color
Color components in the range [0,255].
Definition: CRenderizable.h:54
A base class for all OpenGL objects with loadable textures.
int r_width
Size of the texture image, rounded up to next power of 2.
void loadTextureInOpenGL() const
VERY IMPORTANT: If you use a multi-thread application, you MUST call this from the same thread that w...
virtual void render_pre() const
int m_pad_x_right
The size of the fill in pixels in the textured image, w.r.t the image passed by the user.
void readFromStreamTexturedObject(mrpt::utils::CStream &in)
mrpt::utils::CImage m_textureImage
void assignImage_fast(mrpt::utils::CImage &img, mrpt::utils::CImage &imgAlpha)
Similar to assignImage, but the passed images will be returned as empty: it avoids making a copy of t...
void writeToStreamTexturedObject(mrpt::utils::CStream &out) const
virtual void render_texturedobj() const =0
Must be implemented by derived classes.
void assignImage(const mrpt::utils::CImage &img, const mrpt::utils::CImage &imgAlpha)
Assigns a texture and a transparency image, and enables transparency (If the images are not 2^N x 2^M...
virtual void render_dl() const override
Derived classes must implement this method to the render the object.
mrpt::utils::CImage m_textureImageAlpha
bool m_enableTransparency
Of the texture using "m_textureImageAlpha".
virtual void render_post() const
A generic system for versatile memory pooling.
POOLABLE_DATA * request_memory(const DATA_PARAMS &params)
Request a block of data which fulfils the size requirements stated in params.
static CGenericMemoryPool< DATA_PARAMS, POOLABLE_DATA > * getInstance(const size_t max_pool_entries=5)
Construct-on-first-use (~singleton) pattern: Return the unique instance of this class for a given tem...
void dump_to_pool(const DATA_PARAMS &params, POOLABLE_DATA *block)
Saves the passed data block (characterized by params) to the pool.
A class for storing images as grayscale or RGB bitmaps.
Definition: CImage.h:119
unsigned char * get_unsafe(unsigned int col, unsigned int row, unsigned int channel=0) const
Access to pixels without checking boundaries - Use normally the () operator better,...
Definition: CImage.cpp:496
CImage scaleHalf() const
Returns a new image scaled down to half its original size.
Definition: CImage.h:336
size_t getRowStride() const
Returns the row stride of the image: this is the number of bytes between two consecutive rows.
Definition: CImage.cpp:883
size_t getHeight() const override
Returns the height of the image in pixels.
Definition: CImage.cpp:897
bool isColor() const
Returns true if the image is RGB, false if it is grayscale.
Definition: CImage.cpp:911
size_t getWidth() const override
Returns the width of the image in pixels.
Definition: CImage.cpp:869
void copyFastFrom(CImage &o)
Moves an image from another object, erasing the origin image in the process (this is much faster than...
Definition: CImage.cpp:173
const char * getChannelsOrder() const
Returns a string of the form "BGR","RGB" or "GRAY" indicating the channels ordering.
Definition: CImage.cpp:1188
This base class is used to provide a unified interface to files,memory buffers,..Please see the deriv...
Definition: CStream.h:42
A versatile "profiler" that logs the time spent within each pair of calls to enter(X)-leave(X),...
Definition: CTimeLogger.h:46
void enter(const char *func_name)
Start of a named section.
Definition: CTimeLogger.h:117
double leave(const char *func_name)
End of a named section.
Definition: CTimeLogger.h:123
#define GL_MAX_TEXTURE_SIZE
Definition: glew.h:510
#define GL_TEXTURE_MIN_FILTER
Definition: glew.h:666
GLAPI void GLAPIENTRY glEnable(GLenum cap)
#define GL_TEXTURE_WRAP_S
Definition: glew.h:667
#define GL_BGR
Definition: glew.h:1239
#define GL_LUMINANCE_ALPHA
Definition: glew.h:626
#define GL_DEPTH_TEST
Definition: glew.h:401
#define GL_LINEAR
Definition: glew.h:660
#define GL_SRC_ALPHA
Definition: glew.h:286
#define GL_BGRA
Definition: glew.h:8246
#define GL_LUMINANCE
Definition: glew.h:625
#define GL_RGB
Definition: glew.h:623
#define GL_ZERO
Definition: glew.h:282
#define GL_NEAREST
Definition: glew.h:659
unsigned int GLenum
Definition: glew.h:206
#define GL_UNSIGNED_BYTE
Definition: glew.h:302
#define GL_NO_ERROR
Definition: glew.h:326
GLAPI void GLAPIENTRY glBlendFunc(GLenum sfactor, GLenum dfactor)
#define GL_UNPACK_ALIGNMENT
Definition: glew.h:484
GLAPI void GLAPIENTRY glBindTexture(GLenum target, GLuint texture)
GLAPI GLenum GLAPIENTRY glGetError(void)
#define GL_RGBA
Definition: glew.h:624
#define GL_BLEND
Definition: glew.h:432
#define GL_ONE_MINUS_SRC_ALPHA
Definition: glew.h:287
#define GL_REPEAT
Definition: glew.h:670
#define GL_ONE
Definition: glew.h:283
GLAPI void GLAPIENTRY glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels)
#define GL_TEXTURE_WRAP_T
Definition: glew.h:668
#define GL_TEXTURE_MAG_FILTER
Definition: glew.h:665
int GLint
Definition: glew.h:209
GLAPI void GLAPIENTRY glDisable(GLenum cap)
#define GL_TEXTURE_2D
Definition: glew.h:7238
GLAPI void GLAPIENTRY glPixelStorei(GLenum pname, GLint param)
GLAPI void GLAPIENTRY glGetIntegerv(GLenum pname, GLint *params)
GLAPI void GLAPIENTRY glTexParameterf(GLenum target, GLenum pname, GLfloat param)
#define GL_UNPACK_ROW_LENGTH
Definition: glew.h:481
GLsizei GLsizei GLenum GLenum const GLvoid * data
Definition: glext.h:3547
GLenum GLsizei len
Definition: glext.h:4712
GLenum GLint GLint y
Definition: glext.h:3538
GLenum GLsizei width
Definition: glext.h:3531
GLuint in
Definition: glext.h:7274
GLint GLvoid * img
Definition: glext.h:3763
GLenum GLint x
Definition: glext.h:3538
GLenum GLsizei GLsizei height
Definition: glext.h:3554
GLsizei const GLchar ** string
Definition: glext.h:4101
unsigned long POINTER_TYPE
For performing type casting from a pointer to its numeric value.
Definition: types_simple.h:45
#define MRPT_START
Definition: mrpt_macros.h:425
#define ASSERT_(f)
Definition: mrpt_macros.h:309
#define MRPT_END
Definition: mrpt_macros.h:429
#define MRPT_THROW_UNKNOWN_SERIALIZATION_VERSION(__V)
For use in CSerializable implementations.
Definition: mrpt_macros.h:181
#define THROW_EXCEPTION(msg)
Definition: mrpt_macros.h:111
This base provides a set of functions for maths stuff.
Definition: CArrayNumeric.h:20
The namespace for 3D scene representation and rendering.
Definition: CGlCanvasBase.h:16
Classes for 2D/3D geometry representation, both of single values and probability density distribution...
Definition: CPoint.h:18
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values,...
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
std::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
Definition: format.cpp:19
unsigned char uint8_t
Definition: rptypes.h:41
vector< unsigned char > data



Page generated by Doxygen 1.9.1 for MRPT 1.9.9 Git: 63ea9d1f1 Thu Nov 23 00:06:53 2017 +0100 at mar 26 may 2026 12:19:29 CEST