summaryrefslogtreecommitdiff
path: root/src/mesh/assimp-master/code/AssetLib/X3D/X3DImporter_Postprocess.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesh/assimp-master/code/AssetLib/X3D/X3DImporter_Postprocess.cpp')
-rw-r--r--src/mesh/assimp-master/code/AssetLib/X3D/X3DImporter_Postprocess.cpp731
1 files changed, 731 insertions, 0 deletions
diff --git a/src/mesh/assimp-master/code/AssetLib/X3D/X3DImporter_Postprocess.cpp b/src/mesh/assimp-master/code/AssetLib/X3D/X3DImporter_Postprocess.cpp
new file mode 100644
index 0000000..87121ef
--- /dev/null
+++ b/src/mesh/assimp-master/code/AssetLib/X3D/X3DImporter_Postprocess.cpp
@@ -0,0 +1,731 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+/// \file X3DImporter_Postprocess.cpp
+/// \brief Convert built scenegraph and objects to Assimp scenegraph.
+/// \date 2015-2016
+/// \author smal.root@gmail.com
+
+#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
+
+#include "X3DGeoHelper.h"
+#include "X3DImporter.hpp"
+
+// Header files, Assimp.
+#include <assimp/StandardShapes.h>
+#include <assimp/StringUtils.h>
+#include <assimp/ai_assert.h>
+
+// Header files, stdlib.
+#include <algorithm>
+#include <iterator>
+#include <string>
+
+namespace Assimp {
+
+aiMatrix4x4 X3DImporter::PostprocessHelper_Matrix_GlobalToCurrent() const {
+ X3DNodeElementBase *cur_node;
+ std::list<aiMatrix4x4> matr;
+ aiMatrix4x4 out_matr;
+
+ // starting walk from current element to root
+ cur_node = mNodeElementCur;
+ if (cur_node != nullptr) {
+ do {
+ // if cur_node is group then store group transformation matrix in list.
+ if (cur_node->Type == X3DElemType::ENET_Group) matr.push_back(((X3DNodeElementGroup *)cur_node)->Transformation);
+
+ cur_node = cur_node->Parent;
+ } while (cur_node != nullptr);
+ }
+
+ // multiplicate all matrices in reverse order
+ for (std::list<aiMatrix4x4>::reverse_iterator rit = matr.rbegin(); rit != matr.rend(); ++rit)
+ out_matr = out_matr * (*rit);
+
+ return out_matr;
+}
+
+void X3DImporter::PostprocessHelper_CollectMetadata(const X3DNodeElementBase &pNodeElement, std::list<X3DNodeElementBase *> &pList) const {
+ // walk through childs and find for metadata.
+ for (std::list<X3DNodeElementBase *>::const_iterator el_it = pNodeElement.Children.begin(); el_it != pNodeElement.Children.end(); ++el_it) {
+ if (((*el_it)->Type == X3DElemType::ENET_MetaBoolean) || ((*el_it)->Type == X3DElemType::ENET_MetaDouble) ||
+ ((*el_it)->Type == X3DElemType::ENET_MetaFloat) || ((*el_it)->Type == X3DElemType::ENET_MetaInteger) ||
+ ((*el_it)->Type == X3DElemType::ENET_MetaString)) {
+ pList.push_back(*el_it);
+ } else if ((*el_it)->Type == X3DElemType::ENET_MetaSet) {
+ PostprocessHelper_CollectMetadata(**el_it, pList);
+ }
+ } // for(std::list<X3DNodeElementBase*>::const_iterator el_it = pNodeElement.Children.begin(); el_it != pNodeElement.Children.end(); el_it++)
+}
+
+bool X3DImporter::PostprocessHelper_ElementIsMetadata(const X3DElemType pType) const {
+ if ((pType == X3DElemType::ENET_MetaBoolean) || (pType == X3DElemType::ENET_MetaDouble) ||
+ (pType == X3DElemType::ENET_MetaFloat) || (pType == X3DElemType::ENET_MetaInteger) ||
+ (pType == X3DElemType::ENET_MetaString) || (pType == X3DElemType::ENET_MetaSet)) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool X3DImporter::PostprocessHelper_ElementIsMesh(const X3DElemType pType) const {
+ if ((pType == X3DElemType::ENET_Arc2D) || (pType == X3DElemType::ENET_ArcClose2D) ||
+ (pType == X3DElemType::ENET_Box) || (pType == X3DElemType::ENET_Circle2D) ||
+ (pType == X3DElemType::ENET_Cone) || (pType == X3DElemType::ENET_Cylinder) ||
+ (pType == X3DElemType::ENET_Disk2D) || (pType == X3DElemType::ENET_ElevationGrid) ||
+ (pType == X3DElemType::ENET_Extrusion) || (pType == X3DElemType::ENET_IndexedFaceSet) ||
+ (pType == X3DElemType::ENET_IndexedLineSet) || (pType == X3DElemType::ENET_IndexedTriangleFanSet) ||
+ (pType == X3DElemType::ENET_IndexedTriangleSet) || (pType == X3DElemType::ENET_IndexedTriangleStripSet) ||
+ (pType == X3DElemType::ENET_PointSet) || (pType == X3DElemType::ENET_LineSet) ||
+ (pType == X3DElemType::ENET_Polyline2D) || (pType == X3DElemType::ENET_Polypoint2D) ||
+ (pType == X3DElemType::ENET_Rectangle2D) || (pType == X3DElemType::ENET_Sphere) ||
+ (pType == X3DElemType::ENET_TriangleFanSet) || (pType == X3DElemType::ENET_TriangleSet) ||
+ (pType == X3DElemType::ENET_TriangleSet2D) || (pType == X3DElemType::ENET_TriangleStripSet)) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void X3DImporter::Postprocess_BuildLight(const X3DNodeElementBase &pNodeElement, std::list<aiLight *> &pSceneLightList) const {
+ const X3DNodeElementLight &ne = *((X3DNodeElementLight *)&pNodeElement);
+ aiMatrix4x4 transform_matr = PostprocessHelper_Matrix_GlobalToCurrent();
+ aiLight *new_light = new aiLight;
+
+ new_light->mName = ne.ID;
+ new_light->mColorAmbient = ne.Color * ne.AmbientIntensity;
+ new_light->mColorDiffuse = ne.Color * ne.Intensity;
+ new_light->mColorSpecular = ne.Color * ne.Intensity;
+ switch (pNodeElement.Type) {
+ case X3DElemType::ENET_DirectionalLight:
+ new_light->mType = aiLightSource_DIRECTIONAL;
+ new_light->mDirection = ne.Direction, new_light->mDirection *= transform_matr;
+
+ break;
+ case X3DElemType::ENET_PointLight:
+ new_light->mType = aiLightSource_POINT;
+ new_light->mPosition = ne.Location, new_light->mPosition *= transform_matr;
+ new_light->mAttenuationConstant = ne.Attenuation.x;
+ new_light->mAttenuationLinear = ne.Attenuation.y;
+ new_light->mAttenuationQuadratic = ne.Attenuation.z;
+
+ break;
+ case X3DElemType::ENET_SpotLight:
+ new_light->mType = aiLightSource_SPOT;
+ new_light->mPosition = ne.Location, new_light->mPosition *= transform_matr;
+ new_light->mDirection = ne.Direction, new_light->mDirection *= transform_matr;
+ new_light->mAttenuationConstant = ne.Attenuation.x;
+ new_light->mAttenuationLinear = ne.Attenuation.y;
+ new_light->mAttenuationQuadratic = ne.Attenuation.z;
+ new_light->mAngleInnerCone = ne.BeamWidth;
+ new_light->mAngleOuterCone = ne.CutOffAngle;
+
+ break;
+ default:
+ throw DeadlyImportError("Postprocess_BuildLight. Unknown type of light: " + ai_to_string(pNodeElement.Type) + ".");
+ }
+
+ pSceneLightList.push_back(new_light);
+}
+
+void X3DImporter::Postprocess_BuildMaterial(const X3DNodeElementBase &pNodeElement, aiMaterial **pMaterial) const {
+ // check argument
+ if (pMaterial == nullptr) throw DeadlyImportError("Postprocess_BuildMaterial. pMaterial is nullptr.");
+ if (*pMaterial != nullptr) throw DeadlyImportError("Postprocess_BuildMaterial. *pMaterial must be nullptr.");
+
+ *pMaterial = new aiMaterial;
+ aiMaterial &taimat = **pMaterial; // creating alias for convenience.
+
+ // at this point pNodeElement point to <Appearance> node. Walk through childs and add all stored data.
+ for (std::list<X3DNodeElementBase *>::const_iterator el_it = pNodeElement.Children.begin(); el_it != pNodeElement.Children.end(); ++el_it) {
+ if ((*el_it)->Type == X3DElemType::ENET_Material) {
+ aiColor3D tcol3;
+ float tvalf;
+ X3DNodeElementMaterial &tnemat = *((X3DNodeElementMaterial *)*el_it);
+
+ tcol3.r = tnemat.AmbientIntensity, tcol3.g = tnemat.AmbientIntensity, tcol3.b = tnemat.AmbientIntensity;
+ taimat.AddProperty(&tcol3, 1, AI_MATKEY_COLOR_AMBIENT);
+ taimat.AddProperty(&tnemat.DiffuseColor, 1, AI_MATKEY_COLOR_DIFFUSE);
+ taimat.AddProperty(&tnemat.EmissiveColor, 1, AI_MATKEY_COLOR_EMISSIVE);
+ taimat.AddProperty(&tnemat.SpecularColor, 1, AI_MATKEY_COLOR_SPECULAR);
+ tvalf = 1;
+ taimat.AddProperty(&tvalf, 1, AI_MATKEY_SHININESS_STRENGTH);
+ taimat.AddProperty(&tnemat.Shininess, 1, AI_MATKEY_SHININESS);
+ tvalf = 1.0f - tnemat.Transparency;
+ taimat.AddProperty(&tvalf, 1, AI_MATKEY_OPACITY);
+ } // if((*el_it)->Type == X3DElemType::ENET_Material)
+ else if ((*el_it)->Type == X3DElemType::ENET_ImageTexture) {
+ X3DNodeElementImageTexture &tnetex = *((X3DNodeElementImageTexture *)*el_it);
+ aiString url_str(tnetex.URL.c_str());
+ int mode = aiTextureOp_Multiply;
+
+ taimat.AddProperty(&url_str, AI_MATKEY_TEXTURE_DIFFUSE(0));
+ taimat.AddProperty(&tnetex.RepeatS, 1, AI_MATKEY_MAPPINGMODE_U_DIFFUSE(0));
+ taimat.AddProperty(&tnetex.RepeatT, 1, AI_MATKEY_MAPPINGMODE_V_DIFFUSE(0));
+ taimat.AddProperty(&mode, 1, AI_MATKEY_TEXOP_DIFFUSE(0));
+ } // else if((*el_it)->Type == X3DElemType::ENET_ImageTexture)
+ else if ((*el_it)->Type == X3DElemType::ENET_TextureTransform) {
+ aiUVTransform trans;
+ X3DNodeElementTextureTransform &tnetextr = *((X3DNodeElementTextureTransform *)*el_it);
+
+ trans.mTranslation = tnetextr.Translation - tnetextr.Center;
+ trans.mScaling = tnetextr.Scale;
+ trans.mRotation = tnetextr.Rotation;
+ taimat.AddProperty(&trans, 1, AI_MATKEY_UVTRANSFORM_DIFFUSE(0));
+ } // else if((*el_it)->Type == X3DElemType::ENET_TextureTransform)
+ } // for(std::list<X3DNodeElementBase*>::const_iterator el_it = pNodeElement.Children.begin(); el_it != pNodeElement.Children.end(); el_it++)
+}
+
+void X3DImporter::Postprocess_BuildMesh(const X3DNodeElementBase &pNodeElement, aiMesh **pMesh) const {
+ // check argument
+ if (pMesh == nullptr) throw DeadlyImportError("Postprocess_BuildMesh. pMesh is nullptr.");
+ if (*pMesh != nullptr) throw DeadlyImportError("Postprocess_BuildMesh. *pMesh must be nullptr.");
+
+ /************************************************************************************************************************************/
+ /************************************************************ Geometry2D ************************************************************/
+ /************************************************************************************************************************************/
+ if ((pNodeElement.Type == X3DElemType::ENET_Arc2D) || (pNodeElement.Type == X3DElemType::ENET_ArcClose2D) ||
+ (pNodeElement.Type == X3DElemType::ENET_Circle2D) || (pNodeElement.Type == X3DElemType::ENET_Disk2D) ||
+ (pNodeElement.Type == X3DElemType::ENET_Polyline2D) || (pNodeElement.Type == X3DElemType::ENET_Polypoint2D) ||
+ (pNodeElement.Type == X3DElemType::ENET_Rectangle2D) || (pNodeElement.Type == X3DElemType::ENET_TriangleSet2D)) {
+ X3DNodeElementGeometry2D &tnemesh = *((X3DNodeElementGeometry2D *)&pNodeElement); // create alias for convenience
+ std::vector<aiVector3D> tarr;
+
+ tarr.reserve(tnemesh.Vertices.size());
+ for (std::list<aiVector3D>::iterator it = tnemesh.Vertices.begin(); it != tnemesh.Vertices.end(); ++it)
+ tarr.push_back(*it);
+ *pMesh = StandardShapes::MakeMesh(tarr, static_cast<unsigned int>(tnemesh.NumIndices)); // create mesh from vertices using Assimp help.
+
+ return; // mesh is build, nothing to do anymore.
+ }
+ /************************************************************************************************************************************/
+ /************************************************************ Geometry3D ************************************************************/
+ /************************************************************************************************************************************/
+ //
+ // Predefined figures
+ //
+ if ((pNodeElement.Type == X3DElemType::ENET_Box) || (pNodeElement.Type == X3DElemType::ENET_Cone) ||
+ (pNodeElement.Type == X3DElemType::ENET_Cylinder) || (pNodeElement.Type == X3DElemType::ENET_Sphere)) {
+ X3DNodeElementGeometry3D &tnemesh = *((X3DNodeElementGeometry3D *)&pNodeElement); // create alias for convenience
+ std::vector<aiVector3D> tarr;
+
+ tarr.reserve(tnemesh.Vertices.size());
+ for (std::list<aiVector3D>::iterator it = tnemesh.Vertices.begin(); it != tnemesh.Vertices.end(); ++it)
+ tarr.push_back(*it);
+
+ *pMesh = StandardShapes::MakeMesh(tarr, static_cast<unsigned int>(tnemesh.NumIndices)); // create mesh from vertices using Assimp help.
+
+ return; // mesh is build, nothing to do anymore.
+ }
+ //
+ // Parametric figures
+ //
+ if (pNodeElement.Type == X3DElemType::ENET_ElevationGrid) {
+ X3DNodeElementElevationGrid &tnemesh = *((X3DNodeElementElevationGrid *)&pNodeElement); // create alias for convenience
+
+ // at first create mesh from existing vertices.
+ *pMesh = X3DGeoHelper::make_mesh(tnemesh.CoordIdx, tnemesh.Vertices);
+ // copy additional information from children
+ for (std::list<X3DNodeElementBase *>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it) {
+ if ((*ch_it)->Type == X3DElemType::ENET_Color)
+ X3DGeoHelper::add_color(**pMesh, ((X3DNodeElementColor *)*ch_it)->Value, tnemesh.ColorPerVertex);
+ else if ((*ch_it)->Type == X3DElemType::ENET_ColorRGBA)
+ X3DGeoHelper::add_color(**pMesh, ((X3DNodeElementColorRGBA *)*ch_it)->Value, tnemesh.ColorPerVertex);
+ else if ((*ch_it)->Type == X3DElemType::ENET_Normal)
+ X3DGeoHelper::add_normal(**pMesh, ((X3DNodeElementNormal *)*ch_it)->Value, tnemesh.NormalPerVertex);
+ else if ((*ch_it)->Type == X3DElemType::ENET_TextureCoordinate)
+ X3DGeoHelper::add_tex_coord(**pMesh, ((X3DNodeElementTextureCoordinate *)*ch_it)->Value);
+ else
+ throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of ElevationGrid: " + ai_to_string((*ch_it)->Type) + ".");
+ } // for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it)
+
+ return; // mesh is build, nothing to do anymore.
+ } // if(pNodeElement.Type == X3DElemType::ENET_ElevationGrid)
+ //
+ // Indexed primitives sets
+ //
+ if (pNodeElement.Type == X3DElemType::ENET_IndexedFaceSet) {
+ X3DNodeElementIndexedSet &tnemesh = *((X3DNodeElementIndexedSet *)&pNodeElement); // create alias for convenience
+
+ // at first search for <Coordinate> node and create mesh.
+ for (std::list<X3DNodeElementBase *>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it) {
+ if ((*ch_it)->Type == X3DElemType::ENET_Coordinate) {
+ *pMesh = X3DGeoHelper::make_mesh(tnemesh.CoordIndex, ((X3DNodeElementCoordinate *)*ch_it)->Value);
+ }
+ }
+
+ // copy additional information from children
+ for (std::list<X3DNodeElementBase *>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it) {
+ if ((*ch_it)->Type == X3DElemType::ENET_Color)
+ X3DGeoHelper::add_color(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((X3DNodeElementColor *)*ch_it)->Value, tnemesh.ColorPerVertex);
+ else if ((*ch_it)->Type == X3DElemType::ENET_ColorRGBA)
+ X3DGeoHelper::add_color(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((X3DNodeElementColorRGBA *)*ch_it)->Value,
+ tnemesh.ColorPerVertex);
+ else if ((*ch_it)->Type == X3DElemType::ENET_Coordinate) {
+ } // skip because already read when mesh created.
+ else if ((*ch_it)->Type == X3DElemType::ENET_Normal)
+ X3DGeoHelper::add_normal(**pMesh, tnemesh.CoordIndex, tnemesh.NormalIndex, ((X3DNodeElementNormal *)*ch_it)->Value,
+ tnemesh.NormalPerVertex);
+ else if ((*ch_it)->Type == X3DElemType::ENET_TextureCoordinate)
+ X3DGeoHelper::add_tex_coord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((X3DNodeElementTextureCoordinate *)*ch_it)->Value);
+ else
+ throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of IndexedFaceSet: " + ai_to_string((*ch_it)->Type) + ".");
+ } // for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it)
+
+ return; // mesh is build, nothing to do anymore.
+ } // if(pNodeElement.Type == X3DElemType::ENET_IndexedFaceSet)
+
+ if (pNodeElement.Type == X3DElemType::ENET_IndexedLineSet) {
+ X3DNodeElementIndexedSet &tnemesh = *((X3DNodeElementIndexedSet *)&pNodeElement); // create alias for convenience
+
+ // at first search for <Coordinate> node and create mesh.
+ for (std::list<X3DNodeElementBase *>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it) {
+ if ((*ch_it)->Type == X3DElemType::ENET_Coordinate) {
+ *pMesh = X3DGeoHelper::make_mesh(tnemesh.CoordIndex, ((X3DNodeElementCoordinate *)*ch_it)->Value);
+ }
+ }
+
+ // copy additional information from children
+ for (std::list<X3DNodeElementBase *>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it) {
+ ai_assert(*pMesh);
+ if ((*ch_it)->Type == X3DElemType::ENET_Color)
+ X3DGeoHelper::add_color(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((X3DNodeElementColor *)*ch_it)->Value, tnemesh.ColorPerVertex);
+ else if ((*ch_it)->Type == X3DElemType::ENET_ColorRGBA)
+ X3DGeoHelper::add_color(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((X3DNodeElementColorRGBA *)*ch_it)->Value,
+ tnemesh.ColorPerVertex);
+ else if ((*ch_it)->Type == X3DElemType::ENET_Coordinate) {
+ } // skip because already read when mesh created.
+ else
+ throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of IndexedLineSet: " + ai_to_string((*ch_it)->Type) + ".");
+ } // for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it)
+
+ return; // mesh is build, nothing to do anymore.
+ } // if(pNodeElement.Type == X3DElemType::ENET_IndexedLineSet)
+
+ if ((pNodeElement.Type == X3DElemType::ENET_IndexedTriangleSet) ||
+ (pNodeElement.Type == X3DElemType::ENET_IndexedTriangleFanSet) ||
+ (pNodeElement.Type == X3DElemType::ENET_IndexedTriangleStripSet)) {
+ X3DNodeElementIndexedSet &tnemesh = *((X3DNodeElementIndexedSet *)&pNodeElement); // create alias for convenience
+
+ // at first search for <Coordinate> node and create mesh.
+ for (std::list<X3DNodeElementBase *>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it) {
+ if ((*ch_it)->Type == X3DElemType::ENET_Coordinate) {
+ *pMesh = X3DGeoHelper::make_mesh(tnemesh.CoordIndex, ((X3DNodeElementCoordinate *)*ch_it)->Value);
+ }
+ }
+
+ // copy additional information from children
+ for (std::list<X3DNodeElementBase *>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it) {
+ ai_assert(*pMesh);
+ if ((*ch_it)->Type == X3DElemType::ENET_Color)
+ X3DGeoHelper::add_color(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((X3DNodeElementColor *)*ch_it)->Value, tnemesh.ColorPerVertex);
+ else if ((*ch_it)->Type == X3DElemType::ENET_ColorRGBA)
+ X3DGeoHelper::add_color(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((X3DNodeElementColorRGBA *)*ch_it)->Value,
+ tnemesh.ColorPerVertex);
+ else if ((*ch_it)->Type == X3DElemType::ENET_Coordinate) {
+ } // skip because already read when mesh created.
+ else if ((*ch_it)->Type == X3DElemType::ENET_Normal)
+ X3DGeoHelper::add_normal(**pMesh, tnemesh.CoordIndex, tnemesh.NormalIndex, ((X3DNodeElementNormal *)*ch_it)->Value,
+ tnemesh.NormalPerVertex);
+ else if ((*ch_it)->Type == X3DElemType::ENET_TextureCoordinate)
+ X3DGeoHelper::add_tex_coord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((X3DNodeElementTextureCoordinate *)*ch_it)->Value);
+ else
+ throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of IndexedTriangleSet or IndexedTriangleFanSet, or \
+ IndexedTriangleStripSet: " +
+ ai_to_string((*ch_it)->Type) + ".");
+ } // for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it)
+
+ return; // mesh is build, nothing to do anymore.
+ } // if((pNodeElement.Type == X3DElemType::ENET_IndexedTriangleFanSet) || (pNodeElement.Type == X3DElemType::ENET_IndexedTriangleStripSet))
+
+ if (pNodeElement.Type == X3DElemType::ENET_Extrusion) {
+ X3DNodeElementIndexedSet &tnemesh = *((X3DNodeElementIndexedSet *)&pNodeElement); // create alias for convenience
+
+ *pMesh = X3DGeoHelper::make_mesh(tnemesh.CoordIndex, tnemesh.Vertices);
+
+ return; // mesh is build, nothing to do anymore.
+ } // if(pNodeElement.Type == X3DElemType::ENET_Extrusion)
+
+ //
+ // Primitives sets
+ //
+ if (pNodeElement.Type == X3DElemType::ENET_PointSet) {
+ X3DNodeElementSet &tnemesh = *((X3DNodeElementSet *)&pNodeElement); // create alias for convenience
+
+ // at first search for <Coordinate> node and create mesh.
+ for (std::list<X3DNodeElementBase *>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it) {
+ if ((*ch_it)->Type == X3DElemType::ENET_Coordinate) {
+ std::vector<aiVector3D> vec_copy;
+
+ vec_copy.reserve(((X3DNodeElementCoordinate *)*ch_it)->Value.size());
+ for (std::list<aiVector3D>::const_iterator it = ((X3DNodeElementCoordinate *)*ch_it)->Value.begin();
+ it != ((X3DNodeElementCoordinate *)*ch_it)->Value.end(); ++it) {
+ vec_copy.push_back(*it);
+ }
+
+ *pMesh = StandardShapes::MakeMesh(vec_copy, 1);
+ }
+ }
+
+ // copy additional information from children
+ for (std::list<X3DNodeElementBase *>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it) {
+ ai_assert(*pMesh);
+ if ((*ch_it)->Type == X3DElemType::ENET_Color)
+ X3DGeoHelper::add_color(**pMesh, ((X3DNodeElementColor *)*ch_it)->Value, true);
+ else if ((*ch_it)->Type == X3DElemType::ENET_ColorRGBA)
+ X3DGeoHelper::add_color(**pMesh, ((X3DNodeElementColorRGBA *)*ch_it)->Value, true);
+ else if ((*ch_it)->Type == X3DElemType::ENET_Coordinate) {
+ } // skip because already read when mesh created.
+ else
+ throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of PointSet: " + ai_to_string((*ch_it)->Type) + ".");
+ } // for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it)
+
+ return; // mesh is build, nothing to do anymore.
+ } // if(pNodeElement.Type == X3DElemType::ENET_PointSet)
+
+ if (pNodeElement.Type == X3DElemType::ENET_LineSet) {
+ X3DNodeElementSet &tnemesh = *((X3DNodeElementSet *)&pNodeElement); // create alias for convenience
+
+ // at first search for <Coordinate> node and create mesh.
+ for (std::list<X3DNodeElementBase *>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it) {
+ if ((*ch_it)->Type == X3DElemType::ENET_Coordinate) {
+ *pMesh = X3DGeoHelper::make_mesh(tnemesh.CoordIndex, ((X3DNodeElementCoordinate *)*ch_it)->Value);
+ }
+ }
+
+ // copy additional information from children
+ for (std::list<X3DNodeElementBase *>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it) {
+ ai_assert(*pMesh);
+ if ((*ch_it)->Type == X3DElemType::ENET_Color)
+ X3DGeoHelper::add_color(**pMesh, ((X3DNodeElementColor *)*ch_it)->Value, true);
+ else if ((*ch_it)->Type == X3DElemType::ENET_ColorRGBA)
+ X3DGeoHelper::add_color(**pMesh, ((X3DNodeElementColorRGBA *)*ch_it)->Value, true);
+ else if ((*ch_it)->Type == X3DElemType::ENET_Coordinate) {
+ } // skip because already read when mesh created.
+ else
+ throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of LineSet: " + ai_to_string((*ch_it)->Type) + ".");
+ } // for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it)
+
+ return; // mesh is build, nothing to do anymore.
+ } // if(pNodeElement.Type == X3DElemType::ENET_LineSet)
+
+ if (pNodeElement.Type == X3DElemType::ENET_TriangleFanSet) {
+ X3DNodeElementSet &tnemesh = *((X3DNodeElementSet *)&pNodeElement); // create alias for convenience
+
+ // at first search for <Coordinate> node and create mesh.
+ for (std::list<X3DNodeElementBase *>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it) {
+ if ((*ch_it)->Type == X3DElemType::ENET_Coordinate) {
+ *pMesh = X3DGeoHelper::make_mesh(tnemesh.CoordIndex, ((X3DNodeElementCoordinate *)*ch_it)->Value);
+ }
+ }
+
+ // copy additional information from children
+ for (std::list<X3DNodeElementBase *>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it) {
+ if (nullptr == *pMesh) {
+ break;
+ }
+ if ((*ch_it)->Type == X3DElemType::ENET_Color)
+ X3DGeoHelper::add_color(**pMesh, ((X3DNodeElementColor *)*ch_it)->Value, tnemesh.ColorPerVertex);
+ else if ((*ch_it)->Type == X3DElemType::ENET_ColorRGBA)
+ X3DGeoHelper::add_color(**pMesh, ((X3DNodeElementColorRGBA *)*ch_it)->Value, tnemesh.ColorPerVertex);
+ else if ((*ch_it)->Type == X3DElemType::ENET_Coordinate) {
+ } // skip because already read when mesh created.
+ else if ((*ch_it)->Type == X3DElemType::ENET_Normal)
+ X3DGeoHelper::add_normal(**pMesh, tnemesh.CoordIndex, tnemesh.NormalIndex, ((X3DNodeElementNormal *)*ch_it)->Value,
+ tnemesh.NormalPerVertex);
+ else if ((*ch_it)->Type == X3DElemType::ENET_TextureCoordinate)
+ X3DGeoHelper::add_tex_coord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((X3DNodeElementTextureCoordinate *)*ch_it)->Value);
+ else
+ throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of TrianlgeFanSet: " + ai_to_string((*ch_it)->Type) + ".");
+ } // for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it)
+
+ return; // mesh is build, nothing to do anymore.
+ } // if(pNodeElement.Type == X3DElemType::ENET_TriangleFanSet)
+
+ if (pNodeElement.Type == X3DElemType::ENET_TriangleSet) {
+ X3DNodeElementSet &tnemesh = *((X3DNodeElementSet *)&pNodeElement); // create alias for convenience
+
+ // at first search for <Coordinate> node and create mesh.
+ for (std::list<X3DNodeElementBase *>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it) {
+ if ((*ch_it)->Type == X3DElemType::ENET_Coordinate) {
+ std::vector<aiVector3D> vec_copy;
+
+ vec_copy.reserve(((X3DNodeElementCoordinate *)*ch_it)->Value.size());
+ for (std::list<aiVector3D>::const_iterator it = ((X3DNodeElementCoordinate *)*ch_it)->Value.begin();
+ it != ((X3DNodeElementCoordinate *)*ch_it)->Value.end(); ++it) {
+ vec_copy.push_back(*it);
+ }
+
+ *pMesh = StandardShapes::MakeMesh(vec_copy, 3);
+ }
+ }
+
+ // copy additional information from children
+ for (std::list<X3DNodeElementBase *>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it) {
+ ai_assert(*pMesh);
+ if ((*ch_it)->Type == X3DElemType::ENET_Color)
+ X3DGeoHelper::add_color(**pMesh, ((X3DNodeElementColor *)*ch_it)->Value, tnemesh.ColorPerVertex);
+ else if ((*ch_it)->Type == X3DElemType::ENET_ColorRGBA)
+ X3DGeoHelper::add_color(**pMesh, ((X3DNodeElementColorRGBA *)*ch_it)->Value, tnemesh.ColorPerVertex);
+ else if ((*ch_it)->Type == X3DElemType::ENET_Coordinate) {
+ } // skip because already read when mesh created.
+ else if ((*ch_it)->Type == X3DElemType::ENET_Normal)
+ X3DGeoHelper::add_normal(**pMesh, tnemesh.CoordIndex, tnemesh.NormalIndex, ((X3DNodeElementNormal *)*ch_it)->Value,
+ tnemesh.NormalPerVertex);
+ else if ((*ch_it)->Type == X3DElemType::ENET_TextureCoordinate)
+ X3DGeoHelper::add_tex_coord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((X3DNodeElementTextureCoordinate *)*ch_it)->Value);
+ else
+ throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of TrianlgeSet: " + ai_to_string((*ch_it)->Type) + ".");
+ } // for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it)
+
+ return; // mesh is build, nothing to do anymore.
+ } // if(pNodeElement.Type == X3DElemType::ENET_TriangleSet)
+
+ if (pNodeElement.Type == X3DElemType::ENET_TriangleStripSet) {
+ X3DNodeElementSet &tnemesh = *((X3DNodeElementSet *)&pNodeElement); // create alias for convenience
+
+ // at first search for <Coordinate> node and create mesh.
+ for (std::list<X3DNodeElementBase *>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it) {
+ if ((*ch_it)->Type == X3DElemType::ENET_Coordinate) {
+ *pMesh = X3DGeoHelper::make_mesh(tnemesh.CoordIndex, ((X3DNodeElementCoordinate *)*ch_it)->Value);
+ }
+ }
+
+ // copy additional information from children
+ for (std::list<X3DNodeElementBase *>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it) {
+ ai_assert(*pMesh);
+ if ((*ch_it)->Type == X3DElemType::ENET_Color)
+ X3DGeoHelper::add_color(**pMesh, ((X3DNodeElementColor *)*ch_it)->Value, tnemesh.ColorPerVertex);
+ else if ((*ch_it)->Type == X3DElemType::ENET_ColorRGBA)
+ X3DGeoHelper::add_color(**pMesh, ((X3DNodeElementColorRGBA *)*ch_it)->Value, tnemesh.ColorPerVertex);
+ else if ((*ch_it)->Type == X3DElemType::ENET_Coordinate) {
+ } // skip because already read when mesh created.
+ else if ((*ch_it)->Type == X3DElemType::ENET_Normal)
+ X3DGeoHelper::add_normal(**pMesh, tnemesh.CoordIndex, tnemesh.NormalIndex, ((X3DNodeElementNormal *)*ch_it)->Value,
+ tnemesh.NormalPerVertex);
+ else if ((*ch_it)->Type == X3DElemType::ENET_TextureCoordinate)
+ X3DGeoHelper::add_tex_coord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((X3DNodeElementTextureCoordinate *)*ch_it)->Value);
+ else
+ throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of TriangleStripSet: " + ai_to_string((*ch_it)->Type) + ".");
+ } // for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it)
+
+ return; // mesh is build, nothing to do anymore.
+ } // if(pNodeElement.Type == X3DElemType::ENET_TriangleStripSet)
+
+ throw DeadlyImportError("Postprocess_BuildMesh. Unknown mesh type: " + ai_to_string(pNodeElement.Type) + ".");
+}
+
+void X3DImporter::Postprocess_BuildNode(const X3DNodeElementBase &pNodeElement, aiNode &pSceneNode, std::list<aiMesh *> &pSceneMeshList,
+ std::list<aiMaterial *> &pSceneMaterialList, std::list<aiLight *> &pSceneLightList) const {
+ std::list<X3DNodeElementBase *>::const_iterator chit_begin = pNodeElement.Children.begin();
+ std::list<X3DNodeElementBase *>::const_iterator chit_end = pNodeElement.Children.end();
+ std::list<aiNode *> SceneNode_Child;
+ std::list<unsigned int> SceneNode_Mesh;
+
+ // At first read all metadata
+ Postprocess_CollectMetadata(pNodeElement, pSceneNode);
+ // check if we have deal with grouping node. Which can contain transformation or switch
+ if (pNodeElement.Type == X3DElemType::ENET_Group) {
+ const X3DNodeElementGroup &tne_group = *((X3DNodeElementGroup *)&pNodeElement); // create alias for convenience
+
+ pSceneNode.mTransformation = tne_group.Transformation;
+ if (tne_group.UseChoice) {
+ // If Choice is less than zero or greater than the number of nodes in the children field, nothing is chosen.
+ if ((tne_group.Choice < 0) || ((size_t)tne_group.Choice >= pNodeElement.Children.size())) {
+ chit_begin = pNodeElement.Children.end();
+ chit_end = pNodeElement.Children.end();
+ } else {
+ for (size_t i = 0; i < (size_t)tne_group.Choice; i++)
+ ++chit_begin; // forward iterator to chosen node.
+
+ chit_end = chit_begin;
+ ++chit_end; // point end iterator to next element after chosen node.
+ }
+ } // if(tne_group.UseChoice)
+ } // if(pNodeElement.Type == X3DElemType::ENET_Group)
+
+ // Reserve memory for fast access and check children.
+ for (std::list<X3DNodeElementBase *>::const_iterator it = chit_begin; it != chit_end; ++it) { // in this loop we do not read metadata because it's already read at begin.
+ if ((*it)->Type == X3DElemType::ENET_Group) {
+ // if child is group then create new node and do recursive call.
+ aiNode *new_node = new aiNode;
+
+ new_node->mName = (*it)->ID;
+ new_node->mParent = &pSceneNode;
+ SceneNode_Child.push_back(new_node);
+ Postprocess_BuildNode(**it, *new_node, pSceneMeshList, pSceneMaterialList, pSceneLightList);
+ } else if ((*it)->Type == X3DElemType::ENET_Shape) {
+ // shape can contain only one geometry and one appearance nodes.
+ Postprocess_BuildShape(*((X3DNodeElementShape *)*it), SceneNode_Mesh, pSceneMeshList, pSceneMaterialList);
+ } else if (((*it)->Type == X3DElemType::ENET_DirectionalLight) || ((*it)->Type == X3DElemType::ENET_PointLight) ||
+ ((*it)->Type == X3DElemType::ENET_SpotLight)) {
+ Postprocess_BuildLight(*((X3DNodeElementLight *)*it), pSceneLightList);
+ } else if (!PostprocessHelper_ElementIsMetadata((*it)->Type)) // skip metadata
+ {
+ throw DeadlyImportError("Postprocess_BuildNode. Unknown type: " + ai_to_string((*it)->Type) + ".");
+ }
+ } // for(std::list<X3DNodeElementBase*>::const_iterator it = chit_begin; it != chit_end; it++)
+
+ // copy data about children and meshes to aiNode.
+ if (!SceneNode_Child.empty()) {
+ std::list<aiNode *>::const_iterator it = SceneNode_Child.begin();
+
+ pSceneNode.mNumChildren = static_cast<unsigned int>(SceneNode_Child.size());
+ pSceneNode.mChildren = new aiNode *[pSceneNode.mNumChildren];
+ for (size_t i = 0; i < pSceneNode.mNumChildren; i++)
+ pSceneNode.mChildren[i] = *it++;
+ }
+
+ if (!SceneNode_Mesh.empty()) {
+ std::list<unsigned int>::const_iterator it = SceneNode_Mesh.begin();
+
+ pSceneNode.mNumMeshes = static_cast<unsigned int>(SceneNode_Mesh.size());
+ pSceneNode.mMeshes = new unsigned int[pSceneNode.mNumMeshes];
+ for (size_t i = 0; i < pSceneNode.mNumMeshes; i++)
+ pSceneNode.mMeshes[i] = *it++;
+ }
+
+ // that's all. return to previous deals
+}
+
+void X3DImporter::Postprocess_BuildShape(const X3DNodeElementShape &pShapeNodeElement, std::list<unsigned int> &pNodeMeshInd,
+ std::list<aiMesh *> &pSceneMeshList, std::list<aiMaterial *> &pSceneMaterialList) const {
+ aiMaterial *tmat = nullptr;
+ aiMesh *tmesh = nullptr;
+ X3DElemType mesh_type = X3DElemType::ENET_Invalid;
+ unsigned int mat_ind = 0;
+
+ for (std::list<X3DNodeElementBase *>::const_iterator it = pShapeNodeElement.Children.begin(); it != pShapeNodeElement.Children.end(); ++it) {
+ if (PostprocessHelper_ElementIsMesh((*it)->Type)) {
+ Postprocess_BuildMesh(**it, &tmesh);
+ if (tmesh != nullptr) {
+ // if mesh successfully built then add data about it to arrays
+ pNodeMeshInd.push_back(static_cast<unsigned int>(pSceneMeshList.size()));
+ pSceneMeshList.push_back(tmesh);
+ // keep mesh type. Need above for texture coordinate generation.
+ mesh_type = (*it)->Type;
+ }
+ } else if ((*it)->Type == X3DElemType::ENET_Appearance) {
+ Postprocess_BuildMaterial(**it, &tmat);
+ if (tmat != nullptr) {
+ // if material successfully built then add data about it to array
+ mat_ind = static_cast<unsigned int>(pSceneMaterialList.size());
+ pSceneMaterialList.push_back(tmat);
+ }
+ }
+ } // for(std::list<X3DNodeElementBase*>::const_iterator it = pShapeNodeElement.Children.begin(); it != pShapeNodeElement.Children.end(); it++)
+
+ // associate read material with read mesh.
+ if ((tmesh != nullptr) && (tmat != nullptr)) {
+ tmesh->mMaterialIndex = mat_ind;
+ // Check texture mapping. If material has texture but mesh has no texture coordinate then try to ask Assimp to generate texture coordinates.
+ if ((tmat->GetTextureCount(aiTextureType_DIFFUSE) != 0) && !tmesh->HasTextureCoords(0)) {
+ int32_t tm;
+ aiVector3D tvec3;
+
+ switch (mesh_type) {
+ case X3DElemType::ENET_Box:
+ tm = aiTextureMapping_BOX;
+ break;
+ case X3DElemType::ENET_Cone:
+ case X3DElemType::ENET_Cylinder:
+ tm = aiTextureMapping_CYLINDER;
+ break;
+ case X3DElemType::ENET_Sphere:
+ tm = aiTextureMapping_SPHERE;
+ break;
+ default:
+ tm = aiTextureMapping_PLANE;
+ break;
+ } // switch(mesh_type)
+
+ tmat->AddProperty(&tm, 1, AI_MATKEY_MAPPING_DIFFUSE(0));
+ } // if((tmat->GetTextureCount(aiTextureType_DIFFUSE) != 0) && !tmesh->HasTextureCoords(0))
+ } // if((tmesh != nullptr) && (tmat != nullptr))
+}
+
+void X3DImporter::Postprocess_CollectMetadata(const X3DNodeElementBase &pNodeElement, aiNode &pSceneNode) const {
+ std::list<X3DNodeElementBase *> meta_list;
+ size_t meta_idx;
+
+ PostprocessHelper_CollectMetadata(pNodeElement, meta_list); // find metadata in current node element.
+ if (!meta_list.empty()) {
+ if (pSceneNode.mMetaData != nullptr) {
+ throw DeadlyImportError("Postprocess. MetaData member in node are not nullptr. Something went wrong.");
+ }
+
+ // copy collected metadata to output node.
+ pSceneNode.mMetaData = aiMetadata::Alloc(static_cast<unsigned int>(meta_list.size()));
+ meta_idx = 0;
+ for (std::list<X3DNodeElementBase *>::const_iterator it = meta_list.begin(); it != meta_list.end(); ++it, ++meta_idx) {
+ X3DNodeElementMeta *cur_meta = (X3DNodeElementMeta *)*it;
+
+ // due to limitations we can add only first element of value list.
+ // Add an element according to its type.
+ if ((*it)->Type == X3DElemType::ENET_MetaBoolean) {
+ if (((X3DNodeElementMetaBoolean *)cur_meta)->Value.size() > 0)
+ pSceneNode.mMetaData->Set(static_cast<unsigned int>(meta_idx), cur_meta->Name, *(((X3DNodeElementMetaBoolean *)cur_meta)->Value.begin()) == true);
+ } else if ((*it)->Type == X3DElemType::ENET_MetaDouble) {
+ if (((X3DNodeElementMetaDouble *)cur_meta)->Value.size() > 0)
+ pSceneNode.mMetaData->Set(static_cast<unsigned int>(meta_idx), cur_meta->Name, (float)*(((X3DNodeElementMetaDouble *)cur_meta)->Value.begin()));
+ } else if ((*it)->Type == X3DElemType::ENET_MetaFloat) {
+ if (((X3DNodeElementMetaFloat *)cur_meta)->Value.size() > 0)
+ pSceneNode.mMetaData->Set(static_cast<unsigned int>(meta_idx), cur_meta->Name, *(((X3DNodeElementMetaFloat *)cur_meta)->Value.begin()));
+ } else if ((*it)->Type == X3DElemType::ENET_MetaInteger) {
+ if (((X3DNodeElementMetaInt *)cur_meta)->Value.size() > 0)
+ pSceneNode.mMetaData->Set(static_cast<unsigned int>(meta_idx), cur_meta->Name, *(((X3DNodeElementMetaInt *)cur_meta)->Value.begin()));
+ } else if ((*it)->Type == X3DElemType::ENET_MetaString) {
+ if (((X3DNodeElementMetaString *)cur_meta)->Value.size() > 0) {
+ aiString tstr(((X3DNodeElementMetaString *)cur_meta)->Value.begin()->data());
+
+ pSceneNode.mMetaData->Set(static_cast<unsigned int>(meta_idx), cur_meta->Name, tstr);
+ }
+ } else {
+ throw DeadlyImportError("Postprocess. Unknown metadata type.");
+ } // if((*it)->Type == X3DElemType::ENET_Meta*) else
+ } // for(std::list<X3DNodeElementBase*>::const_iterator it = meta_list.begin(); it != meta_list.end(); it++)
+ } // if( !meta_list.empty() )
+}
+
+} // namespace Assimp
+
+#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER