MRPT  1.9.9
CMesh3D.cpp
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | https://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2019, Individual contributors, see AUTHORS file |
6  | See: https://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See: https://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 
10 #include "opengl-precomp.h" // Precompiled header
11 
12 #include <mrpt/img/color_maps.h>
13 #include <mrpt/opengl/CMesh3D.h>
15 
16 #include "opengl_internals.h"
17 
18 using namespace mrpt;
19 using namespace mrpt::opengl;
20 using namespace mrpt::poses;
21 using namespace mrpt::math;
22 using namespace std;
23 
25 
27  bool enableTransparency, bool antiAliasing, bool enableShowEdges,
28  bool enableShowFaces, bool enableShowVertices)
29  : m_enableTransparency(enableTransparency),
30  m_antiAliasing(antiAliasing),
31  m_showEdges(enableShowEdges),
32  m_showFaces(enableShowFaces),
33  m_showVertices(enableShowVertices)
34 {
35  m_color.R = 1.f;
36  m_color.G = 0.f;
37  m_color.B = 0.f;
38  m_color.A = 1.f;
39 }
40 
41 CMesh3D::~CMesh3D() = default;
42 
44  unsigned int num_verts, unsigned int num_faces, int* verts_per_face,
45  int* face_verts, float* vert_coords)
46 {
47  m_num_verts = num_verts;
48  m_num_faces = num_faces;
49 
50  // Fill number of vertices for each face
51  m_is_quad.resize(num_faces);
52  for (unsigned int i = 0; i < num_faces; i++)
53  {
54  if (verts_per_face[i] == 3)
55  m_is_quad[i] = false;
56  else if (verts_per_face[i] == 4)
57  m_is_quad[i] = true;
58  else
59  {
60  printf(
61  "\n Incorrect mesh format. It can only be composed of "
62  "triangles and/or quads.");
63  return;
64  }
65  }
66 
67  // Fill the vertices of each face
68  m_face_verts.resize(num_faces);
69  unsigned int count = 0;
70  for (unsigned int f = 0; f < num_faces; f++)
71  {
72  m_face_verts[f][0] = face_verts[count++];
73  m_face_verts[f][1] = face_verts[count++];
74  m_face_verts[f][2] = face_verts[count++];
75  if (m_is_quad[f])
76  m_face_verts[f][3] = face_verts[count++];
77  else
78  m_face_verts[f][3] = -1; // Meaning it is a triangle
79  }
80 
81  // Fill the 3D coordinates of the vertex
82  m_vert_coords.resize(num_verts);
83  for (unsigned int i = 0; i < num_verts; i++)
84  {
85  m_vert_coords[i][0] = vert_coords[3 * i];
86  m_vert_coords[i][1] = vert_coords[3 * i + 1];
87  m_vert_coords[i][2] = vert_coords[3 * i + 2];
88  }
89 
90  // Compute the mesh normals (if on)
91  if (m_computeNormals)
92  {
93  m_normals.resize(num_faces);
94 
95  for (unsigned int f = 0; f < num_faces; f++)
96  {
97  const unsigned int v1 = m_face_verts[f][0];
98  const unsigned int v2 = m_face_verts[f][1];
99  const unsigned int v3 = m_face_verts[f][2];
100  const unsigned int v4 = m_face_verts[f][3];
101 
102  if (m_is_quad[f])
103  {
104  const float vec1[3] = {
105  m_vert_coords[v3][0] - m_vert_coords[v1][0],
106  m_vert_coords[v3][1] - m_vert_coords[v1][1],
107  m_vert_coords[v3][2] - m_vert_coords[v1][2]};
108  const float vec2[3] = {
109  m_vert_coords[v4][0] - m_vert_coords[v2][0],
110  m_vert_coords[v4][1] - m_vert_coords[v2][1],
111  m_vert_coords[v4][2] - m_vert_coords[v2][2]};
112  m_normals[f][0] = vec1[1] * vec2[2] - vec1[2] * vec2[1];
113  m_normals[f][1] = vec1[2] * vec2[0] - vec1[0] * vec2[2];
114  m_normals[f][2] = vec1[0] * vec2[1] - vec1[1] * vec2[0];
115  }
116  else
117  {
118  const float vec1[3] = {
119  m_vert_coords[v2][0] - m_vert_coords[v1][0],
120  m_vert_coords[v2][1] - m_vert_coords[v1][1],
121  m_vert_coords[v2][2] - m_vert_coords[v1][2]};
122  const float vec2[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  m_normals[f][0] = vec1[1] * vec2[2] - vec1[2] * vec2[1];
127  m_normals[f][1] = vec1[2] * vec2[0] - vec1[0] * vec2[2];
128  m_normals[f][2] = vec1[0] * vec2[1] - vec1[1] * vec2[0];
129  }
130  }
131  }
132 
134 }
135 
137  unsigned int num_verts, unsigned int num_faces,
138  const mrpt::math::CMatrixDynamic<bool>& is_quad,
139  const mrpt::math::CMatrixDynamic<int>& face_verts,
140  const mrpt::math::CMatrixDynamic<float>& vert_coords)
141 {
142  MRPT_TODO("Refactor: one STL container of faces & another vertices");
143  m_num_verts = num_verts;
144  m_num_faces = num_faces;
145 
146  // Fill number of vertices for each face
147  m_is_quad.resize(num_faces);
148  for (unsigned int i = 0; i < num_faces; i++) m_is_quad[i] = is_quad(i, 0);
149 
150  // Fill the vertices of each face
151  m_face_verts.resize(num_faces);
152  for (unsigned int f = 0; f < num_faces; f++)
153  {
154  m_face_verts[f][0] = face_verts(0, f);
155  m_face_verts[f][1] = face_verts(1, f);
156  m_face_verts[f][2] = face_verts(2, f);
157  if (m_is_quad[f])
158  m_face_verts[f][3] = face_verts(3, f);
159  else
160  m_face_verts[f][3] = -1; // Meaning it is a triangle
161  }
162 
163  // Fill the 3D coordinates of the vertex
164  m_vert_coords.resize(num_verts);
165  for (unsigned int i = 0; i < num_verts; i++)
166  {
167  m_vert_coords[i][0] = vert_coords(0, i);
168  m_vert_coords[i][1] = vert_coords(1, i);
169  m_vert_coords[i][2] = vert_coords(2, i);
170  }
171 
172  // Compute the mesh normals (if on)
173  m_normals.resize(num_faces);
174  if (m_computeNormals)
175  for (unsigned int f = 0; f < num_faces; f++)
176  {
177  const unsigned int v1 = m_face_verts[f][0];
178  const unsigned int v2 = m_face_verts[f][1];
179  const unsigned int v3 = m_face_verts[f][2];
180  const unsigned int v4 = m_face_verts[f][3];
181 
182  if (m_is_quad[f])
183  {
184  const float vec1[3] = {
185  m_vert_coords[v3][0] - m_vert_coords[v1][0],
186  m_vert_coords[v3][1] - m_vert_coords[v1][1],
187  m_vert_coords[v3][2] - m_vert_coords[v1][2]};
188  const float vec2[3] = {
189  m_vert_coords[v4][0] - m_vert_coords[v2][0],
190  m_vert_coords[v4][1] - m_vert_coords[v2][1],
191  m_vert_coords[v4][2] - m_vert_coords[v2][2]};
192  m_normals[f][0] = vec1[1] * vec2[2] - vec1[2] * vec2[1];
193  m_normals[f][1] = vec1[2] * vec2[0] - vec1[0] * vec2[2];
194  m_normals[f][2] = vec1[0] * vec2[1] - vec1[1] * vec2[0];
195  }
196  else
197  {
198  const float vec1[3] = {
199  m_vert_coords[v2][0] - m_vert_coords[v1][0],
200  m_vert_coords[v2][1] - m_vert_coords[v1][1],
201  m_vert_coords[v2][2] - m_vert_coords[v1][2]};
202  const float vec2[3] = {
203  m_vert_coords[v3][0] - m_vert_coords[v1][0],
204  m_vert_coords[v3][1] - m_vert_coords[v1][1],
205  m_vert_coords[v3][2] - m_vert_coords[v1][2]};
206  m_normals[f][0] = vec1[1] * vec2[2] - vec1[2] * vec2[1];
207  m_normals[f][1] = vec1[2] * vec2[0] - vec1[0] * vec2[2];
208  m_normals[f][2] = vec1[0] * vec2[1] - vec1[1] * vec2[0];
209  }
210  }
211 
213 }
214 
215 /*---------------------------------------------------------------
216  render
217  ---------------------------------------------------------------*/
218 void CMesh3D::render_dl() const
219 {
220 #if MRPT_HAS_OPENGL_GLUT
221 
222  if (m_enableTransparency || m_antiAliasing)
223  {
226  }
227  else
228  {
231  }
232 
233  glEnable(GL_NORMALIZE); // So the GPU normalizes the normals instead of
234  // doing it in the CPU
237 
238  if (m_num_verts == 0) return;
239 
240  //---------------------------------------------------------------------------------------------------------
241  // Rendering - Test whether changing the rendering mode
242  // continuously
243  // is
244  // very slow (or not)
245  //---------------------------------------------------------------------------------------------------------
246 
247  // Render the faces
248  if (m_showFaces)
249  {
250  glColor4f(face_color[0], face_color[1], face_color[2], face_color[3]);
251 
252  for (unsigned int f = 0; f < m_num_faces; f++)
253  {
254  // Assign normals to faces (if on)
255  if (m_computeNormals)
256  glNormal3f(m_normals[f][0], m_normals[f][1], m_normals[f][2]);
257 
258  // Render Quads
259  if (m_is_quad[f])
260  {
261  glBegin(GL_QUADS);
262  for (int i = 0; i < 4; i++)
263  {
264  const unsigned int vert_ind = m_face_verts[f][i];
265  glVertex3f(
266  m_vert_coords[vert_ind][0], m_vert_coords[vert_ind][1],
267  m_vert_coords[vert_ind][2]);
268  }
269  glEnd();
270  }
271  // Render Triangles
272  else
273  {
275  for (int i = 0; i < 3; i++)
276  {
277  const unsigned int vert_ind = m_face_verts[f][i];
278  glVertex3f(
279  m_vert_coords[vert_ind][0], m_vert_coords[vert_ind][1],
280  m_vert_coords[vert_ind][2]);
281  }
282  glEnd();
283  }
284  }
285  }
286 
287  // Render the edges - They are rendered twice, which is redundant but simple
288  if (m_showEdges)
289  {
290  glColor4f(edge_color[0], edge_color[1], edge_color[2], edge_color[3]);
291  glDisable(GL_LIGHTING); //??
292  glLineWidth(m_lineWidth);
294  glBegin(GL_LINES);
295  for (unsigned int f = 0; f < m_num_faces; f++)
296  {
297  const unsigned char num_vert = 3 + m_is_quad[f];
298  for (int i = 0; i < num_vert - 1; i++)
299  {
300  const unsigned int v_0 = m_face_verts[f][i];
301  const unsigned int v_1 = m_face_verts[f][i + 1];
302 
303  glVertex3f(
304  m_vert_coords[v_0][0], m_vert_coords[v_0][1],
305  m_vert_coords[v_0][2]);
306  glVertex3f(
307  m_vert_coords[v_1][0], m_vert_coords[v_1][1],
308  m_vert_coords[v_1][2]);
309  }
310 
311  // The last vertex of the face needs to be connected to the first as
312  // well
313  const int v_0 = m_face_verts[f][num_vert - 1];
314  const int v_1 = m_face_verts[f][0];
315 
316  glVertex3f(
317  m_vert_coords[v_0][0], m_vert_coords[v_0][1],
318  m_vert_coords[v_0][2]);
319  glVertex3f(
320  m_vert_coords[v_1][0], m_vert_coords[v_1][1],
321  m_vert_coords[v_1][2]);
322  }
323  glEnd();
326  }
327 
328  // Render the vertices
329  if (m_showVertices)
330  {
331  glColor4f(vert_color[0], vert_color[1], vert_color[2], vert_color[3]);
333  glPointSize(m_pointSize);
336  for (unsigned int v = 0; v < m_num_verts; v++)
337  glVertex3f(
338  m_vert_coords[v][0], m_vert_coords[v][1], m_vert_coords[v][2]);
339 
340  glEnd();
343  }
344 
347 
348 #endif
349 }
350 
351 uint8_t CMesh3D::serializeGetVersion() const { return 0; }
353 {
354  //********** To do **********
355  THROW_EXCEPTION("not implemented yet!");
356 
357  // writeToStreamRender(out);
358 
359  // // Version 0:
360  // out << m_enableTransparency;
361  // out << m_showEdges;
362  // out << m_showFaces;
363  // out << m_showVertices;
364  // out << m_computeNormals;
365  // out << m_num_verts;
366  // out << m_num_faces;
367 
368  // bool *m_is_quad;
369  // f_verts *m_face_verts;
370  // coord3D *m_vert_coords;
371  // coord3D *m_normals;
372 }
373 
375 {
376  //********** To do ************
377 }
378 
381 {
382  // Extreme initialization
383  bb_min.x = 10000.f;
384  bb_min.y = 10000.f;
385  bb_min.z = 10000.f;
386  bb_max.x = -10000.f;
387  bb_max.y = -10000.f;
388  bb_max.z = -10000.f;
389 
390  if (m_num_verts == 0)
391  printf(
392  "\n The mesh is empty and has no size. The returned information "
393  "has no meaning.");
394  else
395  {
396  for (unsigned int i = 0; i < m_num_verts; i++)
397  {
398  // Max
399  if (m_vert_coords[i][0] > bb_max.x) bb_max.x = m_vert_coords[i][0];
400  if (m_vert_coords[i][1] > bb_max.y) bb_max.y = m_vert_coords[i][1];
401  if (m_vert_coords[i][2] > bb_max.z) bb_max.z = m_vert_coords[i][2];
402 
403  // Min
404  if (m_vert_coords[i][0] < bb_min.x) bb_min.x = m_vert_coords[i][0];
405  if (m_vert_coords[i][1] < bb_min.y) bb_min.y = m_vert_coords[i][1];
406  if (m_vert_coords[i][2] < bb_min.z) bb_min.z = m_vert_coords[i][2];
407  }
408  }
409 
410  // Convert to coordinates of my parent:
411  m_pose.composePoint(bb_min, bb_min);
412  m_pose.composePoint(bb_max, bb_max);
413 }
414 
415 void CMesh3D::setEdgeColor(float r, float g, float b, float a)
416 {
417  edge_color[0] = r;
418  edge_color[1] = g;
419  edge_color[2] = b;
420  edge_color[3] = a;
421 }
422 
423 void CMesh3D::setFaceColor(float r, float g, float b, float a)
424 {
425  face_color[0] = r;
426  face_color[1] = g;
427  face_color[2] = b;
428  face_color[3] = a;
429 }
430 
431 void CMesh3D::setVertColor(float r, float g, float b, float a)
432 {
433  vert_color[0] = r;
434  vert_color[1] = g;
435  vert_color[2] = b;
436  vert_color[3] = a;
437 }
GLuint GLuint GLsizei count
Definition: glext.h:3532
void notifyChange() const
Must be called to notify that the object has changed (so, the display list must be updated) ...
void resize(size_t row, size_t col)
void serializeTo(mrpt::serialization::CArchive &out) const override
Pure virtual method for writing (serializing) to an abstract archive.
Definition: CMesh3D.cpp:352
GLAPI void GLAPIENTRY glEnable(GLenum cap)
#define THROW_EXCEPTION(msg)
Definition: exceptions.h:67
GLAPI void GLAPIENTRY glPointSize(GLfloat size)
void serializeFrom(mrpt::serialization::CArchive &in, uint8_t serial_version) override
Pure virtual method for reading (deserializing) from an abstract archive.
Definition: CMesh3D.cpp:374
void render_dl() const override
Render.
Definition: CMesh3D.cpp:218
#define IMPLEMENTS_SERIALIZABLE(class_name, base, NameSpace)
To be added to all CSerializable-classes implementation files.
GLAPI void GLAPIENTRY glNormal3f(GLfloat nx, GLfloat ny, GLfloat nz)
#define GL_TRIANGLES
Definition: glew.h:277
STL namespace.
#define GL_NORMALIZE
Definition: glew.h:417
#define GL_ONE_MINUS_SRC_ALPHA
Definition: glew.h:288
#define GL_COLOR_MATERIAL
Definition: glew.h:393
#define GL_DEPTH_TEST
Definition: glew.h:402
#define GL_SMOOTH
Definition: glew.h:636
A 3D mesh composed of Triangles and/or Quads.
Definition: CMesh3D.h:32
GLAPI void GLAPIENTRY glShadeModel(GLenum mode)
#define GL_LIGHTING
Definition: glew.h:386
GLAPI void GLAPIENTRY glLineWidth(GLfloat width)
GLAPI void GLAPIENTRY glBlendFunc(GLenum sfactor, GLenum dfactor)
A renderizable object suitable for rendering with OpenGL&#39;s display lists.
void setVertColor(float r, float g, float b, float a=1.f)
Definition: CMesh3D.cpp:431
This base provides a set of functions for maths stuff.
#define GL_LINE_SMOOTH
Definition: glew.h:368
uint8_t serializeGetVersion() const override
Must return the current versioning number of the object.
Definition: CMesh3D.cpp:351
#define GL_QUADS
Definition: glew.h:280
GLfloat GLfloat GLfloat GLfloat v3
Definition: glext.h:4125
GLubyte g
Definition: glext.h:6372
GLubyte GLubyte b
Definition: glext.h:6372
#define GL_POINT_SMOOTH
Definition: glew.h:364
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:43
#define GL_BLEND
Definition: glew.h:433
#define GL_POINTS
Definition: glew.h:273
Classes for 2D/3D geometry representation, both of single values and probability density distribution...
GLAPI void GLAPIENTRY glVertex3f(GLfloat x, GLfloat y, GLfloat z)
void setFaceColor(float r, float g, float b, float a=1.f)
Definition: CMesh3D.cpp:423
#define GL_SRC_ALPHA
Definition: glew.h:287
const GLdouble * v
Definition: glext.h:3684
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
Virtual base class for "archives": classes abstracting I/O streams.
Definition: CArchive.h:54
#define MRPT_TODO(x)
Definition: common.h:129
GLdouble GLdouble GLdouble r
Definition: glext.h:3711
GLfloat GLfloat v1
Definition: glext.h:4121
~CMesh3D() override
Private, virtual destructor: only can be deleted from smart pointers.
mrpt::vision::TStereoCalibResults out
GLuint in
Definition: glext.h:7391
The namespace for 3D scene representation and rendering.
Definition: CGlCanvasBase.h:15
const auto bb_max
GLAPI void GLAPIENTRY glEnd(void)
const auto bb_min
GLfloat GLfloat GLfloat v2
Definition: glext.h:4123
#define GL_LINES
Definition: glew.h:274
GLAPI void GLAPIENTRY glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
Lightweight 3D point.
Definition: TPoint3D.h:90
void setEdgeColor(float r, float g, float b, float a=1.f)
Definition: CMesh3D.cpp:415
GLAPI void GLAPIENTRY glDisable(GLenum cap)
This template class provides the basic functionality for a general 2D any-size, resizable container o...
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:379
GLubyte GLubyte GLubyte a
Definition: glext.h:6372



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: 45d659fbb Tue Dec 10 18:21:14 2019 +0100 at mar dic 10 18:30:09 CET 2019