X3DImporter_Postprocess.cpp 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773
  1. /// \file X3DImporter_Postprocess.cpp
  2. /// \brief Convert built scenegraph and objects to Assimp scenegraph.
  3. /// \date 2015-2016
  4. /// \author [email protected]
  5. #ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
  6. #include "X3DImporter.hpp"
  7. // Header files, Assimp.
  8. #include "StandardShapes.h"
  9. // Header files, stdlib.
  10. #include <algorithm>
  11. #include <iterator>
  12. #include <string>
  13. namespace Assimp
  14. {
  15. aiMatrix4x4 X3DImporter::PostprocessHelper_Matrix_GlobalToCurrent() const
  16. {
  17. CX3DImporter_NodeElement* cur_node;
  18. std::list<aiMatrix4x4> matr;
  19. aiMatrix4x4 out_matr;
  20. // starting walk from current element to root
  21. cur_node = NodeElement_Cur;
  22. if(cur_node != nullptr)
  23. {
  24. do
  25. {
  26. // if cur_node is group then store group transformation matrix in list.
  27. if(cur_node->Type == CX3DImporter_NodeElement::ENET_Group) matr.push_back(((CX3DImporter_NodeElement_Group*)cur_node)->Transformation);
  28. cur_node = cur_node->Parent;
  29. } while(cur_node != nullptr);
  30. }
  31. // multiplicate all matrices in reverse order
  32. for(std::list<aiMatrix4x4>::reverse_iterator rit = matr.rbegin(); rit != matr.rend(); rit++) out_matr = out_matr * (*rit);
  33. return out_matr;
  34. }
  35. void X3DImporter::PostprocessHelper_CollectMetadata(const CX3DImporter_NodeElement& pNodeElement, std::list<CX3DImporter_NodeElement*>& pList) const
  36. {
  37. // walk thru childs and find for metadata.
  38. for(std::list<CX3DImporter_NodeElement*>::const_iterator el_it = pNodeElement.Child.begin(); el_it != pNodeElement.Child.end(); el_it++)
  39. {
  40. if(((*el_it)->Type == CX3DImporter_NodeElement::ENET_MetaBoolean) || ((*el_it)->Type == CX3DImporter_NodeElement::ENET_MetaDouble) ||
  41. ((*el_it)->Type == CX3DImporter_NodeElement::ENET_MetaFloat) || ((*el_it)->Type == CX3DImporter_NodeElement::ENET_MetaInteger) ||
  42. ((*el_it)->Type == CX3DImporter_NodeElement::ENET_MetaString))
  43. {
  44. pList.push_back(*el_it);
  45. }
  46. else if((*el_it)->Type == CX3DImporter_NodeElement::ENET_MetaSet)
  47. {
  48. PostprocessHelper_CollectMetadata(**el_it, pList);
  49. }
  50. }// for(std::list<CX3DImporter_NodeElement*>::const_iterator el_it = pNodeElement.Child.begin(); el_it != pNodeElement.Child.end(); el_it++)
  51. }
  52. bool X3DImporter::PostprocessHelper_ElementIsMetadata(const CX3DImporter_NodeElement::EType pType) const
  53. {
  54. if((pType == CX3DImporter_NodeElement::ENET_MetaBoolean) || (pType == CX3DImporter_NodeElement::ENET_MetaDouble) ||
  55. (pType == CX3DImporter_NodeElement::ENET_MetaFloat) || (pType == CX3DImporter_NodeElement::ENET_MetaInteger) ||
  56. (pType == CX3DImporter_NodeElement::ENET_MetaString) || (pType == CX3DImporter_NodeElement::ENET_MetaSet))
  57. {
  58. return true;
  59. }
  60. else
  61. {
  62. return false;
  63. }
  64. }
  65. bool X3DImporter::PostprocessHelper_ElementIsMesh(const CX3DImporter_NodeElement::EType pType) const
  66. {
  67. if((pType == CX3DImporter_NodeElement::ENET_Arc2D) || (pType == CX3DImporter_NodeElement::ENET_ArcClose2D) ||
  68. (pType == CX3DImporter_NodeElement::ENET_Box) || (pType == CX3DImporter_NodeElement::ENET_Circle2D) ||
  69. (pType == CX3DImporter_NodeElement::ENET_Cone) || (pType == CX3DImporter_NodeElement::ENET_Cylinder) ||
  70. (pType == CX3DImporter_NodeElement::ENET_Disk2D) || (pType == CX3DImporter_NodeElement::ENET_ElevationGrid) ||
  71. (pType == CX3DImporter_NodeElement::ENET_Extrusion) || (pType == CX3DImporter_NodeElement::ENET_IndexedFaceSet) ||
  72. (pType == CX3DImporter_NodeElement::ENET_IndexedLineSet) || (pType == CX3DImporter_NodeElement::ENET_IndexedTriangleFanSet) ||
  73. (pType == CX3DImporter_NodeElement::ENET_IndexedTriangleSet) || (pType == CX3DImporter_NodeElement::ENET_IndexedTriangleStripSet) ||
  74. (pType == CX3DImporter_NodeElement::ENET_PointSet) || (pType == CX3DImporter_NodeElement::ENET_LineSet) ||
  75. (pType == CX3DImporter_NodeElement::ENET_Polyline2D) || (pType == CX3DImporter_NodeElement::ENET_Polypoint2D) ||
  76. (pType == CX3DImporter_NodeElement::ENET_Rectangle2D) || (pType == CX3DImporter_NodeElement::ENET_Sphere) ||
  77. (pType == CX3DImporter_NodeElement::ENET_TriangleFanSet) || (pType == CX3DImporter_NodeElement::ENET_TriangleSet) ||
  78. (pType == CX3DImporter_NodeElement::ENET_TriangleSet2D) || (pType == CX3DImporter_NodeElement::ENET_TriangleStripSet))
  79. {
  80. return true;
  81. }
  82. else
  83. {
  84. return false;
  85. }
  86. }
  87. void X3DImporter::Postprocess_BuildLight(const CX3DImporter_NodeElement& pNodeElement, std::list<aiLight*>& pSceneLightList) const
  88. {
  89. const CX3DImporter_NodeElement_Light& ne = *((CX3DImporter_NodeElement_Light*)&pNodeElement);
  90. aiMatrix4x4 transform_matr = PostprocessHelper_Matrix_GlobalToCurrent();
  91. aiLight* new_light = new aiLight;
  92. new_light->mName = ne.ID;
  93. new_light->mColorAmbient = ne.Color * ne.AmbientIntensity;
  94. new_light->mColorDiffuse = ne.Color * ne.Intensity;
  95. new_light->mColorSpecular = ne.Color * ne.Intensity;
  96. switch(pNodeElement.Type)
  97. {
  98. case CX3DImporter_NodeElement::ENET_DirectionalLight:
  99. new_light->mType = aiLightSource_DIRECTIONAL;
  100. new_light->mDirection = ne.Direction, new_light->mDirection *= transform_matr;
  101. break;
  102. case CX3DImporter_NodeElement::ENET_PointLight:
  103. new_light->mType = aiLightSource_POINT;
  104. new_light->mPosition = ne.Location, new_light->mPosition *= transform_matr;
  105. new_light->mAttenuationConstant = ne.Attenuation.x;
  106. new_light->mAttenuationLinear = ne.Attenuation.y;
  107. new_light->mAttenuationQuadratic = ne.Attenuation.z;
  108. break;
  109. case CX3DImporter_NodeElement::ENET_SpotLight:
  110. new_light->mType = aiLightSource_SPOT;
  111. new_light->mPosition = ne.Location, new_light->mPosition *= transform_matr;
  112. new_light->mDirection = ne.Direction, new_light->mDirection *= transform_matr;
  113. new_light->mAttenuationConstant = ne.Attenuation.x;
  114. new_light->mAttenuationLinear = ne.Attenuation.y;
  115. new_light->mAttenuationQuadratic = ne.Attenuation.z;
  116. new_light->mAngleInnerCone = ne.BeamWidth;
  117. new_light->mAngleOuterCone = ne.CutOffAngle;
  118. break;
  119. default:
  120. throw DeadlyImportError("Postprocess_BuildLight. Unknown type of light: " + std::to_string(pNodeElement.Type) + ".");
  121. }
  122. pSceneLightList.push_back(new_light);
  123. }
  124. void X3DImporter::Postprocess_BuildMaterial(const CX3DImporter_NodeElement& pNodeElement, aiMaterial** pMaterial) const
  125. {
  126. // check argument
  127. if(pMaterial == nullptr) throw DeadlyImportError("Postprocess_BuildMaterial. pMaterial is nullptr.");
  128. if(*pMaterial != nullptr) throw DeadlyImportError("Postprocess_BuildMaterial. *pMaterial must be nullptr.");
  129. *pMaterial = new aiMaterial;
  130. aiMaterial& taimat = **pMaterial;// creating alias for convenience.
  131. // at this point pNodeElement point to <Appearance> node. Walk thru childs and add all stored data.
  132. for(std::list<CX3DImporter_NodeElement*>::const_iterator el_it = pNodeElement.Child.begin(); el_it != pNodeElement.Child.end(); el_it++)
  133. {
  134. if((*el_it)->Type == CX3DImporter_NodeElement::ENET_Material)
  135. {
  136. aiColor3D tcol3;
  137. float tvalf;
  138. CX3DImporter_NodeElement_Material& tnemat = *((CX3DImporter_NodeElement_Material*)*el_it);
  139. tcol3.r = tnemat.AmbientIntensity, tcol3.g = tnemat.AmbientIntensity, tcol3.b = tnemat.AmbientIntensity;
  140. taimat.AddProperty(&tcol3, 1, AI_MATKEY_COLOR_AMBIENT);
  141. taimat.AddProperty(&tnemat.DiffuseColor, 1, AI_MATKEY_COLOR_DIFFUSE);
  142. taimat.AddProperty(&tnemat.EmissiveColor, 1, AI_MATKEY_COLOR_EMISSIVE);
  143. taimat.AddProperty(&tnemat.SpecularColor, 1, AI_MATKEY_COLOR_SPECULAR);
  144. tvalf = 1;
  145. taimat.AddProperty(&tvalf, 1, AI_MATKEY_SHININESS_STRENGTH);
  146. taimat.AddProperty(&tnemat.Shininess, 1, AI_MATKEY_SHININESS);
  147. tvalf = 1.0f - tnemat.Transparency;
  148. taimat.AddProperty(&tvalf, 1, AI_MATKEY_OPACITY);
  149. }// if((*el_it)->Type == CX3DImporter_NodeElement::ENET_Material)
  150. else if((*el_it)->Type == CX3DImporter_NodeElement::ENET_ImageTexture)
  151. {
  152. CX3DImporter_NodeElement_ImageTexture& tnetex = *((CX3DImporter_NodeElement_ImageTexture*)*el_it);
  153. aiString url_str(tnetex.URL.c_str());
  154. int mode = aiTextureOp_Multiply;
  155. taimat.AddProperty(&url_str, AI_MATKEY_TEXTURE_DIFFUSE(0));
  156. taimat.AddProperty(&tnetex.RepeatS, 1, AI_MATKEY_MAPPINGMODE_U_DIFFUSE(0));
  157. taimat.AddProperty(&tnetex.RepeatT, 1, AI_MATKEY_MAPPINGMODE_V_DIFFUSE(0));
  158. taimat.AddProperty(&mode, 1, AI_MATKEY_TEXOP_DIFFUSE(0));
  159. }// else if((*el_it)->Type == CX3DImporter_NodeElement::ENET_ImageTexture)
  160. else if((*el_it)->Type == CX3DImporter_NodeElement::ENET_TextureTransform)
  161. {
  162. aiUVTransform trans;
  163. CX3DImporter_NodeElement_TextureTransform& tnetextr = *((CX3DImporter_NodeElement_TextureTransform*)*el_it);
  164. trans.mTranslation = tnetextr.Translation - tnetextr.Center;
  165. trans.mScaling = tnetextr.Scale;
  166. trans.mRotation = tnetextr.Rotation;
  167. taimat.AddProperty(&trans, 1, AI_MATKEY_UVTRANSFORM_DIFFUSE(0));
  168. }// else if((*el_it)->Type == CX3DImporter_NodeElement::ENET_TextureTransform)
  169. }// for(std::list<CX3DImporter_NodeElement*>::const_iterator el_it = pNodeElement.Child.begin(); el_it != pNodeElement.Child.end(); el_it++)
  170. }
  171. void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeElement, aiMesh** pMesh) const
  172. {
  173. // check argument
  174. if(pMesh == nullptr) throw DeadlyImportError("Postprocess_BuildMesh. pMesh is nullptr.");
  175. if(*pMesh != nullptr) throw DeadlyImportError("Postprocess_BuildMesh. *pMesh must be nullptr.");
  176. /************************************************************************************************************************************/
  177. /************************************************************ Geometry2D ************************************************************/
  178. /************************************************************************************************************************************/
  179. if((pNodeElement.Type == CX3DImporter_NodeElement::ENET_Arc2D) || (pNodeElement.Type == CX3DImporter_NodeElement::ENET_ArcClose2D) ||
  180. (pNodeElement.Type == CX3DImporter_NodeElement::ENET_Circle2D) || (pNodeElement.Type == CX3DImporter_NodeElement::ENET_Disk2D) ||
  181. (pNodeElement.Type == CX3DImporter_NodeElement::ENET_Polyline2D) || (pNodeElement.Type == CX3DImporter_NodeElement::ENET_Polypoint2D) ||
  182. (pNodeElement.Type == CX3DImporter_NodeElement::ENET_Rectangle2D) || (pNodeElement.Type == CX3DImporter_NodeElement::ENET_TriangleSet2D))
  183. {
  184. CX3DImporter_NodeElement_Geometry2D& tnemesh = *((CX3DImporter_NodeElement_Geometry2D*)&pNodeElement);// create alias for convenience
  185. std::vector<aiVector3D> tarr;
  186. tarr.reserve(tnemesh.Vertices.size());
  187. for(std::list<aiVector3D>::iterator it = tnemesh.Vertices.begin(); it != tnemesh.Vertices.end(); it++) tarr.push_back(*it);
  188. *pMesh = StandardShapes::MakeMesh(tarr, tnemesh.NumIndices);// create mesh from vertices using Assimp help.
  189. return;// mesh is build, nothing to do anymore.
  190. }
  191. /************************************************************************************************************************************/
  192. /************************************************************ Geometry3D ************************************************************/
  193. /************************************************************************************************************************************/
  194. //
  195. // Predefined figures
  196. //
  197. if((pNodeElement.Type == CX3DImporter_NodeElement::ENET_Box) || (pNodeElement.Type == CX3DImporter_NodeElement::ENET_Cone) ||
  198. (pNodeElement.Type == CX3DImporter_NodeElement::ENET_Cylinder) || (pNodeElement.Type == CX3DImporter_NodeElement::ENET_Sphere))
  199. {
  200. CX3DImporter_NodeElement_Geometry3D& tnemesh = *((CX3DImporter_NodeElement_Geometry3D*)&pNodeElement);// create alias for convenience
  201. std::vector<aiVector3D> tarr;
  202. tarr.reserve(tnemesh.Vertices.size());
  203. for(std::list<aiVector3D>::iterator it = tnemesh.Vertices.begin(); it != tnemesh.Vertices.end(); it++) tarr.push_back(*it);
  204. *pMesh = StandardShapes::MakeMesh(tarr, tnemesh.NumIndices);// create mesh from vertices using Assimp help.
  205. return;// mesh is build, nothing to do anymore.
  206. }
  207. //
  208. // Parametric figures
  209. //
  210. if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_ElevationGrid)
  211. {
  212. CX3DImporter_NodeElement_ElevationGrid& tnemesh = *((CX3DImporter_NodeElement_ElevationGrid*)&pNodeElement);// create alias for convenience
  213. // at first create mesh from existing vertices.
  214. *pMesh = GeometryHelper_MakeMesh(tnemesh.CoordIdx, tnemesh.Vertices);
  215. // copy additional information from children
  216. for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
  217. {
  218. if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color)
  219. MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, tnemesh.ColorPerVertex);
  220. else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA)
  221. MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_ColorRGBA*)*ch_it)->Value, tnemesh.ColorPerVertex);
  222. else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Normal)
  223. MeshGeometry_AddNormal(**pMesh, ((CX3DImporter_NodeElement_Normal*)*ch_it)->Value, tnemesh.NormalPerVertex);
  224. else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_TextureCoordinate)
  225. MeshGeometry_AddTexCoord(**pMesh, ((CX3DImporter_NodeElement_TextureCoordinate*)*ch_it)->Value);
  226. else
  227. throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of ElevationGrid: " + std::to_string((*ch_it)->Type) + ".");
  228. }// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
  229. return;// mesh is build, nothing to do anymore.
  230. }// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_ElevationGrid)
  231. //
  232. // Indexed primitives sets
  233. //
  234. if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_IndexedFaceSet)
  235. {
  236. CX3DImporter_NodeElement_IndexedSet& tnemesh = *((CX3DImporter_NodeElement_IndexedSet*)&pNodeElement);// create alias for convenience
  237. // at first search for <Coordinate> node and create mesh.
  238. for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
  239. {
  240. if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
  241. {
  242. *pMesh = GeometryHelper_MakeMesh(tnemesh.CoordIndex, ((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value);
  243. }
  244. }
  245. // copy additional information from children
  246. for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
  247. {
  248. if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color)
  249. MeshGeometry_AddColor(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, tnemesh.ColorPerVertex);
  250. else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA)
  251. MeshGeometry_AddColor(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((CX3DImporter_NodeElement_ColorRGBA*)*ch_it)->Value,
  252. tnemesh.ColorPerVertex);
  253. else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
  254. {} // skip because already read when mesh created.
  255. else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Normal)
  256. MeshGeometry_AddNormal(**pMesh, tnemesh.CoordIndex, tnemesh.NormalIndex, ((CX3DImporter_NodeElement_Normal*)*ch_it)->Value,
  257. tnemesh.NormalPerVertex);
  258. else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_TextureCoordinate)
  259. MeshGeometry_AddTexCoord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((CX3DImporter_NodeElement_TextureCoordinate*)*ch_it)->Value);
  260. else
  261. throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of IndexedFaceSet: " + std::to_string((*ch_it)->Type) + ".");
  262. }// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
  263. return;// mesh is build, nothing to do anymore.
  264. }// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_IndexedFaceSet)
  265. if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_IndexedLineSet)
  266. {
  267. CX3DImporter_NodeElement_IndexedSet& tnemesh = *((CX3DImporter_NodeElement_IndexedSet*)&pNodeElement);// create alias for convenience
  268. // at first search for <Coordinate> node and create mesh.
  269. for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
  270. {
  271. if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
  272. {
  273. *pMesh = GeometryHelper_MakeMesh(tnemesh.CoordIndex, ((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value);
  274. }
  275. }
  276. // copy additional information from children
  277. for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
  278. {
  279. if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color)
  280. MeshGeometry_AddColor(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, tnemesh.ColorPerVertex);
  281. else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA)
  282. MeshGeometry_AddColor(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((CX3DImporter_NodeElement_ColorRGBA*)*ch_it)->Value,
  283. tnemesh.ColorPerVertex);
  284. else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
  285. {} // skip because already read when mesh created.
  286. else
  287. throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of IndexedLineSet: " + std::to_string((*ch_it)->Type) + ".");
  288. }// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
  289. return;// mesh is build, nothing to do anymore.
  290. }// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_IndexedLineSet)
  291. if((pNodeElement.Type == CX3DImporter_NodeElement::ENET_IndexedTriangleSet) ||
  292. (pNodeElement.Type == CX3DImporter_NodeElement::ENET_IndexedTriangleFanSet) ||
  293. (pNodeElement.Type == CX3DImporter_NodeElement::ENET_IndexedTriangleStripSet))
  294. {
  295. CX3DImporter_NodeElement_IndexedSet& tnemesh = *((CX3DImporter_NodeElement_IndexedSet*)&pNodeElement);// create alias for convenience
  296. // at first search for <Coordinate> node and create mesh.
  297. for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
  298. {
  299. if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
  300. {
  301. *pMesh = GeometryHelper_MakeMesh(tnemesh.CoordIndex, ((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value);
  302. }
  303. }
  304. // copy additional information from children
  305. for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
  306. {
  307. if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color)
  308. MeshGeometry_AddColor(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, tnemesh.ColorPerVertex);
  309. else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA)
  310. MeshGeometry_AddColor(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((CX3DImporter_NodeElement_ColorRGBA*)*ch_it)->Value,
  311. tnemesh.ColorPerVertex);
  312. else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
  313. {} // skip because already read when mesh created.
  314. else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Normal)
  315. MeshGeometry_AddNormal(**pMesh, tnemesh.CoordIndex, tnemesh.NormalIndex, ((CX3DImporter_NodeElement_Normal*)*ch_it)->Value,
  316. tnemesh.NormalPerVertex);
  317. else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_TextureCoordinate)
  318. MeshGeometry_AddTexCoord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((CX3DImporter_NodeElement_TextureCoordinate*)*ch_it)->Value);
  319. else
  320. throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of IndexedTriangleSet or IndexedTriangleFanSet, or \
  321. IndexedTriangleStripSet: " + std::to_string((*ch_it)->Type) + ".");
  322. }// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
  323. return;// mesh is build, nothing to do anymore.
  324. }// if((pNodeElement.Type == CX3DImporter_NodeElement::ENET_IndexedTriangleFanSet) || (pNodeElement.Type == CX3DImporter_NodeElement::ENET_IndexedTriangleStripSet))
  325. if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_Extrusion)
  326. {
  327. CX3DImporter_NodeElement_IndexedSet& tnemesh = *((CX3DImporter_NodeElement_IndexedSet*)&pNodeElement);// create alias for convenience
  328. *pMesh = GeometryHelper_MakeMesh(tnemesh.CoordIndex, tnemesh.Vertices);
  329. return;// mesh is build, nothing to do anymore.
  330. }// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_Extrusion)
  331. //
  332. // Primitives sets
  333. //
  334. if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_PointSet)
  335. {
  336. CX3DImporter_NodeElement_Set& tnemesh = *((CX3DImporter_NodeElement_Set*)&pNodeElement);// create alias for convenience
  337. // at first search for <Coordinate> node and create mesh.
  338. for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
  339. {
  340. if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
  341. {
  342. std::vector<aiVector3D> vec_copy;
  343. vec_copy.reserve(((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value.size());
  344. for(std::list<aiVector3D>::const_iterator it = ((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value.begin();
  345. it != ((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value.end(); it++)
  346. {
  347. vec_copy.push_back(*it);
  348. }
  349. *pMesh = StandardShapes::MakeMesh(vec_copy, 1);
  350. }
  351. }
  352. // copy additional information from children
  353. for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
  354. {
  355. if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color)
  356. MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, true);
  357. else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA)
  358. MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_ColorRGBA*)*ch_it)->Value, true);
  359. else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
  360. {} // skip because already read when mesh created.
  361. else
  362. throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of PointSet: " + std::to_string((*ch_it)->Type) + ".");
  363. }// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
  364. return;// mesh is build, nothing to do anymore.
  365. }// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_PointSet)
  366. if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_LineSet)
  367. {
  368. CX3DImporter_NodeElement_Set& tnemesh = *((CX3DImporter_NodeElement_Set*)&pNodeElement);// create alias for convenience
  369. // at first search for <Coordinate> node and create mesh.
  370. for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
  371. {
  372. if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
  373. {
  374. *pMesh = GeometryHelper_MakeMesh(tnemesh.CoordIndex, ((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value);
  375. }
  376. }
  377. // copy additional information from children
  378. for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
  379. {
  380. if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color)
  381. MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, true);
  382. else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA)
  383. MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_ColorRGBA*)*ch_it)->Value, true);
  384. else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
  385. {} // skip because already read when mesh created.
  386. else
  387. throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of LineSet: " + std::to_string((*ch_it)->Type) + ".");
  388. }// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
  389. return;// mesh is build, nothing to do anymore.
  390. }// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_LineSet)
  391. if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_TriangleFanSet)
  392. {
  393. CX3DImporter_NodeElement_Set& tnemesh = *((CX3DImporter_NodeElement_Set*)&pNodeElement);// create alias for convenience
  394. // at first search for <Coordinate> node and create mesh.
  395. for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
  396. {
  397. if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
  398. {
  399. *pMesh = GeometryHelper_MakeMesh(tnemesh.CoordIndex, ((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value);
  400. }
  401. }
  402. // copy additional information from children
  403. for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
  404. {
  405. if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color)
  406. MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value,tnemesh.ColorPerVertex);
  407. else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA)
  408. MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_ColorRGBA*)*ch_it)->Value, tnemesh.ColorPerVertex);
  409. else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
  410. {} // skip because already read when mesh created.
  411. else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Normal)
  412. MeshGeometry_AddNormal(**pMesh, tnemesh.CoordIndex, tnemesh.NormalIndex, ((CX3DImporter_NodeElement_Normal*)*ch_it)->Value,
  413. tnemesh.NormalPerVertex);
  414. else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_TextureCoordinate)
  415. MeshGeometry_AddTexCoord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((CX3DImporter_NodeElement_TextureCoordinate*)*ch_it)->Value);
  416. else
  417. throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of TrianlgeFanSet: " + std::to_string((*ch_it)->Type) + ".");
  418. }// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
  419. return;// mesh is build, nothing to do anymore.
  420. }// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_TriangleFanSet)
  421. if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_TriangleSet)
  422. {
  423. CX3DImporter_NodeElement_Set& tnemesh = *((CX3DImporter_NodeElement_Set*)&pNodeElement);// create alias for convenience
  424. // at first search for <Coordinate> node and create mesh.
  425. for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
  426. {
  427. if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
  428. {
  429. std::vector<aiVector3D> vec_copy;
  430. vec_copy.reserve(((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value.size());
  431. for(std::list<aiVector3D>::const_iterator it = ((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value.begin();
  432. it != ((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value.end(); it++)
  433. {
  434. vec_copy.push_back(*it);
  435. }
  436. *pMesh = StandardShapes::MakeMesh(vec_copy, 3);
  437. }
  438. }
  439. // copy additional information from children
  440. for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
  441. {
  442. if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color)
  443. MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, tnemesh.ColorPerVertex);
  444. else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA)
  445. MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_ColorRGBA*)*ch_it)->Value, tnemesh.ColorPerVertex);
  446. else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
  447. {} // skip because already read when mesh created.
  448. else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Normal)
  449. MeshGeometry_AddNormal(**pMesh, tnemesh.CoordIndex, tnemesh.NormalIndex, ((CX3DImporter_NodeElement_Normal*)*ch_it)->Value,
  450. tnemesh.NormalPerVertex);
  451. else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_TextureCoordinate)
  452. MeshGeometry_AddTexCoord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((CX3DImporter_NodeElement_TextureCoordinate*)*ch_it)->Value);
  453. else
  454. throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of TrianlgeSet: " + std::to_string((*ch_it)->Type) + ".");
  455. }// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
  456. return;// mesh is build, nothing to do anymore.
  457. }// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_TriangleSet)
  458. if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_TriangleStripSet)
  459. {
  460. CX3DImporter_NodeElement_Set& tnemesh = *((CX3DImporter_NodeElement_Set*)&pNodeElement);// create alias for convenience
  461. // at first search for <Coordinate> node and create mesh.
  462. for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
  463. {
  464. if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
  465. {
  466. *pMesh = GeometryHelper_MakeMesh(tnemesh.CoordIndex, ((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value);
  467. }
  468. }
  469. // copy additional information from children
  470. for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
  471. {
  472. if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color)
  473. MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, tnemesh.ColorPerVertex);
  474. else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA)
  475. MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_ColorRGBA*)*ch_it)->Value, tnemesh.ColorPerVertex);
  476. else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
  477. {} // skip because already read when mesh created.
  478. else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Normal)
  479. MeshGeometry_AddNormal(**pMesh, tnemesh.CoordIndex, tnemesh.NormalIndex, ((CX3DImporter_NodeElement_Normal*)*ch_it)->Value,
  480. tnemesh.NormalPerVertex);
  481. else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_TextureCoordinate)
  482. MeshGeometry_AddTexCoord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((CX3DImporter_NodeElement_TextureCoordinate*)*ch_it)->Value);
  483. else
  484. throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of TriangleStripSet: " + std::to_string((*ch_it)->Type) + ".");
  485. }// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
  486. return;// mesh is build, nothing to do anymore.
  487. }// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_TriangleStripSet)
  488. throw DeadlyImportError("Postprocess_BuildMesh. Unknown mesh type: " + std::to_string(pNodeElement.Type) + ".");
  489. }
  490. void X3DImporter::Postprocess_BuildNode(const CX3DImporter_NodeElement& pNodeElement, aiNode& pSceneNode, std::list<aiMesh*>& pSceneMeshList,
  491. std::list<aiMaterial*>& pSceneMaterialList, std::list<aiLight*>& pSceneLightList) const
  492. {
  493. std::list<CX3DImporter_NodeElement*>::const_iterator chit_begin = pNodeElement.Child.begin();
  494. std::list<CX3DImporter_NodeElement*>::const_iterator chit_end = pNodeElement.Child.end();
  495. std::list<aiNode*> SceneNode_Child;
  496. std::list<unsigned int> SceneNode_Mesh;
  497. // At first read all metadata
  498. Postprocess_CollectMetadata(pNodeElement, pSceneNode);
  499. // check if we have deal with grouping node. Which can contain transformation or switch
  500. if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_Group)
  501. {
  502. const CX3DImporter_NodeElement_Group& tne_group = *((CX3DImporter_NodeElement_Group*)&pNodeElement);// create alias for convenience
  503. pSceneNode.mTransformation = tne_group.Transformation;
  504. if(tne_group.UseChoice)
  505. {
  506. // If Choice is less than zero or greater than the number of nodes in the children field, nothing is chosen.
  507. if((tne_group.Choice < 0) || ((size_t)tne_group.Choice >= pNodeElement.Child.size()))
  508. {
  509. chit_begin = pNodeElement.Child.end();
  510. chit_end = pNodeElement.Child.end();
  511. }
  512. else
  513. {
  514. for(size_t i = 0; i < (size_t)tne_group.Choice; i++) chit_begin++;// forward iterator to choosed node.
  515. chit_end = chit_begin;
  516. chit_end++;// point end iterator to next element after choosed.
  517. }
  518. }// if(tne_group.UseChoice)
  519. }// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_Group)
  520. // Reserve memory for fast access and check children.
  521. for(std::list<CX3DImporter_NodeElement*>::const_iterator it = chit_begin; it != chit_end; it++)
  522. {// in this loop we do not read metadata because it's already read at begin.
  523. if((*it)->Type == CX3DImporter_NodeElement::ENET_Group)
  524. {
  525. // if child is group then create new node and do recursive call.
  526. aiNode* new_node = new aiNode;
  527. new_node->mName = (*it)->ID;
  528. new_node->mParent = &pSceneNode;
  529. SceneNode_Child.push_back(new_node);
  530. Postprocess_BuildNode(**it, *new_node, pSceneMeshList, pSceneMaterialList, pSceneLightList);
  531. }
  532. else if((*it)->Type == CX3DImporter_NodeElement::ENET_Shape)
  533. {
  534. // shape can contain only one geometry and one appearance nodes.
  535. Postprocess_BuildShape(*((CX3DImporter_NodeElement_Shape*)*it), SceneNode_Mesh, pSceneMeshList, pSceneMaterialList);
  536. }
  537. else if(((*it)->Type == CX3DImporter_NodeElement::ENET_DirectionalLight) || ((*it)->Type == CX3DImporter_NodeElement::ENET_PointLight) ||
  538. ((*it)->Type == CX3DImporter_NodeElement::ENET_SpotLight))
  539. {
  540. Postprocess_BuildLight(*((CX3DImporter_NodeElement_Light*)*it), pSceneLightList);
  541. }
  542. else if(!PostprocessHelper_ElementIsMetadata((*it)->Type))// skip metadata
  543. {
  544. throw DeadlyImportError("Postprocess_BuildNode. Unknown type: " + std::to_string((*it)->Type) + ".");
  545. }
  546. }// for(std::list<CX3DImporter_NodeElement*>::const_iterator it = chit_begin; it != chit_end; it++)
  547. // copy data about children and meshes to aiNode.
  548. if(SceneNode_Child.size() > 0)
  549. {
  550. std::list<aiNode*>::const_iterator it = SceneNode_Child.begin();
  551. pSceneNode.mNumChildren = SceneNode_Child.size();
  552. pSceneNode.mChildren = new aiNode*[pSceneNode.mNumChildren];
  553. for(size_t i = 0; i < pSceneNode.mNumChildren; i++) pSceneNode.mChildren[i] = *it++;
  554. }
  555. if(SceneNode_Mesh.size() > 0)
  556. {
  557. std::list<unsigned int>::const_iterator it = SceneNode_Mesh.begin();
  558. pSceneNode.mNumMeshes = SceneNode_Mesh.size();
  559. pSceneNode.mMeshes = new unsigned int[pSceneNode.mNumMeshes];
  560. for(size_t i = 0; i < pSceneNode.mNumMeshes; i++) pSceneNode.mMeshes[i] = *it++;
  561. }
  562. // that's all. return to previous deals
  563. }
  564. void X3DImporter::Postprocess_BuildShape(const CX3DImporter_NodeElement_Shape& pShapeNodeElement, std::list<unsigned int>& pNodeMeshInd,
  565. std::list<aiMesh*>& pSceneMeshList, std::list<aiMaterial*>& pSceneMaterialList) const
  566. {
  567. aiMaterial* tmat = nullptr;
  568. aiMesh* tmesh = nullptr;
  569. CX3DImporter_NodeElement::EType mesh_type = CX3DImporter_NodeElement::ENET_Invalid;
  570. unsigned int mat_ind = 0;
  571. for(std::list<CX3DImporter_NodeElement*>::const_iterator it = pShapeNodeElement.Child.begin(); it != pShapeNodeElement.Child.end(); it++)
  572. {
  573. if(PostprocessHelper_ElementIsMesh((*it)->Type))
  574. {
  575. Postprocess_BuildMesh(**it, &tmesh);
  576. if(tmesh != nullptr)
  577. {
  578. // if mesh successfully built then add data about it to arrays
  579. pNodeMeshInd.push_back(pSceneMeshList.size());
  580. pSceneMeshList.push_back(tmesh);
  581. // keep mesh type. Need above for texture coordinate generation.
  582. mesh_type = (*it)->Type;
  583. }
  584. }
  585. else if((*it)->Type == CX3DImporter_NodeElement::ENET_Appearance)
  586. {
  587. Postprocess_BuildMaterial(**it, &tmat);
  588. if(tmat != nullptr)
  589. {
  590. // if material successfully built then add data about it to array
  591. mat_ind = pSceneMaterialList.size();
  592. pSceneMaterialList.push_back(tmat);
  593. }
  594. }
  595. }// for(std::list<CX3DImporter_NodeElement*>::const_iterator it = pShapeNodeElement.Child.begin(); it != pShapeNodeElement.Child.end(); it++)
  596. // associate read material with read mesh.
  597. if((tmesh != nullptr) && (tmat != nullptr))
  598. {
  599. tmesh->mMaterialIndex = mat_ind;
  600. // Check texture mapping. If material has texture but mesh has no texture coordinate then try to ask Assimp to generate texture coordinates.
  601. if((tmat->GetTextureCount(aiTextureType_DIFFUSE) != 0) && !tmesh->HasTextureCoords(0))
  602. {
  603. int32_t tm;
  604. aiVector3D tvec3;
  605. switch(mesh_type)
  606. {
  607. case CX3DImporter_NodeElement::ENET_Box:
  608. tm = aiTextureMapping_BOX;
  609. break;
  610. case CX3DImporter_NodeElement::ENET_Cone:
  611. case CX3DImporter_NodeElement::ENET_Cylinder:
  612. tm = aiTextureMapping_CYLINDER;
  613. break;
  614. case CX3DImporter_NodeElement::ENET_Sphere:
  615. tm = aiTextureMapping_SPHERE;
  616. break;
  617. default:
  618. tm = aiTextureMapping_PLANE;
  619. break;
  620. }// switch(mesh_type)
  621. tmat->AddProperty(&tm, 1, AI_MATKEY_MAPPING_DIFFUSE(0));
  622. }// if((tmat->GetTextureCount(aiTextureType_DIFFUSE) != 0) && !tmesh->HasTextureCoords(0))
  623. }// if((tmesh != nullptr) && (tmat != nullptr))
  624. }
  625. void X3DImporter::Postprocess_CollectMetadata(const CX3DImporter_NodeElement& pNodeElement, aiNode& pSceneNode) const
  626. {
  627. std::list<CX3DImporter_NodeElement*> meta_list;
  628. size_t meta_idx;
  629. PostprocessHelper_CollectMetadata(pNodeElement, meta_list);// find metadata in current node element.
  630. if(meta_list.size() > 0)
  631. {
  632. if(pSceneNode.mMetaData != nullptr) throw DeadlyImportError("Postprocess. MetaData member in node are not nullptr. Something went wrong.");
  633. // copy collected metadata to output node.
  634. pSceneNode.mMetaData = new aiMetadata();
  635. pSceneNode.mMetaData->mNumProperties = meta_list.size();
  636. pSceneNode.mMetaData->mKeys = new aiString[pSceneNode.mMetaData->mNumProperties];
  637. pSceneNode.mMetaData->mValues = new aiMetadataEntry[pSceneNode.mMetaData->mNumProperties];
  638. meta_idx = 0;
  639. for(std::list<CX3DImporter_NodeElement*>::const_iterator it = meta_list.begin(); it != meta_list.end(); it++, meta_idx++)
  640. {
  641. CX3DImporter_NodeElement_Meta* cur_meta = (CX3DImporter_NodeElement_Meta*)*it;
  642. // due to limitations we can add only first element of value list.
  643. // Add an element according to its type.
  644. if((*it)->Type == CX3DImporter_NodeElement::ENET_MetaBoolean)
  645. {
  646. if(((CX3DImporter_NodeElement_MetaBoolean*)cur_meta)->Value.size() > 0)
  647. pSceneNode.mMetaData->Set(meta_idx, cur_meta->Name, *(((CX3DImporter_NodeElement_MetaBoolean*)cur_meta)->Value.begin()));
  648. }
  649. else if((*it)->Type == CX3DImporter_NodeElement::ENET_MetaDouble)
  650. {
  651. // at this case also converting double to float.
  652. if(((CX3DImporter_NodeElement_MetaBoolean*)cur_meta)->Value.size() > 0)
  653. pSceneNode.mMetaData->Set(meta_idx, cur_meta->Name, (float)*(((CX3DImporter_NodeElement_MetaDouble*)cur_meta)->Value.begin()));
  654. }
  655. else if((*it)->Type == CX3DImporter_NodeElement::ENET_MetaFloat)
  656. {
  657. if(((CX3DImporter_NodeElement_MetaBoolean*)cur_meta)->Value.size() > 0)
  658. pSceneNode.mMetaData->Set(meta_idx, cur_meta->Name, *(((CX3DImporter_NodeElement_MetaFloat*)cur_meta)->Value.begin()));
  659. }
  660. else if((*it)->Type == CX3DImporter_NodeElement::ENET_MetaInteger)
  661. {
  662. if(((CX3DImporter_NodeElement_MetaBoolean*)cur_meta)->Value.size() > 0)
  663. pSceneNode.mMetaData->Set(meta_idx, cur_meta->Name, *(((CX3DImporter_NodeElement_MetaInteger*)cur_meta)->Value.begin()));
  664. }
  665. else if((*it)->Type == CX3DImporter_NodeElement::ENET_MetaString)
  666. {
  667. if(((CX3DImporter_NodeElement_MetaBoolean*)cur_meta)->Value.size() > 0)
  668. pSceneNode.mMetaData->Set(meta_idx, cur_meta->Name, ((CX3DImporter_NodeElement_MetaString*)cur_meta)->Value.begin()->data());
  669. }
  670. else
  671. {
  672. throw DeadlyImportError("Postprocess. Unknown metadata type.");
  673. }// if((*it)->Type == CX3DImporter_NodeElement::ENET_Meta*) else
  674. }// for(std::list<CX3DImporter_NodeElement*>::const_iterator it = meta_list.begin(); it != meta_list.end(); it++)
  675. }// if(meta_list.size() > 0)
  676. }
  677. }// namespace Assimp
  678. #endif // !ASSIMP_BUILD_NO_X3D_IMPORTER