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 {
36  m_color.R = 1.f;
37  m_color.G = 0.f;
38  m_color.B = 0.f;
39  m_color.A = 1.f;
40  edge_color[0] = 0.9f;
41  edge_color[1] = 0.9f;
42  edge_color[2] = 0.9f;
43  edge_color[3] = 1.f;
44  face_color[0] = 0.7f;
45  face_color[1] = 0.7f;
46  face_color[2] = 0.8f;
47  face_color[3] = 1.f;
48  vert_color[0] = 0.3f;
49  vert_color[1] = 0.3f;
50  vert_color[2] = 0.3f;
51  vert_color[3] = 1.f;
52  m_num_faces = 0;
53  m_num_verts = 0;
54 }
55 
56 CMesh3D::~CMesh3D() = default;
57 
59  unsigned int num_verts, unsigned int num_faces, int* verts_per_face,
60  int* face_verts, float* vert_coords)
61 {
62  m_num_verts = num_verts;
63  m_num_faces = num_faces;
64 
65  // Fill number of vertices for each face
66  m_is_quad.resize(num_faces);
67  for (unsigned int i = 0; i < num_faces; i++)
68  {
69  if (verts_per_face[i] == 3)
70  m_is_quad[i] = false;
71  else if (verts_per_face[i] == 4)
72  m_is_quad[i] = true;
73  else
74  {
75  printf(
76  "\n Incorrect mesh format. It can only be composed of "
77  "triangles and/or quads.");
78  return;
79  }
80  }
81 
82  // Fill the vertices of each face
83  m_face_verts.resize(num_faces);
84  unsigned int count = 0;
85  for (unsigned int f = 0; f < num_faces; f++)
86  {
87  m_face_verts[f][0] = face_verts[count++];
88  m_face_verts[f][1] = face_verts[count++];
89  m_face_verts[f][2] = face_verts[count++];
90  if (m_is_quad[f])
91  m_face_verts[f][3] = face_verts[count++];
92  else
93  m_face_verts[f][3] = -1; // Meaning it is a triangle
94  }
95 
96  // Fill the 3D coordinates of the vertex
97  m_vert_coords.resize(num_verts);
98  for (unsigned int i = 0; i < num_verts; i++)
99  {
100  m_vert_coords[i][0] = vert_coords[3 * i];
101  m_vert_coords[i][1] = vert_coords[3 * i + 1];
102  m_vert_coords[i][2] = vert_coords[3 * i + 2];
103  }
104 
105  // Compute the mesh normals (if on)
106  if (m_computeNormals)
107  {
108  m_normals.resize(num_faces);
109 
110  for (unsigned int f = 0; f < num_faces; f++)
111  {
112  const unsigned int v1 = m_face_verts[f][0];
113  const unsigned int v2 = m_face_verts[f][1];
114  const unsigned int v3 = m_face_verts[f][2];
115  const unsigned int v4 = m_face_verts[f][3];
116 
117  if (m_is_quad[f])
118  {
119  const float vec1[3] = {
120  m_vert_coords[v3][0] - m_vert_coords[v1][0],
121  m_vert_coords[v3][1] - m_vert_coords[v1][1],
122  m_vert_coords[v3][2] - m_vert_coords[v1][2]};
123  const float vec2[3] = {
124  m_vert_coords[v4][0] - m_vert_coords[v2][0],
125  m_vert_coords[v4][1] - m_vert_coords[v2][1],
126  m_vert_coords[v4][2] - m_vert_coords[v2][2]};
127  m_normals[f][0] = vec1[1] * vec2[2] - vec1[2] * vec2[1];
128  m_normals[f][1] = vec1[2] * vec2[0] - vec1[0] * vec2[2];
129  m_normals[f][2] = vec1[0] * vec2[1] - vec1[1] * vec2[0];
130  }
131  else
132  {
133  const float vec1[3] = {
134  m_vert_coords[v2][0] - m_vert_coords[v1][0],
135  m_vert_coords[v2][1] - m_vert_coords[v1][1],
136  m_vert_coords[v2][2] - m_vert_coords[v1][2]};
137  const float vec2[3] = {
138  m_vert_coords[v3][0] - m_vert_coords[v1][0],
139  m_vert_coords[v3][1] - m_vert_coords[v1][1],
140  m_vert_coords[v3][2] - m_vert_coords[v1][2]};
141  m_normals[f][0] = vec1[1] * vec2[2] - vec1[2] * vec2[1];
142  m_normals[f][1] = vec1[2] * vec2[0] - vec1[0] * vec2[2];
143  m_normals[f][2] = vec1[0] * vec2[1] - vec1[1] * vec2[0];
144  }
145  }
146  }
147 
149 }
150 
152  unsigned int num_verts, unsigned int num_faces,
153  const mrpt::math::CMatrixDynamic<bool>& is_quad,
154  const mrpt::math::CMatrixDynamic<int>& face_verts,
155  const mrpt::math::CMatrixDynamic<float>& vert_coords)
156 {
157  MRPT_TODO("Refactor: one STL container of faces & another vertices");
158  m_num_verts = num_verts;
159  m_num_faces = num_faces;
160 
161  // Fill number of vertices for each face
162  m_is_quad.resize(num_faces);
163  for (unsigned int i = 0; i < num_faces; i++) m_is_quad[i] = is_quad(i, 0);
164 
165  // Fill the vertices of each face
166  m_face_verts.resize(num_faces);
167  for (unsigned int f = 0; f < num_faces; f++)
168  {
169  m_face_verts[f][0] = face_verts(0, f);
170  m_face_verts[f][1] = face_verts(1, f);
171  m_face_verts[f][2] = face_verts(2, f);
172  if (m_is_quad[f])
173  m_face_verts[f][3] = face_verts(3, f);
174  else
175  m_face_verts[f][3] = -1; // Meaning it is a triangle
176  }
177 
178  // Fill the 3D coordinates of the vertex
179  m_vert_coords.resize(num_verts);
180  for (unsigned int i = 0; i < num_verts; i++)
181  {
182  m_vert_coords[i][0] = vert_coords(0, i);
183  m_vert_coords[i][1] = vert_coords(1, i);
184  m_vert_coords[i][2] = vert_coords(2, i);
185  }
186 
187  // Compute the mesh normals (if on)
188  m_normals.resize(num_faces);
189  if (m_computeNormals)
190  for (unsigned int f = 0; f < num_faces; f++)
191  {
192  const unsigned int v1 = m_face_verts[f][0];
193  const unsigned int v2 = m_face_verts[f][1];
194  const unsigned int v3 = m_face_verts[f][2];
195  const unsigned int v4 = m_face_verts[f][3];
196 
197  if (m_is_quad[f])
198  {
199  const float vec1[3] = {
200  m_vert_coords[v3][0] - m_vert_coords[v1][0],
201  m_vert_coords[v3][1] - m_vert_coords[v1][1],
202  m_vert_coords[v3][2] - m_vert_coords[v1][2]};
203  const float vec2[3] = {
204  m_vert_coords[v4][0] - m_vert_coords[v2][0],
205  m_vert_coords[v4][1] - m_vert_coords[v2][1],
206  m_vert_coords[v4][2] - m_vert_coords[v2][2]};
207  m_normals[f][0] = vec1[1] * vec2[2] - vec1[2] * vec2[1];
208  m_normals[f][1] = vec1[2] * vec2[0] - vec1[0] * vec2[2];
209  m_normals[f][2] = vec1[0] * vec2[1] - vec1[1] * vec2[0];
210  }
211  else
212  {
213  const float vec1[3] = {
214  m_vert_coords[v2][0] - m_vert_coords[v1][0],
215  m_vert_coords[v2][1] - m_vert_coords[v1][1],
216  m_vert_coords[v2][2] - m_vert_coords[v1][2]};
217  const float vec2[3] = {
218  m_vert_coords[v3][0] - m_vert_coords[v1][0],
219  m_vert_coords[v3][1] - m_vert_coords[v1][1],
220  m_vert_coords[v3][2] - m_vert_coords[v1][2]};
221  m_normals[f][0] = vec1[1] * vec2[2] - vec1[2] * vec2[1];
222  m_normals[f][1] = vec1[2] * vec2[0] - vec1[0] * vec2[2];
223  m_normals[f][2] = vec1[0] * vec2[1] - vec1[1] * vec2[0];
224  }
225  }
226 
228 }
229 
230 /*---------------------------------------------------------------
231  render
232  ---------------------------------------------------------------*/
233 void CMesh3D::render_dl() const
234 {
235 #if MRPT_HAS_OPENGL_GLUT
236 
237  if (m_enableTransparency || m_antiAliasing)
238  {
241  }
242  else
243  {
246  }
247 
248  glEnable(GL_NORMALIZE); // So the GPU normalizes the normals instead of
249  // doing it in the CPU
252 
253  if (m_num_verts == 0) return;
254 
255  //---------------------------------------------------------------------------------------------------------
256  // Rendering - Test whether changing the rendering mode
257  // continuously
258  // is
259  // very slow (or not)
260  //---------------------------------------------------------------------------------------------------------
261 
262  // Render the faces
263  if (m_showFaces)
264  {
265  glColor4f(face_color[0], face_color[1], face_color[2], face_color[3]);
266 
267  for (unsigned int f = 0; f < m_num_faces; f++)
268  {
269  // Assign normals to faces (if on)
270  if (m_computeNormals)
271  glNormal3f(m_normals[f][0], m_normals[f][1], m_normals[f][2]);
272 
273  // Render Quads
274  if (m_is_quad[f])
275  {
276  glBegin(GL_QUADS);
277  for (int i = 0; i < 4; i++)
278  {
279  const unsigned int vert_ind = m_face_verts[f][i];
280  glVertex3f(
281  m_vert_coords[vert_ind][0], m_vert_coords[vert_ind][1],
282  m_vert_coords[vert_ind][2]);
283  }
284  glEnd();
285  }
286  // Render Triangles
287  else
288  {
290  for (int i = 0; i < 3; i++)
291  {
292  const unsigned int vert_ind = m_face_verts[f][i];
293  glVertex3f(
294  m_vert_coords[vert_ind][0], m_vert_coords[vert_ind][1],
295  m_vert_coords[vert_ind][2]);
296  }
297  glEnd();
298  }
299  }
300  }
301 
302  // Render the edges - They are rendered twice, which is redundant but simple
303  if (m_showEdges)
304  {
305  glColor4f(edge_color[0], edge_color[1], edge_color[2], edge_color[3]);
306  glDisable(GL_LIGHTING); //??
307  glLineWidth(m_lineWidth);
309  glBegin(GL_LINES);
310  for (unsigned int f = 0; f < m_num_faces; f++)
311  {
312  const unsigned char num_vert = 3 + m_is_quad[f];
313  for (int i = 0; i < num_vert - 1; i++)
314  {
315  const unsigned int v_0 = m_face_verts[f][i];
316  const unsigned int v_1 = m_face_verts[f][i + 1];
317 
318  glVertex3f(
319  m_vert_coords[v_0][0], m_vert_coords[v_0][1],
320  m_vert_coords[v_0][2]);
321  glVertex3f(
322  m_vert_coords[v_1][0], m_vert_coords[v_1][1],
323  m_vert_coords[v_1][2]);
324  }
325 
326  // The last vertex of the face needs to be connected to the first as
327  // well
328  const int v_0 = m_face_verts[f][num_vert - 1];
329  const int v_1 = m_face_verts[f][0];
330 
331  glVertex3f(
332  m_vert_coords[v_0][0], m_vert_coords[v_0][1],
333  m_vert_coords[v_0][2]);
334  glVertex3f(
335  m_vert_coords[v_1][0], m_vert_coords[v_1][1],
336  m_vert_coords[v_1][2]);
337  }
338  glEnd();
341  }
342 
343  // Render the vertices
344  if (m_showVertices)
345  {
346  glColor4f(vert_color[0], vert_color[1], vert_color[2], vert_color[3]);
348  glPointSize(m_pointSize);
351  for (unsigned int v = 0; v < m_num_verts; v++)
352  glVertex3f(
353  m_vert_coords[v][0], m_vert_coords[v][1], m_vert_coords[v][2]);
354 
355  glEnd();
358  }
359 
362 
363 #endif
364 }
365 
368 {
369  //********** To do **********
370  THROW_EXCEPTION("not implemented yet!");
371 
372  // writeToStreamRender(out);
373 
374  // // Version 0:
375  // out << m_enableTransparency;
376  // out << m_showEdges;
377  // out << m_showFaces;
378  // out << m_showVertices;
379  // out << m_computeNormals;
380  // out << m_num_verts;
381  // out << m_num_faces;
382 
383  // bool *m_is_quad;
384  // f_verts *m_face_verts;
385  // coord3D *m_vert_coords;
386  // coord3D *m_normals;
387 }
388 
390 {
391  //********** To do ************
392 }
393 
396 {
397  // Extreme initialization
398  bb_min.x = 10000.f;
399  bb_min.y = 10000.f;
400  bb_min.z = 10000.f;
401  bb_max.x = -10000.f;
402  bb_max.y = -10000.f;
403  bb_max.z = -10000.f;
404 
405  if (m_num_verts == 0)
406  printf(
407  "\n The mesh is empty and has no size. The returned information "
408  "has no meaning.");
409  else
410  {
411  for (unsigned int i = 0; i < m_num_verts; i++)
412  {
413  // Max
414  if (m_vert_coords[i][0] > bb_max.x) bb_max.x = m_vert_coords[i][0];
415  if (m_vert_coords[i][1] > bb_max.y) bb_max.y = m_vert_coords[i][1];
416  if (m_vert_coords[i][2] > bb_max.z) bb_max.z = m_vert_coords[i][2];
417 
418  // Min
419  if (m_vert_coords[i][0] < bb_min.x) bb_min.x = m_vert_coords[i][0];
420  if (m_vert_coords[i][1] < bb_min.y) bb_min.y = m_vert_coords[i][1];
421  if (m_vert_coords[i][2] < bb_min.z) bb_min.z = m_vert_coords[i][2];
422  }
423  }
424 
425  // Convert to coordinates of my parent:
426  m_pose.composePoint(bb_min, bb_min);
427  m_pose.composePoint(bb_max, bb_max);
428 }
429 
430 void CMesh3D::setEdgeColor(float r, float g, float b, float a)
431 {
432  edge_color[0] = r;
433  edge_color[1] = g;
434  edge_color[2] = b;
435  edge_color[3] = a;
436 }
437 
438 void CMesh3D::setFaceColor(float r, float g, float b, float a)
439 {
440  face_color[0] = r;
441  face_color[1] = g;
442  face_color[2] = b;
443  face_color[3] = a;
444 }
445 
446 void CMesh3D::setVertColor(float r, float g, float b, float a)
447 {
448  vert_color[0] = r;
449  vert_color[1] = g;
450  vert_color[2] = b;
451  vert_color[3] = a;
452 }
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:367
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:389
void render_dl() const override
Render.
Definition: CMesh3D.cpp:233
#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)
unsigned char uint8_t
Definition: rptypes.h:44
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:446
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:366
#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:58
#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:438
#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:53
#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.
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:430
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:394
GLubyte GLubyte GLubyte a
Definition: glext.h:6372



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: 8fe78517f Sun Jul 14 19:43:28 2019 +0200 at lun oct 28 02:10:00 CET 2019