TDME2  1.9.200
GenerateConvexMeshes.cpp
Go to the documentation of this file.
2 
3 #include <memory>
4 #include <string>
5 #include <unordered_map>
6 #include <vector>
7 
8 #include <VHACD.h>
9 
10 #include <tdme/tdme.h>
13 #include <tdme/engine/Color4.h>
14 #include <tdme/engine/model/Face.h>
18 #include <tdme/engine/model/Node.h>
27 #include <tdme/gui/nodes/GUINode.h>
38 #include <tdme/utilities/Console.h>
43 
45 
46 using std::make_unique;
47 using std::string;
48 using std::to_string;
49 using std::unordered_map;
50 using std::unique_ptr;
51 using std::vector;
52 
85 
86 void GenerateConvexMeshes::removeConvexMeshes(Prototype* prototype)
87 {
88  // delete old convex meshes
89  for (int i = 0; i < prototype->getBoundingVolumeCount(); i++) {
90  auto boundingVolume = prototype->getBoundingVolume(i);
91  if (boundingVolume->isGenerated() == false) {
92  continue;
93  } else {
94  if (boundingVolume->getConvexMeshFile().empty() == false &&
95  FileSystem::getInstance()->exists(boundingVolume->getConvexMeshFile()) == true) {
96  FileSystem::getInstance()->removeFile(
97  FileSystem::getInstance()->getPathName(boundingVolume->getConvexMeshFile()),
98  FileSystem::getInstance()->getFileName(boundingVolume->getConvexMeshFile())
99  );
100  prototype->removeBoundingVolume(i);
101  i--;
102  } else
103  if (boundingVolume->getConvexMeshData().empty() == false) {
104  prototype->removeBoundingVolume(i);
105  i--;
106  }
107  }
108  }
109 }
110 
111 bool GenerateConvexMeshes::generateConvexMeshes(Prototype* prototype, Mode mode, PopUps* popUps, const string& pathName, const string& fileName, vector<vector<uint8_t>>& convexMeshTMsData, VHACD::IVHACD::Parameters parameters)
112 {
113  auto success = true;
114  if (mode == MODE_GENERATE) {
115  class VHACDCallback : public VHACD::IVHACD::IUserCallback {
116  private:
117  ProgressBarScreenController* progressBarScreenController;
118  public:
119  VHACDCallback(ProgressBarScreenController* progressBarScreenController): progressBarScreenController(progressBarScreenController) {}
120  ~VHACDCallback() {};
121  void Update(
122  const double overallProgress,
123  const double stageProgress,
124  const double operationProgress,
125  const char* const stage,
126  const char* const operation)
127  {
128  // progressBarScreenController->progress((int)(overallProgress + 0.5) / 100.0f);
129  };
130  };
131 
132  class VHACDLogger : public VHACD::IVHACD::IUserLogger {
133  public:
134  VHACDLogger() {}
135  ~VHACDLogger() {};
136  void Log(const char* const msg)
137  {
138  Console::println(msg);
139  }
140  };
141 
142  //
143  // if (popUps != nullptr) popUps->getProgressBarScreenController()->show("Generate convex meshes ...");
144  auto vhacd = VHACD::CreateVHACD();
145  try {
146  //
147  parameters.m_maxRecursionDepth = 15;
148  //
149  if (parameters.m_resolution < 10000 || parameters.m_resolution > 64000000) {
150  throw ExceptionBase("Resolution must be between 10000 and 64000000");
151  }
152  if (parameters.m_minimumVolumePercentErrorAllowed < 0.0f || parameters.m_minimumVolumePercentErrorAllowed > 100.0f) {
153  throw ExceptionBase("Concavity must be between 0.0 and 100.0");
154  }
155  if (parameters.m_maxNumVerticesPerCH < 4 || parameters.m_maxNumVerticesPerCH > 1024) {
156  throw ExceptionBase("Max number of vertices per convex hull must be between 4 and 1024");
157  }
158  if (parameters.m_maxConvexHulls < 1 || parameters.m_maxConvexHulls > 64) {
159  throw ExceptionBase("Max number of convex hulls must be between 1 and 64");
160  }
161  //
162  VHACDLogger vhacdLogger;
163  parameters.m_logger = &vhacdLogger;
164  /*
165  if (popUps != nullptr) {
166  VHACDCallback vhacdCallback(popUps->getProgressBarScreenController());
167  parameters.m_callback = &vhacdCallback;
168  }
169  */
170  vector<float> meshPoints;
171  vector<int> meshTriangles;
172  //
173  {
174  auto meshModel = unique_ptr<Model>(
175  ModelReader::read(
176  pathName,
177  fileName
178  )
179  );
180  {
181  ObjectModel meshObjectModel(meshModel.get());
182  vector<Triangle> meshFaceTriangles;
183  meshObjectModel.getTriangles(meshFaceTriangles);
184  for (const auto& triangle: meshFaceTriangles) {
185  meshTriangles.push_back(meshPoints.size() / 3 + 0);
186  meshTriangles.push_back(meshPoints.size() / 3 + 1);
187  meshTriangles.push_back(meshPoints.size() / 3 + 2);
188  for (auto i = 0; i < triangle.getVertices().size(); i++) {
189  meshPoints.push_back(triangle.getVertices()[i].getX());
190  meshPoints.push_back(triangle.getVertices()[i].getY());
191  meshPoints.push_back(triangle.getVertices()[i].getZ());
192  }
193  }
194  }
195  }
196  //
197  bool vhacdResult =
198  vhacd->Compute(
199  &meshPoints[0],
200  (unsigned int)meshPoints.size() / 3,
201  (const unsigned int *)&meshTriangles[0],
202  (unsigned int)meshTriangles.size() / 3,
203  parameters
204  );
205  if (vhacdResult == true) {
206  auto convexHulls = vhacd->GetNConvexHulls();
207  VHACD::IVHACD::ConvexHull convexHull;
208  for (auto i = 0; i < convexHulls; i++) {
209  vhacd->GetConvexHull(i, convexHull);
210  auto convexHullModel = unique_ptr<Model>(
211  createModel(
212  fileName + ".cm." + to_string(i) + ".tm",
213  convexHull.m_points,
214  convexHull.m_triangles
215  )
216  );
217  convexMeshTMsData.push_back(vector<uint8_t>());
218  TMWriter::write(convexHullModel.get(), convexMeshTMsData[convexMeshTMsData.size() - 1]);
219  }
220  }
221  } catch (Exception &exception) {
222  /*
223  if (popUps != nullptr) {
224  popUps->getInfoDialogScreenController()->show(
225  "Warning: Could not create convex hulls",
226  exception.what()
227  );
228  }
229  */
230  Console::println("Could not create convex hulls: " + string(exception.what()));
231  convexMeshTMsData.clear();
232  success = false;
233  }
234  vhacd->Clean();
235  vhacd->Release();
236  // if (popUps != nullptr) popUps->getProgressBarScreenController()->close();
237  } else
238  if (mode == MODE_IMPORT) {
239  try {
240  //
241  auto meshModel = unique_ptr<Model>(
242  ModelReader::read(
243  pathName,
244  fileName
245  )
246  );
247  //
248  {
249  ObjectModel meshObjectModel(meshModel.get());
250  for (auto i = 0; i < meshObjectModel.getNodeCount(); i++) {
251  vector<Triangle> nodeTriangles;
252  meshObjectModel.getTriangles(nodeTriangles, i);
253  auto convexHullModel = unique_ptr<Model>(
254  createModel(
255  fileName + ".cm." + to_string(i) + ".tm",
256  nodeTriangles
257  )
258  );
259  convexMeshTMsData.push_back(vector<uint8_t>());
260  TMWriter::write(convexHullModel.get(), convexMeshTMsData[convexMeshTMsData.size() - 1]);
261  }
262  }
263  } catch (Exception &exception) {
264  /*
265  if (popUps != nullptr) {
266  popUps->getInfoDialogScreenController()->show(
267  "Warning: Could not create convex hulls",
268  exception.what()
269  );
270  }
271  */
272  Console::println("Could not create convex hulls: " + string(exception.what()));
273  convexMeshTMsData.clear();
274  success = false;
275  }
276  }
277  return success;
278 }
279 
280 Model* GenerateConvexMeshes::createModel(const string& id, const vector<VHACD::Vertex>& points, const vector<VHACD::Triangle>& triangles) {
281  //
282  auto model = make_unique<Model>(id, id, UpVector::Y_UP, RotationOrder::XYZ, nullptr);
283  //
284  auto material = make_unique<Material>("primitive");
285  material->setSpecularMaterialProperties(make_unique<SpecularMaterialProperties>().release());
286  material->getSpecularMaterialProperties()->setAmbientColor(Color4(0.5f, 0.5f, 0.5f, 1.0f));
287  material->getSpecularMaterialProperties()->setDiffuseColor(Color4(1.0f, 0.5f, 0.5f, 0.5f));
288  material->getSpecularMaterialProperties()->setSpecularColor(Color4(0.0f, 0.0f, 0.0f, 1.0f));
289  //
290  auto node = make_unique<Node>(model.get(), nullptr, "node", "node");
291  vector<Vector3> vertices;
292  vector<Vector3> normals;
293  vector<Face> faces;
294  int normalIndex = -1;
295  for (const auto& vertex: points) {
296  vertices.emplace_back(
297  static_cast<float>(vertex.mX),
298  static_cast<float>(vertex.mY),
299  static_cast<float>(vertex.mZ)
300  );
301  }
302  for (const auto& triangle: triangles) {
303  normalIndex = normals.size();
304  {
305  array<Vector3, 3> faceVertices = {
306  vertices[triangle.mI0],
307  vertices[triangle.mI1],
308  vertices[triangle.mI2]
309  };
310  for (const auto& normal: ModelTools::computeNormals(faceVertices)) {
311  normals.push_back(normal);
312  }
313  }
314  faces.emplace_back(
315  node.get(),
316  triangle.mI0,
317  triangle.mI1,
318  triangle.mI2,
319  normalIndex + 0,
320  normalIndex + 1,
321  normalIndex + 2
322  );
323  }
324  FacesEntity nodeFacesEntity(node.get(), "faces entity");
325  nodeFacesEntity.setMaterial(material.get());
326  nodeFacesEntity.setFaces(faces);
327  vector<FacesEntity> nodeFacesEntities;
328  nodeFacesEntities.push_back(nodeFacesEntity);
329  node->setVertices(vertices);
330  node->setNormals(normals);
331  node->setFacesEntities(nodeFacesEntities);
332  model->getNodes()["node"] = node.get();
333  model->getSubNodes()["node"] = node.get();
334  node.release();
335  //
336  model->getMaterials()[material->getId()] = material.get();
337  material.release();
338  //
339  ModelTools::prepareForIndexedRendering(model.get());
340  //
341  return model.release();
342 }
343 
344 Model* GenerateConvexMeshes::createModel(const string& id, vector<Triangle>& triangles) {
345  auto model = make_unique<Model>(id, id, UpVector::Y_UP, RotationOrder::XYZ, nullptr);
346  //
347  auto material = make_unique<Material>("primitive");
348  material->setSpecularMaterialProperties(make_unique<SpecularMaterialProperties>().release());
349  material->getSpecularMaterialProperties()->setAmbientColor(Color4(0.5f, 0.5f, 0.5f, 1.0f));
350  material->getSpecularMaterialProperties()->setDiffuseColor(Color4(1.0f, 0.5f, 0.5f, 0.5f));
351  material->getSpecularMaterialProperties()->setSpecularColor(Color4(0.0f, 0.0f, 0.0f, 1.0f));
352  //
353  auto node = make_unique<Node>(model.get(), nullptr, "node", "node");
354  vector<Vector3> vertices;
355  vector<Vector3> normals;
356  vector<Face> faces;
357  auto index = 0;
358  for (const auto& triangle: triangles) {
359  for (const auto& vertex: triangle.getVertices()) {
360  vertices.push_back(vertex);
361  }
362  {
363  array<Vector3, 3> faceVertices = {
364  triangle.getVertices()[0],
365  triangle.getVertices()[1],
366  triangle.getVertices()[2],
367  };
368  for (const auto& normal: ModelTools::computeNormals(faceVertices)) {
369  normals.push_back(normal);
370  }
371  }
372  faces.emplace_back(
373  node.get(),
374  index + 0,
375  index + 1,
376  index + 2,
377  index + 0,
378  index + 1,
379  index + 2
380  );
381  index+= 3;
382  }
383  FacesEntity nodeFacesEntity(node.get(), "faces entity");
384  nodeFacesEntity.setMaterial(material.get());
385  nodeFacesEntity.setFaces(faces);
386  vector<FacesEntity> nodeFacesEntities;
387  nodeFacesEntities.push_back(nodeFacesEntity);
388  node->setVertices(vertices);
389  node->setNormals(normals);
390  node->setFacesEntities(nodeFacesEntities);
391  //
392  model->getNodes()["node"] = node.get();
393  model->getSubNodes()["node"] = node.get();
394  node.release();
395  //
396  model->getMaterials()[material->getId()] = material.get();
397  material.release();
398  //
399  ModelTools::prepareForIndexedRendering(model.get());
400  //
401  return model.release();
402 }
Color 4 definition class.
Definition: Color4.h:18
Represents a model face, consisting of vertex, normal, tangent and bitangent vectors,...
Definition: Face.h:18
Node faces entity A node can have multiple entities containing faces and a applied material.
Definition: FacesEntity.h:23
void setMaterial(Material *material)
Set up the entity's material.
Definition: FacesEntity.h:67
void setFaces(const vector< Face > &faces)
Set up entity's faces.
Definition: FacesEntity.cpp:43
Represents a material.
Definition: Material.h:23
Representation of a 3D model.
Definition: Model.h:35
Model node.
Definition: Node.h:32
Represents rotation orders of a model.
Definition: RotationOrder.h:23
Represents specular material properties.
Model up vector.
Definition: UpVector.h:20
Triangle entity, this is not directly connectable with physics engine.
Definition: Triangle.h:18
Prototype definition.
Definition: Prototype.h:55
PrototypeBoundingVolume * getBoundingVolume(int idx)
Get bounding volume at given index.
Definition: Prototype.h:288
void removeBoundingVolume(int idx)
Remove bounding volume at given index.
Definition: Prototype.cpp:82
void getTriangles(vector< Triangle > &triangles, int nodeIdx=-1)
Retrieves list of triangles of all or given nodes.
Definition: ObjectBase.cpp:99
GUI node controller base class.
GUI node base class.
Definition: GUINode.h:64
GUI parent node base class thats supporting child nodes.
Definition: GUIParentNode.h:42
GUI screen node that represents a screen that can be rendered via GUI system.
Definition: GUIScreenNode.h:72
File system singleton class.
Definition: FileSystem.h:17
Standard file system implementation.
static Model * createModel(const string &id, const vector< VHACD::Vertex > &points, const vector< VHACD::Triangle > &triangles)
Create model.
static bool generateConvexMeshes(Prototype *prototype, Mode mode, PopUps *popUps, const string &pathName, const string &fileName, vector< vector< uint8_t >> &convexMeshTMsData, VHACD::IVHACD::Parameters parameters=VHACD::IVHACD::Parameters())
Generateconvex meshes.
Pop ups controller accessor class.
Definition: PopUps.h:29
Console class.
Definition: Console.h:29
Exception base class.
Definition: ExceptionBase.h:19
Model tools functions class.
Definition: ModelTools.h:42
Mutable utf8 aware string class.
Definition: MutableString.h:23
std::exception Exception
Exception base class.
Definition: Exception.h:18