MRPT  1.9.9
CMesh3D.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-2018, 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 
12 #include <mrpt/opengl/CMesh3D.h>
13 #include <mrpt/img/color_maps.h>
15 
16 #include "opengl_internals.h"
17 
18 using namespace mrpt;
19 using namespace mrpt::opengl;
20 
21 using namespace mrpt::poses;
22 using namespace mrpt::math;
23 using namespace std;
24 
26 
28  bool enableTransparency, bool antiAliasing, bool enableShowEdges,
29  bool enableShowFaces, bool enableShowVertices)
30  : m_enableTransparency(enableTransparency),
31  m_antiAliasing(antiAliasing),
32  m_showEdges(enableShowEdges),
33  m_showFaces(enableShowFaces),
34  m_showVertices(enableShowVertices),
35  m_computeNormals(true),
36  m_lineWidth(2.f),
37  m_pointSize(6.f),
38  m_colorMap(mrpt::img::cmHOT)
39 {
40  m_color.R = 1.f;
41  m_color.G = 0.f;
42  m_color.B = 0.f;
43  m_color.A = 1.f;
44  edge_color[0] = 0.9f;
45  edge_color[1] = 0.9f;
46  edge_color[2] = 0.9f;
47  edge_color[3] = 1.f;
48  face_color[0] = 0.7f;
49  face_color[1] = 0.7f;
50  face_color[2] = 0.8f;
51  face_color[3] = 1.f;
52  vert_color[0] = 0.3f;
53  vert_color[1] = 0.3f;
54  vert_color[2] = 0.3f;
55  vert_color[3] = 1.f;
56  m_num_faces = 0;
57  m_num_verts = 0;
58 }
59 
62  unsigned int num_verts, unsigned int num_faces, int* verts_per_face,
63  int* face_verts, float* vert_coords)
64 {
65  m_num_verts = num_verts;
66  m_num_faces = num_faces;
67 
68  // Fill number of vertices for each face
69  m_is_quad = new bool[num_faces];
70  for (unsigned int i = 0; i < num_faces; i++)
71  {
72  if (verts_per_face[i] == 3)
73  m_is_quad[i] = false;
74  else if (verts_per_face[i] == 4)
75  m_is_quad[i] = true;
76  else
77  {
78  printf(
79  "\n Incorrect mesh format. It can only be composed of "
80  "triangles and/or quads.");
81  return;
82  }
83  }
84 
85  // Fill the vertices of each face
86  m_face_verts = new f_verts[num_faces];
87  unsigned int count = 0;
88  for (unsigned int f = 0; f < num_faces; f++)
89  {
90  m_face_verts[f][0] = face_verts[count++];
91  m_face_verts[f][1] = face_verts[count++];
92  m_face_verts[f][2] = face_verts[count++];
93  if (m_is_quad[f])
94  m_face_verts[f][3] = face_verts[count++];
95  else
96  m_face_verts[f][3] = -1; // Meaning it is a triangle
97  }
98 
99  // Fill the 3D coordinates of the vertex
100  m_vert_coords = new coord3D[num_verts];
101  for (unsigned int i = 0; i < num_verts; i++)
102  {
103  m_vert_coords[i][0] = vert_coords[3 * i];
104  m_vert_coords[i][1] = vert_coords[3 * i + 1];
105  m_vert_coords[i][2] = vert_coords[3 * i + 2];
106  }
107 
108  // Compute the mesh normals (if on)
109  if (m_computeNormals)
110  {
111  m_normals = new coord3D[num_faces];
112 
113  for (unsigned int f = 0; f < num_faces; f++)
114  {
115  const unsigned int v1 = m_face_verts[f][0];
116  const unsigned int v2 = m_face_verts[f][1];
117  const unsigned int v3 = m_face_verts[f][2];
118  const unsigned int v4 = m_face_verts[f][3];
119 
120  if (m_is_quad[f])
121  {
122  const float vec1[3] = {
123  m_vert_coords[v3][0] - m_vert_coords[v1][0],
124  m_vert_coords[v3][1] - m_vert_coords[v1][1],
125  m_vert_coords[v3][2] - m_vert_coords[v1][2]};
126  const float vec2[3] = {
127  m_vert_coords[v4][0] - m_vert_coords[v2][0],
128  m_vert_coords[v4][1] - m_vert_coords[v2][1],
129  m_vert_coords[v4][2] - m_vert_coords[v2][2]};
130  m_normals[f][0] = vec1[1] * vec2[2] - vec1[2] * vec2[1];
131  m_normals[f][1] = vec1[2] * vec2[0] - vec1[0] * vec2[2];
132  m_normals[f][2] = vec1[0] * vec2[1] - vec1[1] * vec2[0];
133  }
134  else
135  {
136  const float vec1[3] = {
137  m_vert_coords[v2][0] - m_vert_coords[v1][0],
138  m_vert_coords[v2][1] - m_vert_coords[v1][1],
139  m_vert_coords[v2][2] - m_vert_coords[v1][2]};
140  const float vec2[3] = {
141  m_vert_coords[v3][0] - m_vert_coords[v1][0],
142  m_vert_coords[v3][1] - m_vert_coords[v1][1],
143  m_vert_coords[v3][2] - m_vert_coords[v1][2]};
144  m_normals[f][0] = vec1[1] * vec2[2] - vec1[2] * vec2[1];
145  m_normals[f][1] = vec1[2] * vec2[0] - vec1[0] * vec2[2];
146  m_normals[f][2] = vec1[0] * vec2[1] - vec1[1] * vec2[0];
147  }
148  }
149  }
150 
152 }
153 
155  unsigned int num_verts, unsigned int num_faces,
156  const Array<bool, 1, Dynamic>& is_quad,
157  const Array<int, 4, Dynamic>& face_verts,
158  const Array<float, 3, Dynamic>& vert_coords)
159 {
160  m_num_verts = num_verts;
161  m_num_faces = num_faces;
162 
163  // Fill number of vertices for each face
164  m_is_quad = new bool[num_faces];
165  for (unsigned int i = 0; i < num_faces; i++) m_is_quad[i] = is_quad(i);
166 
167  // Fill the vertices of each face
168  m_face_verts = new f_verts[num_faces];
169  for (unsigned int f = 0; f < num_faces; f++)
170  {
171  m_face_verts[f][0] = face_verts(0, f);
172  m_face_verts[f][1] = face_verts(1, f);
173  m_face_verts[f][2] = face_verts(2, f);
174  if (m_is_quad[f])
175  m_face_verts[f][3] = face_verts(3, f);
176  else
177  m_face_verts[f][3] = -1; // Meaning it is a triangle
178  }
179 
180  // Fill the 3D coordinates of the vertex
181  m_vert_coords = new coord3D[num_verts];
182  for (unsigned int i = 0; i < num_verts; i++)
183  {
184  m_vert_coords[i][0] = vert_coords(0, i);
185  m_vert_coords[i][1] = vert_coords(1, i);
186  m_vert_coords[i][2] = vert_coords(2, i);
187  }
188 
189  // Compute the mesh normals (if on)
190  m_normals = new coord3D[num_faces];
191  if (m_computeNormals)
192  for (unsigned int f = 0; f < num_faces; f++)
193  {
194  const unsigned int v1 = m_face_verts[f][0];
195  const unsigned int v2 = m_face_verts[f][1];
196  const unsigned int v3 = m_face_verts[f][2];
197  const unsigned int v4 = m_face_verts[f][3];
198 
199  if (m_is_quad[f])
200  {
201  const float vec1[3] = {
202  m_vert_coords[v3][0] - m_vert_coords[v1][0],
203  m_vert_coords[v3][1] - m_vert_coords[v1][1],
204  m_vert_coords[v3][2] - m_vert_coords[v1][2]};
205  const float vec2[3] = {
206  m_vert_coords[v4][0] - m_vert_coords[v2][0],
207  m_vert_coords[v4][1] - m_vert_coords[v2][1],
208  m_vert_coords[v4][2] - m_vert_coords[v2][2]};
209  m_normals[f][0] = vec1[1] * vec2[2] - vec1[2] * vec2[1];
210  m_normals[f][1] = vec1[2] * vec2[0] - vec1[0] * vec2[2];
211  m_normals[f][2] = vec1[0] * vec2[1] - vec1[1] * vec2[0];
212  }
213  else
214  {
215  const float vec1[3] = {
216  m_vert_coords[v2][0] - m_vert_coords[v1][0],
217  m_vert_coords[v2][1] - m_vert_coords[v1][1],
218  m_vert_coords[v2][2] - m_vert_coords[v1][2]};
219  const float vec2[3] = {
220  m_vert_coords[v3][0] - m_vert_coords[v1][0],
221  m_vert_coords[v3][1] - m_vert_coords[v1][1],
222  m_vert_coords[v3][2] - m_vert_coords[v1][2]};
223  m_normals[f][0] = vec1[1] * vec2[2] - vec1[2] * vec2[1];
224  m_normals[f][1] = vec1[2] * vec2[0] - vec1[0] * vec2[2];
225  m_normals[f][2] = vec1[0] * vec2[1] - vec1[1] * vec2[0];
226  }
227  }
228 
230 }
231 
232 /*---------------------------------------------------------------
233  render
234  ---------------------------------------------------------------*/
235 void CMesh3D::render_dl() const
236 {
237 #if MRPT_HAS_OPENGL_GLUT
238 
239  if (m_enableTransparency || m_antiAliasing)
240  {
243  }
244  else
245  {
248  }
249 
250  glEnable(GL_NORMALIZE); // So the GPU normalizes the normals instead of
251  // doing it in the CPU
254 
255  if (m_num_verts == 0) return;
256 
257  //---------------------------------------------------------------------------------------------------------
258  // Rendering - Test whether changing the rendering mode
259  // continuously
260  // is
261  // very slow (or not)
262  //---------------------------------------------------------------------------------------------------------
263 
264  // Render the faces
265  if (m_showFaces)
266  {
267  glColor4f(face_color[0], face_color[1], face_color[2], face_color[3]);
268 
269  for (unsigned int f = 0; f < m_num_faces; f++)
270  {
271  // Assign normals to faces (if on)
272  if (m_computeNormals)
273  glNormal3f(m_normals[f][0], m_normals[f][1], m_normals[f][2]);
274 
275  // Render Quads
276  if (m_is_quad[f])
277  {
278  glBegin(GL_QUADS);
279  for (int i = 0; i < 4; i++)
280  {
281  const unsigned int vert_ind = m_face_verts[f][i];
282  glVertex3f(
283  m_vert_coords[vert_ind][0], m_vert_coords[vert_ind][1],
284  m_vert_coords[vert_ind][2]);
285  }
286  glEnd();
287  }
288  // Render Triangles
289  else
290  {
292  for (int i = 0; i < 3; i++)
293  {
294  const unsigned int vert_ind = m_face_verts[f][i];
295  glVertex3f(
296  m_vert_coords[vert_ind][0], m_vert_coords[vert_ind][1],
297  m_vert_coords[vert_ind][2]);
298  }
299  glEnd();
300  }
301  }
302  }
303 
304  // Render the edges - They are rendered twice, which is redundant but simple
305  if (m_showEdges)
306  {
307  glColor4f(edge_color[0], edge_color[1], edge_color[2], edge_color[3]);
308  glDisable(GL_LIGHTING); //??
309  glLineWidth(m_lineWidth);
311  glBegin(GL_LINES);
312  for (unsigned int f = 0; f < m_num_faces; f++)
313  {
314  const unsigned char num_vert = 3 + m_is_quad[f];
315  for (int i = 0; i < num_vert - 1; i++)
316  {
317  const unsigned int v_0 = m_face_verts[f][i];
318  const unsigned int v_1 = m_face_verts[f][i + 1];
319 
320  glVertex3f(
321  m_vert_coords[v_0][0], m_vert_coords[v_0][1],
322  m_vert_coords[v_0][2]);
323  glVertex3f(
324  m_vert_coords[v_1][0], m_vert_coords[v_1][1],
325  m_vert_coords[v_1][2]);
326  }
327 
328  // The last vertex of the face needs to be connected to the first as
329  // well
330  const int v_0 = m_face_verts[f][num_vert - 1];
331  const int v_1 = m_face_verts[f][0];
332 
333  glVertex3f(
334  m_vert_coords[v_0][0], m_vert_coords[v_0][1],
335  m_vert_coords[v_0][2]);
336  glVertex3f(
337  m_vert_coords[v_1][0], m_vert_coords[v_1][1],
338  m_vert_coords[v_1][2]);
339  }
340  glEnd();
343  }
344 
345  // Render the vertices
346  if (m_showVertices)
347  {
348  glColor4f(vert_color[0], vert_color[1], vert_color[2], vert_color[3]);
350  glPointSize(m_pointSize);
353  for (unsigned int v = 0; v < m_num_verts; v++)
354  glVertex3f(
355  m_vert_coords[v][0], m_vert_coords[v][1], m_vert_coords[v][2]);
356 
357  glEnd();
360  }
361 
364 
365 #endif
366 }
367 
370 {
371  //********** To do **********
372  THROW_EXCEPTION("not implemented yet!");
373 
374  // writeToStreamRender(out);
375 
376  // // Version 0:
377  // out << m_enableTransparency;
378  // out << m_showEdges;
379  // out << m_showFaces;
380  // out << m_showVertices;
381  // out << m_computeNormals;
382  // out << m_num_verts;
383  // out << m_num_faces;
384 
385  // bool *m_is_quad;
386  // f_verts *m_face_verts;
387  // coord3D *m_vert_coords;
388  // coord3D *m_normals;
389 }
390 
392 {
393  //********** To do ************
394 }
395 
397  mrpt::math::TPoint3D& bb_min, mrpt::math::TPoint3D& bb_max) const
398 {
399  // Extreme initialization
400  bb_min.x = 10000.f;
401  bb_min.y = 10000.f;
402  bb_min.z = 10000.f;
403  bb_max.x = -10000.f;
404  bb_max.y = -10000.f;
405  bb_max.z = -10000.f;
406 
407  if (m_num_verts == 0)
408  printf(
409  "\n The mesh is empty and has no size. The returned information "
410  "has no meaning.");
411  else
412  {
413  for (unsigned int i = 0; i < m_num_verts; i++)
414  {
415  // Max
416  if (m_vert_coords[i][0] > bb_max.x) bb_max.x = m_vert_coords[i][0];
417  if (m_vert_coords[i][1] > bb_max.y) bb_max.y = m_vert_coords[i][1];
418  if (m_vert_coords[i][2] > bb_max.z) bb_max.z = m_vert_coords[i][2];
419 
420  // Min
421  if (m_vert_coords[i][0] < bb_min.x) bb_min.x = m_vert_coords[i][0];
422  if (m_vert_coords[i][1] < bb_min.y) bb_min.y = m_vert_coords[i][1];
423  if (m_vert_coords[i][2] < bb_min.z) bb_min.z = m_vert_coords[i][2];
424  }
425  }
426 
427  // Convert to coordinates of my parent:
428  m_pose.composePoint(bb_min, bb_min);
429  m_pose.composePoint(bb_max, bb_max);
430 }
431 
432 void CMesh3D::setEdgeColor(float r, float g, float b, float a)
433 {
434  edge_color[0] = r;
435  edge_color[1] = g;
436  edge_color[2] = b;
437  edge_color[3] = a;
438 }
439 
440 void CMesh3D::setFaceColor(float r, float g, float b, float a)
441 {
442  face_color[0] = r;
443  face_color[1] = g;
444  face_color[2] = b;
445  face_color[3] = a;
446 }
447 
448 void CMesh3D::setVertColor(float r, float g, float b, float a)
449 {
450  vert_color[0] = r;
451  vert_color[1] = g;
452  vert_color[2] = b;
453  vert_color[3] = a;
454 }
#define IMPLEMENTS_SERIALIZABLE(class_name, base, NameSpace)
This must be inserted in all CSerializable classes implementation files.
A 3D mesh composed of Triangles and/or Quads.
Definition: CMesh3D.h:37
virtual ~CMesh3D()
Private, virtual destructor: only can be deleted from smart pointers
Definition: CMesh3D.cpp:60
void serializeFrom(mrpt::serialization::CArchive &in, uint8_t serial_version) override
Pure virtual method for reading (deserializing) from an abstract archive.
Definition: CMesh3D.cpp:391
void setFaceColor(float r, float g, float b, float a=1.f)
Definition: CMesh3D.cpp:440
void getBoundingBox(mrpt::math::TPoint3D &bb_min, mrpt::math::TPoint3D &bb_max) const override
Evaluates the bounding box of this object (including possible children) in the coordinate frame of th...
Definition: CMesh3D.cpp:396
float[3] coord3D
Definition: CMesh3D.h:41
void loadMesh(unsigned int num_verts, unsigned int num_faces, int *verts_per_face, int *face_verts, float *vert_coords)
Load a 3D mesh.
Definition: CMesh3D.cpp:61
void setEdgeColor(float r, float g, float b, float a=1.f)
Definition: CMesh3D.cpp:432
void serializeTo(mrpt::serialization::CArchive &out) const override
Pure virtual method for writing (serializing) to an abstract archive.
Definition: CMesh3D.cpp:369
uint8_t serializeGetVersion() const override
Must return the current versioning number of the object.
Definition: CMesh3D.cpp:368
void render_dl() const override
Render.
Definition: CMesh3D.cpp:235
void setVertColor(float r, float g, float b, float a=1.f)
Definition: CMesh3D.cpp:448
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)
Virtual base class for "archives": classes abstracting I/O streams.
Definition: CArchive.h:53
#define THROW_EXCEPTION(msg)
Definition: exceptions.h:41
GLAPI void GLAPIENTRY glEnable(GLenum cap)
#define GL_QUADS
Definition: glew.h:279
#define GL_DEPTH_TEST
Definition: glew.h:401
#define GL_SRC_ALPHA
Definition: glew.h:286
#define GL_LINES
Definition: glew.h:273
#define GL_NORMALIZE
Definition: glew.h:416
#define GL_SMOOTH
Definition: glew.h:635
#define GL_POINT_SMOOTH
Definition: glew.h:363
#define GL_TRIANGLES
Definition: glew.h:276
GLAPI void GLAPIENTRY glPointSize(GLfloat size)
GLAPI void GLAPIENTRY glLineWidth(GLfloat width)
#define GL_POINTS
Definition: glew.h:272
GLAPI void GLAPIENTRY glBlendFunc(GLenum sfactor, GLenum dfactor)
GLAPI void GLAPIENTRY glNormal3f(GLfloat nx, GLfloat ny, GLfloat nz)
GLAPI void GLAPIENTRY glBegin(GLenum mode)
GLAPI void GLAPIENTRY glVertex3f(GLfloat x, GLfloat y, GLfloat z)
#define GL_COLOR_MATERIAL
Definition: glew.h:392
#define GL_BLEND
Definition: glew.h:432
#define GL_ONE_MINUS_SRC_ALPHA
Definition: glew.h:287
GLAPI void GLAPIENTRY glEnd(void)
GLAPI void GLAPIENTRY glDisable(GLenum cap)
GLAPI void GLAPIENTRY glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
GLAPI void GLAPIENTRY glShadeModel(GLenum mode)
#define GL_LINE_SMOOTH
Definition: glew.h:367
#define GL_LIGHTING
Definition: glew.h:385
GLfloat GLfloat v1
Definition: glext.h:4105
const GLdouble * v
Definition: glext.h:3678
GLuint GLuint GLsizei count
Definition: glext.h:3528
GLubyte GLubyte b
Definition: glext.h:6279
GLuint in
Definition: glext.h:7274
GLint GLvoid * img
Definition: glext.h:3763
GLfloat GLfloat GLfloat v2
Definition: glext.h:4107
GLubyte g
Definition: glext.h:6279
GLdouble GLdouble GLdouble r
Definition: glext.h:3705
GLubyte GLubyte GLubyte a
Definition: glext.h:6279
GLfloat GLfloat GLfloat GLfloat v3
Definition: glext.h:4109
@ cmHOT
[New in MRPT 1.5.0]
Definition: color_maps.h:35
This base provides a set of functions for maths stuff.
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...
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
unsigned char uint8_t
Definition: rptypes.h:41
Lightweight 3D point.
double x
X,Y,Z coordinates.



Page generated by Doxygen 1.9.1 for MRPT 1.9.9 Git: 814d80880 Fri Aug 24 01:51:28 2018 +0200 at mar 26 may 2026 12:30:59 CEST