MRPT  2.0.3
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-2020, 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>
16 
17 #include <mrpt/opengl/opengl_api.h>
18 
19 using namespace mrpt;
20 using namespace mrpt::opengl;
21 using namespace mrpt::poses;
22 using namespace mrpt::math;
23 using namespace std;
24 
26 
27 CMesh3D::~CMesh3D() = default;
28 
30  unsigned int num_verts, unsigned int num_faces, int* verts_per_face,
31  int* face_verts, float* vert_coords)
32 {
33  // Fill number of vertices for each face
34  m_is_quad.resize(num_faces);
35  for (unsigned int i = 0; i < num_faces; i++)
36  {
37  if (verts_per_face[i] == 3)
38  m_is_quad[i] = false;
39  else if (verts_per_face[i] == 4)
40  m_is_quad[i] = true;
41  else
42  {
44  "Incorrect mesh format. It can only be composed of triangles "
45  "and/or quads");
46  }
47  }
48 
49  // Fill the vertices of each face
50  m_face_verts.resize(num_faces);
51  unsigned int count = 0;
52  for (unsigned int f = 0; f < num_faces; f++)
53  {
54  m_face_verts[f][0] = face_verts[count++];
55  m_face_verts[f][1] = face_verts[count++];
56  m_face_verts[f][2] = face_verts[count++];
57  if (m_is_quad[f])
58  m_face_verts[f][3] = face_verts[count++];
59  else
60  m_face_verts[f][3] = -1; // Meaning it is a triangle
61  }
62 
63  // Fill the 3D coordinates of the vertex
64  m_vertices.resize(num_verts);
65  for (unsigned int i = 0; i < num_verts; i++)
66  {
67  m_vertices[i][0] = vert_coords[3 * i];
68  m_vertices[i][1] = vert_coords[3 * i + 1];
69  m_vertices[i][2] = vert_coords[3 * i + 2];
70  }
71 
72  // Compute the mesh normals (if on)
73  if (m_computeNormals)
74  {
75  m_normals.resize(num_faces);
76 
77  for (unsigned int f = 0; f < num_faces; f++)
78  {
79  const unsigned int v1 = m_face_verts[f][3];
80  const unsigned int v2 = m_face_verts[f][2];
81  const unsigned int v3 = m_face_verts[f][1];
82  const unsigned int v4 = m_face_verts[f][0];
83 
84  if (m_is_quad[f])
85  {
86  const float vec1[3] = {m_vertices[v3][0] - m_vertices[v1][0],
87  m_vertices[v3][1] - m_vertices[v1][1],
88  m_vertices[v3][2] - m_vertices[v1][2]};
89  const float vec2[3] = {m_vertices[v4][0] - m_vertices[v2][0],
90  m_vertices[v4][1] - m_vertices[v2][1],
91  m_vertices[v4][2] - m_vertices[v2][2]};
92  m_normals[f][0] = vec1[1] * vec2[2] - vec1[2] * vec2[1];
93  m_normals[f][1] = vec1[2] * vec2[0] - vec1[0] * vec2[2];
94  m_normals[f][2] = vec1[0] * vec2[1] - vec1[1] * vec2[0];
95  }
96  else
97  {
98  const float vec1[3] = {m_vertices[v2][0] - m_vertices[v1][0],
99  m_vertices[v2][1] - m_vertices[v1][1],
100  m_vertices[v2][2] - m_vertices[v1][2]};
101  const float vec2[3] = {m_vertices[v3][0] - m_vertices[v1][0],
102  m_vertices[v3][1] - m_vertices[v1][1],
103  m_vertices[v3][2] - m_vertices[v1][2]};
104  m_normals[f][0] = vec1[1] * vec2[2] - vec1[2] * vec2[1];
105  m_normals[f][1] = vec1[2] * vec2[0] - vec1[0] * vec2[2];
106  m_normals[f][2] = vec1[0] * vec2[1] - vec1[1] * vec2[0];
107  }
108  m_normals[f] = m_normals[f].unitarize();
109  }
110  }
111 
113 }
114 
116  unsigned int num_verts, unsigned int num_faces,
117  const mrpt::math::CMatrixDynamic<bool>& is_quad,
118  const mrpt::math::CMatrixDynamic<int>& face_verts,
119  const mrpt::math::CMatrixDynamic<float>& vert_coords)
120 {
121  // Fill number of vertices for each face
122  m_is_quad.resize(num_faces);
123  for (unsigned int i = 0; i < num_faces; i++) m_is_quad[i] = is_quad(i, 0);
124 
125  // Fill the vertices of each face
126  m_face_verts.resize(num_faces);
127  for (unsigned int f = 0; f < num_faces; f++)
128  {
129  m_face_verts[f][0] = face_verts(0, f);
130  m_face_verts[f][1] = face_verts(1, f);
131  m_face_verts[f][2] = face_verts(2, f);
132  if (m_is_quad[f])
133  m_face_verts[f][3] = face_verts(3, f);
134  else
135  m_face_verts[f][3] = -1; // Meaning it is a triangle
136  }
137 
138  // Fill the 3D coordinates of the vertex
139  m_vertices.resize(num_verts);
140  for (unsigned int i = 0; i < num_verts; i++)
141  {
142  m_vertices[i][0] = vert_coords(0, i);
143  m_vertices[i][1] = vert_coords(1, i);
144  m_vertices[i][2] = vert_coords(2, i);
145  }
146 
147  // Compute the mesh normals (if on)
148  m_normals.resize(num_faces);
149  if (m_computeNormals)
150  for (unsigned int f = 0; f < num_faces; f++)
151  {
152  const unsigned int v1 = m_face_verts[f][0];
153  const unsigned int v2 = m_face_verts[f][1];
154  const unsigned int v3 = m_face_verts[f][2];
155  const unsigned int v4 = m_face_verts[f][3];
156 
157  if (m_is_quad[f])
158  {
159  const float vec1[3] = {m_vertices[v3][0] - m_vertices[v1][0],
160  m_vertices[v3][1] - m_vertices[v1][1],
161  m_vertices[v3][2] - m_vertices[v1][2]};
162  const float vec2[3] = {m_vertices[v4][0] - m_vertices[v2][0],
163  m_vertices[v4][1] - m_vertices[v2][1],
164  m_vertices[v4][2] - m_vertices[v2][2]};
165  m_normals[f][0] = vec1[1] * vec2[2] - vec1[2] * vec2[1];
166  m_normals[f][1] = vec1[2] * vec2[0] - vec1[0] * vec2[2];
167  m_normals[f][2] = vec1[0] * vec2[1] - vec1[1] * vec2[0];
168  }
169  else
170  {
171  const float vec1[3] = {m_vertices[v2][0] - m_vertices[v1][0],
172  m_vertices[v2][1] - m_vertices[v1][1],
173  m_vertices[v2][2] - m_vertices[v1][2]};
174  const float vec2[3] = {m_vertices[v3][0] - m_vertices[v1][0],
175  m_vertices[v3][1] - m_vertices[v1][1],
176  m_vertices[v3][2] - m_vertices[v1][2]};
177  m_normals[f][0] = vec1[1] * vec2[2] - vec1[2] * vec2[1];
178  m_normals[f][1] = vec1[2] * vec2[0] - vec1[0] * vec2[2];
179  m_normals[f][2] = vec1[0] * vec2[1] - vec1[1] * vec2[0];
180  }
181  }
182 
184 }
185 
186 void CMesh3D::render(const RenderContext& rc) const
187 {
188  switch (rc.shader_id)
189  {
191  if (m_showFaces) CRenderizableShaderTriangles::render(rc);
192  break;
194  if (m_showEdges) CRenderizableShaderWireFrame::render(rc);
195  break;
197  if (m_showVertices) CRenderizableShaderPoints::render(rc);
198  break;
199  };
200 }
202 {
206 }
207 
209 {
212  vbd.clear();
213 
214  for (size_t f = 0; f < m_face_verts.size(); f++)
215  {
216  const unsigned char num_vert = 3 + m_is_quad[f];
217  for (int i = 0; i < num_vert - 1; i++)
218  {
219  const unsigned int v_0 = m_face_verts[f][i];
220  const unsigned int v_1 = m_face_verts[f][i + 1];
221 
222  vbd.emplace_back(m_vertices[v_0]);
223  vbd.emplace_back(m_vertices[v_1]);
224  }
225 
226  // The last vertex of the face needs to be connected to the first as
227  // well
228  const int v_0 = m_face_verts[f][num_vert - 1];
229  const int v_1 = m_face_verts[f][0];
230 
231  vbd.emplace_back(m_vertices[v_0]);
232  vbd.emplace_back(m_vertices[v_1]);
233  }
234 
235  cbd.assign(vbd.size(), edge_color.asTColor());
236 }
237 
239 {
241  tris.clear();
242 
243  for (size_t f = 0; f < m_is_quad.size(); f++)
244  {
245  // Assign normals to faces (if on)
246  const auto& normal = m_normals[f];
247 
248  tris.emplace_back(
249  m_vertices[m_face_verts[f][0]], m_vertices[m_face_verts[f][1]],
250  m_vertices[m_face_verts[f][2]], normal, normal, normal);
251  if (m_is_quad[f])
252  {
253  tris.emplace_back(
254  m_vertices[m_face_verts[f][0]], m_vertices[m_face_verts[f][2]],
255  m_vertices[m_face_verts[f][3]], normal, normal, normal);
256  }
257  }
258 
259  for (auto& t : tris) t.setColor(face_color);
260 }
262 {
265 
266  vbd = m_vertices;
267  cbd.assign(m_vertices.size(), vert_color.asTColor());
268 }
269 
270 uint8_t CMesh3D::serializeGetVersion() const { return 0; }
272 {
273  writeToStreamRender(out);
274  out << m_showEdges << m_showFaces << m_showVertices << m_computeNormals;
275  out << m_is_quad << m_vertices << m_normals;
276  out.WriteAs<uint32_t>(m_face_verts.size());
277  if (!m_face_verts.empty())
278  out.WriteBufferFixEndianness<uint32_t>(
279  m_face_verts[0].data(),
280  m_face_verts.size() * m_face_verts[0].size());
281 }
282 
284 {
285  readFromStreamRender(in);
286  in >> m_showEdges >> m_showFaces >> m_showVertices >> m_computeNormals;
287  in >> m_is_quad >> m_vertices >> m_normals;
288  const auto N = in.ReadAs<uint32_t>();
289  m_face_verts.resize(N);
290  if (!m_face_verts.empty())
291  in.ReadBufferFixEndianness<uint32_t>(
292  m_face_verts[0].data(),
293  m_face_verts.size() * m_face_verts[0].size());
294 }
295 
298 {
299  if (m_vertices.empty())
300  {
301  bb_max = TPoint3D(0, 0, 0);
302  bb_min = TPoint3D(0, 0, 0);
303  }
304  else
305  {
306  bb_min.x = std::numeric_limits<double>::max();
307  bb_min.y = std::numeric_limits<double>::max();
308  bb_min.z = std::numeric_limits<double>::max();
309  bb_max.x = -std::numeric_limits<double>::max();
310  bb_max.y = -std::numeric_limits<double>::max();
311  bb_max.z = -std::numeric_limits<double>::max();
312 
313  for (size_t i = 0; i < m_vertices.size(); i++)
314  {
315  // Max
316  mrpt::keep_max(bb_max.x, m_vertices[i][0]);
317  mrpt::keep_max(bb_max.y, m_vertices[i][1]);
318  mrpt::keep_max(bb_max.z, m_vertices[i][2]);
319 
320  // Min
321  mrpt::keep_min(bb_min.x, m_vertices[i][0]);
322  mrpt::keep_min(bb_min.y, m_vertices[i][1]);
323  mrpt::keep_min(bb_min.z, m_vertices[i][2]);
324  }
325  }
326 
327  // Convert to coordinates of my parent:
328  m_pose.composePoint(bb_min, bb_min);
329  m_pose.composePoint(bb_max, bb_max);
330 }
opengl_api.h
mrpt::opengl::CMesh3D::loadMesh
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:29
mrpt::math::TPoint3D
TPoint3D_< double > TPoint3D
Lightweight 3D point.
Definition: TPoint3D.h:268
mrpt::opengl::CRenderizable::notifyChange
void notifyChange() const
Call to enable calling renderUpdateBuffers() before the next render() rendering iteration.
Definition: CRenderizable.h:315
mrpt::math::TPoint3D_< double >
mrpt::opengl::CRenderizableShaderTriangles::render
void render(const RenderContext &rc) const override
Implements the rendering of 3D objects in each class derived from CRenderizable.
Definition: CRenderizableShaderTriangles.cpp:45
mrpt::opengl::CMesh3D::onUpdateBuffers_Points
void onUpdateBuffers_Points() override
Must be implemented in derived classes to update the geometric entities to be drawn in "m_*_buffer" f...
Definition: CMesh3D.cpp:261
mrpt::opengl::CRenderizableShaderPoints::render
void render(const RenderContext &rc) const override
Implements the rendering of 3D objects in each class derived from CRenderizable.
Definition: CRenderizableShaderPoints.cpp:52
mrpt::opengl::CRenderizable
The base class of 3D objects that can be directly rendered through OpenGL.
Definition: CRenderizable.h:48
mrpt::opengl::CMesh3D::~CMesh3D
virtual ~CMesh3D() override
color_maps.h
mrpt::opengl::CRenderizableShaderWireFrame::m_color_buffer_data
std::vector< mrpt::img::TColor > m_color_buffer_data
Definition: CRenderizableShaderWireFrame.h:68
mrpt::opengl::CRenderizableShaderTriangles::m_triangles
std::vector< mrpt::opengl::TTriangle > m_triangles
List of triangles.
Definition: CRenderizableShaderTriangles.h:53
stl_serialization.h
out
mrpt::vision::TStereoCalibResults out
Definition: chessboard_stereo_camera_calib_unittest.cpp:25
mrpt::opengl::CMesh3D::getBoundingBox
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:296
mrpt
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
Definition: BaseAppDataSource.h:15
mrpt::opengl::CMesh3D::onUpdateBuffers_Triangles
void onUpdateBuffers_Triangles() override
Must be implemented in derived classes to update the geometric entities to be drawn in "m_*_buffer" f...
Definition: CMesh3D.cpp:238
THROW_EXCEPTION
#define THROW_EXCEPTION(msg)
Definition: exceptions.h:67
mrpt::poses
Classes for 2D/3D geometry representation, both of single values and probability density distribution...
Definition: CHierarchicalMapMHPartition.h:22
mrpt::serialization::CArchive
Virtual base class for "archives": classes abstracting I/O streams.
Definition: CArchive.h:54
mrpt::serialization::CArchive::ReadAs
STORED_TYPE ReadAs()
De-serialize a variable and returns it by value.
Definition: CArchive.h:155
bb_max
const auto bb_max
Definition: CPose3DPDFGrid_unittest.cpp:25
mrpt::opengl::CMesh3D::onUpdateBuffers_Wireframe
void onUpdateBuffers_Wireframe() override
Must be implemented in derived classes to update the geometric entities to be drawn in "m_*_buffer" f...
Definition: CMesh3D.cpp:208
mrpt::opengl::DefaultShaderID::WIREFRAME
static constexpr shader_id_t WIREFRAME
Definition: DefaultShaders.h:25
bb_min
const auto bb_min
Definition: CPose3DPDFGrid_unittest.cpp:23
mrpt::opengl::DefaultShaderID::TRIANGLES
static constexpr shader_id_t TRIANGLES
Definition: DefaultShaders.h:27
mrpt::opengl::CRenderizableShaderWireFrame::m_vertex_buffer_data
std::vector< mrpt::math::TPoint3Df > m_vertex_buffer_data
Definition: CRenderizableShaderWireFrame.h:67
mrpt::opengl::CMesh3D
A 3D mesh composed of Triangles and/or Quads.
Definition: CMesh3D.h:35
mrpt::opengl::CRenderizableShaderPoints::renderUpdateBuffers
void renderUpdateBuffers() const override
Called whenever m_outdatedBuffers is true: used to re-generate OpenGL vertex buffers,...
mrpt::opengl::CRenderizableShaderWireFrame::render
void render(const RenderContext &rc) const override
Implements the rendering of 3D objects in each class derived from CRenderizable.
Definition: CRenderizableShaderWireFrame.cpp:52
mrpt::keep_max
void keep_max(T &var, const K test_val)
If the second argument is above the first one, set the first argument to this higher value.
Definition: core/include/mrpt/core/bits_math.h:152
mrpt::keep_min
void keep_min(T &var, const K test_val)
If the second argument is below the first one, set the first argument to this lower value.
Definition: core/include/mrpt/core/bits_math.h:145
mrpt::opengl::CMesh3D::serializeFrom
void serializeFrom(mrpt::serialization::CArchive &in, uint8_t serial_version) override
Pure virtual method for reading (deserializing) from an abstract archive.
Definition: CMesh3D.cpp:283
mrpt::opengl::CRenderizable::RenderContext
Context for calls to render()
Definition: CRenderizable.h:266
IMPLEMENTS_SERIALIZABLE
#define IMPLEMENTS_SERIALIZABLE(class_name, base, NameSpace)
To be added to all CSerializable-classes implementation files.
Definition: CSerializable.h:166
mrpt::opengl::CRenderizable::RenderContext::shader_id
mrpt::opengl::shader_id_t shader_id
Definition: CRenderizable.h:272
mrpt::opengl::CMesh3D::serializeTo
void serializeTo(mrpt::serialization::CArchive &out) const override
Pure virtual method for writing (serializing) to an abstract archive.
Definition: CMesh3D.cpp:271
opengl-precomp.h
mrpt::math::CMatrixDynamic::resize
void resize(size_t row, size_t col)
Definition: CMatrixDynamic.h:356
mrpt::opengl::CRenderizableShaderTriangles::renderUpdateBuffers
void renderUpdateBuffers() const override
Called whenever m_outdatedBuffers is true: used to re-generate OpenGL vertex buffers,...
mrpt::serialization::CArchive::ReadBufferFixEndianness
size_t ReadBufferFixEndianness(T *ptr, size_t ElementCount)
Reads a sequence of elemental datatypes, taking care of reordering their bytes from the MRPT stream s...
Definition: CArchive.h:94
mrpt::math
This base provides a set of functions for maths stuff.
Definition: math/include/mrpt/math/bits_math.h:11
mrpt::opengl::CRenderizableShaderPoints::m_vertex_buffer_data
std::vector< mrpt::math::TPoint3Df > m_vertex_buffer_data
Definition: CRenderizableShaderPoints.h:94
mrpt::opengl::CMesh3D::renderUpdateBuffers
void renderUpdateBuffers() const override
Called whenever m_outdatedBuffers is true: used to re-generate OpenGL vertex buffers,...
Definition: CMesh3D.cpp:201
CArchive.h
mrpt::opengl::CMesh3D::render
void render(const RenderContext &rc) const override
Implements the rendering of 3D objects in each class derived from CRenderizable.
Definition: CMesh3D.cpp:186
mrpt::opengl::CRenderizableShaderWireFrame::renderUpdateBuffers
void renderUpdateBuffers() const override
Called whenever m_outdatedBuffers is true: used to re-generate OpenGL vertex buffers,...
mrpt::opengl::CMesh3D::serializeGetVersion
uint8_t serializeGetVersion() const override
Must return the current versioning number of the object.
Definition: CMesh3D.cpp:270
mrpt::opengl::CRenderizableShaderPoints::m_color_buffer_data
std::vector< mrpt::img::TColor > m_color_buffer_data
Definition: CRenderizableShaderPoints.h:95
mrpt::opengl
The namespace for 3D scene representation and rendering.
Definition: CGlCanvasBase.h:13
mrpt::opengl::DefaultShaderID::POINTS
static constexpr shader_id_t POINTS
Definition: DefaultShaders.h:24
mrpt::math::CMatrixDynamic
This template class provides the basic functionality for a general 2D any-size, resizable container o...
Definition: CMatrixDynamic.h:39
CMesh3D.h



Page generated by Doxygen 1.8.17 for MRPT 2.0.3 at Fri May 15 15:49:54 UTC 2020