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 }
virtual void render_post() const
#define GL_BGR
Definition: glew.h:1239
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...
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values, timewatch, extensions to STL.
#define GL_TEXTURE_WRAP_T
Definition: glew.h:668
#define GL_RGBA
Definition: glew.h:624
std::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
A base class for all OpenGL objects with loadable textures.
virtual void render_dl() const override
Derived classes must implement this method to the render the object.
GLAPI void GLAPIENTRY glEnable(GLenum cap)
#define GL_ZERO
Definition: glew.h:282
A class for storing images as grayscale or RGB bitmaps.
Definition: CImage.h:118
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
#define THROW_EXCEPTION(msg)
const char * getChannelsOrder() const
Returns a string of the form "BGR","RGB" or "GRAY" indicating the channels ordering.
Definition: CImage.cpp:1188
void dump_to_pool(const DATA_PARAMS &params, POOLABLE_DATA *block)
Saves the passed data block (characterized by params) to the pool.
#define GL_BGRA
Definition: glew.h:8246
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...
EIGEN_STRONG_INLINE void notifyChange() const
Must be called to notify that the object has changed (so, the display list must be updated) ...
STL namespace.
#define GL_UNSIGNED_BYTE
Definition: glew.h:302
#define GL_LINEAR
Definition: glew.h:660
#define GL_ONE_MINUS_SRC_ALPHA
Definition: glew.h:287
int r_width
Size of the texture image, rounded up to next power of 2.
#define GL_DEPTH_TEST
Definition: glew.h:401
POOLABLE_DATA * request_memory(const DATA_PARAMS &params)
Request a block of data which fulfils the size requirements stated in params.
GLenum GLsizei len
Definition: glext.h:4712
GLenum GLsizei width
Definition: glext.h:3531
GLAPI void GLAPIENTRY glBlendFunc(GLenum sfactor, GLenum dfactor)
unsigned char uint8_t
Definition: rptypes.h:41
A renderizable object suitable for rendering with OpenGL&#39;s display lists.
GLAPI void GLAPIENTRY glTexParameterf(GLenum target, GLenum pname, GLfloat param)
A generic system for versatile memory pooling.
GLAPI void GLAPIENTRY glBindTexture(GLenum target, GLuint texture)
This base class is used to provide a unified interface to files,memory buffers,..Please see the deriv...
Definition: CStream.h:41
vector< unsigned char > data
This base provides a set of functions for maths stuff.
Definition: CArrayNumeric.h:19
size_t getWidth() const override
Returns the width of the image in pixels.
Definition: CImage.cpp:869
IMPLEMENTS_VIRTUAL_SERIALIZABLE(CTexturedObject, CRenderizableDisplayList, mrpt::opengl) struct CTexturedObject_MemPoolParams
#define MRPT_END
bool m_enableTransparency
Of the texture using "m_textureImageAlpha".
#define MRPT_THROW_UNKNOWN_SERIALIZATION_VERSION(__V)
For use in CSerializable implementations.
#define GL_ONE
Definition: glew.h:283
GLint GLvoid * img
Definition: glext.h:3763
size_t getHeight() const override
Returns the height of the image in pixels.
Definition: CImage.cpp:897
std::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
Definition: format.cpp:19
mrpt::utils::TColor m_color
Color components in the range [0,255].
Definition: CRenderizable.h:54
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
#define GL_RGB
Definition: glew.h:623
#define GL_BLEND
Definition: glew.h:432
virtual void render_pre() const
void writeToStreamTexturedObject(mrpt::utils::CStream &out) const
#define GL_REPEAT
Definition: glew.h:670
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...
GLsizei const GLchar ** string
Definition: glext.h:4101
Classes for 2D/3D geometry representation, both of single values and probability density distribution...
Definition: CPoint.h:17
virtual void render_texturedobj() const =0
Must be implemented by derived classes.
unsigned char * reserveDataBuffer(const size_t len, vector< unsigned char > &data)
unsigned int GLenum
Definition: glew.h:206
#define GL_NEAREST
Definition: glew.h:659
#define MRPT_START
#define GL_SRC_ALPHA
Definition: glew.h:286
static void checkOpenGLError()
Checks glGetError and throws an exception if an error situation is found.
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
#define GL_NO_ERROR
Definition: glew.h:326
#define GL_UNPACK_ROW_LENGTH
Definition: glew.h:481
#define GL_TEXTURE_MIN_FILTER
Definition: glew.h:666
#define GL_UNPACK_ALIGNMENT
Definition: glew.h:484
static unsigned int getNewTextureNumber()
Returns the lowest next free texture name (avoid using OpenGL&#39;s own function since we may call them f...
unsigned long POINTER_TYPE
For performing type casting from a pointer to its numeric value.
Definition: types_simple.h:45
#define GL_TEXTURE_MAG_FILTER
Definition: glew.h:665
mrpt::utils::CImage m_textureImage
CImage scaleHalf() const
Returns a new image scaled down to half its original size.
Definition: CImage.h:336
GLAPI void GLAPIENTRY glGetIntegerv(GLenum pname, GLint *params)
GLAPI GLenum GLAPIENTRY glGetError(void)
GLuint in
Definition: glext.h:7274
The namespace for 3D scene representation and rendering.
Definition: CGlCanvasBase.h:15
#define ASSERT_(f)
A versatile "profiler" that logs the time spent within each pair of calls to enter(X)-leave(X), among other stats.
Definition: CTimeLogger.h:45
double leave(const char *func_name)
End of a named section.
Definition: CTimeLogger.h:123
GLenum GLint GLint y
Definition: glext.h:3538
mrpt::system::CGenericMemoryPool< CTexturedObject_MemPoolParams, CTexturedObject_MemPoolData > TMyMemPool
bool isColor() const
Returns true if the image is RGB, false if it is grayscale.
Definition: CImage.cpp:911
int GLint
Definition: glew.h:209
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, which checks the coordinates.
Definition: CImage.cpp:496
#define GL_MAX_TEXTURE_SIZE
Definition: glew.h:510
GLenum GLint x
Definition: glext.h:3538
#define GL_LUMINANCE_ALPHA
Definition: glew.h:626
void loadTextureInOpenGL() const
VERY IMPORTANT: If you use a multi-thread application, you MUST call this from the same thread that w...
GLenum GLsizei GLsizei height
Definition: glext.h:3554
void enter(const char *func_name)
Start of a named section.
Definition: CTimeLogger.h:117
GLAPI void GLAPIENTRY glDisable(GLenum cap)
GLsizei GLsizei GLenum GLenum const GLvoid * data
Definition: glext.h:3546
GLAPI void GLAPIENTRY glPixelStorei(GLenum pname, GLint param)
#define GL_TEXTURE_WRAP_S
Definition: glew.h:667
#define GL_TEXTURE_2D
Definition: glew.h:7238
static void releaseTextureName(unsigned int i)
#define GL_LUMINANCE
Definition: glew.h:625
GLAPI void GLAPIENTRY glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels)
mrpt::utils::CImage m_textureImageAlpha
void readFromStreamTexturedObject(mrpt::utils::CStream &in)
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...



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: ae4571287 Thu Nov 23 00:06:53 2017 +0100 at dom oct 27 23:51:55 CET 2019