TDME2  1.9.200
SceneReader.cpp
Go to the documentation of this file.
2 
3 #include <memory>
4 #include <string>
5 
6 #include <tdme/tdme.h>
14 #include <tdme/engine/Color4.h>
16 #include <tdme/engine/model/Node.h>
27 #include <tdme/engine/Transform.h>
28 #include <tdme/math/Math.h>
29 #include <tdme/math/Vector3.h>
30 #include <tdme/math/Vector4.h>
34 #include <tdme/utilities/Console.h>
36 #include <tdme/utilities/Float.h>
39 
40 #include <ext/rapidjson/document.h>
41 
42 // this fixes:
43 // error C2039: 'GetObjectA': is not a member of 'rapidjson::GenericValue<rapidjson::UTF8<char>,rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>>'
44 #ifdef GetObject
45  #undef GetObject
46 #endif
47 
48 using std::make_unique;
49 using std::string;
50 using std::to_string;
51 using std::unique_ptr;
52 
75 using tdme::math::Math;
86 
87 using rapidjson::Document;
88 using rapidjson::Value;
89 
90 Scene* SceneReader::read(const string& pathName, const string& fileName, ProgressCallback* progressCallback, PrototypeTransformFilter* prototypeTransformFilter)
91 {
92  return read(pathName, fileName, "", progressCallback, prototypeTransformFilter);
93 }
94 
95 Scene* SceneReader::read(const string& pathName, const string& fileName, const string& objectIdPrefix, ProgressCallback* progressCallback, PrototypeTransformFilter* prototypeTransformFilter)
96 {
97  if (progressCallback != nullptr) progressCallback->progress(0.0f);
98 
99  //
100  auto jsonContent = FileSystem::getInstance()->getContentAsString(pathName, fileName);
101  if (progressCallback != nullptr) progressCallback->progress(0.165f);
102 
103  //
104  Document jRoot;
105  jRoot.Parse(jsonContent.c_str());
106  if (progressCallback != nullptr) progressCallback->progress(0.33f);
107 
108  //
109  auto progressCallbackUniquePtr = unique_ptr<ProgressCallback>(progressCallback);
110  auto scene = make_unique<Scene>(fileName, "");
111  //
112  scene->setApplicationRootPathName(Tools::getApplicationRootPathName(pathName));
113  // auto version = Float::parseFloat((jRoot["version"].GetString()));
114  scene->setRotationOrder(jRoot.FindMember("ro") != jRoot.MemberEnd()?RotationOrder::valueOf(jRoot["ro"].GetString()):RotationOrder::XYZ);
115  for (auto i = 0; i < jRoot["properties"].GetArray().Size(); i++) {
116  const auto& jSceneProperty = jRoot["properties"].GetArray()[i];
117  scene->addProperty(
118  jSceneProperty["name"].GetString(),
119  jSceneProperty["value"].GetString()
120  );
121  }
122  if (jRoot.FindMember("lights") != jRoot.MemberEnd()) {
123  auto lightIdx = 0;
124  auto jLights = jRoot["lights"].GetArray();
125  for (auto i = 0; i < jLights.Size(); i++) {
126  const auto& jLight = jLights[i];
127  if (jLight["e"].GetBool() == false) continue;
128  auto light = lightIdx < scene->getLightCount()?(scene->getLightAt(jLight.FindMember("id") != jLight.MemberEnd()?jLight["id"].GetInt():lightIdx)):scene->addLight();
129  light->setAmbient(
130  Color4(
131  jLight["ar"].GetFloat(),
132  jLight["ag"].GetFloat(),
133  jLight["ab"].GetFloat(),
134  jLight["aa"].GetFloat()
135  )
136  );
137  light->setDiffuse(
138  Color4(
139  jLight["dr"].GetFloat(),
140  jLight["dg"].GetFloat(),
141  jLight["db"].GetFloat(),
142  jLight["da"].GetFloat()
143  )
144  );
145  light->setSpecular(
146  Color4(
147  jLight["sr"].GetFloat(),
148  jLight["sg"].GetFloat(),
149  jLight["sb"].GetFloat(),
150  jLight["sa"].GetFloat()
151  )
152  );
153  light->setPosition(
154  Vector4(
155  jLight["px"].GetFloat(),
156  jLight["py"].GetFloat(),
157  jLight["pz"].GetFloat(),
158  jLight["pw"].GetFloat()
159  )
160  );
161  light->setConstantAttenuation(jLight["ca"].GetFloat());
162  light->setLinearAttenuation(jLight["la"].GetFloat());
163  light->setQuadraticAttenuation(jLight["qa"].GetFloat());
164  light->setSpotDirection(
165  Vector3(
166  jLight["sdx"].GetFloat(),
167  jLight["sdy"].GetFloat(),
168  jLight["sdz"].GetFloat()
169  )
170  );
171  light->setSpotExponent(jLight["se"].GetFloat());
172  light->setSpotCutOff(jLight["sco"].GetFloat());
173  light->setEnabled(jLight["e"].GetBool());
174  lightIdx++;
175  }
176  }
177 
178  auto progressStepCurrent = 0;
179  auto jPrototypes = jRoot["models"].GetArray();
180  for (auto i = 0; i < jPrototypes.Size(); i++) {
181  const auto& jPrototype = jPrototypes[i];
182  unique_ptr<Prototype> prototype;
183  try {
184  auto embedded = jPrototype.FindMember("e") != jPrototype.MemberEnd()?jPrototype["e"].GetBool():true;
185  if (embedded == true) {
186  prototype = unique_ptr<Prototype>(
187  PrototypeReader::read(
188  jPrototype["id"].GetInt(),
189  pathName,
190  jPrototype["entity"],
191  prototypeTransformFilter
192  )
193  );
194  prototype->setEmbedded(true);
195  } else {
196  auto externalPrototypePathName = PrototypeReader::getResourcePathName(pathName, jPrototype["pf"].GetString());
197  auto externalPrototypeFileName = FileSystem::getInstance()->getFileName(jPrototype["pf"].GetString());
198  prototype = unique_ptr<Prototype>(
199  PrototypeReader::read(
200  jPrototype["id"].GetInt(),
201  externalPrototypePathName,
202  externalPrototypeFileName,
203  prototypeTransformFilter
204  )
205  );
206  prototype->setEmbedded(false);
207  }
208  } catch (Exception& exception) {
209  Console::println(string() + "SceneReader::read(): An error occurred: " + exception.what() + ": Using empty prototype");
210  //
211  string prototypeName = "Missing-Prototype-" + to_string(jPrototype["id"].GetInt());
212  //
213  prototype = make_unique<Prototype>(
214  jPrototype["id"].GetInt(),
215  Prototype_Type::EMPTY,
216  prototypeName,
217  string(),
218  prototypeName + ".tempty",
219  "resources/engine/models/empty.tm",
220  string(),
221  ModelReader::read("resources/engine/models", "empty.tm") // TODO: exception
222  );
223  }
224  if (prototype == nullptr) {
225  Console::println("SceneReader::read(): Invalid prototype = " + to_string(jPrototype["id"].GetInt()));
226  continue;
227  }
228  if (jPrototype.FindMember("properties") != jPrototype.MemberEnd()) {
229  for (auto j = 0; j < jPrototype["properties"].GetArray().Size(); j++) {
230  const auto& jPrototypeProperty = jPrototype["properties"].GetArray()[j];
231  prototype->addProperty(
232  jPrototypeProperty["name"].GetString(),
233  jPrototypeProperty["value"].GetString()
234  );
235  }
236  }
237  scene->getLibrary()->addPrototype(prototype.release());
238  //
239  if (progressCallback != nullptr) progressCallback->progress(0.33f + static_cast<float>(progressStepCurrent) / static_cast<float>(jRoot["models"].GetArray().Size()) * 0.33f);
240  progressStepCurrent++;
241  }
242 
243  auto jEntities = jRoot["objects"].GetArray();
244  for (auto i = 0; i < jEntities.Size(); i++) {
245  const auto& jSceneEntity = jEntities[i];
246  auto prototype = scene->getLibrary()->getPrototype(jSceneEntity["mid"].GetInt());
247  if (prototype == nullptr) {
248  Console::println("SceneReader::read(): No prototype found with id = " + to_string(jSceneEntity["mid"].GetInt()));
249 
250  if (progressCallback != nullptr && progressStepCurrent % 1000 == 0) progressCallback->progress(0.66f + static_cast<float>(progressStepCurrent) / static_cast<float>(jRoot["objects"].GetArray().Size()) * 0.33f);
251  progressStepCurrent++;
252 
253  continue;
254  }
255 
256  Transform transform;
257  transform.setTranslation(
258  Vector3(
259  jSceneEntity["tx"].GetFloat(),
260  jSceneEntity["ty"].GetFloat(),
261  jSceneEntity["tz"].GetFloat()
262  )
263  );
264  transform.setScale(
265  Vector3(
266  jSceneEntity["sx"].GetFloat(),
267  jSceneEntity["sy"].GetFloat(),
268  jSceneEntity["sz"].GetFloat()
269  )
270  );
271  Vector3 rotation(
272  jSceneEntity["rx"].GetFloat(),
273  jSceneEntity["ry"].GetFloat(),
274  jSceneEntity["rz"].GetFloat()
275  );
276  transform.addRotation(scene->getRotationOrder()->getAxis0(), rotation.getArray()[scene->getRotationOrder()->getAxis0VectorIndex()]);
277  transform.addRotation(scene->getRotationOrder()->getAxis1(), rotation.getArray()[scene->getRotationOrder()->getAxis1VectorIndex()]);
278  transform.addRotation(scene->getRotationOrder()->getAxis2(), rotation.getArray()[scene->getRotationOrder()->getAxis2VectorIndex()]);
279  transform.update();
280  auto sceneEntity = make_unique<SceneEntity>(
281  objectIdPrefix != "" ?
282  objectIdPrefix + jSceneEntity["id"].GetString() :
283  (jSceneEntity["id"].GetString()),
284  jSceneEntity.FindMember("descr") != jSceneEntity.MemberEnd()?jSceneEntity["descr"].GetString() : "",
285  transform,
286  prototype
287  );
288  if (jSceneEntity.FindMember("properties") != jSceneEntity.MemberEnd()) {
289  auto jSceneEntities = jSceneEntity["properties"].GetArray();
290  for (auto j = 0; j < jSceneEntities.Size(); j++) {
291  const auto& jSceneEntityProperty = jSceneEntity["properties"].GetArray()[j];
292  sceneEntity->addProperty(
293  jSceneEntityProperty["name"].GetString(),
294  jSceneEntityProperty["value"].GetString()
295  );
296  }
297  }
298  sceneEntity->setReflectionEnvironmentMappingId(jSceneEntity.FindMember("r") != jSceneEntity.MemberEnd()?jSceneEntity["r"].GetString():"");
299  scene->addEntity(sceneEntity.release());
300 
301  if (progressCallback != nullptr && progressStepCurrent % 1000 == 0) progressCallback->progress(0.66f + static_cast<float>(progressStepCurrent) / static_cast<float>(jRoot["objects"].GetArray().Size()) * 0.33f);
302  progressStepCurrent++;
303  }
304  scene->setEntityIdx(jRoot["objects_eidx"].GetInt());
305  scene->setFileName((pathName.empty() == false?pathName + "/":"") + fileName);
306  scene->update();
307 
308  // sky shader parameter
309  if (jRoot.FindMember("skyshader") != jRoot.MemberEnd()) {
310  const auto& jSkyShaderParameters = jRoot["skyshader"];
311  EntityShaderParameters skyShaderParameters;
312  skyShaderParameters.setShader("sky");
313  for (auto jShaderParameterIt = jSkyShaderParameters.MemberBegin(); jShaderParameterIt != jSkyShaderParameters.MemberEnd(); ++jShaderParameterIt) {
314  skyShaderParameters.setShaderParameter(jShaderParameterIt->name.GetString(), string(jShaderParameterIt->value.GetString()));
315  }
316  scene->setSkyShaderParameters(skyShaderParameters);
317  }
318 
319  // post processing shaders
320  if (jRoot.FindMember("postprocessingshaders") != jRoot.MemberEnd()) {
321  //
322  const auto& jPostProcessingShaders = jRoot["postprocessingshaders"];
323  //
324  const auto& jEnabledPostProcessingShaders = jPostProcessingShaders["enabled"].GetArray();
325  for (auto i = 0; i < jEnabledPostProcessingShaders.Size(); i++) {
326  scene->enablePostProcessingShader(jEnabledPostProcessingShaders[i].GetString());
327  }
328  //
329  const auto& jAllPostProcessingShaderParameters = jPostProcessingShaders["parameters"].GetObject();
330  for (auto jAllPostProcessingShaderParameterIt = jAllPostProcessingShaderParameters.MemberBegin(); jAllPostProcessingShaderParameterIt != jAllPostProcessingShaderParameters.MemberEnd(); ++jAllPostProcessingShaderParameterIt) {
331  const auto& jShaderId = jAllPostProcessingShaderParameterIt->name.GetString();
332  const auto& jShaderParameters = jAllPostProcessingShaderParameterIt->value.GetObject();
333  //
334  EntityShaderParameters shaderParameters;
335  shaderParameters.setShader(jShaderId);
336  for (auto jShaderParameterIt = jShaderParameters.MemberBegin(); jShaderParameterIt != jShaderParameters.MemberEnd(); ++jShaderParameterIt) {
337  shaderParameters.setShaderParameter(jShaderParameterIt->name.GetString(), string(jShaderParameterIt->value.GetString()));
338  }
339  //
340  scene->setPostProcessingShaderParameters(jShaderId, shaderParameters);
341  }
342  }
343 
344  //
345  if (jRoot.FindMember("gui") != jRoot.MemberEnd()) {
346  auto guiFileName = jRoot["gui"].GetString();
347  auto externalPrototypePathName = PrototypeReader::getResourcePathName(pathName, guiFileName);
348  auto externalPrototypeFileName = FileSystem::getInstance()->getFileName(guiFileName);
349  scene->setGUIFileName(guiFileName);
350  }
351 
352  //
353  if (progressCallback != nullptr) {
354  progressCallback->progress(1.0f);
355  }
356 
357  //
358  return scene.release();
359 }
360 
361 void SceneReader::determineMeshNodes(Scene* scene, Node* node, const string& parentName, const Matrix4x4& parentTransformMatrix, vector<PrototypeMeshNode>& meshNodes) {
362  auto sceneLibrary = scene->getLibrary();
363  auto nodeId = node->getId();
364  if (parentName.length() > 0) nodeId = parentName + "." + nodeId;
365  auto modelName = nodeId;
366  modelName = StringTools::regexReplace(modelName, "[-_]{1}[0-9]+$", "");
367  modelName = StringTools::regexReplace(modelName, "[0-9]+$", "");
368  auto haveName = sceneLibrary->getPrototypeCount() == 0;
369  if (haveName == false) {
370  for (auto i = 0; i < 10000; i++) {
371  haveName = true;
372  auto modelNameTry = modelName;
373  if (i > 0) modelNameTry+= to_string(i);
374  for (auto entity: sceneLibrary->getPrototypes()) {
375  if (entity->getName() == modelNameTry) {
376  haveName = false;
377  break;
378  }
379  }
380  if (haveName == true) {
381  modelName = modelNameTry;
382  break;
383  }
384  }
385  }
386  if (haveName == false) {
387  Console::println(
388  string(
389  "SceneReader::doImportFromModel(): Skipping model '" +
390  modelName +
391  "' as no name could be created for it."
392  )
393  );
394  return;
395  }
396  Matrix4x4 transformMatrix;
397  // compute animation matrix if animation setups exist
398  auto animation = node->getAnimation();
399  if (animation != nullptr) {
400  const auto& animationMatrices = animation->getTransformMatrices();
401  transformMatrix.set(animationMatrices[0 % animationMatrices.size()]);
402  } else {
403  // no animation matrix, set up local transform matrix up as node matrix
404  transformMatrix.set(node->getTransformMatrix());
405  }
406 
407  // apply parent transform matrix
408  transformMatrix.multiply(parentTransformMatrix);
409 
410  // check if no mesh?
411  if (node->getVertices().size() == 0 && node->getSubNodes().size() > 0) {
412  // ok, check sub meshes
413  for (const auto& [subNodeId, subNode]: node->getSubNodes()) {
414  determineMeshNodes(scene, subNode, nodeId, transformMatrix.clone(), meshNodes);
415  }
416  } else {
417  // add to node meshes, even if empty as its a empty :D
418  PrototypeMeshNode prototypeMeshNode;
419  prototypeMeshNode.id = nodeId;
420  prototypeMeshNode.name = modelName;
421  prototypeMeshNode.node = node;
422  prototypeMeshNode.transformMatrix.set(transformMatrix);
423  meshNodes.push_back(prototypeMeshNode);
424  }
425 }
426 
427 Scene* SceneReader::readFromModel(const string& pathName, const string& fileName, ProgressCallback* progressCallback) {
428  // TODO: this method seems to be broken currently, need to check later
429  if (progressCallback != nullptr) progressCallback->progress(0.0f);
430 
431  string modelPathName = pathName + "/" + fileName + "-models";
432  if (FileSystem::getInstance()->exists(modelPathName)) {
433  FileSystem::getInstance()->removePath(modelPathName, true);
434  }
435  FileSystem::getInstance()->createPath(modelPathName);
436 
437  unique_ptr<Model> sceneModel(ModelReader::read(pathName, fileName));
438 
439  if (progressCallback != nullptr) progressCallback->progress(0.1f);
440 
441  auto upVector = sceneModel->getUpVector();
442  RotationOrder* rotationOrder = sceneModel->getRotationOrder();
443 
444  //
445  auto scene = make_unique<Scene>(fileName, "");
446  scene->setRotationOrder(rotationOrder);
447 
448  auto sceneLibrary = scene->getLibrary();
449  auto nodeIdx = 0;
450  Prototype* emptyPrototype = nullptr;
451  Matrix4x4 sceneModelImportRotationMatrix;
452  Vector3 sceneModelScale;
453  sceneModelImportRotationMatrix.set(sceneModel->getImportTransformMatrix());
454  sceneModelImportRotationMatrix.getScale(sceneModelScale);
455  sceneModelImportRotationMatrix.scale(Vector3(1.0f / sceneModelScale.getX(), 1.0f / sceneModelScale.getY(), 1.0f / sceneModelScale.getZ()));
456  auto progressTotal = sceneModel->getSubNodes().size();
457  auto progressIdx = 0;
458  for (const auto& [subNodeId, subNode]: sceneModel->getSubNodes()) {
459  if (progressCallback != nullptr) progressCallback->progress(0.1f + static_cast<float>(progressIdx) / static_cast<float>(progressTotal) * 0.8f);
460  vector<PrototypeMeshNode> meshNodes;
461  determineMeshNodes(scene.get(), subNode, "", (Matrix4x4()).identity(), meshNodes);
462  for (const auto& meshNode: meshNodes) {
463  auto model = make_unique<Model>(
464  meshNode.name + ".tm",
465  fileName + "-" + meshNode.name,
466  upVector,
467  rotationOrder,
468  nullptr
469  );
470  model->setImportTransformMatrix(sceneModel->getImportTransformMatrix());
471  float importFixScale = 1.0f;
472  Vector3 translation, scale;
473  Vector3 xAxis, yAxis, zAxis;
474  Matrix4x4 nodeTransformMatrix;
475  nodeTransformMatrix.set(meshNode.transformMatrix);
476  nodeTransformMatrix.getAxes(xAxis, yAxis, zAxis);
477  nodeTransformMatrix.getTranslation(translation);
478  nodeTransformMatrix.getScale(scale);
479  xAxis.normalize();
480  yAxis.normalize();
481  zAxis.normalize();
482  nodeTransformMatrix.setAxes(xAxis, yAxis, zAxis);
483  if ((upVector == UpVector::Y_UP && Vector3::computeDotProduct(Vector3::computeCrossProduct(xAxis, yAxis), zAxis) < 0.0f) ||
484  (upVector == UpVector::Z_UP && Vector3::computeDotProduct(Vector3::computeCrossProduct(xAxis, zAxis), yAxis) < 0.0f)) {
485  xAxis.scale(-1.0f);
486  yAxis.scale(-1.0f);
487  zAxis.scale(-1.0f);
488  nodeTransformMatrix.setAxes(xAxis, yAxis, zAxis);
489  scale.scale(-1.0f);
490  }
491  auto rotation = nodeTransformMatrix.computeEulerAngles();
492  scale = sceneModelImportRotationMatrix.multiply(scale);
493  rotation = sceneModelImportRotationMatrix.multiply(rotation);
494  translation = model->getImportTransformMatrix().multiply(translation);
495 
496  ModelTools::cloneNode(meshNode.node, model.get());
497  if (model->getSubNodes().begin() != model->getSubNodes().end()) {
498  model->getSubNodes().begin()->second->setTransformMatrix(Matrix4x4().identity());
499  }
500  model->addAnimationSetup(Model::ANIMATIONSETUP_DEFAULT, 0, 0, true);
501  ModelTools::prepareForIndexedRendering(model.get());
502  // scale up model if dimension too less, this occurres with importing FBX that was exported by UE
503  // TODO: maybe make this conditional
504  {
505  auto width = model->getBoundingBox()->getDimensions().getX();
506  auto height = model->getBoundingBox()->getDimensions().getY();
507  auto depth = model->getBoundingBox()->getDimensions().getZ();
508  if (width < 0.2f && height < 0.2f && depth < 0.2f) {
509  if (width > Math::EPSILON && width < height && width < depth) {
510  importFixScale = 1.0f / width / 5.0f;
511  } else
512  if (height > Math::EPSILON && height < width && height < depth) {
513  importFixScale = 1.0f / height / 5.0f;
514  } else
515  if (depth > Math::EPSILON) {
516  importFixScale = 1.0f / depth / 5.0f;
517  }
518  }
519  model->setImportTransformMatrix(model->getImportTransformMatrix().clone().scale(importFixScale));
520  model->getBoundingBox()->getMin().scale(importFixScale);
521  model->getBoundingBox()->getMax().scale(importFixScale);
522  model->getBoundingBox()->update();
523  scale.scale(1.0f / importFixScale);
524  }
525  auto prototypeType = Prototype_Type::MODEL;
526  if (meshNode.node->getVertices().size() == 0) {
527  prototypeType = Prototype_Type::EMPTY;
528  model = nullptr;
529  }
530  Prototype* prototype = nullptr;
531  if (prototypeType == Prototype_Type::MODEL && model != nullptr) {
532  for (auto prototypeCompare: scene->getLibrary()->getPrototypes()) {
533  if (prototypeCompare->getType() != Prototype_Type::MODEL)
534  continue;
535 
536  if (ModelUtilities::equals(model.get(), prototypeCompare->getModel()) == true) {
537  prototype = prototypeCompare;
538  model = nullptr;
539  break;
540  }
541  }
542  if (prototype == nullptr && model != nullptr) {
543  auto modelFileName = meshNode.name + ".tm";
544  try {
545  TMWriter::write(
546  model.get(),
547  modelPathName,
548  modelFileName
549  );
550  } catch (Exception& exception) {
551  throw exception;
552  }
553  auto newPrototype = make_unique<Prototype>(
554  Prototype::ID_NONE,
555  Prototype_Type::MODEL,
556  Tools::removeFileExtension(fileName),
557  Tools::removeFileExtension(fileName),
558  modelPathName + "/" + modelFileName,
559  "resources/engine/models/empty.tm",
560  string(),
561  model.release()
562  );
563  sceneLibrary->addPrototype(newPrototype.get());
564  prototype = newPrototype.release();
565  }
566  } else
567  if (prototypeType == Prototype_Type::EMPTY) {
568  if (emptyPrototype == nullptr) {
569  auto newEmptyPrototype = make_unique<Prototype>(
570  nodeIdx++,
571  Prototype_Type::EMPTY,
572  "Default Empty",
573  "Default Empty",
574  string(),
575  "resources/engine/models/empty.tm",
576  string(),
577  ModelReader::read("resources/engine/models", "empty.tm") // TODO: exception
578  );
579  sceneLibrary->addPrototype(newEmptyPrototype.get());
580  emptyPrototype = newEmptyPrototype.release();
581  }
582  prototype = emptyPrototype;
583  } else {
584  Console::println(string("SceneReader::readFromModel(): unknown entity type. Skipping"));
585  continue;
586  }
587  Transform sceneEntityTransform;
588  sceneEntityTransform.setTranslation(translation);
589  sceneEntityTransform.addRotation(rotationOrder->getAxis0(), rotation.getArray()[rotationOrder->getAxis0VectorIndex()]);
590  sceneEntityTransform.addRotation(rotationOrder->getAxis1(), rotation.getArray()[rotationOrder->getAxis1VectorIndex()]);
591  sceneEntityTransform.addRotation(rotationOrder->getAxis2(), rotation.getArray()[rotationOrder->getAxis2VectorIndex()]);
592  sceneEntityTransform.setScale(scale);
593  sceneEntityTransform.update();
594  auto sceneEntity = make_unique<SceneEntity>(
595  meshNode.id,
596  meshNode.id,
597  sceneEntityTransform,
598  prototype
599  );
600  scene->addEntity(sceneEntity.release());
601  }
602  //
603  progressIdx++;
604  }
605 
606  if (progressCallback != nullptr) progressCallback->progress(0.9f);
607 
608  try {
609  // export to tscene
611  pathName,
612  Tools::removeFileExtension(fileName) + ".tscene",
613  scene.get()
614  );
615  } catch (Exception& exception) {
616  Console::println("SceneReader::readFromModel(): An error occurred: " + string(exception.what()));
617  throw exception;
618  }
619 
620  //
621  if (progressCallback != nullptr) progressCallback->progress(1.0f);
622 
623  //
624  return scene.release();
625 }
Color 4 definition class.
Definition: Color4.h:18
TDME2 engine entity shader parameters.
void setShaderParameter(const string &parameterName, const ShaderParameter &parameterValue)
Set shader parameter for given parameter name.
void setShader(const string &shaderId)
Set shader.
Transform which contain scale, rotations and translation.
Definition: Transform.h:29
void setTranslation(const Vector3 &translation)
Set translation.
Definition: Transform.h:64
void setScale(const Vector3 &scale)
Set scale.
Definition: Transform.h:79
virtual void update()
Computes transform matrix.
Definition: Transform.cpp:33
void addRotation(const Vector3 &axis, const float angle)
Add rotation.
Definition: Transform.h:113
static Scene * read(const string &pathName, const string &fileName, ProgressCallback *progressCallback=nullptr, PrototypeTransformFilter *prototypeTransformFilter=nullptr)
Reads a scene.
Definition: SceneReader.cpp:90
static Scene * readFromModel(const string &pathName, const string &fileName, ProgressCallback *progressCallback=nullptr)
Reads a scene.
static void determineMeshNodes(Scene *scene, Node *node, const string &parentName, const Matrix4x4 &parentTransformMatrix, vector< PrototypeMeshNode > &meshNodes)
Determine mesh nodes in node hierarchy.
static void write(const string &pathName, const string &fileName, Scene *scene)
Writes a scene.
Definition: SceneWriter.cpp:59
const vector< Matrix4x4 > & getTransformMatrices() const
Returns transform matrices.
Definition: Animation.h:43
Representation of a 3D model.
Definition: Model.h:35
Model node.
Definition: Node.h:32
unordered_map< string, Node * > & getSubNodes()
Definition: Node.h:293
Animation * getAnimation()
Definition: Node.h:229
const vector< Vector3 > & getVertices() const
Definition: Node.h:155
const string & getId()
Returns id.
Definition: Node.h:89
const Matrix4x4 & getTransformMatrix() const
Definition: Node.h:125
Represents rotation orders of a model.
Definition: RotationOrder.h:23
const Vector3 & getAxis1() const
Definition: RotationOrder.h:67
const Vector3 & getAxis0() const
Definition: RotationOrder.h:60
const Vector3 & getAxis2() const
Definition: RotationOrder.h:74
Model up vector.
Definition: UpVector.h:20
Prototype definition.
Definition: Prototype.h:55
Scene entity definition.
Definition: SceneEntity.h:23
Scene prototype library definition.
Definition: SceneLibrary.h:32
Scene light definition.
Definition: SceneLight.h:20
Scene definition.
Definition: Scene.h:50
SceneLibrary * getLibrary()
Definition: Scene.h:185
static bool equals(Model *model1, Model *model2)
Compute if model 1 equals model 2.
Standard math functions.
Definition: Math.h:19
Matrix4x4 class representing matrix4x4 mathematical structure and operations for 3d space.
Definition: Matrix4x4.h:23
Matrix4x4 clone() const
Clones this matrix.
Definition: Matrix4x4.h:619
Matrix4x4 & scale(float scalar)
Scales by scalar.
Definition: Matrix4x4.h:183
Vector3 multiply(const Vector3 &vector3) const
Multiplies this matrix with vector3.
Definition: Matrix4x4.h:225
void getAxes(Vector3 &xAxis, Vector3 &yAxis, Vector3 &zAxis) const
Get coordinate system axes.
Definition: Matrix4x4.h:321
Matrix4x4 & set(float r0c0, float r0c1, float r0c2, float r0c3, float r1c0, float r1c1, float r1c2, float r1c3, float r2c0, float r2c1, float r2c2, float r2c3, float r3c0, float r3c1, float r3c2, float r3c3)
Sets this matrix by its components.
Definition: Matrix4x4.h:108
Vector3 computeEulerAngles() const
Compute Euler angles (rotation around x, y, z axes)
Definition: Matrix4x4.h:531
void getScale(Vector3 &scale) const
Get scale.
Definition: Matrix4x4.h:388
void getTranslation(Vector3 &translation) const
Get translation.
Definition: Matrix4x4.h:433
Matrix4x4 & setAxes(const Vector3 &xAxis, const Vector3 &yAxis, const Vector3 &zAxis)
Set coordinate system axes.
Definition: Matrix4x4.h:334
Vector3 class representing vector3 mathematical structure and operations with x, y,...
Definition: Vector3.h:20
float getY() const
Definition: Vector3.h:117
float getX() const
Definition: Vector3.h:100
float getZ() const
Definition: Vector3.h:134
const array< float, 3 > & getArray() const
Definition: Vector3.h:366
Vector3 & scale(float scalar)
Scales by scalar.
Definition: Vector3.h:201
Vector3 & normalize()
Normalizes this vector3.
Definition: Vector3.h:239
Vector4 class representing vector4 mathematical structure and operations with x, y,...
Definition: Vector4.h:22
File system singleton class.
Definition: FileSystem.h:17
Console class.
Definition: Console.h:29
Float class.
Definition: Float.h:27
Model tools functions class.
Definition: ModelTools.h:42
String tools class.
Definition: StringTools.h:22
std::exception Exception
Exception base class.
Definition: Exception.h:18
virtual void progress(float value)=0
Perform action.