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 
GLuint GLuint GLsizei count
Definition: glext.h:3512
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values, timewatch, extensions to STL.
Definition: zip.h:16
GLAPI void GLAPIENTRY glEnable(GLenum cap)
GLAPI void GLAPIENTRY glPointSize(GLfloat size)
unsigned int m_num_verts
Number of vertices of the mesh.
Definition: CMesh3D.h:58
[New in MRPT 1.5.0]
Definition: color_maps.h:34
#define IMPLEMENTS_SERIALIZABLE(class_name, base, NameSpace)
This must be inserted in all CSerializable classes implementation files.
float face_color[4]
Color of the faces (when shown)
Definition: CMesh3D.h:67
#define THROW_EXCEPTION(msg)
GLAPI void GLAPIENTRY glNormal3f(GLfloat nx, GLfloat ny, GLfloat nz)
#define GL_TRIANGLES
Definition: glew.h:272
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_NORMALIZE
Definition: glew.h:412
#define GL_ONE_MINUS_SRC_ALPHA
Definition: glew.h:283
double z
X,Y,Z coordinates.
#define GL_COLOR_MATERIAL
Definition: glew.h:388
#define GL_DEPTH_TEST
Definition: glew.h:397
#define GL_SMOOTH
Definition: glew.h:631
A 3D mesh composed of Triangles and/or Quads.
Definition: CMesh3D.h:39
GLAPI void GLAPIENTRY glShadeModel(GLenum mode)
#define GL_LIGHTING
Definition: glew.h:381
GLAPI void GLAPIENTRY glLineWidth(GLfloat width)
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
GLAPI void GLAPIENTRY glBlendFunc(GLenum sfactor, GLenum dfactor)
A renderizable object suitable for rendering with OpenGL&#39;s display lists.
bool m_enableTransparency
Definition: CMesh3D.h:48
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:38
void setVertColor(float r, float g, float b, float a=1.f)
Definition: CMesh3D.cpp:434
This base provides a set of functions for maths stuff.
Definition: CArrayNumeric.h:19
#define GL_LINE_SMOOTH
Definition: glew.h:363
CMesh3D(bool enableTransparency=false, bool antiAliasing=false, bool enableShowEdges=true, bool enableShowFaces=true, bool enableShowVertices=false)
Constructor.
Definition: CMesh3D.cpp:32
#define GL_QUADS
Definition: glew.h:275
GLfloat GLfloat GLfloat GLfloat v3
Definition: glext.h:3924
GLubyte g
Definition: glext.h:5575
GLubyte GLubyte b
Definition: glext.h:5575
mrpt::utils::TColor m_color
Color components in the range [0,255].
Definition: CRenderizable.h:54
#define GL_POINT_SMOOTH
Definition: glew.h:359
int version
Definition: mrpt_jpeglib.h:898
GLAPI void GLAPIENTRY glBegin(GLenum mode)
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
#define GL_BLEND
Definition: glew.h:428
#define GL_POINTS
Definition: glew.h:268
unsigned int m_num_faces
Number of faces of the mesh.
Definition: CMesh3D.h:59
Classes for 2D/3D geometry representation, both of single values and probability density distribution...
Definition: CPoint.h:17
GLAPI void GLAPIENTRY glVertex3f(GLfloat x, GLfloat y, GLfloat z)
void writeToStream(mrpt::utils::CStream &out, int *getVersion) const
Introduces a pure virtual method responsible for writing to a CStream.
Definition: CMesh3D.cpp:320
float coord3D[3]
Definition: CMesh3D.h:44
void setFaceColor(float r, float g, float b, float a=1.f)
Definition: CMesh3D.cpp:426
#define GL_SRC_ALPHA
Definition: glew.h:282
const GLdouble * v
Definition: glext.h:3603
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
void render_dl() const MRPT_OVERRIDE
Render.
Definition: CMesh3D.cpp:200
GLdouble GLdouble GLdouble r
Definition: glext.h:3618
GLfloat GLfloat v1
Definition: glext.h:3922
virtual ~CMesh3D()
Private, virtual destructor: only can be deleted from smart pointers.
Definition: CMesh3D.cpp:51
GLuint in
Definition: glext.h:6301
The namespace for 3D scene representation and rendering.
GLAPI void GLAPIENTRY glEnd(void)
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
GLfloat GLfloat GLfloat v2
Definition: glext.h:3923
#define GL_LINES
Definition: glew.h:269
GLAPI void GLAPIENTRY glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
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
Lightweight 3D point.
float vert_color[4]
Color of the vertices (when shown)
Definition: CMesh3D.h:68
void setEdgeColor(float r, float g, float b, float a=1.f)
Definition: CMesh3D.cpp:418
GLAPI void GLAPIENTRY glDisable(GLenum cap)
GLubyte GLubyte GLubyte a
Definition: glext.h:5575
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
coord3D * m_vert_coords
Pointer storing the coordinates of the vertices. Size: 3 x num_vertices.
Definition: CMesh3D.h:62
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
float edge_color[4]
Color of the edges (when shown)
Definition: CMesh3D.h:66



Page generated by Doxygen 1.8.14 for MRPT 1.5.7 Git: 5902e14cc Wed Apr 24 15:04:01 2019 +0200 at lun oct 28 01:39:17 CET 2019