Main MRPT website > C++ reference for MRPT 1.5.7
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-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 
12 #include <mrpt/opengl/CMesh3D.h>
13 #include <mrpt/utils/color_maps.h>
14 #include <mrpt/utils/CStream.h>
15 
16 #include "opengl_internals.h"
17 
18 using namespace mrpt;
19 using namespace mrpt::opengl;
20 using namespace mrpt::utils;
21 using namespace mrpt::poses;
22 using namespace mrpt::math;
23 using namespace std;
24 
26 
27 CMesh3DPtr CMesh3D::Create(bool enableTransparency, bool enableShowEdges, bool enableShowFaces, bool enableShowVertices)
28 {
29  return CMesh3DPtr(new CMesh3D(enableTransparency, enableShowEdges, enableShowFaces, enableShowVertices));
30 }
31 
32 CMesh3D::CMesh3D(bool enableTransparency, bool antiAliasing , bool enableShowEdges , bool enableShowFaces, bool enableShowVertices ) :
33  m_enableTransparency(enableTransparency),
34  m_antiAliasing(antiAliasing),
35  m_showEdges(enableShowEdges),
36  m_showFaces(enableShowFaces),
37  m_showVertices(enableShowVertices),
38  m_computeNormals(true),
39  m_lineWidth(2.f),
40  m_pointSize(6.f),
41  m_colorMap(mrpt::utils::cmHOT)
42 {
43  m_color.R = 1.f; m_color.G = 0.f; m_color.B = 0.f; m_color.A = 1.f;
44  edge_color[0] = 0.9f; edge_color[1] = 0.9f; edge_color[2] = 0.9f; edge_color[3] = 1.f;
45  face_color[0] = 0.7f; face_color[1] = 0.7f; face_color[2] = 0.8f; face_color[3] = 1.f;
46  vert_color[0] = 0.3f; vert_color[1] = 0.3f; vert_color[2] = 0.3f; vert_color[3] = 1.f;
47  m_num_faces = 0;
48  m_num_verts = 0;
49 }
50 
52 {
53 }
54 
55 void CMesh3D::loadMesh(unsigned int num_verts, unsigned int num_faces, int *verts_per_face, int *face_verts, float *vert_coords)
56 {
57  m_num_verts = num_verts;
58  m_num_faces = num_faces;
59 
60  //Fill number of vertices for each face
61  m_is_quad = new bool[num_faces];
62  for (unsigned int i = 0; i < num_faces; i++)
63  {
64  if (verts_per_face[i] == 3)
65  m_is_quad[i] = false;
66  else if (verts_per_face[i] == 4)
67  m_is_quad[i] = true;
68  else
69  {
70  printf("\n Incorrect mesh format. It can only be composed of triangles and/or quads.");
71  return;
72  }
73  }
74 
75  //Fill the vertices of each face
76  m_face_verts = new f_verts[num_faces];
77  unsigned int count = 0;
78  for (unsigned int f = 0; f < num_faces; f++)
79  {
80  m_face_verts[f][0] = face_verts[count++];
81  m_face_verts[f][1] = face_verts[count++];
82  m_face_verts[f][2] = face_verts[count++];
83  if (m_is_quad[f])
84  m_face_verts[f][3] = face_verts[count++];
85  else
86  m_face_verts[f][3] = -1; // Meaning it is a triangle
87  }
88 
89  //Fill the 3D coordinates of the vertex
90  m_vert_coords = new coord3D[num_verts];
91  for (unsigned int i = 0; i < num_verts; i++)
92  {
93  m_vert_coords[i][0] = vert_coords[3 * i];
94  m_vert_coords[i][1] = vert_coords[3 * i + 1];
95  m_vert_coords[i][2] = vert_coords[3 * i + 2];
96  }
97 
98  //Compute the mesh normals (if on)
99  if (m_computeNormals)
100  {
101  m_normals = new coord3D[num_faces];
102 
103  for (unsigned int f = 0; f < num_faces; f++)
104  {
105  const unsigned int v1 = m_face_verts[f][0];
106  const unsigned int v2 = m_face_verts[f][1];
107  const unsigned int v3 = m_face_verts[f][2];
108  const unsigned int v4 = m_face_verts[f][3];
109 
110  if (m_is_quad[f])
111  {
112  const float vec1[3] = { m_vert_coords[v3][0] - m_vert_coords[v1][0], m_vert_coords[v3][1] - m_vert_coords[v1][1], m_vert_coords[v3][2] - m_vert_coords[v1][2] };
113  const float vec2[3] = { m_vert_coords[v4][0] - m_vert_coords[v2][0], m_vert_coords[v4][1] - m_vert_coords[v2][1], m_vert_coords[v4][2] - m_vert_coords[v2][2] };
114  m_normals[f][0] = vec1[1] * vec2[2] - vec1[2] * vec2[1];
115  m_normals[f][1] = vec1[2] * vec2[0] - vec1[0] * vec2[2];
116  m_normals[f][2] = vec1[0] * vec2[1] - vec1[1] * vec2[0];
117  }
118  else
119  {
120  const float vec1[3] = { m_vert_coords[v2][0] - m_vert_coords[v1][0], m_vert_coords[v2][1] - m_vert_coords[v1][1], m_vert_coords[v2][2] - m_vert_coords[v1][2] };
121  const float vec2[3] = { m_vert_coords[v3][0] - m_vert_coords[v1][0], m_vert_coords[v3][1] - m_vert_coords[v1][1], m_vert_coords[v3][2] - m_vert_coords[v1][2] };
122  m_normals[f][0] = vec1[1] * vec2[2] - vec1[2] * vec2[1];
123  m_normals[f][1] = vec1[2] * vec2[0] - vec1[0] * vec2[2];
124  m_normals[f][2] = vec1[0] * vec2[1] - vec1[1] * vec2[0];
125  }
126  }
127  }
128 
130 }
131 
132 void CMesh3D::loadMesh(unsigned int num_verts, unsigned int num_faces, const Array<bool, 1, Dynamic> &is_quad, const Array<int, 4, Dynamic> &face_verts, const Array<float, 3, Dynamic> &vert_coords)
133 {
134  m_num_verts = num_verts;
135  m_num_faces = num_faces;
136 
137  //Fill number of vertices for each face
138  m_is_quad = new bool[num_faces];
139  for (unsigned int i = 0; i < num_faces; i++)
140  m_is_quad[i] = is_quad(i);
141 
142  //Fill the vertices of each face
143  m_face_verts = new f_verts[num_faces];
144  for (unsigned int f = 0; f < num_faces; f++)
145  {
146  m_face_verts[f][0] = face_verts(0,f);
147  m_face_verts[f][1] = face_verts(1,f);
148  m_face_verts[f][2] = face_verts(2,f);
149  if (m_is_quad[f])
150  m_face_verts[f][3] = face_verts(3,f);
151  else
152  m_face_verts[f][3] = -1; // Meaning it is a triangle
153  }
154 
155  //Fill the 3D coordinates of the vertex
156  m_vert_coords = new coord3D[num_verts];
157  for (unsigned int i = 0; i < num_verts; i++)
158  {
159  m_vert_coords[i][0] = vert_coords(0,i);
160  m_vert_coords[i][1] = vert_coords(1,i);
161  m_vert_coords[i][2] = vert_coords(2,i);
162  }
163 
164  //Compute the mesh normals (if on)
165  m_normals = new coord3D[num_faces];
166  if (m_computeNormals)
167  for (unsigned int f = 0; f < num_faces; f++)
168  {
169  const unsigned int v1 = m_face_verts[f][0];
170  const unsigned int v2 = m_face_verts[f][1];
171  const unsigned int v3 = m_face_verts[f][2];
172  const unsigned int v4 = m_face_verts[f][3];
173 
174  if (m_is_quad[f])
175  {
176  const float vec1[3] = { m_vert_coords[v3][0] - m_vert_coords[v1][0], m_vert_coords[v3][1] - m_vert_coords[v1][1], m_vert_coords[v3][2] - m_vert_coords[v1][2] };
177  const float vec2[3] = { m_vert_coords[v4][0] - m_vert_coords[v2][0], m_vert_coords[v4][1] - m_vert_coords[v2][1], m_vert_coords[v4][2] - m_vert_coords[v2][2] };
178  m_normals[f][0] = vec1[1] * vec2[2] - vec1[2] * vec2[1];
179  m_normals[f][1] = vec1[2] * vec2[0] - vec1[0] * vec2[2];
180  m_normals[f][2] = vec1[0] * vec2[1] - vec1[1] * vec2[0];
181  }
182  else
183  {
184  const float vec1[3] = { m_vert_coords[v2][0] - m_vert_coords[v1][0], m_vert_coords[v2][1] - m_vert_coords[v1][1], m_vert_coords[v2][2] - m_vert_coords[v1][2] };
185  const float vec2[3] = { m_vert_coords[v3][0] - m_vert_coords[v1][0], m_vert_coords[v3][1] - m_vert_coords[v1][1], m_vert_coords[v3][2] - m_vert_coords[v1][2] };
186  m_normals[f][0] = vec1[1] * vec2[2] - vec1[2] * vec2[1];
187  m_normals[f][1] = vec1[2] * vec2[0] - vec1[0] * vec2[2];
188  m_normals[f][2] = vec1[0] * vec2[1] - vec1[1] * vec2[0];
189  }
190  }
191 
193 }
194 
195 
196 
197 /*---------------------------------------------------------------
198  render
199  ---------------------------------------------------------------*/
200 void CMesh3D::render_dl() const {
201 #if MRPT_HAS_OPENGL_GLUT
202 
204  {
207  }
208  else
209  {
212  }
213 
214 
215  glEnable(GL_NORMALIZE); // So the GPU normalizes the normals instead of doing it in the CPU
218 
219  if (m_num_verts == 0)
220  return;
221 
222  //---------------------------------------------------------------------------------------------------------
223  // Rendering - Test whether changing the rendering mode continuously is very slow (or not)
224  //---------------------------------------------------------------------------------------------------------
225 
226  //Render the faces
227  if (m_showFaces)
228  {
230 
231  for (unsigned int f = 0; f < m_num_faces; f++)
232  {
233  //Assign normals to faces (if on)
234  if (m_computeNormals) glNormal3f(m_normals[f][0], m_normals[f][1], m_normals[f][2]);
235 
236  //Render Quads
237  if (m_is_quad[f])
238  {
239  glBegin(GL_QUADS);
240  for (int i = 0; i < 4; i++)
241  {
242  const unsigned int vert_ind = m_face_verts[f][i];
243  glVertex3f(m_vert_coords[vert_ind][0], m_vert_coords[vert_ind][1], m_vert_coords[vert_ind][2]);
244  }
245  glEnd();
246  }
247  //Render Triangles
248  else
249  {
251  for (int i = 0; i < 3; i++)
252  {
253  const unsigned int vert_ind = m_face_verts[f][i];
254  glVertex3f(m_vert_coords[vert_ind][0], m_vert_coords[vert_ind][1], m_vert_coords[vert_ind][2]);
255  }
256  glEnd();
257  }
258  }
259  }
260 
261  //Render the edges - They are rendered twice, which is redundant but simple
262  if (m_showEdges)
263  {
265  glDisable(GL_LIGHTING); //??
268  glBegin(GL_LINES);
269  for (unsigned int f = 0; f < m_num_faces; f++)
270  {
271  const unsigned char num_vert = 3 + m_is_quad[f];
272  for (int i = 0; i < num_vert - 1; i++)
273  {
274  const unsigned int v_0 = m_face_verts[f][i];
275  const unsigned int v_1 = m_face_verts[f][i + 1];
276 
277  glVertex3f(m_vert_coords[v_0][0], m_vert_coords[v_0][1], m_vert_coords[v_0][2]);
278  glVertex3f(m_vert_coords[v_1][0], m_vert_coords[v_1][1], m_vert_coords[v_1][2]);
279  }
280 
281  //The last vertex of the face needs to be connected to the first as well
282  const int v_0 = m_face_verts[f][num_vert - 1];
283  const int v_1 = m_face_verts[f][0];
284 
285  glVertex3f(m_vert_coords[v_0][0], m_vert_coords[v_0][1], m_vert_coords[v_0][2]);
286  glVertex3f(m_vert_coords[v_1][0], m_vert_coords[v_1][1], m_vert_coords[v_1][2]);
287  }
288  glEnd();
291  }
292 
293  //Render the vertices
294  if (m_showVertices)
295  {
301  for (unsigned int v = 0; v < m_num_verts; v++)
303 
304  glEnd();
307  }
308 
311 
312 #endif
313 }
314 
315 
316 /*---------------------------------------------------------------
317  Implements the writing to a CStream capability of
318  CSerializable objects
319  ---------------------------------------------------------------*/
321 {
322  //********** To do **********
323  THROW_EXCEPTION("not implemented yet!")
324 
325  //if (version)
326  // *version = 0;
327  //else
328  //{
329  // writeToStreamRender(out);
330 
331  // // Version 0:
332  // out << m_enableTransparency;
333  // out << m_showEdges;
334  // out << m_showFaces;
335  // out << m_showVertices;
336  // out << m_computeNormals;
337  // out << m_num_verts;
338  // out << m_num_faces;
339 
340  // bool *m_is_quad;
341  // f_verts *m_face_verts;
342  // coord3D *m_vert_coords;
343  // coord3D *m_normals;
344  //}
345 }
346 
347 /*---------------------------------------------------------------
348  Implements the reading from a CStream capability of
349  CSerializable objects
350  ---------------------------------------------------------------*/
352 {
353  //********** To do ************
354 
355  //switch(version)
356  //{
357  //case 0:
358  // {
359  // readFromStreamRender(in);
360 
361  //in >> m_enableTransparency;
362  //in >> m_showEdges;
363  //in >> m_showFaces;
364  //in >> m_showVertices;
365  //in >> m_computeNormals;
366  //in >> m_num_verts;
367  //in >> m_num_faces;
368 
369  //bool *m_is_quad;
370  //f_verts *m_face_verts;
371  //coord3D *m_vert_coords;
372  //coord3D *m_normals;
373  // }
374  // break;
375  //default:
376  // MRPT_THROW_UNKNOWN_SERIALIZATION_VERSION(version)
377 
378  //};
379  //CRenderizableDisplayList::notifyChange();
380 }
381 
382 
384 {
385  //Extreme initialization
386  bb_min.x = 10000.f; bb_min.y = 10000.f; bb_min.z = 10000.f;
387  bb_max.x = -10000.f; bb_max.y = -10000.f; bb_max.z = -10000.f;
388 
389  if (m_num_verts == 0)
390  printf("\n The mesh is empty and has no size. The returned information has no meaning.");
391  else
392  {
393  for (unsigned int i = 0; i<m_num_verts; i++)
394  {
395  //Max
396  if (m_vert_coords[i][0] > bb_max.x)
397  bb_max.x = m_vert_coords[i][0];
398  if (m_vert_coords[i][1] > bb_max.y)
399  bb_max.y = m_vert_coords[i][1];
400  if (m_vert_coords[i][2] > bb_max.z)
401  bb_max.z = m_vert_coords[i][2];
402 
403  //Min
404  if (m_vert_coords[i][0] < bb_min.x)
405  bb_min.x = m_vert_coords[i][0];
406  if (m_vert_coords[i][1] < bb_min.y)
407  bb_min.y = m_vert_coords[i][1];
408  if (m_vert_coords[i][2] < bb_min.z)
409  bb_min.z = m_vert_coords[i][2];
410  }
411  }
412 
413  // Convert to coordinates of my parent:
414  m_pose.composePoint(bb_min, bb_min);
415  m_pose.composePoint(bb_max, bb_max);
416 }
417 
418 void CMesh3D::setEdgeColor(float r, float g, float b, float a)
419 {
420  edge_color[0] = r;
421  edge_color[1] = g;
422  edge_color[2] = b;
423  edge_color[3] = a;
424 }
425 
426 void CMesh3D::setFaceColor(float r, float g, float b, float a)
427 {
428  face_color[0] = r;
429  face_color[1] = g;
430  face_color[2] = b;
431  face_color[3] = a;
432 }
433 
434 void CMesh3D::setVertColor(float r, float g, float b, float a)
435 {
436  vert_color[0] = r;
437  vert_color[1] = g;
438  vert_color[2] = b;
439  vert_color[3] = a;
440 }
441 
#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:40
unsigned int m_num_verts
Number of vertices of the mesh.
Definition: CMesh3D.h:58
CMesh3D(bool enableTransparency=false, bool antiAliasing=false, bool enableShowEdges=true, bool enableShowFaces=true, bool enableShowVertices=false)
Constructor.
Definition: CMesh3D.cpp:32
float coord3D[3]
Definition: CMesh3D.h:44
virtual ~CMesh3D()
Private, virtual destructor: only can be deleted from smart pointers
Definition: CMesh3D.cpp:51
void readFromStream(mrpt::utils::CStream &in, int version)
Introduces a pure virtual method responsible for loading from a CStream This can not be used directly...
Definition: CMesh3D.cpp:351
void setFaceColor(float r, float g, float b, float a=1.f)
Definition: CMesh3D.cpp:426
void writeToStream(mrpt::utils::CStream &out, int *getVersion) const
Introduces a pure virtual method responsible for writing to a CStream.
Definition: CMesh3D.cpp:320
void render_dl() const MRPT_OVERRIDE
Render.
Definition: CMesh3D.cpp:200
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:55
bool * m_is_quad
Pointer storing whether a face is a quad (1) or a triangle (0)
Definition: CMesh3D.h:60
coord3D * m_normals
Pointer storing the face normals. Size: 3 x num_faces.
Definition: CMesh3D.h:63
void setEdgeColor(float r, float g, float b, float a=1.f)
Definition: CMesh3D.cpp:418
float edge_color[4]
Color of the edges (when shown)
Definition: CMesh3D.h:66
coord3D * m_vert_coords
Pointer storing the coordinates of the vertices. Size: 3 x num_vertices.
Definition: CMesh3D.h:62
void getBoundingBox(mrpt::math::TPoint3D &bb_min, mrpt::math::TPoint3D &bb_max) const MRPT_OVERRIDE
Evaluates the bounding box of this object (including possible children) in the coordinate frame of th...
Definition: CMesh3D.cpp:383
f_verts * m_face_verts
Pointer storing the vertices that compose each face. Size: 4 x num_faces (4 for the possible max numb...
Definition: CMesh3D.h:61
bool m_enableTransparency
Definition: CMesh3D.h:48
float face_color[4]
Color of the faces (when shown)
Definition: CMesh3D.h:67
float vert_color[4]
Color of the vertices (when shown)
Definition: CMesh3D.h:68
void setVertColor(float r, float g, float b, float a=1.f)
Definition: CMesh3D.cpp:434
unsigned int m_num_faces
Number of faces of the mesh.
Definition: CMesh3D.h:59
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)
mrpt::poses::CPose3D m_pose
6D pose wrt the parent coordinate reference. This class automatically holds the cached 3x3 rotation m...
Definition: CRenderizable.h:55
mrpt::utils::TColor m_color
Color components in the range [0,255].
Definition: CRenderizable.h:54
void composePoint(double lx, double ly, double lz, double &gx, double &gy, double &gz, mrpt::math::CMatrixFixedNumeric< double, 3, 3 > *out_jacobian_df_dpoint=NULL, mrpt::math::CMatrixFixedNumeric< double, 3, 6 > *out_jacobian_df_dpose=NULL, mrpt::math::CMatrixFixedNumeric< double, 3, 6 > *out_jacobian_df_dse3=NULL, bool use_small_rot_approx=false) const
An alternative, slightly more efficient way of doing with G and L being 3D points and P this 6D pose...
Definition: CPose3D.cpp:427
This base class is used to provide a unified interface to files,memory buffers,..Please see the deriv...
Definition: CStream.h:39
GLAPI void GLAPIENTRY glEnable(GLenum cap)
#define GL_QUADS
Definition: glew.h:275
#define GL_DEPTH_TEST
Definition: glew.h:397
#define GL_SRC_ALPHA
Definition: glew.h:282
#define GL_LINES
Definition: glew.h:269
#define GL_NORMALIZE
Definition: glew.h:412
#define GL_SMOOTH
Definition: glew.h:631
#define GL_POINT_SMOOTH
Definition: glew.h:359
#define GL_TRIANGLES
Definition: glew.h:272
GLAPI void GLAPIENTRY glPointSize(GLfloat size)
GLAPI void GLAPIENTRY glLineWidth(GLfloat width)
#define GL_POINTS
Definition: glew.h:268
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:388
#define GL_BLEND
Definition: glew.h:428
#define GL_ONE_MINUS_SRC_ALPHA
Definition: glew.h:283
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:363
#define GL_LIGHTING
Definition: glew.h:381
GLfloat GLfloat v1
Definition: glext.h:3922
const GLdouble * v
Definition: glext.h:3603
GLuint GLuint GLsizei count
Definition: glext.h:3512
GLubyte GLubyte b
Definition: glext.h:5575
GLuint in
Definition: glext.h:6301
GLfloat GLfloat GLfloat v2
Definition: glext.h:3923
GLubyte g
Definition: glext.h:5575
GLdouble GLdouble GLdouble r
Definition: glext.h:3618
GLubyte GLubyte GLubyte a
Definition: glext.h:5575
GLfloat GLfloat GLfloat GLfloat v3
Definition: glext.h:3924
@ cmHOT
[New in MRPT 1.5.0]
Definition: color_maps.h:34
int version
Definition: mrpt_jpeglib.h:898
#define THROW_EXCEPTION(msg)
Definition: mrpt_macros.h:154
This base provides a set of functions for maths stuff.
Definition: CArrayNumeric.h:20
The namespace for 3D scene representation and rendering.
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,...
Definition: zip.h:16
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
Lightweight 3D point.
double z
X,Y,Z coordinates.



Page generated by Doxygen 1.9.1 for MRPT 1.5.7 Git: 5902e14cc Wed Apr 24 15:04:01 2019 +0200 at mar 26 may 2026 13:12:03 CEST