MRPT  2.0.4
CAssimpModel.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 // This file contains portions of code from Assimp's example:
11 // "Sample_SimpleOpenGL.c"
12 
13 #include "opengl-precomp.h" // Precompiled header
14 
16 
17 #if MRPT_HAS_ASSIMP
18 #if defined(MRPT_ASSIMP_VERSION_MAJOR) && MRPT_ASSIMP_VERSION_MAJOR < 3
19 #include <aiPostProcess.h>
20 #include <aiScene.h>
21 #include <assimp.h>
22 #else
23 #include <assimp/cimport.h>
24 #include <assimp/postprocess.h>
25 #include <assimp/scene.h>
26 #include <assimp/DefaultLogger.hpp>
27 #include <assimp/LogStream.hpp>
28 #endif
29 #endif
30 
32 #include <mrpt/system/filesystem.h>
33 
34 using namespace mrpt;
35 using namespace mrpt::opengl;
36 using namespace mrpt::math;
37 using namespace std;
38 using mrpt::img::CImage;
39 
41 
43 {
44  std::vector<mrpt::math::TPoint3Df>* lines_vbd = nullptr;
45  std::vector<mrpt::img::TColor>* lines_cbd = nullptr;
46  std::vector<mrpt::math::TPoint3Df>* pts_vbd = nullptr;
47  std::vector<mrpt::img::TColor>* pts_cbd = nullptr;
48  std::vector<mrpt::opengl::TTriangle>* tris = nullptr;
49 };
50 
51 #if MRPT_HAS_OPENGL_GLUT && MRPT_HAS_ASSIMP
52 // Note: Look at older git versions to see pre-OpenGL3 version with more texture
53 // supports, etc. load_textures(), etc.
54 static void recursive_render(
55  const aiScene* sc, const aiNode* nd, const mrpt::poses::CPose3D& transf,
56  RenderElements& re);
57 
58 // Just return the diffuse color:
59 static mrpt::img::TColor apply_material(const aiMaterial* mtl);
60 static void get_bounding_box(
61  const aiScene* sc, aiVector3D* min, aiVector3D* max);
62 static void get_bounding_box_for_node(
63  const aiScene* sc, const aiNode* nd, aiVector3D* min, aiVector3D* max,
64  aiMatrix4x4* trafo);
65 #endif // MRPT_HAS_OPENGL_GLUT && MRPT_HAS_ASSIMP
66 
67 void CAssimpModel::render(const RenderContext& rc) const
68 {
69  switch (rc.shader_id)
70  {
73  break;
76  break;
79  break;
80  };
81 }
83 {
84  // onUpdateBuffers_all: already called upon loading of the model from file.
85 
89 }
90 
91 // special case for assimp: update all buffers within one run over the scene
92 // structure.
94 {
97  lines_vbd.clear();
98  lines_cbd.clear();
99 
102  pts_vbd.clear();
103  pts_cbd.clear();
104 
106  tris.clear();
107 
108  if (!m_assimp_scene->scene) return; // No scene
109 
110  RenderElements re;
111  re.lines_vbd = &lines_vbd;
112  re.lines_cbd = &lines_cbd;
113  re.pts_vbd = &pts_vbd;
114  re.pts_cbd = &pts_cbd;
115  re.tris = &tris;
116 
117 #if MRPT_HAS_OPENGL_GLUT && MRPT_HAS_ASSIMP
118  auto* scene = reinterpret_cast<aiScene*>(m_assimp_scene->scene);
119 
120  const auto transf = mrpt::poses::CPose3D();
121 
122  recursive_render(scene, scene->mRootNode, transf, re);
123 #endif
124 }
125 
126 // These 3: already done in onUpdateBuffers_all()
130 
131 uint8_t CAssimpModel::serializeGetVersion() const { return 0; }
133 {
134  writeToStreamRender(out);
135 
136  const bool empty = m_assimp_scene->scene != nullptr;
137  out << empty;
138 
139  if (!empty)
140  {
141 #if MRPT_HAS_OPENGL_GLUT && MRPT_HAS_ASSIMP
142  // aiScene *scene = (aiScene *) m_assimp_scene->scene;
143  THROW_EXCEPTION("MRPT can't serialize Assimp objects yet!");
144 #else
145  THROW_EXCEPTION("MRPT compiled without OpenGL and/or Assimp");
146 #endif
147  }
148 }
149 
151  mrpt::serialization::CArchive& in, uint8_t version)
152 {
153  THROW_EXCEPTION("MRPT can't serialize Assimp objects yet!");
154 
155  switch (version)
156  {
157  case 0:
158  {
159  readFromStreamRender(in);
160 
161  clear();
162  }
163  break;
164  default:
166  };
168 }
169 
170 CAssimpModel::CAssimpModel() : m_bbox_min(0, 0, 0), m_bbox_max(0, 0, 0)
171 {
172  m_assimp_scene = std::make_shared<TImplAssimp>();
173 }
174 
176 /*---------------------------------------------------------------
177  clear
178  ---------------------------------------------------------------*/
180 {
182  m_assimp_scene = std::make_shared<TImplAssimp>();
183  m_modelPath.clear();
184  // m_textures_loaded = false;
185 
186 #if MRPT_HAS_OPENGL_GLUT
187 #if 0
188  if (!m_textureIds.empty())
189  {
190  glDeleteTextures(m_textureIds.size(), &m_textureIds[0]);
191  m_textureIds.clear();
192  }
193  m_textureIdMap.clear();
194 #endif
195 #endif
196 }
197 
198 void CAssimpModel::loadScene(const std::string& filepath)
199 {
200 #if MRPT_HAS_OPENGL_GLUT && MRPT_HAS_ASSIMP
201  clear();
203 
204  // we are taking one of the postprocessing presets to avoid
205  // spelling out 20+ single postprocessing flags here.
206  m_assimp_scene->scene = (void*)aiImportFile(
207  filepath.c_str(), aiProcessPreset_TargetRealtime_MaxQuality);
208  m_modelPath = filepath;
209 
210  if (m_assimp_scene->scene)
211  {
212  aiVector3D scene_min, scene_max;
213  auto* scene = (aiScene*)m_assimp_scene->scene;
214  get_bounding_box(scene, &scene_min, &scene_max);
215  m_bbox_min.x = scene_min.x;
216  m_bbox_min.y = scene_min.y;
217  m_bbox_min.z = scene_min.z;
218  m_bbox_max.x = scene_max.x;
219  m_bbox_max.y = scene_max.y;
220  m_bbox_max.z = scene_max.z;
221  }
222 
223  // Process all elements at once:
224  // This populates the structures that will be attached to opengl buffers
225  const_cast<CAssimpModel&>(*this).onUpdateBuffers_all();
226 
227 #else
228  THROW_EXCEPTION("MRPT compiled without OpenGL and/or Assimp");
229 #endif
230 }
231 
234 {
235  bb_min = m_bbox_min;
236  bb_max = m_bbox_max;
237 
238  // Convert to coordinates of my parent:
241 }
242 
245 {
246 #if MRPT_HAS_OPENGL_GLUT && MRPT_HAS_ASSIMP
247  if (scene)
248  {
249  // cleanup - calling 'aiReleaseImport' is important, as the library
250  // keeps internal resources until the scene is freed again. Not
251  // doing so can cause severe resource leaking.
252  aiReleaseImport((aiScene*)scene);
253  scene = nullptr;
254  }
255 #endif
256 }
257 
258 bool CAssimpModel::traceRay(const mrpt::poses::CPose3D& o, double& dist) const
259 {
260  // TODO
261  return false;
262 }
263 
264 #if MRPT_HAS_OPENGL_GLUT && MRPT_HAS_ASSIMP
265 
266 static void get_bounding_box_for_node(
267  const aiScene* scene, const aiNode* nd, aiVector3D* min, aiVector3D* max,
268  aiMatrix4x4* trafo)
269 {
270  aiMatrix4x4 prev;
271  unsigned int n = 0, t;
272 
273  prev = *trafo;
274  aiMultiplyMatrix4(trafo, &nd->mTransformation);
275 
276  for (; n < nd->mNumMeshes; ++n)
277  {
278  const aiMesh* mesh = scene->mMeshes[nd->mMeshes[n]];
279  for (t = 0; t < mesh->mNumVertices; ++t)
280  {
281  aiVector3D tmp = mesh->mVertices[t];
282  aiTransformVecByMatrix4(&tmp, trafo);
283 
284  min->x = std::min(min->x, tmp.x);
285  min->y = std::min(min->y, tmp.y);
286  min->z = std::min(min->z, tmp.z);
287 
288  max->x = std::max(max->x, tmp.x);
289  max->y = std::max(max->y, tmp.y);
290  max->z = std::max(max->z, tmp.z);
291  }
292  }
293 
294  for (n = 0; n < nd->mNumChildren; ++n)
295  {
296  get_bounding_box_for_node(scene, nd->mChildren[n], min, max, trafo);
297  }
298  *trafo = prev;
299 }
300 
301 static void get_bounding_box(
302  const aiScene* scene, aiVector3D* min, aiVector3D* max)
303 {
304  aiMatrix4x4 trafo;
305  aiIdentityMatrix4(&trafo);
306 
307  min->x = min->y = min->z = 1e10f;
308  max->x = max->y = max->z = -1e10f;
309  get_bounding_box_for_node(scene, scene->mRootNode, min, max, &trafo);
310 }
311 
312 static mrpt::img::TColor color4_to_TColor(const aiColor4D& c)
313 {
314  return mrpt::img::TColorf(c.r, c.g, c.b, c.a).asTColor();
315 }
316 
317 static mrpt::img::TColor apply_material(const aiMaterial* mtl)
318 {
319  aiColor4D diffuse;
320  if (AI_SUCCESS ==
321  aiGetMaterialColor(mtl, AI_MATKEY_COLOR_DIFFUSE, &diffuse))
322  {
323  return color4_to_TColor(diffuse);
324  }
325  else
326  {
327  // Default color:
328  return {0xa0, 0xa0, 0xa0, 0xff};
329  }
330 }
331 
332 static mrpt::math::CMatrixDouble44 aiMatrix_to_mrpt(const aiMatrix4x4& m)
333 {
335  M(0, 0) = m.a1;
336  M(0, 1) = m.a2;
337  M(0, 2) = m.a3;
338  M(0, 3) = m.a4;
339 
340  M(1, 0) = m.b1;
341  M(1, 1) = m.b2;
342  M(1, 2) = m.b3;
343  M(1, 3) = m.b4;
344 
345  M(2, 0) = m.c1;
346  M(2, 1) = m.c2;
347  M(2, 2) = m.c3;
348  M(2, 3) = m.c4;
349 
350  M(3, 0) = m.d1;
351  M(3, 1) = m.d2;
352  M(3, 2) = m.d3;
353  M(3, 3) = m.d4;
354  return M;
355 }
356 
357 static mrpt::math::TPoint3Df to_mrpt(const aiVector3D& v)
358 {
359  return {v.x, v.y, v.z};
360 }
361 
362 static void recursive_render(
363  const aiScene* sc, const aiNode* nd, const mrpt::poses::CPose3D& transf,
364  RenderElements& re)
365 {
366  aiMatrix4x4 m = nd->mTransformation;
367 
368  // update transform
369  const auto nodeTransf = mrpt::poses::CPose3D(aiMatrix_to_mrpt(m));
370  const mrpt::poses::CPose3D curTf = transf + nodeTransf;
371 
372  // draw all meshes assigned to this node
373  for (unsigned int n = 0; n < nd->mNumMeshes; ++n)
374  {
375  const struct aiMesh* mesh = sc->mMeshes[nd->mMeshes[n]];
376 
377  mrpt::img::TColor color =
378  apply_material(sc->mMaterials[mesh->mMaterialIndex]);
379 
380  for (unsigned int t = 0; t < mesh->mNumFaces; ++t)
381  {
382  const struct aiFace* face = &mesh->mFaces[t];
383 
384  switch (face->mNumIndices)
385  {
386  case 1:
387  // GL_POINTS ================
388  for (unsigned int i = 0; i < face->mNumIndices; i++)
389  {
390  // get group index for current index
391  int vertexIndex = face->mIndices[i];
392  if (mesh->mColors[0] != nullptr)
393  color =
394  color4_to_TColor(mesh->mColors[0][vertexIndex]);
395 
396  re.pts_vbd->emplace_back(curTf.composePoint(
397  to_mrpt(mesh->mVertices[vertexIndex])));
398  re.pts_cbd->emplace_back(color);
399  }
400  break;
401 
402  case 2:
403  // GL_LINES ================
404  for (unsigned int i = 0; i < face->mNumIndices; i++)
405  {
406  // get group index for current index
407  int vertexIndex = face->mIndices[i];
408  if (mesh->mColors[0] != nullptr)
409  color =
410  color4_to_TColor(mesh->mColors[0][vertexIndex]);
411 
412  re.lines_vbd->emplace_back(curTf.composePoint(
413  to_mrpt(mesh->mVertices[vertexIndex])));
414  re.lines_cbd->emplace_back(color);
415  }
416  break;
417 
418  case 3:
419  {
420  // GL_TRIANGLES ================
421  const unsigned int nTri = face->mNumIndices / 3;
422  ASSERT_EQUAL_(face->mNumIndices % 3, 0);
423 
424  for (unsigned int iTri = 0; iTri < nTri; iTri++)
425  {
427  for (unsigned int v = 0; v < 3; v++)
428  {
429  unsigned int i = iTri * 3 + v;
430  // get group index for current index
431  int vertexIndex = face->mIndices[i];
432  if (mesh->mColors[0] != nullptr)
433  color = color4_to_TColor(
434  mesh->mColors[0][vertexIndex]);
435 
436  tri.r(v) = color.R;
437  tri.g(v) = color.G;
438  tri.b(v) = color.B;
439  tri.a(v) = color.A;
440 
441  // texture_coordinates_set=0
442  if (mesh->HasTextureCoords(0))
443  {
444  tri.vertices[v].uv.x =
445  mesh->mTextureCoords[0][vertexIndex].x;
446  tri.vertices[v].uv.y =
447  mesh->mTextureCoords[0][vertexIndex].y;
448  }
449 
450  if (mesh->mNormals)
451  tri.vertices[v].normal = curTf.rotateVector(
452  to_mrpt(mesh->mNormals[vertexIndex]));
453 
454  auto pt = curTf.composePoint(
455  to_mrpt(mesh->mVertices[vertexIndex]));
456  tri.x(v) = pt.x;
457  tri.y(v) = pt.y;
458  tri.z(v) = pt.z;
459  }
460 
461  re.tris->emplace_back(std::move(tri));
462  }
463  }
464  break;
465  default:
466  // GL_POLYGON ================
467  THROW_EXCEPTION("ASSIMP polygons not implemented yet.");
468  break;
469  }
470  }
471  }
472 
473  // draw all children
474  for (unsigned int n = 0; n < nd->mNumChildren; ++n)
475  recursive_render(sc, nd->mChildren[n], curTf, re);
476 }
477 
478 #endif // MRPT_HAS_OPENGL_GLUT && MRPT_HAS_ASSIMP
A compile-time fixed-size numeric matrix container.
Definition: CMatrixFixed.h:33
const uint8_t & b(size_t i) const
Definition: TTriangle.h:95
std::vector< mrpt::math::TPoint3Df > m_vertex_buffer_data
#define THROW_EXCEPTION(msg)
Definition: exceptions.h:67
void serializeFrom(mrpt::serialization::CArchive &in, uint8_t serial_version) override
Pure virtual method for reading (deserializing) from an abstract archive.
#define IMPLEMENTS_SERIALIZABLE(class_name, base, NameSpace)
To be added to all CSerializable-classes implementation files.
void onUpdateBuffers_Triangles() override
Must be implemented in derived classes to update the geometric entities to be drawn in "m_*_buffer" f...
const uint8_t & r(size_t i) const
Definition: TTriangle.h:93
void notifyChange() const
Call to enable calling renderUpdateBuffers() before the next render() rendering iteration.
const float & x(size_t i) const
Definition: TTriangle.h:90
std::vector< mrpt::img::TColor > * lines_cbd
std::vector< mrpt::math::TPoint3Df > * pts_vbd
A triangle (float coordinates) with RGBA colors (u8) and UV (texture coordinates) for each vertex...
Definition: TTriangle.h:35
The base class of 3D objects that can be directly rendered through OpenGL.
Definition: CRenderizable.h:48
void onUpdateBuffers_Points() override
Must be implemented in derived classes to update the geometric entities to be drawn in "m_*_buffer" f...
const uint8_t & g(size_t i) const
Definition: TTriangle.h:94
STL namespace.
uint8_t B
Definition: TColor.h:51
uint8_t G
Definition: TColor.h:51
void loadScene(const std::string &file_name)
Loads a scene from a file in any supported file.
mrpt::math::TPoint3D m_bbox_min
Bounding box.
Definition: CAssimpModel.h:113
mrpt::poses::CPose3D m_pose
6D pose wrt the parent coordinate reference.
Definition: CRenderizable.h:62
void renderUpdateBuffers() const override
Called whenever m_outdatedBuffers is true: used to re-generate OpenGL vertex buffers, etc.
bool traceRay(const mrpt::poses::CPose3D &o, double &dist) const override
Simulation of ray-trace, given a pose.
void renderUpdateBuffers() const override
Called whenever m_outdatedBuffers is true: used to re-generate OpenGL vertex buffers, etc.
Context for calls to render()
mrpt::math::TVector3D rotateVector(const mrpt::math::TVector3D &local) const
Rotates a vector (i.e.
Definition: CPose3D.cpp:460
std::vector< mrpt::math::TPoint3Df > m_vertex_buffer_data
#define MRPT_THROW_UNKNOWN_SERIALIZATION_VERSION(__V)
For use in CSerializable implementations.
Definition: exceptions.h:97
const uint8_t & a(size_t i) const
Definition: TTriangle.h:96
std::vector< mrpt::img::TColor > m_color_buffer_data
std::array< Vertex, 3 > vertices
Definition: TTriangle.h:88
void onUpdateBuffers_Wireframe() override
Must be implemented in derived classes to update the geometric entities to be drawn in "m_*_buffer" f...
mrpt::img::CImage CImage
Definition: utils/CImage.h:5
This base provides a set of functions for maths stuff.
mrpt::math::TPoint3D m_bbox_max
Definition: CAssimpModel.h:113
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...
void clear()
Empty the object.
#define ASSERT_EQUAL_(__A, __B)
Assert comparing two values, reporting their actual values upon failure.
Definition: exceptions.h:137
std::vector< mrpt::math::TPoint3Df > * lines_vbd
static constexpr shader_id_t WIREFRAME
uint8_t serializeGetVersion() const override
Must return the current versioning number of the object.
virtual ~CAssimpModel() override
uint8_t R
Definition: TColor.h:51
void renderUpdateBuffers() const override
Called whenever m_outdatedBuffers is true: used to re-generate OpenGL vertex buffers, etc.
bool empty() const
Definition: ts_hash_map.h:191
static constexpr shader_id_t TRIANGLES
std::vector< mrpt::img::TColor > * pts_cbd
T x
X,Y,Z coordinates.
Definition: TPoint3D.h:29
void render(const RenderContext &rc) const override
Implements the rendering of 3D objects in each class derived from CRenderizable.
std::vector< mrpt::img::TColor > m_color_buffer_data
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
std::vector< mrpt::opengl::TTriangle > * tris
const float & y(size_t i) const
Definition: TTriangle.h:91
Virtual base class for "archives": classes abstracting I/O streams.
Definition: CArchive.h:54
std::vector< mrpt::opengl::TTriangle > m_triangles
List of triangles.
A class used to store a 3D pose (a 3D translation + a rotation in 3D).
Definition: CPose3D.h:85
mrpt::vision::TStereoCalibResults out
const float & z(size_t i) const
Definition: TTriangle.h:92
An RGBA color - floats in the range [0,1].
Definition: TColor.h:88
The namespace for 3D scene representation and rendering.
Definition: CGlCanvasBase.h:13
const auto bb_max
void render(const RenderContext &rc) const override
Implements the rendering of 3D objects in each class derived from CRenderizable.
void serializeTo(mrpt::serialization::CArchive &out) const override
Pure virtual method for writing (serializing) to an abstract archive.
void composePoint(double lx, double ly, double lz, double &gx, double &gy, double &gz, mrpt::optional_ref< mrpt::math::CMatrixDouble33 > out_jacobian_df_dpoint=std::nullopt, mrpt::optional_ref< mrpt::math::CMatrixDouble36 > out_jacobian_df_dpose=std::nullopt, mrpt::optional_ref< mrpt::math::CMatrixDouble36 > out_jacobian_df_dse3=std::nullopt, 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...
const auto bb_min
TColor asTColor() const
Returns the 0-255 integer version of this color: RGBA_u8.
Definition: TColor.h:101
A RGB color - 8bit.
Definition: TColor.h:25
void render(const RenderContext &rc) const override
Implements the rendering of 3D objects in each class derived from CRenderizable.
void clear()
Clear the contents of this container.
Definition: ts_hash_map.h:183
This class can load & render 3D models in a number of different formats (requires the library assimp)...
Definition: CAssimpModel.h:41
static constexpr shader_id_t POINTS
uint8_t A
Definition: TColor.h:51
std::shared_ptr< TImplAssimp > m_assimp_scene
Definition: CAssimpModel.h:110
void render(const RenderContext &rc) const override
Implements the rendering of 3D objects in each class derived from CRenderizable.
void renderUpdateBuffers() const override
Called whenever m_outdatedBuffers is true: used to re-generate OpenGL vertex buffers, etc.



Page generated by Doxygen 1.8.14 for MRPT 2.0.4 Git: 33de1d0ad Sat Jun 20 11:02:42 2020 +0200 at sáb jun 20 17:35:17 CEST 2020