Browse Source

3MF: Migration.

kimkulling 5 years ago
parent
commit
7e93ae4428

+ 0 - 1
code/AssetLib/3MF/3MFXmlTags.h

@@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
 
 Copyright (c) 2006-2020, assimp team
 
-
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,

+ 0 - 1
code/AssetLib/3MF/D3MFExporter.cpp

@@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
 
 Copyright (c) 2006-2020, assimp team
 
-
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,

+ 0 - 1
code/AssetLib/3MF/D3MFExporter.h

@@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
 
 Copyright (c) 2006-2020, assimp team
 
-
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,

+ 84 - 110
code/AssetLib/3MF/D3MFImporter.cpp

@@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
 
 Copyright (c) 2006-2020, assimp team
 
-
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -46,12 +45,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include <assimp/StringComparison.h>
 #include <assimp/StringUtils.h>
+#include <assimp/XmlParser.h>
 #include <assimp/ZipArchiveIOSystem.h>
 #include <assimp/importerdesc.h>
 #include <assimp/scene.h>
 #include <assimp/DefaultLogger.hpp>
 #include <assimp/IOSystem.hpp>
-
 #include <cassert>
 #include <map>
 #include <memory>
@@ -61,7 +60,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "3MFXmlTags.h"
 #include "D3MFOpcPackage.h"
 #include <assimp/fast_atof.h>
-#include <assimp/irrXMLWrapper.h>
 
 #include <iomanip>
 
@@ -73,12 +71,12 @@ public:
     using MatArray = std::vector<aiMaterial *>;
     using MatId2MatArray = std::map<unsigned int, std::vector<unsigned int>>;
 
-    XmlSerializer(XmlReader *xmlReader) :
+    XmlSerializer(XmlParser *xmlParser) :
             mMeshes(),
             mMatArray(),
             mActiveMatGroup(99999999),
             mMatId2MatArray(),
-            xmlReader(xmlReader) {
+            mXmlParser(xmlParser) {
         // empty
     }
 
@@ -95,16 +93,17 @@ public:
         std::vector<aiNode *> children;
 
         std::string nodeName;
-        while (ReadToEndElement(D3MF::XmlTag::model)) {
-            nodeName = xmlReader->getNodeName();
-            if (nodeName == D3MF::XmlTag::object) {
-                children.push_back(ReadObject(scene));
-            } else if (nodeName == D3MF::XmlTag::build) {
+        XmlNode *root = mXmlParser->getRootNode();
+        for (XmlNode &currentNode : root->children()) {
+            const std::string &currentNodeName = currentNode.name();
+            if (currentNodeName == D3MF::XmlTag::object) {
+                children.push_back(ReadObject(currentNode, scene));
+            } else if (currentNodeName == D3MF::XmlTag::build) {
                 //
-            } else if (nodeName == D3MF::XmlTag::basematerials) {
-                ReadBaseMaterials();
-            } else if (nodeName == D3MF::XmlTag::meta) {
-                ReadMetadata();
+            } else if (currentNodeName == D3MF::XmlTag::basematerials) {
+                ReadBaseMaterials(currentNode);
+            } else if (currentNodeName == D3MF::XmlTag::meta) {
+                ReadMetadata(currentNode);
             }
         }
 
@@ -141,31 +140,30 @@ public:
     }
 
 private:
-    aiNode *ReadObject(aiScene *scene) {
-        std::unique_ptr<aiNode> node(new aiNode());
+    aiNode *ReadObject(XmlNode &node, aiScene *scene) {
+        std::unique_ptr<aiNode> nodePtr(new aiNode());
 
         std::vector<unsigned long> meshIds;
 
-        const char *attrib(nullptr);
         std::string name, type;
-        attrib = xmlReader->getAttributeValue(D3MF::XmlTag::id.c_str());
-        if (nullptr != attrib) {
-            name = attrib;
+        pugi::xml_attribute attr = node.attribute(D3MF::XmlTag::id.c_str());
+        if (!attr.empty()) {
+            name = attr.as_string();
         }
-        attrib = xmlReader->getAttributeValue(D3MF::XmlTag::type.c_str());
-        if (nullptr != attrib) {
-            type = attrib;
+        attr = node.attribute(D3MF::XmlTag::id.c_str());
+        if (!attr.empty()) {
+            type = attr.as_string();
         }
 
-        node->mParent = scene->mRootNode;
-        node->mName.Set(name);
+        nodePtr->mParent = scene->mRootNode;
+        nodePtr->mName.Set(name);
 
         size_t meshIdx = mMeshes.size();
 
-        while (ReadToEndElement(D3MF::XmlTag::object)) {
-            if (xmlReader->getNodeName() == D3MF::XmlTag::mesh) {
-                auto mesh = ReadMesh();
-
+        for (pugi::xml_node &currentNode : node.children()) {
+            const std::string &currentName = currentNode.name();
+            if (currentName == D3MF::XmlTag::mesh) {
+                auto mesh = ReadMesh(currentNode);
                 mesh->mName.Set(name);
                 mMeshes.push_back(mesh);
                 meshIds.push_back(static_cast<unsigned long>(meshIdx));
@@ -173,33 +171,34 @@ private:
             }
         }
 
-        node->mNumMeshes = static_cast<unsigned int>(meshIds.size());
+        nodePtr->mNumMeshes = static_cast<unsigned int>(meshIds.size());
 
-        node->mMeshes = new unsigned int[node->mNumMeshes];
+        nodePtr->mMeshes = new unsigned int[nodePtr->mNumMeshes];
 
-        std::copy(meshIds.begin(), meshIds.end(), node->mMeshes);
+        std::copy(meshIds.begin(), meshIds.end(), nodePtr->mMeshes);
 
-        return node.release();
+        return nodePtr.release();
     }
 
-    aiMesh *ReadMesh() {
+    aiMesh *ReadMesh(XmlNode &node) {
         aiMesh *mesh = new aiMesh();
-        while (ReadToEndElement(D3MF::XmlTag::mesh)) {
-            if (xmlReader->getNodeName() == D3MF::XmlTag::vertices) {
-                ImportVertices(mesh);
-            } else if (xmlReader->getNodeName() == D3MF::XmlTag::triangles) {
-                ImportTriangles(mesh);
+        for (pugi::xml_node &currentNode : node.children()) {
+            const std::string &currentName = currentNode.name();
+            if (currentName == D3MF::XmlTag::vertices) {
+                ImportVertices(currentNode, mesh);
+            } else if (currentName == D3MF::XmlTag::triangles) {
+                ImportTriangles(currentNode, mesh);
             }
+
         }
 
         return mesh;
     }
 
-    void ReadMetadata() {
-        const std::string name = xmlReader->getAttributeValue(D3MF::XmlTag::meta_name.c_str());
-        xmlReader->read();
-        const std::string value = xmlReader->getNodeData();
-
+    void ReadMetadata(XmlNode &node) {
+        pugi::xml_attribute attribute = node.attribute(D3MF::XmlTag::meta_name.c_str());
+        const std::string name = attribute.as_string();
+        const std::string value = node.value();
         if (name.empty()) {
             return;
         }
@@ -210,37 +209,36 @@ private:
         mMetaData.push_back(entry);
     }
 
-    void ImportVertices(aiMesh *mesh) {
+    void ImportVertices(XmlNode &node, aiMesh *mesh) {
         std::vector<aiVector3D> vertices;
-        while (ReadToEndElement(D3MF::XmlTag::vertices)) {
-            if (xmlReader->getNodeName() == D3MF::XmlTag::vertex) {
-                vertices.push_back(ReadVertex());
+        for (pugi::xml_node &currentNode : node.children()) {
+            const std::string &currentName = currentNode.name();
+            if (currentName == D3MF::XmlTag::vertex) {
+                vertices.push_back(ReadVertex(currentNode));
             }
         }
+
         mesh->mNumVertices = static_cast<unsigned int>(vertices.size());
         mesh->mVertices = new aiVector3D[mesh->mNumVertices];
-
         std::copy(vertices.begin(), vertices.end(), mesh->mVertices);
     }
 
-    aiVector3D ReadVertex() {
+    aiVector3D ReadVertex(XmlNode &node) {
         aiVector3D vertex;
-
-        vertex.x = ai_strtof(xmlReader->getAttributeValue(D3MF::XmlTag::x.c_str()), nullptr);
-        vertex.y = ai_strtof(xmlReader->getAttributeValue(D3MF::XmlTag::y.c_str()), nullptr);
-        vertex.z = ai_strtof(xmlReader->getAttributeValue(D3MF::XmlTag::z.c_str()), nullptr);
+        vertex.x = ai_strtof(node.attribute(D3MF::XmlTag::x.c_str()).as_string(), nullptr);
+        vertex.x = ai_strtof(node.attribute(D3MF::XmlTag::y.c_str()).as_string(), nullptr);
+        vertex.z = ai_strtof(node.attribute(D3MF::XmlTag::z.c_str()).as_string(), nullptr);
 
         return vertex;
     }
 
-    void ImportTriangles(aiMesh *mesh) {
+    void ImportTriangles(XmlNode &node, aiMesh *mesh) {
         std::vector<aiFace> faces;
-
-        while (ReadToEndElement(D3MF::XmlTag::triangles)) {
-            const std::string nodeName(xmlReader->getNodeName());
-            if (xmlReader->getNodeName() == D3MF::XmlTag::triangle) {
-                faces.push_back(ReadTriangle());
-                const char *pidToken(xmlReader->getAttributeValue(D3MF::XmlTag::p1.c_str()));
+        for (pugi::xml_node &currentNode : node.children()) {
+            const std::string &currentName = currentNode.name();
+            if (currentName == D3MF::XmlTag::triangle) {
+                faces.push_back(ReadTriangle(currentNode));
+                const char *pidToken = currentNode.attribute(D3MF::XmlTag::p1.c_str()).as_string();
                 if (nullptr != pidToken) {
                     int matIdx(std::atoi(pidToken));
                     mesh->mMaterialIndex = matIdx;
@@ -255,21 +253,21 @@ private:
         std::copy(faces.begin(), faces.end(), mesh->mFaces);
     }
 
-    aiFace ReadTriangle() {
+    aiFace ReadTriangle(XmlNode &node) {
         aiFace face;
 
         face.mNumIndices = 3;
         face.mIndices = new unsigned int[face.mNumIndices];
-        face.mIndices[0] = static_cast<unsigned int>(std::atoi(xmlReader->getAttributeValue(D3MF::XmlTag::v1.c_str())));
-        face.mIndices[1] = static_cast<unsigned int>(std::atoi(xmlReader->getAttributeValue(D3MF::XmlTag::v2.c_str())));
-        face.mIndices[2] = static_cast<unsigned int>(std::atoi(xmlReader->getAttributeValue(D3MF::XmlTag::v3.c_str())));
+        face.mIndices[0] = static_cast<unsigned int>(std::atoi(node.attribute(D3MF::XmlTag::v1.c_str()).as_string()));
+        face.mIndices[1] = static_cast<unsigned int>(std::atoi(node.attribute(D3MF::XmlTag::v2.c_str()).as_string()));
+        face.mIndices[2] = static_cast<unsigned int>(std::atoi(node.attribute(D3MF::XmlTag::v3.c_str()).as_string()));
 
         return face;
     }
 
-    void ReadBaseMaterials() {
+    void ReadBaseMaterials(XmlNode &node) {
         std::vector<unsigned int> MatIdArray;
-        const char *baseMaterialId(xmlReader->getAttributeValue(D3MF::XmlTag::basematerials_id.c_str()));
+        const char *baseMaterialId = node.attribute(D3MF::XmlTag::basematerials_id.c_str()).as_string();
         if (nullptr != baseMaterialId) {
             unsigned int id = std::atoi(baseMaterialId);
             const size_t newMatIdx(mMatArray.size());
@@ -287,9 +285,7 @@ private:
             mMatId2MatArray[mActiveMatGroup] = MatIdArray;
         }
 
-        while (ReadToEndElement(D3MF::XmlTag::basematerials)) {
-            mMatArray.push_back(readMaterialDef());
-        }
+        mMatArray.push_back(readMaterialDef(node));
     }
 
     bool parseColor(const char *color, aiColor4D &diffuse) {
@@ -339,19 +335,23 @@ private:
         return true;
     }
 
-    void assignDiffuseColor(aiMaterial *mat) {
-        const char *color = xmlReader->getAttributeValue(D3MF::XmlTag::basematerials_displaycolor.c_str());
+    void assignDiffuseColor(XmlNode &node, aiMaterial *mat) {
+        const char *color = node.attribute(D3MF::XmlTag::basematerials_displaycolor.c_str()).as_string();
+        //const char *color = xmlReader->getAttributeValue(D3MF::XmlTag::basematerials_displaycolor.c_str());
         aiColor4D diffuse;
         if (parseColor(color, diffuse)) {
             mat->AddProperty<aiColor4D>(&diffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
         }
     }
-    aiMaterial *readMaterialDef() {
+
+    aiMaterial *readMaterialDef(XmlNode &node) {
         aiMaterial *mat(nullptr);
         const char *name(nullptr);
-        const std::string nodeName(xmlReader->getNodeName());
+        const std::string nodeName = node.name();
+        //const std::string nodeName(xmlReader->getNodeName());
         if (nodeName == D3MF::XmlTag::basematerials_base) {
-            name = xmlReader->getAttributeValue(D3MF::XmlTag::basematerials_name.c_str());
+            name = node.attribute(D3MF::XmlTag::basematerials_name.c_str()).as_string();
+            //name = xmlReader->getAttributeValue(D3MF::XmlTag::basematerials_name.c_str());
             std::string stdMatName;
             aiString matName;
             std::string strId(to_string(mActiveMatGroup));
@@ -368,40 +368,12 @@ private:
             mat = new aiMaterial;
             mat->AddProperty(&matName, AI_MATKEY_NAME);
 
-            assignDiffuseColor(mat);
+            assignDiffuseColor(node, mat);
         }
 
         return mat;
     }
 
-private:
-    bool ReadToStartElement(const std::string &startTag) {
-        while (xmlReader->read()) {
-            const std::string &nodeName(xmlReader->getNodeName());
-            if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT && nodeName == startTag) {
-                return true;
-            } else if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT_END && nodeName == startTag) {
-                return false;
-            }
-        }
-
-        return false;
-    }
-
-    bool ReadToEndElement(const std::string &closeTag) {
-        while (xmlReader->read()) {
-            const std::string &nodeName(xmlReader->getNodeName());
-            if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT) {
-                return true;
-            } else if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT_END && nodeName == closeTag) {
-                return false;
-            }
-        }
-        ASSIMP_LOG_ERROR("unexpected EOF, expected closing <" + closeTag + "> tag");
-
-        return false;
-    }
-
 private:
     struct MetaEntry {
         std::string name;
@@ -412,7 +384,7 @@ private:
     MatArray mMatArray;
     unsigned int mActiveMatGroup;
     MatId2MatArray mMatId2MatArray;
-    XmlReader *xmlReader;
+    XmlParser *mXmlParser;
 };
 
 } //namespace D3MF
@@ -468,12 +440,14 @@ const aiImporterDesc *D3MFImporter::GetInfo() const {
 void D3MFImporter::InternReadFile(const std::string &filename, aiScene *pScene, IOSystem *pIOHandler) {
     D3MF::D3MFOpcPackage opcPackage(pIOHandler, filename);
 
-    std::unique_ptr<CIrrXML_IOStreamReader> xmlStream(new CIrrXML_IOStreamReader(opcPackage.RootStream()));
-    std::unique_ptr<D3MF::XmlReader> xmlReader(irr::io::createIrrXMLReader(xmlStream.get()));
-
-    D3MF::XmlSerializer xmlSerializer(xmlReader.get());
+    //std::unique_ptr<CIrrXML_IOStreamReader> xmlStream(new CIrrXML_IOStreamReader(opcPackage.RootStream()));
+    //std::unique_ptr<D3MF::XmlReader> xmlReader(irr::io::createIrrXMLReader(xmlStream.get()));
 
-    xmlSerializer.ImportXml(pScene);
+    XmlParser xmlParser;
+    if (xmlParser.parse(opcPackage.RootStream())) {
+        D3MF::XmlSerializer xmlSerializer(&xmlParser);
+        xmlSerializer.ImportXml(pScene);
+    }
 }
 
 } // Namespace Assimp

+ 22 - 23
code/AssetLib/3MF/D3MFOpcPackage.cpp

@@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
 
 Copyright (c) 2006-2020, assimp team
 
-
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -45,6 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "D3MFOpcPackage.h"
 #include <assimp/Exceptional.h>
 
+#include <assimp/XmlParser.h>
 #include <assimp/ZipArchiveIOSystem.h>
 #include <assimp/ai_assert.h>
 #include <assimp/DefaultLogger.hpp>
@@ -68,27 +68,23 @@ typedef std::shared_ptr<OpcPackageRelationship> OpcPackageRelationshipPtr;
 
 class OpcPackageRelationshipReader {
 public:
-    OpcPackageRelationshipReader(XmlReader *xmlReader) {
-        while (xmlReader->read()) {
-            if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT &&
-                    xmlReader->getNodeName() == XmlTag::RELS_RELATIONSHIP_CONTAINER) {
-                ParseRootNode(xmlReader);
-            }
+    OpcPackageRelationshipReader(XmlParser &parser) {
+        XmlNode *root = parser.getRootNode();
+        if (nullptr != root) {
+            ParseRootNode(*root);
         }
     }
 
-    void ParseRootNode(XmlReader *xmlReader) {
-        ParseAttributes(xmlReader);
+    void ParseRootNode(XmlNode &node) {
+        ParseAttributes(node);
+
+        for (XmlNode currentNode : node.children()) {
+            ParseChildNode(currentNode);
 
-        while (xmlReader->read()) {
-            if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT &&
-                    xmlReader->getNodeName() == XmlTag::RELS_RELATIONSHIP_NODE) {
-                ParseChildNode(xmlReader);
-            }
         }
     }
 
-    void ParseAttributes(XmlReader *) {
+    void ParseAttributes(XmlNode &/*node*/) {
         // empty
     }
 
@@ -99,12 +95,12 @@ public:
         return true;
     }
 
-    void ParseChildNode(XmlReader *xmlReader) {
+    void ParseChildNode(XmlNode &node) {
         OpcPackageRelationshipPtr relPtr(new OpcPackageRelationship());
 
-        relPtr->id = xmlReader->getAttributeValueSafe(XmlTag::RELS_ATTRIB_ID.c_str());
-        relPtr->type = xmlReader->getAttributeValueSafe(XmlTag::RELS_ATTRIB_TYPE.c_str());
-        relPtr->target = xmlReader->getAttributeValueSafe(XmlTag::RELS_ATTRIB_TARGET.c_str());
+        relPtr->id = node.attribute(XmlTag::RELS_ATTRIB_ID.c_str()).as_string();
+        relPtr->type = node.attribute(XmlTag::RELS_ATTRIB_TYPE.c_str()).as_string();
+        relPtr->target = node.attribute(XmlTag::RELS_ATTRIB_TARGET.c_str()).as_string();
         if (validateRels(relPtr)) {
             m_relationShips.push_back(relPtr);
         }
@@ -115,7 +111,8 @@ public:
 
 // ------------------------------------------------------------------------------------------------
 D3MFOpcPackage::D3MFOpcPackage(IOSystem *pIOHandler, const std::string &rFile) :
-        mRootStream(nullptr), mZipArchive() {
+        mRootStream(nullptr),
+        mZipArchive() {
     mZipArchive.reset(new ZipArchiveIOSystem(pIOHandler, rFile));
     if (!mZipArchive->isOpen()) {
         throw DeadlyImportError("Failed to open file " + rFile + ".");
@@ -182,10 +179,12 @@ bool D3MFOpcPackage::validate() {
 }
 
 std::string D3MFOpcPackage::ReadPackageRootRelationship(IOStream *stream) {
-    std::unique_ptr<CIrrXML_IOStreamReader> xmlStream(new CIrrXML_IOStreamReader(stream));
-    std::unique_ptr<XmlReader> xml(irr::io::createIrrXMLReader(xmlStream.get()));
+    XmlParser xmlParser;
+    if (!xmlParser.parse(stream)) {
+        return "";
+    }
 
-    OpcPackageRelationshipReader reader(xml.get());
+    OpcPackageRelationshipReader reader(xmlParser);
 
     auto itr = std::find_if(reader.m_relationShips.begin(), reader.m_relationShips.end(), [](const OpcPackageRelationshipPtr &rel) {
         return rel->type == XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE;

+ 3 - 7
code/AssetLib/3MF/D3MFOpcPackage.h

@@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
 
 Copyright (c) 2006-2020, assimp team
 
-
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -44,18 +43,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #define D3MFOPCPACKAGE_H
 
 #include <memory>
-
+#include <string>
 #include <assimp/IOSystem.hpp>
-#include <assimp/irrXMLWrapper.h>
+//#include <assimp/irrXMLWrapper.h>
 
 namespace Assimp {
     class ZipArchiveIOSystem;
 
 namespace D3MF {
 
-using XmlReader = irr::io::IrrXMLReader ;
-using XmlReaderPtr = std::shared_ptr<XmlReader> ;
-
 struct OpcPackageRelationship {
     std::string id;
     std::string type;
@@ -64,7 +60,7 @@ struct OpcPackageRelationship {
 
 class D3MFOpcPackage {
 public:
-    D3MFOpcPackage( IOSystem* pIOHandler, const std::string& rFile );
+    D3MFOpcPackage( IOSystem* pIOHandler, const std::string& file );
     ~D3MFOpcPackage();
     IOStream* RootStream() const;
     bool validate();

+ 0 - 1864
code/AssetLib/X3D/FIReader.cpp

@@ -1,1864 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2020, 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   FIReader.cpp
-/// \brief  Reader for Fast Infoset encoded binary XML files.
-/// \date   2017
-/// \author Patrick Daehne
-
-#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
-
-#include "FIReader.hpp"
-#include <assimp/StringUtils.h>
-
-// Workaround for issue #1361
-// https://github.com/assimp/assimp/issues/1361
-#ifdef __ANDROID__
-#define _GLIBCXX_USE_C99 1
-#endif
-
-#include <assimp/Exceptional.h>
-#include <assimp/MemoryIOWrapper.h>
-#include <assimp/types.h>
-#include <assimp/IOStream.hpp>
-#ifdef ASSIMP_USE_HUNTER
-#include <utf8/utf8.h>
-#else
-#include "../contrib/utf8cpp/source/utf8.h"
-#endif
-#include <assimp/fast_atof.h>
-#include <iomanip>
-#include <iostream>
-#include <map>
-#include <sstream>
-#include <stack>
-
-namespace Assimp {
-
-static const char *parseErrorMessage = "Fast Infoset parse error";
-
-static const char *xmlDeclarations[] = {
-    "<?xml encoding='finf'?>",
-    "<?xml encoding='finf' standalone='yes'?>",
-    "<?xml encoding='finf' standalone='no'?>",
-    "<?xml version='1.0' encoding='finf'?>",
-    "<?xml version='1.0' encoding='finf' standalone='yes'?>",
-    "<?xml version='1.0' encoding='finf' standalone='no'?>",
-    "<?xml version='1.1' encoding='finf'?>",
-    "<?xml version='1.1' encoding='finf' standalone='yes'?>",
-    "<?xml version='1.1' encoding='finf' standalone='no'?>"
-};
-
-static size_t parseMagic(const uint8_t *data, const uint8_t *dataEnd) {
-    ai_assert(nullptr != data);
-    ai_assert(nullptr != dataEnd);
-
-    if (dataEnd - data < 4) {
-        return 0;
-    }
-
-    uint32_t magic = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
-    switch (magic) {
-    case 0xe0000001:
-        return 4;
-    case 0x3c3f786d: // "<?xm"
-    {
-        size_t xmlDeclarationsLength = sizeof(xmlDeclarations) / sizeof(xmlDeclarations[0]);
-        for (size_t i = 0; i < xmlDeclarationsLength; ++i) {
-            auto xmlDeclaration = xmlDeclarations[i];
-            ptrdiff_t xmlDeclarationLength = strlen(xmlDeclaration);
-            if ((dataEnd - data >= xmlDeclarationLength) && (memcmp(xmlDeclaration, data, xmlDeclarationLength) == 0)) {
-                data += xmlDeclarationLength;
-                if (dataEnd - data < 4) {
-                    return 0;
-                }
-                magic = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
-                return magic == 0xe0000001 ? xmlDeclarationLength + 4 : 0;
-            }
-        }
-        return 0;
-    }
-    default:
-        return 0;
-    }
-}
-
-static std::string parseUTF8String(const uint8_t *data, size_t len) {
-    return std::string((char *)data, len);
-}
-
-static std::string parseUTF16String(const uint8_t *data, size_t len) {
-    if (len & 1) {
-        throw DeadlyImportError(parseErrorMessage);
-    }
-    size_t numShorts = len / 2;
-    std::vector<short> utf16;
-    utf16.reserve(numShorts);
-    for (size_t i = 0; i < numShorts; ++i) {
-        short v = (data[0] << 8) | data[1];
-        utf16.push_back(v);
-        data += 2;
-    }
-    std::string result;
-    utf8::utf16to8(utf16.begin(), utf16.end(), back_inserter(result));
-    return result;
-}
-
-struct FIStringValueImpl : public FIStringValue {
-    FIStringValueImpl(std::string &&value_) {
-        value = std::move(value_);
-    }
-
-    const std::string &toString() const override {
-        return value;
-    }
-};
-
-std::shared_ptr<FIStringValue> FIStringValue::create(std::string &&value) {
-    return std::make_shared<FIStringValueImpl>(std::move(value));
-}
-
-struct FIHexValueImpl : public FIHexValue {
-    mutable std::string strValue;
-    mutable bool strValueValid;
-
-    FIHexValueImpl(std::vector<uint8_t> &&value_) :
-            strValueValid(false) {
-        value = std::move(value_);
-    }
-
-    const std::string &toString() const override {
-        if (!strValueValid) {
-            strValueValid = true;
-            std::ostringstream os;
-            os << std::hex << std::uppercase << std::setfill('0');
-            std::for_each(value.begin(), value.end(), [&](uint8_t c) { os << std::setw(2) << static_cast<int>(c); });
-            strValue = os.str();
-        }
-
-        return strValue;
-    }
-};
-
-std::shared_ptr<FIHexValue> FIHexValue::create(std::vector<uint8_t> &&value) {
-    return std::make_shared<FIHexValueImpl>(std::move(value));
-}
-
-struct FIBase64ValueImpl : public FIBase64Value {
-    mutable std::string strValue;
-    mutable bool strValueValid;
-
-    FIBase64ValueImpl(std::vector<uint8_t> &&value_) :
-            strValueValid(false) {
-        value = std::move(value_);
-    }
-
-    const std::string &toString() const override {
-        if (!strValueValid) {
-            strValueValid = true;
-            std::ostringstream os;
-            uint8_t c1 = 0, c2;
-            int imod3 = 0;
-            std::vector<uint8_t>::size_type valueSize = value.size();
-            for (std::vector<uint8_t>::size_type i = 0; i < valueSize; ++i) {
-                c2 = value[i];
-                switch (imod3) {
-                case 0:
-                    os << basis_64[c2 >> 2];
-                    imod3 = 1;
-                    break;
-                case 1:
-                    os << basis_64[((c1 & 0x03) << 4) | ((c2 & 0xf0) >> 4)];
-                    imod3 = 2;
-                    break;
-                case 2:
-                    os << basis_64[((c1 & 0x0f) << 2) | ((c2 & 0xc0) >> 6)] << basis_64[c2 & 0x3f];
-                    imod3 = 0;
-                    break;
-                }
-                c1 = c2;
-            }
-            switch (imod3) {
-            case 1:
-                os << basis_64[(c1 & 0x03) << 4] << "==";
-                break;
-            case 2:
-                os << basis_64[(c1 & 0x0f) << 2] << '=';
-                break;
-            }
-            strValue = os.str();
-        }
-
-        return strValue;
-    };
-
-    static const char basis_64[];
-};
-
-const char FIBase64ValueImpl::basis_64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
-std::shared_ptr<FIBase64Value> FIBase64Value::create(std::vector<uint8_t> &&value) {
-    return std::make_shared<FIBase64ValueImpl>(std::move(value));
-}
-
-struct FIShortValueImpl : public FIShortValue {
-    mutable std::string strValue;
-    mutable bool strValueValid;
-
-    FIShortValueImpl(std::vector<int16_t> &&value_) :
-            strValueValid(false) {
-        value = std::move(value_);
-    }
-
-    const std::string &toString() const override {
-        if (!strValueValid) {
-            strValueValid = true;
-            std::ostringstream os;
-            int n = 0;
-            std::for_each(value.begin(), value.end(), [&](int16_t s) { if (++n > 1) os << ' '; os << s; });
-            strValue = os.str();
-        }
-
-        return strValue;
-    }
-};
-
-std::shared_ptr<FIShortValue> FIShortValue::create(std::vector<int16_t> &&value) {
-    return std::make_shared<FIShortValueImpl>(std::move(value));
-}
-
-struct FIIntValueImpl : public FIIntValue {
-    mutable std::string strValue;
-    mutable bool strValueValid;
-
-    FIIntValueImpl(std::vector<int32_t> &&value_) :
-            strValueValid(false) {
-        value = std::move(value_);
-    }
-
-    const std::string &toString() const override {
-        if (!strValueValid) {
-            strValueValid = true;
-            std::ostringstream os;
-            int n = 0;
-            std::for_each(value.begin(), value.end(), [&](int32_t i) { if (++n > 1) os << ' '; os << i; });
-            strValue = os.str();
-        }
-
-        return strValue;
-    }
-};
-
-std::shared_ptr<FIIntValue> FIIntValue::create(std::vector<int32_t> &&value) {
-    return std::make_shared<FIIntValueImpl>(std::move(value));
-}
-
-struct FILongValueImpl : public FILongValue {
-    mutable std::string strValue;
-    mutable bool strValueValid;
-
-    FILongValueImpl(std::vector<int64_t> &&value_) :
-            strValueValid(false) {
-        value = std::move(value_);
-    }
-
-    const std::string &toString() const override {
-        if (!strValueValid) {
-            strValueValid = true;
-            std::ostringstream os;
-            int n = 0;
-            std::for_each(value.begin(), value.end(), [&](int64_t l) { if (++n > 1) os << ' '; os << l; });
-            strValue = os.str();
-        }
-
-        return strValue;
-    }
-};
-
-std::shared_ptr<FILongValue> FILongValue::create(std::vector<int64_t> &&value) {
-    return std::make_shared<FILongValueImpl>(std::move(value));
-}
-
-struct FIBoolValueImpl : public FIBoolValue {
-    mutable std::string strValue;
-    mutable bool strValueValid;
-
-    FIBoolValueImpl(std::vector<bool> &&value_) :
-            strValueValid(false) {
-        value = std::move(value_);
-    }
-
-    const std::string &toString() const override {
-        if (!strValueValid) {
-            strValueValid = true;
-            std::ostringstream os;
-            os << std::boolalpha;
-            int n = 0;
-            std::for_each(value.begin(), value.end(), [&](bool b) {
-                if (++n > 1) os << ' ';
-                os << b;
-            });
-            strValue = os.str();
-        }
-
-        return strValue;
-    };
-};
-
-std::shared_ptr<FIBoolValue> FIBoolValue::create(std::vector<bool> &&value) {
-    return std::make_shared<FIBoolValueImpl>(std::move(value));
-}
-
-struct FIFloatValueImpl : public FIFloatValue {
-    mutable std::string strValue;
-    mutable bool strValueValid;
-
-    FIFloatValueImpl(std::vector<float> &&value_) :
-            strValueValid(false) {
-        value = std::move(value_);
-    }
-
-    const std::string &toString() const override {
-        if (!strValueValid) {
-            strValueValid = true;
-            std::ostringstream os;
-            int n = 0;
-            std::for_each(value.begin(), value.end(), [&](float f) { if (++n > 1) os << ' '; os << f; });
-            strValue = os.str();
-        }
-
-        return strValue;
-    }
-};
-
-std::shared_ptr<FIFloatValue> FIFloatValue::create(std::vector<float> &&value) {
-    return std::make_shared<FIFloatValueImpl>(std::move(value));
-}
-
-struct FIDoubleValueImpl : public FIDoubleValue {
-    mutable std::string strValue;
-    mutable bool strValueValid;
-
-    FIDoubleValueImpl(std::vector<double> &&value_) :
-            strValueValid(false) {
-        value = std::move(value_);
-    }
-
-    const std::string &toString() const override {
-        if (!strValueValid) {
-            strValueValid = true;
-            std::ostringstream os;
-            int n = 0;
-            std::for_each(value.begin(), value.end(), [&](double d) { if (++n > 1) os << ' '; os << d; });
-            strValue = os.str();
-        }
-        return strValue;
-    }
-};
-
-std::shared_ptr<FIDoubleValue> FIDoubleValue::create(std::vector<double> &&value) {
-    return std::make_shared<FIDoubleValueImpl>(std::move(value));
-}
-
-struct FIUUIDValueImpl : public FIUUIDValue {
-    mutable std::string strValue;
-    mutable bool strValueValid;
-
-    FIUUIDValueImpl(std::vector<uint8_t> &&value_) :
-            strValueValid(false) {
-        value = std::move(value_);
-    }
-
-    const std::string &toString() const override {
-        if (!strValueValid) {
-            strValueValid = true;
-            std::ostringstream os;
-            os << std::hex << std::uppercase << std::setfill('0');
-            std::vector<uint8_t>::size_type valueSize = value.size();
-            for (std::vector<uint8_t>::size_type i = 0; i < valueSize; ++i) {
-                switch (i & 15) {
-                case 0:
-                    if (i > 0) {
-                        os << ' ';
-                    }
-                    os << std::setw(2) << static_cast<int>(value[i]);
-                    break;
-                case 4:
-                case 6:
-                case 8:
-                case 10:
-                    os << '-';
-                    // intentionally fall through!
-                case 1:
-                case 2:
-                case 3:
-                case 5:
-                case 7:
-                case 9:
-                case 11:
-                case 12:
-                case 13:
-                case 14:
-                case 15:
-                    os << std::setw(2) << static_cast<int>(value[i]);
-                    break;
-                }
-            }
-            strValue = os.str();
-        }
-        return strValue;
-    }
-};
-
-std::shared_ptr<FIUUIDValue> FIUUIDValue::create(std::vector<uint8_t> &&value) {
-    return std::make_shared<FIUUIDValueImpl>(std::move(value));
-}
-
-struct FICDATAValueImpl : public FICDATAValue {
-    FICDATAValueImpl(std::string &&value_) {
-        value = std::move(value_);
-    }
-
-    const std::string &toString() const override {
-        return value;
-    }
-};
-
-std::shared_ptr<FICDATAValue> FICDATAValue::create(std::string &&value) {
-    return std::make_shared<FICDATAValueImpl>(std::move(value));
-}
-
-struct FIHexDecoder : public FIDecoder {
-    std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) override {
-        return FIHexValue::create(std::vector<uint8_t>(data, data + len));
-    }
-};
-
-struct FIBase64Decoder : public FIDecoder {
-    std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) override {
-        return FIBase64Value::create(std::vector<uint8_t>(data, data + len));
-    }
-};
-
-struct FIShortDecoder : public FIDecoder {
-    std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) override {
-        if (len & 1) {
-            throw DeadlyImportError(parseErrorMessage);
-        }
-        std::vector<int16_t> value;
-        size_t numShorts = len / 2;
-        value.reserve(numShorts);
-        for (size_t i = 0; i < numShorts; ++i) {
-            int16_t v = (data[0] << 8) | data[1];
-            value.push_back(v);
-            data += 2;
-        }
-        return FIShortValue::create(std::move(value));
-    }
-};
-
-struct FIIntDecoder : public FIDecoder {
-    std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) override {
-        if (len & 3) {
-            throw DeadlyImportError(parseErrorMessage);
-        }
-        std::vector<int32_t> value;
-        size_t numInts = len / 4;
-        value.reserve(numInts);
-        for (size_t i = 0; i < numInts; ++i) {
-            int32_t v = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
-            value.push_back(v);
-            data += 4;
-        }
-        return FIIntValue::create(std::move(value));
-    }
-};
-
-struct FILongDecoder : public FIDecoder {
-    std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) override {
-        if (len & 7) {
-            throw DeadlyImportError(parseErrorMessage);
-        }
-        std::vector<int64_t> value;
-        size_t numLongs = len / 8;
-        value.reserve(numLongs);
-        for (size_t i = 0; i < numLongs; ++i) {
-            int64_t b0 = data[0], b1 = data[1], b2 = data[2], b3 = data[3], b4 = data[4], b5 = data[5], b6 = data[6], b7 = data[7];
-            int64_t v = (b0 << 56) | (b1 << 48) | (b2 << 40) | (b3 << 32) | (b4 << 24) | (b5 << 16) | (b6 << 8) | b7;
-            value.push_back(v);
-            data += 8;
-        }
-        return FILongValue::create(std::move(value));
-    }
-};
-
-struct FIBoolDecoder : public FIDecoder {
-    virtual std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) /*override*/ {
-        if (len < 1) {
-            throw DeadlyImportError(parseErrorMessage);
-        }
-        std::vector<bool> value;
-        uint8_t b = *data++;
-        size_t unusedBits = b >> 4;
-        size_t numBools = (len * 8) - 4 - unusedBits;
-        value.reserve(numBools);
-        uint8_t mask = 1 << 3;
-        for (size_t i = 0; i < numBools; ++i) {
-            if (!mask) {
-                mask = 1 << 7;
-                b = *data++;
-            }
-            value.push_back((b & mask) != 0);
-        }
-        return FIBoolValue::create(std::move(value));
-    }
-};
-
-struct FIFloatDecoder : public FIDecoder {
-    virtual std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) /*override*/ {
-        if (len & 3) {
-            throw DeadlyImportError(parseErrorMessage);
-        }
-        std::vector<float> value;
-        size_t numFloats = len / 4;
-        value.reserve(numFloats);
-        for (size_t i = 0; i < numFloats; ++i) {
-            int v = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
-            float f;
-            memcpy(&f, &v, 4);
-            value.push_back(f);
-            data += 4;
-        }
-        return FIFloatValue::create(std::move(value));
-    }
-};
-
-struct FIDoubleDecoder : public FIDecoder {
-    virtual std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) /*override*/ {
-        if (len & 7) {
-            throw DeadlyImportError(parseErrorMessage);
-        }
-        std::vector<double> value;
-        size_t numDoubles = len / 8;
-        value.reserve(numDoubles);
-        for (size_t i = 0; i < numDoubles; ++i) {
-            long long b0 = data[0], b1 = data[1], b2 = data[2], b3 = data[3], b4 = data[4], b5 = data[5], b6 = data[6], b7 = data[7];
-            long long v = (b0 << 56) | (b1 << 48) | (b2 << 40) | (b3 << 32) | (b4 << 24) | (b5 << 16) | (b6 << 8) | b7;
-            double f;
-            memcpy(&f, &v, 8);
-            value.push_back(f);
-            data += 8;
-        }
-        return FIDoubleValue::create(std::move(value));
-    }
-};
-
-struct FIUUIDDecoder : public FIDecoder {
-    virtual std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) /*override*/ {
-        if (len & 15) {
-            throw DeadlyImportError(parseErrorMessage);
-        }
-        return FIUUIDValue::create(std::vector<uint8_t>(data, data + len));
-    }
-};
-
-struct FICDATADecoder : public FIDecoder {
-    virtual std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) /*override*/ {
-        return FICDATAValue::create(parseUTF8String(data, len));
-    }
-};
-
-class CFIReaderImpl : public FIReader {
-public:
-    CFIReaderImpl(std::unique_ptr<uint8_t[]> data_, size_t size) :
-            data(std::move(data_)),
-            dataP(data.get()),
-            dataEnd(data.get() + size),
-            currentNodeType(irr::io::EXN_NONE),
-            emptyElement(false),
-            headerPending(true),
-            terminatorPending(false) {
-        // empty
-    }
-
-    ~CFIReaderImpl() override {
-        // override
-    }
-
-    virtual bool read() {
-        if (headerPending) {
-            headerPending = false;
-            parseHeader();
-        }
-        if (terminatorPending) {
-            terminatorPending = false;
-            if (elementStack.empty()) {
-                return false;
-            }
-            nodeName = elementStack.top();
-            elementStack.pop();
-            currentNodeType = nodeName.empty() ? irr::io::EXN_UNKNOWN : irr::io::EXN_ELEMENT_END;
-            return true;
-        }
-
-        if (dataP >= dataEnd) {
-            return false;
-        }
-        uint8_t b = *dataP;
-        if (b < 0x80) { // Element (C.2.11.2, C.3.7.2)
-            // C.3
-            parseElement();
-            return true;
-        } else if (b < 0xc0) { // Characters (C.3.7.5)
-            // C.7
-            auto chars = parseNonIdentifyingStringOrIndex3(vocabulary.charactersTable);
-            nodeName = chars->toString();
-            currentNodeType = irr::io::EXN_TEXT;
-            return true;
-        } else if (b < 0xe0) {
-            if ((b & 0xfc) == 0xc4) { // DTD (C.2.11.5)
-                // C.9
-                ++dataP;
-                if (b & 0x02) {
-                    /*const std::string &systemID =*/parseIdentifyingStringOrIndex(vocabulary.otherURITable);
-                }
-                if (b & 0x01) {
-                    /*const std::string &publicID =*/parseIdentifyingStringOrIndex(vocabulary.otherURITable);
-                }
-                elementStack.push(EmptyString);
-                currentNodeType = irr::io::EXN_UNKNOWN;
-                return true;
-            } else if ((b & 0xfc) == 0xc8) { // Unexpanded entity reference (C.3.7.4)
-                // C.6
-                ++dataP;
-                /*const std::string &name =*/parseIdentifyingStringOrIndex(vocabulary.otherNCNameTable);
-                if (b & 0x02) {
-                    /*const std::string &systemID =*/parseIdentifyingStringOrIndex(vocabulary.otherURITable);
-                }
-                if (b & 0x01) {
-                    /*const std::string &publicID =*/parseIdentifyingStringOrIndex(vocabulary.otherURITable);
-                }
-                currentNodeType = irr::io::EXN_UNKNOWN;
-                return true;
-            }
-        } else if (b < 0xf0) {
-            if (b == 0xe1) { // Processing instruction (C.2.11.3, C.3.7.3)
-                // C.5
-                ++dataP;
-                /*const std::string &target =*/parseIdentifyingStringOrIndex(vocabulary.otherNCNameTable);
-                if (dataEnd - dataP < 1) {
-                    throw DeadlyImportError(parseErrorMessage);
-                }
-                /*std::shared_ptr<const FIValue> data =*/parseNonIdentifyingStringOrIndex1(vocabulary.otherStringTable);
-                currentNodeType = irr::io::EXN_UNKNOWN;
-                return true;
-            } else if (b == 0xe2) { // Comment (C.2.11.4, C.3.7.6)
-                // C.8
-                ++dataP;
-                if (dataEnd - dataP < 1) {
-                    throw DeadlyImportError(parseErrorMessage);
-                }
-                std::shared_ptr<const FIValue> comment = parseNonIdentifyingStringOrIndex1(vocabulary.otherStringTable);
-                nodeName = comment->toString();
-                currentNodeType = irr::io::EXN_COMMENT;
-                return true;
-            }
-        } else { // Terminator (C.2.12, C.3.8)
-            ++dataP;
-            if (b == 0xff) {
-                terminatorPending = true;
-            }
-            if (elementStack.empty()) {
-                return false;
-            } else {
-                nodeName = elementStack.top();
-                elementStack.pop();
-                currentNodeType = nodeName.empty() ? irr::io::EXN_UNKNOWN : irr::io::EXN_ELEMENT_END;
-                return true;
-            }
-        }
-        throw DeadlyImportError(parseErrorMessage);
-    }
-
-    virtual irr::io::EXML_NODE getNodeType() const /*override*/ {
-        return currentNodeType;
-    }
-
-    virtual int getAttributeCount() const /*override*/ {
-        return static_cast<int>(attributes.size());
-    }
-
-    virtual const char *getAttributeName(int idx) const /*override*/ {
-        if (idx < 0 || idx >= (int)attributes.size()) {
-            return nullptr;
-        }
-        return attributes[idx].name.c_str();
-    }
-
-    virtual const char *getAttributeValue(int idx) const /*override*/ {
-        if (idx < 0 || idx >= (int)attributes.size()) {
-            return nullptr;
-        }
-        return attributes[idx].value->toString().c_str();
-    }
-
-    virtual const char *getAttributeValue(const char *name) const /*override*/ {
-        const Attribute *attr = getAttributeByName(name);
-        if (!attr) {
-            return nullptr;
-        }
-        return attr->value->toString().c_str();
-    }
-
-    virtual const char *getAttributeValueSafe(const char *name) const /*override*/ {
-        const Attribute *attr = getAttributeByName(name);
-        if (!attr) {
-            return EmptyString.c_str();
-        }
-        return attr->value->toString().c_str();
-    }
-
-    virtual int getAttributeValueAsInt(const char *name) const /*override*/ {
-        const Attribute *attr = getAttributeByName(name);
-        if (!attr) {
-            return 0;
-        }
-        std::shared_ptr<const FIIntValue> intValue = std::dynamic_pointer_cast<const FIIntValue>(attr->value);
-        if (intValue) {
-            return intValue->value.size() == 1 ? intValue->value.front() : 0;
-        }
-        return atoi(attr->value->toString().c_str());
-    }
-
-    virtual int getAttributeValueAsInt(int idx) const /*override*/ {
-        if (idx < 0 || idx >= (int)attributes.size()) {
-            return 0;
-        }
-        std::shared_ptr<const FIIntValue> intValue = std::dynamic_pointer_cast<const FIIntValue>(attributes[idx].value);
-        if (intValue) {
-            return intValue->value.size() == 1 ? intValue->value.front() : 0;
-        }
-        return atoi(attributes[idx].value->toString().c_str());
-    }
-
-    virtual float getAttributeValueAsFloat(const char *name) const /*override*/ {
-        const Attribute *attr = getAttributeByName(name);
-        if (!attr) {
-            return 0;
-        }
-        std::shared_ptr<const FIFloatValue> floatValue = std::dynamic_pointer_cast<const FIFloatValue>(attr->value);
-        if (floatValue) {
-            return floatValue->value.size() == 1 ? floatValue->value.front() : 0;
-        }
-
-        return fast_atof(attr->value->toString().c_str());
-    }
-
-    virtual float getAttributeValueAsFloat(int idx) const /*override*/ {
-        if (idx < 0 || idx >= (int)attributes.size()) {
-            return 0;
-        }
-        std::shared_ptr<const FIFloatValue> floatValue = std::dynamic_pointer_cast<const FIFloatValue>(attributes[idx].value);
-        if (floatValue) {
-            return floatValue->value.size() == 1 ? floatValue->value.front() : 0;
-        }
-        return fast_atof(attributes[idx].value->toString().c_str());
-    }
-
-    virtual const char *getNodeName() const /*override*/ {
-        return nodeName.c_str();
-    }
-
-    virtual const char *getNodeData() const /*override*/ {
-        return nodeName.c_str();
-    }
-
-    virtual bool isEmptyElement() const /*override*/ {
-        return emptyElement;
-    }
-
-    virtual irr::io::ETEXT_FORMAT getSourceFormat() const /*override*/ {
-        return irr::io::ETF_UTF8;
-    }
-
-    virtual irr::io::ETEXT_FORMAT getParserFormat() const /*override*/ {
-        return irr::io::ETF_UTF8;
-    }
-
-    virtual std::shared_ptr<const FIValue> getAttributeEncodedValue(int idx) const /*override*/ {
-        if (idx < 0 || idx >= (int)attributes.size()) {
-            return nullptr;
-        }
-        return attributes[idx].value;
-    }
-
-    virtual std::shared_ptr<const FIValue> getAttributeEncodedValue(const char *name) const /*override*/ {
-        const Attribute *attr = getAttributeByName(name);
-        if (!attr) {
-            return nullptr;
-        }
-        return attr->value;
-    }
-
-    virtual void registerDecoder(const std::string &algorithmUri, std::unique_ptr<FIDecoder> decoder) /*override*/ {
-        decoderMap[algorithmUri] = std::move(decoder);
-    }
-
-    virtual void registerVocabulary(const std::string &vocabularyUri, const FIVocabulary *_vocabulary) /*override*/ {
-        vocabularyMap[vocabularyUri] = _vocabulary;
-    }
-
-private:
-    struct QName {
-        std::string prefix;
-        std::string uri;
-        std::string name;
-        inline QName() {}
-        inline QName(const FIQName &qname) :
-                prefix(qname.prefix ? qname.prefix : ""), uri(qname.uri ? qname.uri : ""), name(qname.name) {}
-    };
-
-    struct Attribute {
-        QName qname;
-        std::string name;
-        std::shared_ptr<const FIValue> value;
-    };
-
-    struct Vocabulary {
-        std::vector<std::string> restrictedAlphabetTable;
-        std::vector<std::string> encodingAlgorithmTable;
-        std::vector<std::string> prefixTable;
-        std::vector<std::string> namespaceNameTable;
-        std::vector<std::string> localNameTable;
-        std::vector<std::string> otherNCNameTable;
-        std::vector<std::string> otherURITable;
-        std::vector<std::shared_ptr<const FIValue>> attributeValueTable;
-        std::vector<std::shared_ptr<const FIValue>> charactersTable;
-        std::vector<std::shared_ptr<const FIValue>> otherStringTable;
-        std::vector<QName> elementNameTable;
-        std::vector<QName> attributeNameTable;
-        Vocabulary() {
-            prefixTable.push_back("xml");
-            namespaceNameTable.push_back("http://www.w3.org/XML/1998/namespace");
-        }
-    };
-
-    const Attribute *getAttributeByName(const char *name) const {
-        if (!name) {
-            return 0;
-        }
-        std::string n = name;
-        for (int i = 0; i < (int)attributes.size(); ++i) {
-            if (attributes[i].name == n) {
-                return &attributes[i];
-            }
-        }
-        return 0;
-    }
-
-    size_t parseInt2() { // C.25
-        uint8_t b = *dataP++;
-        if (!(b & 0x40)) { // x0...... (C.25.2)
-            return b & 0x3f;
-        } else if ((b & 0x60) == 0x40) { // x10..... ........ (C.25.3)
-            if (dataEnd - dataP > 0) {
-                return (((b & 0x1f) << 8) | *dataP++) + 0x40;
-            }
-        } else if ((b & 0x70) == 0x60) { // x110.... ........ ........ (C.25.4)
-            if (dataEnd - dataP > 1) {
-                size_t result = (((b & 0x0f) << 16) | (dataP[0] << 8) | dataP[1]) + 0x2040;
-                dataP += 2;
-                return result;
-            }
-        }
-        throw DeadlyImportError(parseErrorMessage);
-    }
-
-    size_t parseInt3() { // C.27
-        uint8_t b = *dataP++;
-        if (!(b & 0x20)) { // xx0..... (C.27.2)
-            return b & 0x1f;
-        } else if ((b & 0x38) == 0x20) { // xx100... ........ (C.27.3)
-            if (dataEnd - dataP > 0) {
-                return (((b & 0x07) << 8) | *dataP++) + 0x20;
-            }
-        } else if ((b & 0x38) == 0x28) { // xx101... ........ ........ (C.27.4)
-            if (dataEnd - dataP > 1) {
-                size_t result = (((b & 0x07) << 16) | (dataP[0] << 8) | dataP[1]) + 0x820;
-                dataP += 2;
-                return result;
-            }
-        } else if ((b & 0x3f) == 0x30) { // xx110000 0000.... ........ ........ (C.27.5)
-            if ((dataEnd - dataP > 2) && !(dataP[0] & 0xf0)) {
-                size_t result = (((dataP[0] & 0x0f) << 16) | (dataP[1] << 8) | dataP[2]) + 0x80820;
-                dataP += 3;
-                return result;
-            }
-        }
-        throw DeadlyImportError(parseErrorMessage);
-    }
-
-    size_t parseInt4() { // C.28
-        uint8_t b = *dataP++;
-        if (!(b & 0x10)) { // xxx0.... (C.28.2)
-            return b & 0x0f;
-        } else if ((b & 0x1c) == 0x10) { // xxx100.. ........ (C.28.3)
-            if (dataEnd - dataP > 0) {
-                return (((b & 0x03) << 8) | *dataP++) + 0x10;
-            }
-        } else if ((b & 0x1c) == 0x14) { // xxx101.. ........ ........ (C.28.4)
-            if (dataEnd - dataP > 1) {
-                size_t result = (((b & 0x03) << 16) | (dataP[0] << 8) | dataP[1]) + 0x410;
-                dataP += 2;
-                return result;
-            }
-        } else if ((b & 0x1f) == 0x18) { // xxx11000 0000.... ........ ........ (C.28.5)
-            if ((dataEnd - dataP > 2) && !(dataP[0] & 0xf0)) {
-                size_t result = (((dataP[0] & 0x0f) << 16) | (dataP[1] << 8) | dataP[2]) + 0x40410;
-                dataP += 3;
-                return result;
-            }
-        }
-        throw DeadlyImportError(parseErrorMessage);
-    }
-
-    size_t parseSequenceLen() { // C.21
-        if (dataEnd - dataP > 0) {
-            uint8_t b = *dataP++;
-            if (b < 0x80) { // 0....... (C.21.2)
-                return b;
-            } else if ((b & 0xf0) == 0x80) { // 1000.... ........ ........ (C.21.3)
-                if (dataEnd - dataP > 1) {
-                    size_t result = (((b & 0x0f) << 16) | (dataP[0] << 8) | dataP[1]) + 0x80;
-                    dataP += 2;
-                    return result;
-                }
-            }
-        }
-        throw DeadlyImportError(parseErrorMessage);
-    }
-
-    std::string parseNonEmptyOctetString2() { // C.22
-        // Parse the length of the string
-        uint8_t b = *dataP++ & 0x7f;
-        size_t len;
-        if (!(b & 0x40)) { // x0...... (C.22.3.1)
-            len = b + 1;
-        } else if (b == 0x40) { // x1000000 ........ (C.22.3.2)
-            if (dataEnd - dataP < 1) {
-                throw DeadlyImportError(parseErrorMessage);
-            }
-            len = *dataP++ + 0x41;
-        } else if (b == 0x60) { // x1100000 ........ ........ ........ ........ (C.22.3.3)
-            if (dataEnd - dataP < 4) {
-                throw DeadlyImportError(parseErrorMessage);
-            }
-            len = ((dataP[0] << 24) | (dataP[1] << 16) | (dataP[2] << 8) | dataP[3]) + 0x141;
-            dataP += 4;
-        } else {
-            throw DeadlyImportError(parseErrorMessage);
-        }
-
-        // Parse the string (C.22.4)
-        if (dataEnd - dataP < static_cast<ptrdiff_t>(len)) {
-            throw DeadlyImportError(parseErrorMessage);
-        }
-        std::string s = parseUTF8String(dataP, len);
-        dataP += len;
-
-        return s;
-    }
-
-    size_t parseNonEmptyOctetString5Length() { // C.23
-        // Parse the length of the string
-        size_t b = *dataP++ & 0x0f;
-        if (!(b & 0x08)) { // xxxx0... (C.23.3.1)
-            return b + 1;
-        } else if (b == 0x08) { // xxxx1000 ........ (C.23.3.2)
-            if (dataEnd - dataP > 0) {
-                return *dataP++ + 0x09;
-            }
-        } else if (b == 0x0c) { // xxxx1100 ........ ........ ........ ........ (C.23.3.3)
-            if (dataEnd - dataP > 3) {
-                size_t result = ((dataP[0] << 24) | (dataP[1] << 16) | (dataP[2] << 8) | dataP[3]) + 0x109;
-                dataP += 4;
-                return result;
-            }
-        }
-        throw DeadlyImportError(parseErrorMessage);
-    }
-
-    size_t parseNonEmptyOctetString7Length() { // C.24
-        // Parse the length of the string
-        size_t b = *dataP++ & 0x03;
-        if (!(b & 0x02)) { // xxxxxx0. (C.24.3.1)
-            return b + 1;
-        } else if (b == 0x02) { // xxxxxx10 ........ (C.24.3.2)
-            if (dataEnd - dataP > 0) {
-                return *dataP++ + 0x3;
-            }
-        } else if (b == 0x03) { // xxxxxx11 ........ ........ ........ ........ (C.24.3.3)
-            if (dataEnd - dataP > 3) {
-                size_t result = ((dataP[0] << 24) | (dataP[1] << 16) | (dataP[2] << 8) | dataP[3]) + 0x103;
-                dataP += 4;
-                return result;
-            }
-        }
-        throw DeadlyImportError(parseErrorMessage);
-    }
-
-    std::shared_ptr<const FIValue> parseEncodedData(size_t index, size_t len) {
-        if (index < 32) {
-            FIDecoder *decoder = defaultDecoder[index];
-            if (!decoder) {
-                throw DeadlyImportError("Invalid encoding algorithm index " + to_string(index));
-            }
-            return decoder->decode(dataP, len);
-        } else {
-            if (index - 32 >= vocabulary.encodingAlgorithmTable.size()) {
-                throw DeadlyImportError("Invalid encoding algorithm index " + to_string(index));
-            }
-            std::string uri = vocabulary.encodingAlgorithmTable[index - 32];
-            auto it = decoderMap.find(uri);
-            if (it == decoderMap.end()) {
-                throw DeadlyImportError("Unsupported encoding algorithm " + uri);
-            } else {
-                return it->second->decode(dataP, len);
-            }
-        }
-    }
-
-    std::shared_ptr<const FIValue> parseRestrictedAlphabet(size_t index, size_t len) {
-        std::string alphabet;
-        if (index < 16) {
-            switch (index) {
-            case 0: // numeric
-                alphabet = "0123456789-+.e ";
-                break;
-            case 1: // date and time
-                alphabet = "0123456789-:TZ ";
-                break;
-            default:
-                throw DeadlyImportError("Invalid restricted alphabet index " + to_string(index));
-            }
-        } else {
-            if (index - 16 >= vocabulary.restrictedAlphabetTable.size()) {
-                throw DeadlyImportError("Invalid restricted alphabet index " + to_string(index));
-            }
-            alphabet = vocabulary.restrictedAlphabetTable[index - 16];
-        }
-        std::vector<uint32_t> alphabetUTF32;
-        utf8::utf8to32(alphabet.begin(), alphabet.end(), back_inserter(alphabetUTF32));
-        std::string::size_type alphabetLength = alphabetUTF32.size();
-        if (alphabetLength < 2) {
-            throw DeadlyImportError("Invalid restricted alphabet length " + to_string(alphabetLength));
-        }
-        std::string::size_type bitsPerCharacter = 1;
-        while ((1ull << bitsPerCharacter) <= alphabetLength) {
-            ++bitsPerCharacter;
-        }
-        size_t bitsAvail = 0;
-        uint8_t mask = (1 << bitsPerCharacter) - 1;
-        uint32_t bits = 0;
-        std::string s;
-        for (size_t i = 0; i < len; ++i) {
-            bits = (bits << 8) | dataP[i];
-            bitsAvail += 8;
-            while (bitsAvail >= bitsPerCharacter) {
-                bitsAvail -= bitsPerCharacter;
-                const size_t charIndex = (bits >> bitsAvail) & mask;
-                if (charIndex < alphabetLength) {
-                    s += (char)alphabetUTF32[charIndex];
-                } else if (charIndex != mask) {
-                    throw DeadlyImportError(parseErrorMessage);
-                }
-            }
-        }
-        return FIStringValue::create(std::move(s));
-    }
-
-    std::shared_ptr<const FIValue> parseEncodedCharacterString3() { // C.19
-        std::shared_ptr<const FIValue> result;
-        size_t len;
-        uint8_t b = *dataP;
-        if (b & 0x20) {
-            ++dataP;
-            if (dataEnd - dataP < 1) {
-                throw DeadlyImportError(parseErrorMessage);
-            }
-            size_t index = ((b & 0x0f) << 4) | ((*dataP & 0xf0) >> 4); // C.29
-            len = parseNonEmptyOctetString5Length();
-            if (dataEnd - dataP < static_cast<ptrdiff_t>(len)) {
-                throw DeadlyImportError(parseErrorMessage);
-            }
-            if (b & 0x10) {
-                // encoding algorithm (C.19.3.4)
-                result = parseEncodedData(index, len);
-            } else {
-                // Restricted alphabet (C.19.3.3)
-                result = parseRestrictedAlphabet(index, len);
-            }
-        } else {
-            len = parseNonEmptyOctetString5Length();
-            if (dataEnd - dataP < static_cast<ptrdiff_t>(len)) {
-                throw DeadlyImportError(parseErrorMessage);
-            }
-            if (b & 0x10) {
-                // UTF-16 (C.19.3.2)
-                if (len & 1) {
-                    throw DeadlyImportError(parseErrorMessage);
-                }
-                result = FIStringValue::create(parseUTF16String(dataP, len));
-            } else {
-                // UTF-8 (C.19.3.1)
-                result = FIStringValue::create(parseUTF8String(dataP, len));
-            }
-        }
-        dataP += len;
-        return result;
-    }
-
-    std::shared_ptr<const FIValue> parseEncodedCharacterString5() { // C.20
-        std::shared_ptr<const FIValue> result;
-        size_t len;
-        uint8_t b = *dataP;
-        if (b & 0x08) {
-            ++dataP;
-            if (dataEnd - dataP < 1) {
-                throw DeadlyImportError(parseErrorMessage);
-            }
-            size_t index = ((b & 0x03) << 6) | ((*dataP & 0xfc) >> 2); /* C.29 */
-            len = parseNonEmptyOctetString7Length();
-            if (dataEnd - dataP < static_cast<ptrdiff_t>(len)) {
-                throw DeadlyImportError(parseErrorMessage);
-            }
-            if (b & 0x04) {
-                // encoding algorithm (C.20.3.4)
-                result = parseEncodedData(index, len);
-            } else {
-                // Restricted alphabet (C.20.3.3)
-                result = parseRestrictedAlphabet(index, len);
-            }
-        } else {
-            len = parseNonEmptyOctetString7Length();
-            if (dataEnd - dataP < static_cast<ptrdiff_t>(len)) {
-                throw DeadlyImportError(parseErrorMessage);
-            }
-            if (b & 0x04) {
-                // UTF-16 (C.20.3.2)
-                if (len & 1) {
-                    throw DeadlyImportError(parseErrorMessage);
-                }
-                result = FIStringValue::create(parseUTF16String(dataP, len));
-            } else {
-                // UTF-8 (C.20.3.1)
-                result = FIStringValue::create(parseUTF8String(dataP, len));
-            }
-        }
-        dataP += len;
-        return result;
-    }
-
-    const std::string &parseIdentifyingStringOrIndex(std::vector<std::string> &stringTable) { // C.13
-        if (dataEnd - dataP < 1) {
-            throw DeadlyImportError(parseErrorMessage);
-        }
-        uint8_t b = *dataP;
-        if (b & 0x80) {
-            // We have an index (C.13.4)
-            size_t index = parseInt2();
-            if (index >= stringTable.size()) {
-                throw DeadlyImportError(parseErrorMessage);
-            }
-            return stringTable[index];
-        } else {
-            // We have a string (C.13.3)
-            stringTable.push_back(parseNonEmptyOctetString2());
-            return stringTable.back();
-        }
-    }
-
-    QName parseNameSurrogate() { // C.16
-        if (dataEnd - dataP < 1) {
-            throw DeadlyImportError(parseErrorMessage);
-        }
-        uint8_t b = *dataP++;
-        if (b & 0xfc) { // Padding '000000' C.2.5.5
-            throw DeadlyImportError(parseErrorMessage);
-        }
-        QName result;
-        size_t index;
-        if (b & 0x02) { // prefix (C.16.3)
-            if ((dataEnd - dataP < 1) || (*dataP & 0x80)) {
-                throw DeadlyImportError(parseErrorMessage);
-            }
-            index = parseInt2();
-            if (index >= vocabulary.prefixTable.size()) {
-                throw DeadlyImportError(parseErrorMessage);
-            }
-            result.prefix = vocabulary.prefixTable[index];
-        }
-        if (b & 0x01) { // namespace-name (C.16.4)
-            if ((dataEnd - dataP < 1) || (*dataP & 0x80)) {
-                throw DeadlyImportError(parseErrorMessage);
-            }
-            index = parseInt2();
-            if (index >= vocabulary.namespaceNameTable.size()) {
-                throw DeadlyImportError(parseErrorMessage);
-            }
-            result.uri = vocabulary.namespaceNameTable[index];
-        }
-        // local-name
-        if ((dataEnd - dataP < 1) || (*dataP & 0x80)) {
-            throw DeadlyImportError(parseErrorMessage);
-        }
-        index = parseInt2();
-        if (index >= vocabulary.localNameTable.size()) {
-            throw DeadlyImportError(parseErrorMessage);
-        }
-        result.name = vocabulary.localNameTable[index];
-        return result;
-    }
-
-    const QName &parseQualifiedNameOrIndex2(std::vector<QName> &qNameTable) { // C.17
-        uint8_t b = *dataP;
-        if ((b & 0x7c) == 0x78) { // x11110..
-            // We have a literal (C.17.3)
-            ++dataP;
-            QName result;
-            // prefix (C.17.3.1)
-            result.prefix = b & 0x02 ? parseIdentifyingStringOrIndex(vocabulary.prefixTable) : std::string();
-            // namespace-name (C.17.3.1)
-            result.uri = b & 0x01 ? parseIdentifyingStringOrIndex(vocabulary.namespaceNameTable) : std::string();
-            // local-name
-            result.name = parseIdentifyingStringOrIndex(vocabulary.localNameTable);
-            qNameTable.push_back(result);
-            return qNameTable.back();
-        } else {
-            // We have an index (C.17.4)
-            size_t index = parseInt2();
-            if (index >= qNameTable.size()) {
-                throw DeadlyImportError(parseErrorMessage);
-            }
-            return qNameTable[index];
-        }
-    }
-
-    const QName &parseQualifiedNameOrIndex3(std::vector<QName> &qNameTable) { // C.18
-        uint8_t b = *dataP;
-        if ((b & 0x3c) == 0x3c) { // xx1111..
-            // We have a literal (C.18.3)
-            ++dataP;
-            QName result;
-            // prefix (C.18.3.1)
-            result.prefix = b & 0x02 ? parseIdentifyingStringOrIndex(vocabulary.prefixTable) : std::string();
-            // namespace-name (C.18.3.1)
-            result.uri = b & 0x01 ? parseIdentifyingStringOrIndex(vocabulary.namespaceNameTable) : std::string();
-            // local-name
-            result.name = parseIdentifyingStringOrIndex(vocabulary.localNameTable);
-            qNameTable.push_back(result);
-            return qNameTable.back();
-        } else {
-            // We have an index (C.18.4)
-            size_t index = parseInt3();
-            if (index >= qNameTable.size()) {
-                throw DeadlyImportError(parseErrorMessage);
-            }
-            return qNameTable[index];
-        }
-    }
-
-    std::shared_ptr<const FIValue> parseNonIdentifyingStringOrIndex1(std::vector<std::shared_ptr<const FIValue>> &valueTable) { // C.14
-        uint8_t b = *dataP;
-        if (b == 0xff) { // C.26.2
-            // empty string
-            ++dataP;
-            return EmptyFIString;
-        } else if (b & 0x80) { // C.14.4
-            // We have an index
-            size_t index = parseInt2();
-            if (index >= valueTable.size()) {
-                throw DeadlyImportError(parseErrorMessage);
-            }
-            return valueTable[index];
-        } else { // C.14.3
-            // We have a literal
-            std::shared_ptr<const FIValue> result = parseEncodedCharacterString3();
-            if (b & 0x40) { // C.14.3.1
-                valueTable.push_back(result);
-            }
-            return result;
-        }
-    }
-
-    std::shared_ptr<const FIValue> parseNonIdentifyingStringOrIndex3(std::vector<std::shared_ptr<const FIValue>> &valueTable) { // C.15
-        uint8_t b = *dataP;
-        if (b & 0x20) { // C.15.4
-            // We have an index
-            size_t index = parseInt4();
-            if (index >= valueTable.size()) {
-                throw DeadlyImportError(parseErrorMessage);
-            }
-            return valueTable[index];
-        } else { // C.15.3
-            // We have a literal
-            std::shared_ptr<const FIValue> result = parseEncodedCharacterString5();
-            if (b & 0x10) { // C.15.3.1
-                valueTable.push_back(result);
-            }
-            return result;
-        }
-    }
-
-    void parseElement() {
-        // C.3
-
-        attributes.clear();
-
-        uint8_t b = *dataP;
-        bool hasAttributes = (b & 0x40) != 0; // C.3.3
-        if ((b & 0x3f) == 0x38) { // C.3.4.1
-            // Parse namespaces
-            ++dataP;
-            for (;;) {
-                if (dataEnd - dataP < 1) {
-                    throw DeadlyImportError(parseErrorMessage);
-                }
-                b = *dataP++;
-                if (b == 0xf0) { // C.3.4.3
-                    break;
-                }
-                if ((b & 0xfc) != 0xcc) { // C.3.4.2
-                    throw DeadlyImportError(parseErrorMessage);
-                }
-                // C.12
-                Attribute attr;
-                attr.qname.prefix = "xmlns";
-                attr.qname.name = b & 0x02 ? parseIdentifyingStringOrIndex(vocabulary.prefixTable) : std::string();
-                attr.qname.uri = b & 0x01 ? parseIdentifyingStringOrIndex(vocabulary.namespaceNameTable) : std::string();
-                attr.name = attr.qname.name.empty() ? "xmlns" : "xmlns:" + attr.qname.name;
-                attr.value = FIStringValue::create(std::string(attr.qname.uri));
-                attributes.push_back(attr);
-            }
-            if ((dataEnd - dataP < 1) || (*dataP & 0xc0)) {
-                throw DeadlyImportError(parseErrorMessage);
-            }
-        }
-
-        // Parse Element name (C.3.5)
-        const QName &elemName = parseQualifiedNameOrIndex3(vocabulary.elementNameTable);
-        nodeName = elemName.prefix.empty() ? elemName.name : elemName.prefix + ':' + elemName.name;
-
-        if (hasAttributes) {
-            for (;;) {
-                if (dataEnd - dataP < 1) {
-                    throw DeadlyImportError(parseErrorMessage);
-                }
-                b = *dataP;
-                if (b < 0x80) { // C.3.6.1
-                    // C.4
-                    Attribute attr;
-                    attr.qname = parseQualifiedNameOrIndex2(vocabulary.attributeNameTable);
-                    attr.name = attr.qname.prefix.empty() ? attr.qname.name : attr.qname.prefix + ':' + attr.qname.name;
-                    if (dataEnd - dataP < 1) {
-                        throw DeadlyImportError(parseErrorMessage);
-                    }
-                    attr.value = parseNonIdentifyingStringOrIndex1(vocabulary.attributeValueTable);
-                    attributes.push_back(attr);
-                } else {
-                    if ((b & 0xf0) != 0xf0) { // C.3.6.2
-                        throw DeadlyImportError(parseErrorMessage);
-                    }
-                    emptyElement = b == 0xff; // C.3.6.2, C.3.8
-                    ++dataP;
-                    break;
-                }
-            }
-        } else {
-            if (dataEnd - dataP < 1) {
-                throw DeadlyImportError(parseErrorMessage);
-            }
-            b = *dataP;
-            switch (b) {
-            case 0xff:
-                terminatorPending = true;
-                // Intentionally fall through
-            case 0xf0:
-                emptyElement = true;
-                ++dataP;
-                break;
-            default:
-                emptyElement = false;
-            }
-        }
-        if (!emptyElement) {
-            elementStack.push(nodeName);
-        }
-
-        currentNodeType = irr::io::EXN_ELEMENT;
-    }
-
-    void parseHeader() {
-        // Parse header (C.1.3)
-        size_t magicSize = parseMagic(dataP, dataEnd);
-        if (!magicSize) {
-            throw DeadlyImportError(parseErrorMessage);
-        }
-        dataP += magicSize;
-        // C.2.3
-        if (dataEnd - dataP < 1) {
-            throw DeadlyImportError(parseErrorMessage);
-        }
-        uint8_t b = *dataP++;
-        if (b & 0x40) {
-            // Parse additional data (C.2.4)
-            size_t len = parseSequenceLen();
-            for (size_t i = 0; i < len; ++i) {
-                if (dataEnd - dataP < 1) {
-                    throw DeadlyImportError(parseErrorMessage);
-                }
-                /*std::string id =*/parseNonEmptyOctetString2();
-                if (dataEnd - dataP < 1) {
-                    throw DeadlyImportError(parseErrorMessage);
-                }
-                /*std::string data =*/parseNonEmptyOctetString2();
-            }
-        }
-        if (b & 0x20) {
-            // Parse initial vocabulary (C.2.5)
-            if (dataEnd - dataP < 2) {
-                throw DeadlyImportError(parseErrorMessage);
-            }
-            uint16_t b1 = (dataP[0] << 8) | dataP[1];
-            dataP += 2;
-            if (b1 & 0x1000) {
-                // External vocabulary (C.2.5.2)
-                if (dataEnd - dataP < 1) {
-                    throw DeadlyImportError(parseErrorMessage);
-                }
-                std::string uri = parseNonEmptyOctetString2();
-                auto it = vocabularyMap.find(uri);
-                if (it == vocabularyMap.end()) {
-                    throw DeadlyImportError("Unknown vocabulary " + uri);
-                }
-                const FIVocabulary *externalVocabulary = it->second;
-                if (externalVocabulary->restrictedAlphabetTable) {
-                    std::copy(externalVocabulary->restrictedAlphabetTable, externalVocabulary->restrictedAlphabetTable + externalVocabulary->restrictedAlphabetTableSize, std::back_inserter(vocabulary.restrictedAlphabetTable));
-                }
-                if (externalVocabulary->encodingAlgorithmTable) {
-                    std::copy(externalVocabulary->encodingAlgorithmTable, externalVocabulary->encodingAlgorithmTable + externalVocabulary->encodingAlgorithmTableSize, std::back_inserter(vocabulary.encodingAlgorithmTable));
-                }
-                if (externalVocabulary->prefixTable) {
-                    std::copy(externalVocabulary->prefixTable, externalVocabulary->prefixTable + externalVocabulary->prefixTableSize, std::back_inserter(vocabulary.prefixTable));
-                }
-                if (externalVocabulary->namespaceNameTable) {
-                    std::copy(externalVocabulary->namespaceNameTable, externalVocabulary->namespaceNameTable + externalVocabulary->namespaceNameTableSize, std::back_inserter(vocabulary.namespaceNameTable));
-                }
-                if (externalVocabulary->localNameTable) {
-                    std::copy(externalVocabulary->localNameTable, externalVocabulary->localNameTable + externalVocabulary->localNameTableSize, std::back_inserter(vocabulary.localNameTable));
-                }
-                if (externalVocabulary->otherNCNameTable) {
-                    std::copy(externalVocabulary->otherNCNameTable, externalVocabulary->otherNCNameTable + externalVocabulary->otherNCNameTableSize, std::back_inserter(vocabulary.otherNCNameTable));
-                }
-                if (externalVocabulary->otherURITable) {
-                    std::copy(externalVocabulary->otherURITable, externalVocabulary->otherURITable + externalVocabulary->otherURITableSize, std::back_inserter(vocabulary.otherURITable));
-                }
-                if (externalVocabulary->attributeValueTable) {
-                    std::copy(externalVocabulary->attributeValueTable, externalVocabulary->attributeValueTable + externalVocabulary->attributeValueTableSize, std::back_inserter(vocabulary.attributeValueTable));
-                }
-                if (externalVocabulary->charactersTable) {
-                    std::copy(externalVocabulary->charactersTable, externalVocabulary->charactersTable + externalVocabulary->charactersTableSize, std::back_inserter(vocabulary.charactersTable));
-                }
-                if (externalVocabulary->otherStringTable) {
-                    std::copy(externalVocabulary->otherStringTable, externalVocabulary->otherStringTable + externalVocabulary->otherStringTableSize, std::back_inserter(vocabulary.otherStringTable));
-                }
-                if (externalVocabulary->elementNameTable) {
-                    std::copy(externalVocabulary->elementNameTable, externalVocabulary->elementNameTable + externalVocabulary->elementNameTableSize, std::back_inserter(vocabulary.elementNameTable));
-                }
-                if (externalVocabulary->attributeNameTable) {
-                    std::copy(externalVocabulary->attributeNameTable, externalVocabulary->attributeNameTable + externalVocabulary->attributeNameTableSize, std::back_inserter(vocabulary.attributeNameTable));
-                }
-            }
-            if (b1 & 0x0800) {
-                // Parse restricted alphabets (C.2.5.3)
-                for (size_t len = parseSequenceLen(); len > 0; --len) {
-                    if (dataEnd - dataP < 1) {
-                        throw DeadlyImportError(parseErrorMessage);
-                    }
-                    vocabulary.restrictedAlphabetTable.push_back(parseNonEmptyOctetString2());
-                }
-            }
-            if (b1 & 0x0400) {
-                // Parse encoding algorithms (C.2.5.3)
-                for (size_t len = parseSequenceLen(); len > 0; --len) {
-                    if (dataEnd - dataP < 1) {
-                        throw DeadlyImportError(parseErrorMessage);
-                    }
-                    vocabulary.encodingAlgorithmTable.push_back(parseNonEmptyOctetString2());
-                }
-            }
-            if (b1 & 0x0200) {
-                // Parse prefixes (C.2.5.3)
-                for (size_t len = parseSequenceLen(); len > 0; --len) {
-                    if (dataEnd - dataP < 1) {
-                        throw DeadlyImportError(parseErrorMessage);
-                    }
-                    vocabulary.prefixTable.push_back(parseNonEmptyOctetString2());
-                }
-            }
-            if (b1 & 0x0100) {
-                // Parse namespace names (C.2.5.3)
-                for (size_t len = parseSequenceLen(); len > 0; --len) {
-                    if (dataEnd - dataP < 1) {
-                        throw DeadlyImportError(parseErrorMessage);
-                    }
-                    vocabulary.namespaceNameTable.push_back(parseNonEmptyOctetString2());
-                }
-            }
-            if (b1 & 0x0080) {
-                // Parse local names (C.2.5.3)
-                for (size_t len = parseSequenceLen(); len > 0; --len) {
-                    if (dataEnd - dataP < 1) {
-                        throw DeadlyImportError(parseErrorMessage);
-                    }
-                    vocabulary.localNameTable.push_back(parseNonEmptyOctetString2());
-                }
-            }
-            if (b1 & 0x0040) {
-                // Parse other ncnames (C.2.5.3)
-                for (size_t len = parseSequenceLen(); len > 0; --len) {
-                    if (dataEnd - dataP < 1) {
-                        throw DeadlyImportError(parseErrorMessage);
-                    }
-                    vocabulary.otherNCNameTable.push_back(parseNonEmptyOctetString2());
-                }
-            }
-            if (b1 & 0x0020) {
-                // Parse other uris (C.2.5.3)
-                for (size_t len = parseSequenceLen(); len > 0; --len) {
-                    if (dataEnd - dataP < 1) {
-                        throw DeadlyImportError(parseErrorMessage);
-                    }
-                    vocabulary.otherURITable.push_back(parseNonEmptyOctetString2());
-                }
-            }
-            if (b1 & 0x0010) {
-                // Parse attribute values (C.2.5.4)
-                for (size_t len = parseSequenceLen(); len > 0; --len) {
-                    if (dataEnd - dataP < 1) {
-                        throw DeadlyImportError(parseErrorMessage);
-                    }
-                    vocabulary.attributeValueTable.push_back(parseEncodedCharacterString3());
-                }
-            }
-            if (b1 & 0x0008) {
-                // Parse content character chunks (C.2.5.4)
-                for (size_t len = parseSequenceLen(); len > 0; --len) {
-                    if (dataEnd - dataP < 1) {
-                        throw DeadlyImportError(parseErrorMessage);
-                    }
-                    vocabulary.charactersTable.push_back(parseEncodedCharacterString3());
-                }
-            }
-            if (b1 & 0x0004) {
-                // Parse other strings (C.2.5.4)
-                for (size_t len = parseSequenceLen(); len > 0; --len) {
-                    if (dataEnd - dataP < 1) {
-                        throw DeadlyImportError(parseErrorMessage);
-                    }
-                    vocabulary.otherStringTable.push_back(parseEncodedCharacterString3());
-                }
-            }
-            if (b1 & 0x0002) {
-                // Parse element name surrogates (C.2.5.5)
-                for (size_t len = parseSequenceLen(); len > 0; --len) {
-                    vocabulary.elementNameTable.push_back(parseNameSurrogate());
-                }
-            }
-            if (b1 & 0x0001) {
-                // Parse attribute name surrogates (C.2.5.5)
-                for (size_t len = parseSequenceLen(); len > 0; --len) {
-                    vocabulary.attributeNameTable.push_back(parseNameSurrogate());
-                }
-            }
-        }
-        if (b & 0x10) {
-            // Parse notations (C.2.6)
-            for (;;) {
-                if (dataEnd - dataP < 1) {
-                    throw DeadlyImportError(parseErrorMessage);
-                }
-                uint8_t b1 = *dataP++;
-                if (b1 == 0xf0) {
-                    break;
-                }
-                if ((b1 & 0xfc) != 0xc0) {
-                    throw DeadlyImportError(parseErrorMessage);
-                }
-                /* C.11 */
-                /*const std::string &name =*/parseIdentifyingStringOrIndex(vocabulary.otherNCNameTable);
-                if (b1 & 0x02) {
-                    /*const std::string &systemId =*/parseIdentifyingStringOrIndex(vocabulary.otherURITable);
-                }
-                if (b1 & 0x01) {
-                    /*const std::string &publicId =*/parseIdentifyingStringOrIndex(vocabulary.otherURITable);
-                }
-            }
-        }
-        if (b & 0x08) {
-            // Parse unparsed entities (C.2.7)
-            for (;;) {
-                if (dataEnd - dataP < 1) {
-                    throw DeadlyImportError(parseErrorMessage);
-                }
-                uint8_t b1 = *dataP++;
-                if (b1 == 0xf0) {
-                    break;
-                }
-                if ((b1 & 0xfe) != 0xd0) {
-                    throw DeadlyImportError(parseErrorMessage);
-                }
-                /* C.10 */
-                /*const std::string &name =*/parseIdentifyingStringOrIndex(vocabulary.otherNCNameTable);
-                /*const std::string &systemId =*/parseIdentifyingStringOrIndex(vocabulary.otherURITable);
-                if (b1 & 0x01) {
-                    /*const std::string &publicId =*/parseIdentifyingStringOrIndex(vocabulary.otherURITable);
-                }
-                /*const std::string &notationName =*/parseIdentifyingStringOrIndex(vocabulary.otherNCNameTable);
-            }
-        }
-        if (b & 0x04) {
-            // Parse character encoding scheme (C.2.8)
-            if (dataEnd - dataP < 1) {
-                throw DeadlyImportError(parseErrorMessage);
-            }
-            /*std::string characterEncodingScheme =*/parseNonEmptyOctetString2();
-        }
-        if (b & 0x02) {
-            // Parse standalone flag (C.2.9)
-            if (dataEnd - dataP < 1) {
-                throw DeadlyImportError(parseErrorMessage);
-            }
-            uint8_t b1 = *dataP++;
-            if (b1 & 0xfe) {
-                throw DeadlyImportError(parseErrorMessage);
-            }
-            //bool standalone = b1 & 0x01;
-        }
-        if (b & 0x01) {
-            // Parse version (C.2.10)
-            if (dataEnd - dataP < 1) {
-                throw DeadlyImportError(parseErrorMessage);
-            }
-            /*std::shared_ptr<const FIValue> version =*/parseNonIdentifyingStringOrIndex1(vocabulary.otherStringTable);
-        }
-    }
-
-    std::unique_ptr<uint8_t[]> data;
-    uint8_t *dataP, *dataEnd;
-    irr::io::EXML_NODE currentNodeType;
-    bool emptyElement;
-    bool headerPending;
-    bool terminatorPending;
-    Vocabulary vocabulary;
-    std::vector<Attribute> attributes;
-    std::stack<std::string> elementStack;
-    std::string nodeName;
-    std::map<std::string, std::unique_ptr<FIDecoder>> decoderMap;
-    std::map<std::string, const FIVocabulary *> vocabularyMap;
-
-    static const std::string EmptyString;
-    static std::shared_ptr<const FIValue> EmptyFIString;
-
-    static FIHexDecoder hexDecoder;
-    static FIBase64Decoder base64Decoder;
-    static FIShortDecoder shortDecoder;
-    static FIIntDecoder intDecoder;
-    static FILongDecoder longDecoder;
-    static FIBoolDecoder boolDecoder;
-    static FIFloatDecoder floatDecoder;
-    static FIDoubleDecoder doubleDecoder;
-    static FIUUIDDecoder uuidDecoder;
-    static FICDATADecoder cdataDecoder;
-    static FIDecoder *defaultDecoder[32];
-};
-
-const std::string CFIReaderImpl::EmptyString;
-std::shared_ptr<const FIValue> CFIReaderImpl::EmptyFIString = FIStringValue::create(std::string());
-
-FIHexDecoder CFIReaderImpl::hexDecoder;
-FIBase64Decoder CFIReaderImpl::base64Decoder;
-FIShortDecoder CFIReaderImpl::shortDecoder;
-FIIntDecoder CFIReaderImpl::intDecoder;
-FILongDecoder CFIReaderImpl::longDecoder;
-FIBoolDecoder CFIReaderImpl::boolDecoder;
-FIFloatDecoder CFIReaderImpl::floatDecoder;
-FIDoubleDecoder CFIReaderImpl::doubleDecoder;
-FIUUIDDecoder CFIReaderImpl::uuidDecoder;
-FICDATADecoder CFIReaderImpl::cdataDecoder;
-
-FIDecoder *CFIReaderImpl::defaultDecoder[32] = {
-    &hexDecoder,
-    &base64Decoder,
-    &shortDecoder,
-    &intDecoder,
-    &longDecoder,
-    &boolDecoder,
-    &floatDecoder,
-    &doubleDecoder,
-    &uuidDecoder,
-    &cdataDecoder
-};
-
-class CXMLReaderImpl : public FIReader {
-public:
-    //! Constructor
-    CXMLReaderImpl(std::unique_ptr<irr::io::IIrrXMLReader<char, irr::io::IXMLBase>> reader_) :
-            reader(std::move(reader_)) {}
-
-    virtual ~CXMLReaderImpl() {}
-
-    virtual bool read() /*override*/ {
-        return reader->read();
-    }
-
-    virtual irr::io::EXML_NODE getNodeType() const /*override*/ {
-        return reader->getNodeType();
-    }
-
-    virtual int getAttributeCount() const /*override*/ {
-        return reader->getAttributeCount();
-    }
-
-    virtual const char *getAttributeName(int idx) const /*override*/ {
-        return reader->getAttributeName(idx);
-    }
-
-    virtual const char *getAttributeValue(int idx) const /*override*/ {
-        return reader->getAttributeValue(idx);
-    }
-
-    virtual const char *getAttributeValue(const char *name) const /*override*/ {
-        return reader->getAttributeValue(name);
-    }
-
-    virtual const char *getAttributeValueSafe(const char *name) const /*override*/ {
-        return reader->getAttributeValueSafe(name);
-    }
-
-    virtual int getAttributeValueAsInt(const char *name) const /*override*/ {
-        return reader->getAttributeValueAsInt(name);
-    }
-
-    virtual int getAttributeValueAsInt(int idx) const /*override*/ {
-        return reader->getAttributeValueAsInt(idx);
-    }
-
-    virtual float getAttributeValueAsFloat(const char *name) const /*override*/ {
-        return reader->getAttributeValueAsFloat(name);
-    }
-
-    virtual float getAttributeValueAsFloat(int idx) const /*override*/ {
-        return reader->getAttributeValueAsFloat(idx);
-    }
-
-    virtual const char *getNodeName() const /*override*/ {
-        return reader->getNodeName();
-    }
-
-    virtual const char *getNodeData() const /*override*/ {
-        return reader->getNodeData();
-    }
-
-    virtual bool isEmptyElement() const /*override*/ {
-        return reader->isEmptyElement();
-    }
-
-    virtual irr::io::ETEXT_FORMAT getSourceFormat() const /*override*/ {
-        return reader->getSourceFormat();
-    }
-
-    virtual irr::io::ETEXT_FORMAT getParserFormat() const /*override*/ {
-        return reader->getParserFormat();
-    }
-
-    virtual std::shared_ptr<const FIValue> getAttributeEncodedValue(int /*idx*/) const /*override*/ {
-        return nullptr;
-    }
-
-    virtual std::shared_ptr<const FIValue> getAttributeEncodedValue(const char * /*name*/) const /*override*/ {
-        return nullptr;
-    }
-
-    virtual void registerDecoder(const std::string & /*algorithmUri*/, std::unique_ptr<FIDecoder> /*decoder*/) /*override*/ {}
-
-    virtual void registerVocabulary(const std::string & /*vocabularyUri*/, const FIVocabulary * /*vocabulary*/) /*override*/ {}
-
-private:
-    std::unique_ptr<irr::io::IIrrXMLReader<char, irr::io::IXMLBase>> reader;
-};
-
-static std::unique_ptr<uint8_t[]> readFile(IOStream *stream, size_t &size, bool &isFI) {
-    size = stream->FileSize();
-    std::unique_ptr<uint8_t[]> data = std::unique_ptr<uint8_t[]>(new uint8_t[size]);
-    if (stream->Read(data.get(), size, 1) != 1) {
-        size = 0;
-        data.reset();
-    }
-    isFI = parseMagic(data.get(), data.get() + size) > 0;
-    return data;
-}
-
-std::unique_ptr<FIReader> FIReader::create(IOStream *stream) {
-    size_t size;
-    bool isFI;
-    auto data = readFile(stream, size, isFI);
-    if (isFI) {
-        return std::unique_ptr<FIReader>(new CFIReaderImpl(std::move(data), size));
-    } else {
-        auto memios = std::unique_ptr<MemoryIOStream>(new MemoryIOStream(data.release(), size, true));
-        auto callback = std::unique_ptr<CIrrXML_IOStreamReader>(new CIrrXML_IOStreamReader(memios.get()));
-        return std::unique_ptr<FIReader>(new CXMLReaderImpl(std::unique_ptr<irr::io::IIrrXMLReader<char, irr::io::IXMLBase>>(createIrrXMLReader(callback.get()))));
-    }
-}
-
-} // namespace Assimp
-
-#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER

+ 0 - 186
code/AssetLib/X3D/FIReader.hpp

@@ -1,186 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2020, 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   FIReader.hpp
-/// \brief  Reader for Fast Infoset encoded binary XML files.
-/// \date   2017
-/// \author Patrick Daehne
-
-#ifndef INCLUDED_AI_FI_READER_H
-#define INCLUDED_AI_FI_READER_H
-
-#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
-
-#include <cerrno>
-#include <cwchar>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include <assimp/XmlParser.h>
-
-namespace Assimp {
-
-struct FIValue {
-    virtual const std::string &toString() const = 0;
-    virtual ~FIValue() {}
-};
-
-struct FIStringValue : public FIValue {
-    std::string value;
-    static std::shared_ptr<FIStringValue> create(std::string &&value);
-};
-
-struct FIByteValue : public FIValue {
-    std::vector<uint8_t> value;
-};
-
-struct FIHexValue : public FIByteValue {
-    static std::shared_ptr<FIHexValue> create(std::vector<uint8_t> &&value);
-};
-
-struct FIBase64Value : public FIByteValue {
-    static std::shared_ptr<FIBase64Value> create(std::vector<uint8_t> &&value);
-};
-
-struct FIShortValue : public FIValue {
-    std::vector<int16_t> value;
-    static std::shared_ptr<FIShortValue> create(std::vector<int16_t> &&value);
-};
-
-struct FIIntValue : public FIValue {
-    std::vector<int32_t> value;
-    static std::shared_ptr<FIIntValue> create(std::vector<int32_t> &&value);
-};
-
-struct FILongValue : public FIValue {
-    std::vector<int64_t> value;
-    static std::shared_ptr<FILongValue> create(std::vector<int64_t> &&value);
-};
-
-struct FIBoolValue : public FIValue {
-    std::vector<bool> value;
-    static std::shared_ptr<FIBoolValue> create(std::vector<bool> &&value);
-};
-
-struct FIFloatValue : public FIValue {
-    std::vector<float> value;
-    static std::shared_ptr<FIFloatValue> create(std::vector<float> &&value);
-};
-
-struct FIDoubleValue : public FIValue {
-    std::vector<double> value;
-    static std::shared_ptr<FIDoubleValue> create(std::vector<double> &&value);
-};
-
-struct FIUUIDValue : public FIByteValue {
-    static std::shared_ptr<FIUUIDValue> create(std::vector<uint8_t> &&value);
-};
-
-struct FICDATAValue : public FIStringValue {
-    static std::shared_ptr<FICDATAValue> create(std::string &&value);
-};
-
-struct FIDecoder {
-    virtual std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) = 0;
-    virtual ~FIDecoder() {}
-};
-
-struct FIQName {
-    const char *name;
-    const char *prefix;
-    const char *uri;
-};
-
-struct FIVocabulary {
-    const char **restrictedAlphabetTable;
-    size_t restrictedAlphabetTableSize;
-    const char **encodingAlgorithmTable;
-    size_t encodingAlgorithmTableSize;
-    const char **prefixTable;
-    size_t prefixTableSize;
-    const char **namespaceNameTable;
-    size_t namespaceNameTableSize;
-    const char **localNameTable;
-    size_t localNameTableSize;
-    const char **otherNCNameTable;
-    size_t otherNCNameTableSize;
-    const char **otherURITable;
-    size_t otherURITableSize;
-    const std::shared_ptr<const FIValue> *attributeValueTable;
-    size_t attributeValueTableSize;
-    const std::shared_ptr<const FIValue> *charactersTable;
-    size_t charactersTableSize;
-    const std::shared_ptr<const FIValue> *otherStringTable;
-    size_t otherStringTableSize;
-    const FIQName *elementNameTable;
-    size_t elementNameTableSize;
-    const FIQName *attributeNameTable;
-    size_t attributeNameTableSize;
-};
-
-class IOStream;
-
-class FIReader {
-public:
-    virtual ~FIReader();
-
-    virtual std::shared_ptr<const FIValue> getAttributeEncodedValue(int idx) const = 0;
-
-    virtual std::shared_ptr<const FIValue> getAttributeEncodedValue(const char *name) const = 0;
-
-    virtual void registerDecoder(const std::string &algorithmUri, std::unique_ptr<FIDecoder> decoder) = 0;
-
-    virtual void registerVocabulary(const std::string &vocabularyUri, const FIVocabulary *vocabulary) = 0;
-
-    virtual bool read() = 0;
-
-    static std::unique_ptr<FIReader> create(IOStream *stream);
-
-}; // class IFIReader
-
-inline FIReader::~FIReader() {
-    // empty
-}
-
-} // namespace Assimp
-
-#endif // #ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
-
-#endif // INCLUDED_AI_FI_READER_H

File diff suppressed because it is too large
+ 3 - 1261
code/AssetLib/X3D/X3DImporter.cpp


+ 62 - 521
code/AssetLib/X3D/X3DImporter.hpp

@@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
 
 Copyright (c) 2006-2020, assimp team
 
-
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -48,7 +47,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef INCLUDED_AI_X3D_IMPORTER_H
 #define INCLUDED_AI_X3D_IMPORTER_H
 
-#include "X3DImporter_Node.hpp"
 
 // Header files, Assimp.
 #include <assimp/DefaultLogger.hpp>
@@ -57,8 +55,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/types.h>
 #include <assimp/BaseImporter.h>
 #include <assimp/XmlParser.h>
-#include "FIReader.hpp"
-//#include <regex>
+#include <assimp/scene.h>
+
+#include <list>
 
 namespace Assimp {
 
@@ -234,6 +233,62 @@ inline void LogInfo(const std::string &message) {
 ///
 ///	That's all for now. Enjoy
 ///
+enum class X3DElemType {
+    ENET_Group, ///< Element has type "Group".
+    ENET_MetaBoolean, ///< Element has type "Metadata boolean".
+    ENET_MetaDouble, ///< Element has type "Metadata double".
+    ENET_MetaFloat, ///< Element has type "Metadata float".
+    ENET_MetaInteger, ///< Element has type "Metadata integer".
+    ENET_MetaSet, ///< Element has type "Metadata set".
+    ENET_MetaString, ///< Element has type "Metadata string".
+    ENET_Arc2D, ///< Element has type "Arc2D".
+    ENET_ArcClose2D, ///< Element has type "ArcClose2D".
+    ENET_Circle2D, ///< Element has type "Circle2D".
+    ENET_Disk2D, ///< Element has type "Disk2D".
+    ENET_Polyline2D, ///< Element has type "Polyline2D".
+    ENET_Polypoint2D, ///< Element has type "Polypoint2D".
+    ENET_Rectangle2D, ///< Element has type "Rectangle2D".
+    ENET_TriangleSet2D, ///< Element has type "TriangleSet2D".
+    ENET_Box, ///< Element has type "Box".
+    ENET_Cone, ///< Element has type "Cone".
+    ENET_Cylinder, ///< Element has type "Cylinder".
+    ENET_Sphere, ///< Element has type "Sphere".
+    ENET_ElevationGrid, ///< Element has type "ElevationGrid".
+    ENET_Extrusion, ///< Element has type "Extrusion".
+    ENET_Coordinate, ///< Element has type "Coordinate".
+    ENET_Normal, ///< Element has type "Normal".
+    ENET_TextureCoordinate, ///< Element has type "TextureCoordinate".
+    ENET_IndexedFaceSet, ///< Element has type "IndexedFaceSet".
+    ENET_IndexedLineSet, ///< Element has type "IndexedLineSet".
+    ENET_IndexedTriangleSet, ///< Element has type "IndexedTriangleSet".
+    ENET_IndexedTriangleFanSet, ///< Element has type "IndexedTriangleFanSet".
+    ENET_IndexedTriangleStripSet, ///< Element has type "IndexedTriangleStripSet".
+    ENET_LineSet, ///< Element has type "LineSet".
+    ENET_PointSet, ///< Element has type "PointSet".
+    ENET_TriangleSet, ///< Element has type "TriangleSet".
+    ENET_TriangleFanSet, ///< Element has type "TriangleFanSet".
+    ENET_TriangleStripSet, ///< Element has type "TriangleStripSet".
+    ENET_Color, ///< Element has type "Color".
+    ENET_ColorRGBA, ///< Element has type "ColorRGBA".
+    ENET_Shape, ///< Element has type "Shape".
+    ENET_Appearance, ///< Element has type "Appearance".
+    ENET_Material, ///< Element has type "Material".
+    ENET_ImageTexture, ///< Element has type "ImageTexture".
+    ENET_TextureTransform, ///< Element has type "TextureTransform".
+    ENET_DirectionalLight, ///< Element has type "DirectionalLight".
+    ENET_PointLight, ///< Element has type "PointLight".
+    ENET_SpotLight, ///< Element has type "SpotLight".
+
+    ENET_Invalid ///< Element has invalid type and possible contain invalid data.
+};
+
+struct X3DNodeElementBase {
+    X3DNodeElementBase *Parent;
+    std::string ID;
+    std::list<X3DNodeElementBase *> Child;
+    X3DElemType Type;
+};
+
 class X3DImporter : public BaseImporter
 {
 public:
@@ -259,527 +314,13 @@ public:
     /// \param [in] pFile - name of file to be parsed.
     /// \param [in] pIOHandler - pointer to IO helper object.
     void ParseFile( const std::string& pFile, IOSystem* pIOHandler );
-
-    /***********************************************/
-    /********* Functions: BaseImporter set *********/
-    /***********************************************/
-
     bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool pCheckSig ) const;
     void GetExtensionList( std::set<std::string>& pExtensionList );
     void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler );
     const aiImporterDesc* GetInfo()const;
+    void Clear();
 
-
-private:
-	/// Disabled copy constructor.
-	X3DImporter(const X3DImporter& pScene);
-
-	/// Disabled assign operator.
-	X3DImporter& operator=(const X3DImporter& pScene);
-
-	/// Clear all temporary data.
-	void Clear();
-
-	/***********************************************/
-	/************* Functions: find set *************/
-	/***********************************************/
-
-	/// Find requested node element. Search will be made in all existing nodes.
-	/// \param [in] pID - ID of requested element.
-	/// \param [in] pType - type of requested element.
-	/// \param [out] pElement - pointer to pointer to item found.
-	/// \return true - if the element is found, else - false.
-	bool FindNodeElement_FromRoot(const std::string& pID, const X3DNodeElementBase::EType pType, X3DNodeElementBase** pElement);
-
-	/// Find requested node element. Search will be made from pointed node down to childs.
-	/// \param [in] pStartNode - pointer to start node.
-	/// \param [in] pID - ID of requested element.
-	/// \param [in] pType - type of requested element.
-	/// \param [out] pElement - pointer to pointer to item found.
-	/// \return true - if the element is found, else - false.
-	bool FindNodeElement_FromNode(X3DNodeElementBase* pStartNode, const std::string& pID, const X3DNodeElementBase::EType pType,
-									X3DNodeElementBase** pElement);
-
-	/// Find requested node element. For "Node"'s accounting flag "Static".
-	/// \param [in] pName - name of requested element.
-	/// \param [in] pType - type of requested element.
-	/// \param [out] pElement - pointer to pointer to item found.
-	/// \return true - if the element is found, else - false.
-	bool FindNodeElement(const std::string& pName, const X3DNodeElementBase::EType pType, X3DNodeElementBase** pElement);
-
-	/***********************************************/
-	/********* Functions: postprocess set **********/
-	/***********************************************/
-
-	/// \return transformation matrix from global coordinate system to local.
-	aiMatrix4x4 PostprocessHelper_Matrix_GlobalToCurrent() const;
-
-	/// Check if child elements of node element is metadata and add it to temporary list.
-	/// \param [in] pNodeElement - node element where metadata is searching.
-	/// \param [out] pList - temporary list for collected metadata.
-	void PostprocessHelper_CollectMetadata(const X3DNodeElementBase& pNodeElement, std::list<X3DNodeElementBase*>& pList) const;
-
-	/// Check if type of node element is metadata. E.g. <MetadataSet>, <MetadataString>.
-	/// \param [in] pType - checked type.
-	/// \return true - if the type corresponds to the metadata.
-	bool PostprocessHelper_ElementIsMetadata(const X3DNodeElementBase::EType pType) const;
-
-	/// Check if type of node element is geometry object and can be used to build mesh. E.g. <Box>, <Arc2D>.
-	/// \param [in] pType - checked type.
-	/// \return true - if the type corresponds to the mesh.
-	bool PostprocessHelper_ElementIsMesh(const X3DNodeElementBase::EType pType) const;
-
-	/// Read CX3DImporter_NodeElement_Light, create aiLight and add it to list of the lights.
-	/// \param [in] pNodeElement - reference to lisght element(<DirectionalLight>, <PointLight>, <SpotLight>).
-	/// \param [out] pSceneLightList - reference to list of the lights.
-	void Postprocess_BuildLight(const X3DNodeElementBase& pNodeElement, std::list<aiLight*>& pSceneLightList) const;
-
-	/// Create filled structure with type \ref aiMaterial from \ref CX3DImporter_NodeElement. This function itseld extract
-	/// all needed data from scene graph.
-	/// \param [in] pNodeElement - reference to material element(<Appearance>).
-	/// \param [out] pMaterial - pointer to pointer to created material. *pMaterial must be nullptr.
-	void Postprocess_BuildMaterial(const X3DNodeElementBase& pNodeElement, aiMaterial** pMaterial) const;
-
-	/// Create filled structure with type \ref aiMaterial from \ref CX3DImporter_NodeElement. This function itseld extract
-	/// all needed data from scene graph.
-	/// \param [in] pNodeElement - reference to geometry object.
-	/// \param [out] pMesh - pointer to pointer to created mesh. *pMesh must be nullptr.
-	void Postprocess_BuildMesh(const X3DNodeElementBase& pNodeElement, aiMesh** pMesh) const;
-
-	/// Create aiNode from CX3DImporter_NodeElement. Also function check children and make recursive call.
-	/// \param [out] pNode - pointer to pointer to created node. *pNode must be nullptr.
-	/// \param [in] pNodeElement - CX3DImporter_NodeElement which read.
-	/// \param [out] pSceneNode - aiNode for filling.
-	/// \param [out] pSceneMeshList - list with aiMesh which belong to scene.
-	/// \param [out] pSceneMaterialList - list with aiMaterial which belong to scene.
-	/// \param [out] pSceneLightList - list with aiLight which belong to scene.
-	void Postprocess_BuildNode(const X3DNodeElementBase& pNodeElement, aiNode& pSceneNode, std::list<aiMesh*>& pSceneMeshList,
-								std::list<aiMaterial*>& pSceneMaterialList, std::list<aiLight*>& pSceneLightList) const;
-
-	/// To create mesh and material kept in <Schape>.
-	/// \param pShapeNodeElement - reference to node element which kept <Shape> data.
-	/// \param pNodeMeshInd - reference to list with mesh indices. When pShapeNodeElement will read new mesh index will be added to this list.
-	/// \param pSceneMeshList - reference to list with meshes. When pShapeNodeElement will read new mesh will be added to this list.
-	/// \param pSceneMaterialList - reference to list with materials. When pShapeNodeElement will read new material will be added to this list.
-	void Postprocess_BuildShape(const X3DShape& pShapeNodeElement, std::list<unsigned int>& pNodeMeshInd,
-								std::list<aiMesh*>& pSceneMeshList, std::list<aiMaterial*>& pSceneMaterialList) const;
-
-	/// Check if child elements of node element is metadata and add it to scene node.
-	/// \param [in] pNodeElement - node element where metadata is searching.
-	/// \param [out] pSceneNode - scene node in which metadata will be added.
-	void Postprocess_CollectMetadata(const X3DNodeElementBase& pNodeElement, aiNode& pSceneNode) const;
-
-	/***********************************************/
-	/************** Functions: XML set *************/
-	/***********************************************/
-
-	/// Check if current node is empty: <node />. If not then exception will throwed.
-	void XML_CheckNode_MustBeEmpty();
-
-	/// Check if current node name is equal to pNodeName.
-	/// \param [in] pNodeName - name for checking.
-	/// return true if current node name is equal to pNodeName, else - false.
-	//bool XML_CheckNode_NameEqual(const std::string& pNodeName) { return mReader->getNodeName() == pNodeName; }
-
-	/// Skip unsupported node and report about that. Depend on node name can be skipped begin tag of node all whole node.
-	/// \param [in] pParentNodeName - parent node name. Used for reporting.
-	void XML_CheckNode_SkipUnsupported(const std::string& pParentNodeName);
-
-	/// Search for specified node in file. XML file read pointer(mReader) will point to found node or file end after search is end.
-	/// \param [in] pNodeName - requested node name.
-	/// return true - if node is found, else - false.
-	bool XML_SearchNode(const std::string& pNodeName);
-
-	/// Read attribute value.
-	/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
-	/// \return read data.
-	bool XML_ReadNode_GetAttrVal_AsBool(const int pAttrIdx);
-
-	/// Read attribute value.
-	/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
-	/// \return read data.
-	float XML_ReadNode_GetAttrVal_AsFloat(const int pAttrIdx);
-
-	/// Read attribute value.
-	/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
-	/// \return read data.
-	int32_t XML_ReadNode_GetAttrVal_AsI32(const int pAttrIdx);
-
-	/// Read attribute value.
-	/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
-	/// \param [out] pValue - read data.
-	void XML_ReadNode_GetAttrVal_AsCol3f(const int pAttrIdx, aiColor3D& pValue);
-
-	/// Read attribute value.
-	/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
-	/// \param [out] pValue - read data.
-	void XML_ReadNode_GetAttrVal_AsVec2f(const int pAttrIdx, aiVector2D& pValue);
-
-	/// Read attribute value.
-	/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
-	/// \param [out] pValue - read data.
-	void XML_ReadNode_GetAttrVal_AsVec3f(const int pAttrIdx, aiVector3D& pValue);
-
-	/// Read attribute value.
-	/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
-	/// \param [out] pValue - read data.
-	void XML_ReadNode_GetAttrVal_AsArrB(const int pAttrIdx, std::vector<bool>& pValue);
-
-	/// Read attribute value.
-	/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
-	/// \param [out] pValue - read data.
-	void XML_ReadNode_GetAttrVal_AsArrI32(const int pAttrIdx, std::vector<int32_t>& pValue);
-
-	/// Read attribute value.
-	/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
-	/// \param [out] pValue - read data.
-	void XML_ReadNode_GetAttrVal_AsArrF(const int pAttrIdx, std::vector<float>& pValue);
-
-    /// Read attribute value.
-	/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
-	/// \param [out] pValue - read data.
-	void XML_ReadNode_GetAttrVal_AsArrD(const int pAttrIdx, std::vector<double>& pValue);
-
-	/// Read attribute value.
-	/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
-	/// \param [out] pValue - read data.
-	void XML_ReadNode_GetAttrVal_AsListCol3f(const int pAttrIdx, std::list<aiColor3D>& pValue);
-
-	/// \overload void XML_ReadNode_GetAttrVal_AsListCol3f(const int pAttrIdx, std::vector<aiColor3D>& pValue)
-	void XML_ReadNode_GetAttrVal_AsArrCol3f(const int pAttrIdx, std::vector<aiColor3D>& pValue);
-
-	/// Read attribute value.
-	/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
-	/// \param [out] pValue - read data.
-	void XML_ReadNode_GetAttrVal_AsListCol4f(const int pAttrIdx, std::list<aiColor4D>& pValue);
-
-	/// \overload void XML_ReadNode_GetAttrVal_AsListCol4f(const int pAttrIdx, std::list<aiColor4D>& pValue)
-	void XML_ReadNode_GetAttrVal_AsArrCol4f(const int pAttrIdx, std::vector<aiColor4D>& pValue);
-
-	/// Read attribute value.
-	/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
-	/// \param [out] pValue - read data.
-	void XML_ReadNode_GetAttrVal_AsListVec2f(const int pAttrIdx, std::list<aiVector2D>& pValue);
-
-	/// \overload void XML_ReadNode_GetAttrVal_AsListVec2f(const int pAttrIdx, std::list<aiVector2D>& pValue)
-	void XML_ReadNode_GetAttrVal_AsArrVec2f(const int pAttrIdx, std::vector<aiVector2D>& pValue);
-
-	/// Read attribute value.
-	/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
-	/// \param [out] pValue - read data.
-	void XML_ReadNode_GetAttrVal_AsListVec3f(const int pAttrIdx, std::list<aiVector3D>& pValue);
-
-	/// \overload void XML_ReadNode_GetAttrVal_AsListVec3f(const int pAttrIdx, std::list<aiVector3D>& pValue)
-	void XML_ReadNode_GetAttrVal_AsArrVec3f(const int pAttrIdx, std::vector<aiVector3D>& pValue);
-
-	/// Read attribute value.
-	/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
-	/// \param [out] pValue - read data.
-	void XML_ReadNode_GetAttrVal_AsListS(const int pAttrIdx, std::list<std::string>& pValue);
-
-	/***********************************************/
-	/******* Functions: geometry helper set  *******/
-	/***********************************************/
-
-	/// Make point on surface oXY.
-	/// \param [in] pAngle - angle in radians between radius-vector of point and oX axis. Angle extends from the oX axis counterclockwise to the radius-vector.
-	/// \param [in] pRadius - length of radius-vector.
-	/// \return made point coordinates.
-	aiVector3D GeometryHelper_Make_Point2D(const float pAngle, const float pRadius);
-
-	/// Make 2D figure - linear circular arc with center in (0, 0). The z-coordinate is 0. The arc extends from the pStartAngle counterclockwise
-	/// to the pEndAngle. If pStartAngle and pEndAngle have the same value, a circle is specified. If the absolute difference between pStartAngle
-	/// and pEndAngle is greater than or equal to 2pi, a circle is specified.
-	/// \param [in] pStartAngle - angle in radians of start of the arc.
-	/// \param [in] pEndAngle - angle in radians of end of the arc.
-	/// \param [in] pRadius - radius of the arc.
-	/// \param [out] pNumSegments - number of segments in arc. In other words - tessellation factor.
-	/// \param [out] pVertices - generated vertices.
-	void GeometryHelper_Make_Arc2D(const float pStartAngle, const float pEndAngle, const float pRadius, size_t pNumSegments, std::list<aiVector3D>& pVertices);
-
-	/// Create line set from point set.
-	/// \param [in] pPoint - input points list.
-	/// \param [out] pLine - made lines list.
-	void GeometryHelper_Extend_PointToLine(const std::list<aiVector3D>& pPoint, std::list<aiVector3D>& pLine);
-
-	/// Create CoordIdx of line set from CoordIdx of polyline set.
-	/// \param [in] pPolylineCoordIdx - vertices indices divided by delimiter "-1". Must contain faces with two or more indices.
-	/// \param [out] pLineCoordIdx - made CoordIdx of line set.
-	void GeometryHelper_Extend_PolylineIdxToLineIdx(const std::list<int32_t>& pPolylineCoordIdx, std::list<int32_t>& pLineCoordIdx);
-
-	/// Make 3D body - rectangular parallelepiped with center in (0, 0). QL mean quadlist (\sa pVertices).
-	/// \param [in] pSize - scale factor for body for every axis. E.g. (1, 2, 1) mean: X-size and Z-size - 1, Y-size - 2.
-	/// \param [out] pVertices - generated vertices. The list of vertices is grouped in quads.
-	void GeometryHelper_MakeQL_RectParallelepiped(const aiVector3D& pSize, std::list<aiVector3D>& pVertices);
-
-	/// Create faces array from vertices indices array.
-	/// \param [in] pCoordIdx - vertices indices divided by delimiter "-1".
-	/// \param [in] pFaces - created faces array.
-	/// \param [in] pPrimitiveTypes - type of primitives in faces.
-	void GeometryHelper_CoordIdxStr2FacesArr(const std::vector<int32_t>& pCoordIdx, std::vector<aiFace>& pFaces, unsigned int& pPrimitiveTypes) const;
-
-	/// Add colors to mesh.
-	/// a. If colorPerVertex is FALSE, colours are applied to each face, as follows:
-	///		If the colorIndex field is not empty, one colour is used for each face of the mesh. There shall be at least as many indices in the
-	///			colorIndex field as there are faces in the mesh. The colorIndex field shall not contain any negative entries.
-	///		If the colorIndex field is empty, the colours in the X3DColorNode node are applied to each face of the mesh in order.
-	///			There shall be at least as many colours in the X3DColorNode node as there are faces.
-	/// b. If colorPerVertex is TRUE, colours are applied to each vertex, as follows:
-	///		If the colorIndex field is not empty, colours are applied to each vertex of the mesh in exactly the same manner that the coordIndex
-	///			field is used to choose coordinates for each vertex from the <Coordinate> node. The colorIndex field shall contain end-of-face markers (-1)
-	///			in exactly the same places as the coordIndex field.
-	///		If the colorIndex field is empty, the coordIndex field is used to choose colours from the X3DColorNode node.
-	/// \param [in] pMesh - mesh for adding data.
-	/// \param [in] pCoordIdx - vertices indices divided by delimiter "-1".
-	/// \param [in] pColorIdx - color indices for every vertex divided by delimiter "-1" if \ref pColorPerVertex is true. if \ref pColorPerVertex is false
-	/// then pColorIdx contain color indices for every faces and must not contain delimiter "-1".
-	/// \param [in] pColors - defined colors.
-	/// \param [in] pColorPerVertex - if \ref pColorPerVertex is true then color in \ref pColors defined for every vertex, if false - for every face.
-	void MeshGeometry_AddColor(aiMesh& pMesh, const std::vector<int32_t>& pCoordIdx, const std::vector<int32_t>& pColorIdx,
-								const std::list<aiColor4D>& pColors, const bool pColorPerVertex) const;
-
-	/// \overload void MeshGeometry_AddColor(aiMesh& pMesh, const std::list<int32_t>& pCoordIdx, const std::list<int32_t>& pColorIdx, const std::list<aiColor4D>& pColors, const bool pColorPerVertex) const;
-	void MeshGeometry_AddColor(aiMesh& pMesh, const std::vector<int32_t>& pCoordIdx, const std::vector<int32_t>& pColorIdx,
-								const std::list<aiColor3D>& pColors, const bool pColorPerVertex) const;
-
-	/// Add colors to mesh.
-	/// \param [in] pMesh - mesh for adding data.
-	/// \param [in] pColors - defined colors.
-	/// \param [in] pColorPerVertex - if \ref pColorPerVertex is true then color in \ref pColors defined for every vertex, if false - for every face.
-	void MeshGeometry_AddColor(aiMesh& pMesh, const std::list<aiColor4D>& pColors, const bool pColorPerVertex) const;
-
-	/// \overload void MeshGeometry_AddColor(aiMesh& pMesh, const std::list<aiColor4D>& pColors, const bool pColorPerVertex) const
-	void MeshGeometry_AddColor(aiMesh& pMesh, const std::list<aiColor3D>& pColors, const bool pColorPerVertex) const;
-
-	/// Add normals to mesh. Function work similar to \ref MeshGeometry_AddColor;
-	void MeshGeometry_AddNormal(aiMesh& pMesh, const std::vector<int32_t>& pCoordIdx, const std::vector<int32_t>& pNormalIdx,
-								const std::list<aiVector3D>& pNormals, const bool pNormalPerVertex) const;
-
-	/// Add normals to mesh. Function work similar to \ref MeshGeometry_AddColor;
-	void MeshGeometry_AddNormal(aiMesh& pMesh, const std::list<aiVector3D>& pNormals, const bool pNormalPerVertex) const;
-
-    /// Add texture coordinates to mesh. Function work similar to \ref MeshGeometry_AddColor;
-	void MeshGeometry_AddTexCoord(aiMesh& pMesh, const std::vector<int32_t>& pCoordIdx, const std::vector<int32_t>& pTexCoordIdx,
-								const std::list<aiVector2D>& pTexCoords) const;
-
-    /// Add texture coordinates to mesh. Function work similar to \ref MeshGeometry_AddColor;
-	void MeshGeometry_AddTexCoord(aiMesh& pMesh, const std::list<aiVector2D>& pTexCoords) const;
-
-	/// Create mesh.
-	/// \param [in] pCoordIdx - vertices indices divided by delimiter "-1".
-	/// \param [in] pVertices - vertices of mesh.
-	/// \return created mesh.
-	aiMesh* GeometryHelper_MakeMesh(const std::vector<int32_t>& pCoordIdx, const std::list<aiVector3D>& pVertices) const;
-
-	/***********************************************/
-	/******** Functions: parse set private *********/
-	/***********************************************/
-
-	/// Create node element with type "Node" in scene graph. That operation is needed when you enter to X3D group node
-	/// like <Group>, <Transform> etc. When exiting from X3D group node(e.g. </Group>) \ref ParseHelper_Node_Exit must
-	/// be called.
-	/// \param [in] pStatic - flag: if true then static node is created(e.g. <StaticGroup>).
-	void ParseHelper_Group_Begin(const bool pStatic = false);
-
-	/// Make pNode as current and enter deeper for parsing child nodes. At end \ref ParseHelper_Node_Exit must be called.
-	/// \param [in] pNode - new current node.
-	void ParseHelper_Node_Enter(X3DNodeElementBase* pNode);
-
-	/// This function must be called when exiting from X3D group node(e.g. </Group>). \ref ParseHelper_Group_Begin.
-	void ParseHelper_Node_Exit();
-
-	/// Attribute values of floating point types can take form ".x"(without leading zero). irrXMLReader can not read this form of values and it
-	/// must be converted to right form - "0.xxx".
-	/// \param [in] pInStr - pointer to input string which can contain incorrect form of values.
-	/// \param [out[ pOutString - output string with right form of values.
-	void ParseHelper_FixTruncatedFloatString(const char* pInStr, std::string& pOutString);
-
-	/// Check if current node has nodes of type X3DMetadataObject. Why we must do it? Because X3DMetadataObject can be in any non-empty X3DNode.
-	/// Meaning that X3DMetadataObject can be in any non-empty node in <Scene>.
-	/// \return true - if metadata node are found and parsed, false - metadata not found.
-	bool ParseHelper_CheckRead_X3DMetadataObject();
-
-	/// Check if current node has nodes of type X3DGeometricPropertyNode. X3DGeometricPropertyNode
-	/// X3DGeometricPropertyNode inheritors:
-	/// <FogCoordinate>, <HAnimDisplacer>, <Color>, <ColorRGBA>, <Coordinate>, <CoordinateDouble>, <GeoCoordinate>, <Normal>,
-	/// <MultiTextureCoordinate>, <TextureCoordinate>, <TextureCoordinate3D>, <TextureCoordinate4D>, <TextureCoordinateGenerator>,
-	/// <FloatVertexAttribute>, <Matrix3VertexAttribute>, <Matrix4VertexAttribute>.
-	/// \return true - if nodes are found and parsed, false - nodes not found.
-	bool ParseHelper_CheckRead_X3DGeometricPropertyNode();
-
-	/// Parse <X3D> node of the file.
-	void ParseNode_Root();
-
-	/// Parse <head> node of the file.
-	void ParseNode_Head();
-
-	/// Parse <Scene> node of the file.
-	void ParseNode_Scene();
-
-	/// Parse child nodes of <Metadata*> node.
-	/// \param [in] pNodeName - parsed node name. Must be set because that function is general and name needed for checking the end
-	/// and error reporing.
-	/// \param [in] pParentElement - parent metadata element.
-	void ParseNode_Metadata(X3DNodeElementBase* pParentElement, const std::string& pNodeName);
-
-	/// Parse <MetadataBoolean> node of the file.
-	void ParseNode_MetadataBoolean();
-
-	/// Parse <MetadataDouble> node of the file.
-	void ParseNode_MetadataDouble();
-
-	/// Parse <MetadataFloat> node of the file.
-	void ParseNode_MetadataFloat();
-
-	/// Parse <MetadataInteger> node of the file.
-	void ParseNode_MetadataInteger();
-
-	/// Parse <MetadataSet> node of the file.
-	void ParseNode_MetadataSet();
-
-	/// \fn void ParseNode_MetadataString()
-	/// Parse <MetadataString> node of the file.
-	void ParseNode_MetadataString();
-
-	/// Parse <Arc2D> node of the file.
-	void ParseNode_Geometry2D_Arc2D(XmlNode &node);
-
-	/// Parse <ArcClose2D> node of the file.
-    void ParseNode_Geometry2D_ArcClose2D(XmlNode &node);
-
-	/// Parse <Circle2D> node of the file.
-    void ParseNode_Geometry2D_Circle2D(XmlNode &node);
-
-	/// Parse <Disk2D> node of the file.
-    void ParseNode_Geometry2D_Disk2D(XmlNode &node);
-
-	/// Parse <Polyline2D> node of the file.
-    void ParseNode_Geometry2D_Polyline2D(XmlNode &node);
-
-	/// Parse <Polypoint2D> node of the file.
-    void ParseNode_Geometry2D_Polypoint2D(XmlNode &node);
-
-	/// Parse <Rectangle2D> node of the file.
-    void ParseNode_Geometry2D_Rectangle2D(XmlNode &node);
-
-	/// Parse <TriangleSet2D> node of the file.
-    void ParseNode_Geometry2D_TriangleSet2D(XmlNode &node);
-
-	/// Parse <Box> node of the file.
-    void ParseNode_Geometry3D_Box(XmlNode &node);
-
-	/// Parse <Cone> node of the file.
-    void ParseNode_Geometry3D_Cone(XmlNode &node);
-
-	/// Parse <Cylinder> node of the file.
-    void ParseNode_Geometry3D_Cylinder(XmlNode &node);
-
-	/// Parse <ElevationGrid> node of the file.
-    void ParseNode_Geometry3D_ElevationGrid(XmlNode &node);
-
-	/// Parse <Extrusion> node of the file.
-    void ParseNode_Geometry3D_Extrusion(XmlNode &node);
-
-	/// Parse <IndexedFaceSet> node of the file.
-    void ParseNode_Geometry3D_IndexedFaceSet(XmlNode &node);
-
-	/// Parse <Sphere> node of the file.
-    void ParseNode_Geometry3D_Sphere(XmlNode &node);
-
-	/// Parse <Group> node of the file. And create new node in scene graph.
-    void ParseNode_Grouping_Group(XmlNode &node);
-
-	/// Doing actions at an exit from <Group>. Walk up in scene graph.
-	void ParseNode_Grouping_GroupEnd();
-
-	/// Parse <StaticGroup> node of the file. And create new node in scene graph.
-    void ParseNode_Grouping_StaticGroup(XmlNode &node);
-
-	/// Doing actions at an exit from <StaticGroup>. Walk up in scene graph.
-	void ParseNode_Grouping_StaticGroupEnd();
-
-	/// Parse <Switch> node of the file. And create new node in scene graph.
-    void ParseNode_Grouping_Switch(XmlNode &node);
-
-	/// Doing actions at an exit from <Switch>. Walk up in scene graph.
-	void ParseNode_Grouping_SwitchEnd();
-
-	/// Parse <Transform> node of the file. And create new node in scene graph.
-    void ParseNode_Grouping_Transform(XmlNode &node);
-
-	/// Doing actions at an exit from <Transform>. Walk up in scene graph.
-	void ParseNode_Grouping_TransformEnd();
-
-	/// Parse <Color> node of the file.
-	void ParseNode_Rendering_Color();
-
-	/// Parse <ColorRGBA> node of the file.
-	void ParseNode_Rendering_ColorRGBA();
-
-	/// Parse <Coordinate> node of the file.
-	void ParseNode_Rendering_Coordinate();
-
-	/// Parse <Normal> node of the file.
-	void ParseNode_Rendering_Normal();
-
-	/// Parse <IndexedLineSet> node of the file.
-	void ParseNode_Rendering_IndexedLineSet();
-
-	/// Parse <IndexedTriangleFanSet> node of the file.
-	void ParseNode_Rendering_IndexedTriangleFanSet();
-
-	/// Parse <IndexedTriangleSet> node of the file.
-	void ParseNode_Rendering_IndexedTriangleSet();
-
-	/// Parse <IndexedTriangleStripSet> node of the file.
-	void ParseNode_Rendering_IndexedTriangleStripSet();
-
-	/// Parse <LineSet> node of the file.
-	void ParseNode_Rendering_LineSet();
-
-	/// Parse <PointSet> node of the file.
-	void ParseNode_Rendering_PointSet();
-
-	/// Parse <TriangleFanSet> node of the file.
-	void ParseNode_Rendering_TriangleFanSet();
-
-	/// Parse <TriangleSet> node of the file.
-	void ParseNode_Rendering_TriangleSet();
-
-	/// Parse <TriangleStripSet> node of the file.
-	void ParseNode_Rendering_TriangleStripSet();
-
-	/// Parse <ImageTexture> node of the file.
-	void ParseNode_Texturing_ImageTexture();
-
-	/// Parse <TextureCoordinate> node of the file.
-	void ParseNode_Texturing_TextureCoordinate();
-
-	/// Parse <TextureTransform> node of the file.
-	void ParseNode_Texturing_TextureTransform();
-
-	/// Parse <Shape> node of the file.
-	void ParseNode_Shape_Shape();
-
-	/// Parse <Appearance> node of the file.
-	void ParseNode_Shape_Appearance();
-
-	/// Parse <Material> node of the file.
-	void ParseNode_Shape_Material();
-
-	/// Parse <Inline> node of the file.
-	void ParseNode_Networking_Inline();
-
-	/// Parse <DirectionalLight> node of the file.
-	void ParseNode_Lighting_DirectionalLight();
-
-	/// Parse <PointLight> node of the file.
-	void ParseNode_Lighting_PointLight();
-
-	/// Parse <SpotLight> node of the file.
-	void ParseNode_Lighting_SpotLight();
-
-private:
+    private:
     /***********************************************/
     /******************** Types ********************/
     /***********************************************/
@@ -796,7 +337,7 @@ private:
     /****************** Variables ******************/
     /***********************************************/
     X3DNodeElementBase* mNodeElementCur;///< Current element.
-    std::unique_ptr<FIReader> mReader;///< Pointer to XML-reader object
+    XmlParser *mXmlParser;
     IOSystem *mpIOHandler;
 };// class X3DImporter
 

+ 0 - 521
code/AssetLib/X3D/X3DImporter_Geometry2D.cpp

@@ -1,521 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2020, 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_Geometry2D.cpp
-/// \brief  Parsing data from nodes of "Geometry2D" set of X3D.
-/// \date   2015-2016
-/// \author [email protected]
-
-#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
-
-#include "X3DImporter.hpp"
-#include "X3DImporter_Node.hpp"
-#include "X3DImporter_Macro.hpp"
-
-namespace Assimp
-{
-
-// <Arc2D
-// DEF=""              ID
-// USE=""              IDREF
-// endAngle="1.570796" SFFloat [initializeOnly]
-// radius="1"          SFFloat [initializeOnly]
-// startAngle="0"      SFFloat [initializeOnly]
-// />
-// The Arc2D node specifies a linear circular arc whose center is at (0,0) and whose angles are measured starting at the positive x-axis and sweeping
-// towards the positive y-axis. The radius field specifies the radius of the circle of which the arc is a portion. The arc extends from the startAngle
-// counterclockwise to the endAngle. The values of startAngle and endAngle shall be in the range [-2pi, 2pi] radians (or the equivalent if a different
-// angle base unit has been specified). If startAngle and endAngle have the same value, a circle is specified.
-void X3DImporter::ParseNode_Geometry2D_Arc2D() {
-    std::string def, use;
-    float endAngle = AI_MATH_HALF_PI_F;
-    float radius = 1;
-    float startAngle = 0;
-    X3DNodeElementBase* ne = nullptr;
-
-	/*MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
-		MACRO_ATTRREAD_CHECK_RET("endAngle", endAngle, XML_ReadNode_GetAttrVal_AsFloat);
-		MACRO_ATTRREAD_CHECK_RET("radius", radius, XML_ReadNode_GetAttrVal_AsFloat);
-		MACRO_ATTRREAD_CHECK_RET("startAngle", startAngle, XML_ReadNode_GetAttrVal_AsFloat);
-	MACRO_ATTRREAD_LOOPEND;*/
-
-	// if "USE" defined then find already defined element.
-	if(!use.empty())
-	{
-		MACRO_USE_CHECKANDAPPLY(def, use, ENET_Arc2D, ne);
-	}
-	else
-	{
-		// create and if needed - define new geometry object.
-		ne = new X3DGeometry2D(X3DNodeElementBase::ENET_Arc2D, mNodeElementCur);
-		if(!def.empty()) ne->ID = def;
-
-		// create point list of geometry object and convert it to line set.
-		std::list<aiVector3D> tlist;
-
-		GeometryHelper_Make_Arc2D(startAngle, endAngle, radius, 10, tlist);///TODO: IME - AI_CONFIG for NumSeg
-		GeometryHelper_Extend_PointToLine(tlist, ((X3DGeometry2D*)ne)->Vertices);
-		((X3DGeometry2D*)ne)->NumIndices = 2;
-		// check for X3DMetadataObject childs.
-		if(!mReader->isEmptyElement())
-			ParseNode_Metadata(ne, "Arc2D");
-		else
-			mNodeElementCur->Child.push_back(ne);// add made object as child to current element
-
-		NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
-	}// if(!use.empty()) else
-}
-
-// <ArcClose2D
-// DEF=""              ID
-// USE=""              IDREF
-// closureType="PIE"   SFString [initializeOnly], {"PIE", "CHORD"}
-// endAngle="1.570796" SFFloat  [initializeOnly]
-// radius="1"          SFFloat  [initializeOnly]
-// solid="false"       SFBool   [initializeOnly]
-// startAngle="0"      SFFloat  [initializeOnly]
-// />
-// The ArcClose node specifies a portion of a circle whose center is at (0,0) and whose angles are measured starting at the positive x-axis and sweeping
-// towards the positive y-axis. The end points of the arc specified are connected as defined by the closureType field. The radius field specifies the radius
-// of the circle of which the arc is a portion. The arc extends from the startAngle counterclockwise to the endAngle. The value of radius shall be greater
-// than zero. The values of startAngle and endAngle shall be in the range [-2pi, 2pi] radians (or the equivalent if a different default angle base unit has
-// been specified). If startAngle and endAngle have the same value, a circle is specified and closureType is ignored. If the absolute difference between
-// startAngle and endAngle is greater than or equal to 2pi, a complete circle is produced with no chord or radial line(s) drawn from the center.
-// A closureType of "PIE" connects the end point to the start point by defining two straight line segments first from the end point to the center and then
-// the center to the start point. A closureType of "CHORD" connects the end point to the start point by defining a straight line segment from the end point
-// to the start point. Textures are applied individually to each face of the ArcClose2D. On the front (+Z) and back (-Z) faces of the ArcClose2D, when
-// viewed from the +Z-axis, the texture is mapped onto each face with the same orientation as if the image were displayed normally in 2D.
-void X3DImporter::ParseNode_Geometry2D_ArcClose2D()
-{
-    std::string def, use;
-    std::string closureType("PIE");
-    float endAngle = AI_MATH_HALF_PI_F;
-    float radius = 1;
-    bool solid = false;
-    float startAngle = 0;
-    X3DNodeElementBase* ne( nullptr );
-
-	MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
-		MACRO_ATTRREAD_CHECK_RET("closureType", closureType, mReader->getAttributeValue);
-		MACRO_ATTRREAD_CHECK_RET("endAngle", endAngle, XML_ReadNode_GetAttrVal_AsFloat);
-		MACRO_ATTRREAD_CHECK_RET("radius", radius, XML_ReadNode_GetAttrVal_AsFloat);
-		MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_RET("startAngle", startAngle, XML_ReadNode_GetAttrVal_AsFloat);
-	MACRO_ATTRREAD_LOOPEND;
-
-	// if "USE" defined then find already defined element.
-	if(!use.empty())
-	{
-		MACRO_USE_CHECKANDAPPLY(def, use, ENET_ArcClose2D, ne);
-	}
-	else
-	{
-		// create and if needed - define new geometry object.
-		ne = new X3DGeometry2D(X3DNodeElementBase::ENET_ArcClose2D, mNodeElementCur);
-		if(!def.empty()) ne->ID = def;
-
-		((X3DGeometry2D*)ne)->Solid = solid;
-		// create point list of geometry object.
-		GeometryHelper_Make_Arc2D(startAngle, endAngle, radius, 10, ((X3DGeometry2D*)ne)->Vertices);///TODO: IME - AI_CONFIG for NumSeg
-		// add chord or two radiuses only if not a circle was defined
-		if(!((std::fabs(endAngle - startAngle) >= AI_MATH_TWO_PI_F) || (endAngle == startAngle)))
-		{
-			std::list<aiVector3D>& vlist = ((X3DGeometry2D*)ne)->Vertices;// just short alias.
-
-			if((closureType == "PIE") || (closureType == "\"PIE\""))
-				vlist.push_back(aiVector3D(0, 0, 0));// center point - first radial line
-			else if((closureType != "CHORD") && (closureType != "\"CHORD\""))
-				Throw_IncorrectAttrValue("closureType");
-
-			vlist.push_back(*vlist.begin());// arc first point - chord from first to last point of arc(if CHORD) or second radial line(if PIE).
-		}
-
-		((X3DGeometry2D*)ne)->NumIndices = ((X3DGeometry2D*)ne)->Vertices.size();
-		// check for X3DMetadataObject childs.
-		if(!mReader->isEmptyElement())
-			ParseNode_Metadata(ne, "ArcClose2D");
-		else
-			mNodeElementCur->Child.push_back(ne);// add made object as child to current element
-
-		NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
-	}// if(!use.empty()) else
-}
-
-// <Circle2D
-// DEF=""     ID
-// USE=""     IDREF
-// radius="1" SFFloat  [initializeOnly]
-// />
-void X3DImporter::ParseNode_Geometry2D_Circle2D()
-{
-    std::string def, use;
-    float radius = 1;
-    X3DNodeElementBase* ne( nullptr );
-
-	MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
-		MACRO_ATTRREAD_CHECK_RET("radius", radius, XML_ReadNode_GetAttrVal_AsFloat);
-	MACRO_ATTRREAD_LOOPEND;
-
-	// if "USE" defined then find already defined element.
-	if(!use.empty())
-	{
-		MACRO_USE_CHECKANDAPPLY(def, use, ENET_Circle2D, ne);
-	}
-	else
-	{
-		// create and if needed - define new geometry object.
-		ne = new X3DGeometry2D(X3DNodeElementBase::ENET_Circle2D, mNodeElementCur);
-		if(!def.empty()) ne->ID = def;
-
-		// create point list of geometry object and convert it to line set.
-		std::list<aiVector3D> tlist;
-
-		GeometryHelper_Make_Arc2D(0, 0, radius, 10, tlist);///TODO: IME - AI_CONFIG for NumSeg
-		GeometryHelper_Extend_PointToLine(tlist, ((X3DGeometry2D*)ne)->Vertices);
-		((X3DGeometry2D*)ne)->NumIndices = 2;
-		// check for X3DMetadataObject childs.
-		if(!mReader->isEmptyElement())
-			ParseNode_Metadata(ne, "Circle2D");
-		else
-			mNodeElementCur->Child.push_back(ne);// add made object as child to current element
-
-		NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
-	}// if(!use.empty()) else
-}
-
-// <Disk2D
-// DEF=""          ID
-// USE=""          IDREF
-// innerRadius="0" SFFloat  [initializeOnly]
-// outerRadius="1" SFFloat  [initializeOnly]
-// solid="false"   SFBool   [initializeOnly]
-// />
-// The Disk2D node specifies a circular disk which is centred at (0, 0) in the local coordinate system. The outerRadius field specifies the radius of the
-// outer dimension of the Disk2D. The innerRadius field specifies the inner dimension of the Disk2D. The value of outerRadius shall be greater than zero.
-// The value of innerRadius shall be greater than or equal to zero and less than or equal to outerRadius. If innerRadius is zero, the Disk2D is completely
-// filled. Otherwise, the area within the innerRadius forms a hole in the Disk2D. If innerRadius is equal to outerRadius, a solid circular line shall
-// be drawn using the current line properties. Textures are applied individually to each face of the Disk2D. On the front (+Z) and back (-Z) faces of
-// the Disk2D, when viewed from the +Z-axis, the texture is mapped onto each face with the same orientation as if the image were displayed normally in 2D.
-void X3DImporter::ParseNode_Geometry2D_Disk2D()
-{
-    std::string def, use;
-    float innerRadius = 0;
-    float outerRadius = 1;
-    bool solid = false;
-    X3DNodeElementBase* ne( nullptr );
-
-	MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
-		MACRO_ATTRREAD_CHECK_RET("innerRadius", innerRadius, XML_ReadNode_GetAttrVal_AsFloat);
-		MACRO_ATTRREAD_CHECK_RET("outerRadius", outerRadius, XML_ReadNode_GetAttrVal_AsFloat);
-		MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
-	MACRO_ATTRREAD_LOOPEND;
-
-	// if "USE" defined then find already defined element.
-	if(!use.empty())
-	{
-		MACRO_USE_CHECKANDAPPLY(def, use, ENET_Disk2D, ne);
-	}
-	else
-	{
-		std::list<aiVector3D> tlist_o, tlist_i;
-
-		if(innerRadius > outerRadius) Throw_IncorrectAttrValue("innerRadius");
-
-		// create and if needed - define new geometry object.
-		ne = new X3DGeometry2D(X3DNodeElementBase::ENET_Disk2D, mNodeElementCur);
-		if(!def.empty()) ne->ID = def;
-
-		// create point list of geometry object.
-		///TODO: IME - AI_CONFIG for NumSeg
-		GeometryHelper_Make_Arc2D(0, 0, outerRadius, 10, tlist_o);// outer circle
-		if(innerRadius == 0.0f)
-		{// make filled disk
-			// in tlist_o we already have points of circle. just copy it and sign as polygon.
-			((X3DGeometry2D*)ne)->Vertices = tlist_o;
-			((X3DGeometry2D*)ne)->NumIndices = tlist_o.size();
-		}
-		else if(innerRadius == outerRadius)
-		{// make circle
-			// in tlist_o we already have points of circle. convert it to line set.
-			GeometryHelper_Extend_PointToLine(tlist_o, ((X3DGeometry2D*)ne)->Vertices);
-			((X3DGeometry2D*)ne)->NumIndices = 2;
-		}
-		else
-		{// make disk
-			std::list<aiVector3D>& vlist = ((X3DGeometry2D*)ne)->Vertices;// just short alias.
-
-			GeometryHelper_Make_Arc2D(0, 0, innerRadius, 10, tlist_i);// inner circle
-			//
-			// create quad list from two point lists
-			//
-			if(tlist_i.size() < 2) throw DeadlyImportError("Disk2D. Not enough points for creating quad list.");// tlist_i and tlist_o has equal size.
-
-			// add all quads except last
-			for(std::list<aiVector3D>::iterator it_i = tlist_i.begin(), it_o = tlist_o.begin(); it_i != tlist_i.end();)
-			{
-				// do not forget - CCW direction
-				vlist.push_back(*it_i++);// 1st point
-				vlist.push_back(*it_o++);// 2nd point
-				vlist.push_back(*it_o);// 3rd point
-				vlist.push_back(*it_i);// 4th point
-			}
-
-			// add last quad
-			vlist.push_back(*tlist_i.end());// 1st point
-			vlist.push_back(*tlist_o.end());// 2nd point
-			vlist.push_back(*tlist_o.begin());// 3rd point
-			vlist.push_back(*tlist_o.begin());// 4th point
-
-			((X3DGeometry2D*)ne)->NumIndices = 4;
-		}
-
-		((X3DGeometry2D*)ne)->Solid = solid;
-		// check for X3DMetadataObject childs.
-		if(!mReader->isEmptyElement())
-			ParseNode_Metadata(ne, "Disk2D");
-		else
-			mNodeElementCur->Child.push_back(ne);// add made object as child to current element
-
-		NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
-	}// if(!use.empty()) else
-}
-
-// <Polyline2D
-// DEF=""          ID
-// USE=""          IDREF
-// lineSegments="" MFVec2F [intializeOnly]
-// />
-void X3DImporter::ParseNode_Geometry2D_Polyline2D()
-{
-    std::string def, use;
-    std::list<aiVector2D> lineSegments;
-    X3DNodeElementBase* ne( nullptr );
-
-	MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
-		MACRO_ATTRREAD_CHECK_REF("lineSegments", lineSegments, XML_ReadNode_GetAttrVal_AsListVec2f);
-	MACRO_ATTRREAD_LOOPEND;
-
-	// if "USE" defined then find already defined element.
-	if(!use.empty())
-	{
-		MACRO_USE_CHECKANDAPPLY(def, use, ENET_Polyline2D, ne);
-	}
-	else
-	{
-		// create and if needed - define new geometry object.
-		ne = new X3DGeometry2D(X3DNodeElementBase::ENET_Polyline2D, mNodeElementCur);
-		if(!def.empty()) ne->ID = def;
-
-		//
-		// convert read point list of geometry object to line set.
-		//
-		std::list<aiVector3D> tlist;
-
-		// convert vec2 to vec3
-		for(std::list<aiVector2D>::iterator it2 = lineSegments.begin(); it2 != lineSegments.end(); ++it2) tlist.push_back(aiVector3D(it2->x, it2->y, 0));
-
-		// convert point set to line set
-		GeometryHelper_Extend_PointToLine(tlist, ((X3DGeometry2D*)ne)->Vertices);
-		((X3DGeometry2D*)ne)->NumIndices = 2;
-		// check for X3DMetadataObject childs.
-		if(!mReader->isEmptyElement())
-			ParseNode_Metadata(ne, "Polyline2D");
-		else
-			mNodeElementCur->Child.push_back(ne);// add made object as child to current element
-
-		NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
-	}// if(!use.empty()) else
-}
-
-// <Polypoint2D
-// DEF=""   ID
-// USE=""   IDREF
-// point="" MFVec2F [inputOutput]
-// />
-void X3DImporter::ParseNode_Geometry2D_Polypoint2D()
-{
-    std::string def, use;
-    std::list<aiVector2D> point;
-    X3DNodeElementBase* ne( nullptr );
-
-	MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
-		MACRO_ATTRREAD_CHECK_REF("point", point, XML_ReadNode_GetAttrVal_AsListVec2f);
-	MACRO_ATTRREAD_LOOPEND;
-
-	// if "USE" defined then find already defined element.
-	if(!use.empty())
-	{
-		MACRO_USE_CHECKANDAPPLY(def, use, ENET_Polypoint2D, ne);
-	}
-	else
-	{
-		// create and if needed - define new geometry object.
-		ne = new X3DGeometry2D(X3DNodeElementBase::ENET_Polypoint2D, mNodeElementCur);
-		if(!def.empty()) ne->ID = def;
-
-		// convert vec2 to vec3
-		for(std::list<aiVector2D>::iterator it2 = point.begin(); it2 != point.end(); ++it2)
-		{
-			((X3DGeometry2D*)ne)->Vertices.push_back(aiVector3D(it2->x, it2->y, 0));
-		}
-
-		((X3DGeometry2D*)ne)->NumIndices = 1;
-		// check for X3DMetadataObject childs.
-		if(!mReader->isEmptyElement())
-			ParseNode_Metadata(ne, "Polypoint2D");
-		else
-			mNodeElementCur->Child.push_back(ne);// add made object as child to current element
-
-		NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
-	}// if(!use.empty()) else
-}
-
-// <Rectangle2D
-// DEF=""        ID
-// USE=""        IDREF
-// size="2 2"    SFVec2f [initializeOnly]
-// solid="false" SFBool  [initializeOnly]
-// />
-void X3DImporter::ParseNode_Geometry2D_Rectangle2D()
-{
-    std::string def, use;
-    aiVector2D size(2, 2);
-    bool solid = false;
-    X3DNodeElementBase* ne( nullptr );
-
-	MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
-		MACRO_ATTRREAD_CHECK_REF("size", size, XML_ReadNode_GetAttrVal_AsVec2f);
-		MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
-	MACRO_ATTRREAD_LOOPEND;
-
-	// if "USE" defined then find already defined element.
-	if(!use.empty())
-	{
-		MACRO_USE_CHECKANDAPPLY(def, use, ENET_Rectangle2D, ne);
-	}
-	else
-	{
-		// create and if needed - define new geometry object.
-		ne = new X3DGeometry2D(X3DNodeElementBase::ENET_Rectangle2D, mNodeElementCur);
-		if(!def.empty()) ne->ID = def;
-
-		float x1 = -size.x / 2.0f;
-		float x2 = size.x / 2.0f;
-		float y1 = -size.y / 2.0f;
-		float y2 = size.y / 2.0f;
-		std::list<aiVector3D>& vlist = ((X3DGeometry2D*)ne)->Vertices;// just short alias.
-
-		vlist.push_back(aiVector3D(x2, y1, 0));// 1st point
-		vlist.push_back(aiVector3D(x2, y2, 0));// 2nd point
-		vlist.push_back(aiVector3D(x1, y2, 0));// 3rd point
-		vlist.push_back(aiVector3D(x1, y1, 0));// 4th point
-		((X3DGeometry2D*)ne)->Solid = solid;
-		((X3DGeometry2D*)ne)->NumIndices = 4;
-		// check for X3DMetadataObject childs.
-		if(!mReader->isEmptyElement())
-			ParseNode_Metadata(ne, "Rectangle2D");
-		else
-			mNodeElementCur->Child.push_back(ne);// add made object as child to current element
-
-		NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
-	}// if(!use.empty()) else
-}
-
-// <TriangleSet2D
-// DEF=""        ID
-// USE=""        IDREF
-// solid="false" SFBool  [initializeOnly]
-// vertices=""   MFVec2F [inputOutput]
-// />
-void X3DImporter::ParseNode_Geometry2D_TriangleSet2D()
-{
-    std::string def, use;
-    bool solid = false;
-    std::list<aiVector2D> vertices;
-    X3DNodeElementBase* ne( nullptr );
-
-	MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
-		MACRO_ATTRREAD_CHECK_REF("vertices", vertices, XML_ReadNode_GetAttrVal_AsListVec2f);
-		MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
-	MACRO_ATTRREAD_LOOPEND;
-
-	// if "USE" defined then find already defined element.
-	if(!use.empty())
-	{
-		MACRO_USE_CHECKANDAPPLY(def, use, ENET_TriangleSet2D, ne);
-	}
-	else
-	{
-		if(vertices.size() % 3) throw DeadlyImportError("TriangleSet2D. Not enough points for defining triangle.");
-
-		// create and if needed - define new geometry object.
-		ne = new X3DGeometry2D(X3DNodeElementBase::ENET_TriangleSet2D, mNodeElementCur);
-		if(!def.empty()) ne->ID = def;
-
-		// convert vec2 to vec3
-		for(std::list<aiVector2D>::iterator it2 = vertices.begin(); it2 != vertices.end(); ++it2)
-		{
-			((X3DGeometry2D*)ne)->Vertices.push_back(aiVector3D(it2->x, it2->y, 0));
-		}
-
-		((X3DGeometry2D*)ne)->Solid = solid;
-		((X3DGeometry2D*)ne)->NumIndices = 3;
-		// check for X3DMetadataObject childs.
-		if(!mReader->isEmptyElement())
-			ParseNode_Metadata(ne, "TriangleSet2D");
-		else
-			mNodeElementCur->Child.push_back(ne);// add made object as child to current element
-
-		NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
-	}// if(!use.empty()) else
-}
-
-}// namespace Assimp
-
-#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER

+ 0 - 999
code/AssetLib/X3D/X3DImporter_Geometry3D.cpp

@@ -1,999 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2020, 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_Geometry3D.cpp
-/// \brief  Parsing data from nodes of "Geometry3D" set of X3D.
-/// \date   2015-2016
-/// \author [email protected]
-
-#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
-
-#include "X3DImporter.hpp"
-#include "X3DImporter_Macro.hpp"
-
-// Header files, Assimp.
-#include <assimp/StandardShapes.h>
-
-namespace Assimp
-{
-
-// <Box
-// DEF=""       ID
-// USE=""       IDREF
-// size="2 2 2" SFVec3f [initializeOnly]
-// solid="true" SFBool  [initializeOnly]
-// />
-// The Box node specifies a rectangular parallelepiped box centred at (0, 0, 0) in the local coordinate system and aligned with the local coordinate axes.
-// By default, the box measures 2 units in each dimension, from -1 to +1. The size field specifies the extents of the box along the X-, Y-, and Z-axes
-// respectively and each component value shall be greater than zero.
-void X3DImporter::ParseNode_Geometry3D_Box()
-{
-    std::string def, use;
-    bool solid = true;
-    aiVector3D size(2, 2, 2);
-    X3DNodeElementBase* ne( nullptr );
-
-	MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
-		MACRO_ATTRREAD_CHECK_REF("size", size, XML_ReadNode_GetAttrVal_AsVec3f);
-		MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
-	MACRO_ATTRREAD_LOOPEND;
-
-	// if "USE" defined then find already defined element.
-	if(!use.empty())
-	{
-		MACRO_USE_CHECKANDAPPLY(def, use, ENET_Box, ne);
-	}
-	else
-	{
-		// create and if needed - define new geometry object.
-		ne = new X3DGeometry3D(X3DNodeElementBase::ENET_Box, mNodeElementCur);
-		if(!def.empty()) ne->ID = def;
-
-		GeometryHelper_MakeQL_RectParallelepiped(size, ((X3DGeometry3D*)ne)->Vertices);// get quad list
-		((X3DGeometry3D*)ne)->Solid = solid;
-		((X3DGeometry3D*)ne)->NumIndices = 4;
-		// check for X3DMetadataObject childs.
-		if(!mReader->isEmptyElement())
-			ParseNode_Metadata(ne, "Box");
-		else
-			mNodeElementCur->Child.push_back(ne);// add made object as child to current element
-
-		NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
-	}// if(!use.empty()) else
-}
-
-// <Cone
-// DEF=""           ID
-// USE=""           IDREF
-// bottom="true"    SFBool [initializeOnly]
-// bottomRadius="1" SFloat [initializeOnly]
-// height="2"       SFloat [initializeOnly]
-// side="true"      SFBool [initializeOnly]
-// solid="true"     SFBool [initializeOnly]
-// />
-void X3DImporter::ParseNode_Geometry3D_Cone()
-{
-    std::string use, def;
-    bool bottom = true;
-    float bottomRadius = 1;
-    float height = 2;
-    bool side = true;
-    bool solid = true;
-    X3DNodeElementBase* ne( nullptr );
-
-	MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
-		MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_RET("side", side, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_RET("bottom", bottom, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_RET("height", height, XML_ReadNode_GetAttrVal_AsFloat);
-		MACRO_ATTRREAD_CHECK_RET("bottomRadius", bottomRadius, XML_ReadNode_GetAttrVal_AsFloat);
-	MACRO_ATTRREAD_LOOPEND;
-
-	// if "USE" defined then find already defined element.
-	if(!use.empty())
-	{
-		MACRO_USE_CHECKANDAPPLY(def, use, ENET_Cone, ne);
-	}
-	else
-	{
-		const unsigned int tess = 30;///TODO: IME tessellation factor through ai_property
-
-		std::vector<aiVector3D> tvec;// temp array for vertices.
-
-		// create and if needed - define new geometry object.
-		ne = new X3DGeometry3D(X3DNodeElementBase::ENET_Cone, mNodeElementCur);
-		if(!def.empty()) ne->ID = def;
-
-		// make cone or parts according to flags.
-		if(side)
-		{
-			StandardShapes::MakeCone(height, 0, bottomRadius, tess, tvec, !bottom);
-		}
-		else if(bottom)
-		{
-			StandardShapes::MakeCircle(bottomRadius, tess, tvec);
-			height = -(height / 2);
-			for(std::vector<aiVector3D>::iterator it = tvec.begin(); it != tvec.end(); ++it) it->y = height;// y - because circle made in oXZ.
-		}
-
-		// copy data from temp array
-		for(std::vector<aiVector3D>::iterator it = tvec.begin(); it != tvec.end(); ++it) ((X3DGeometry3D*)ne)->Vertices.push_back(*it);
-
-		((X3DGeometry3D*)ne)->Solid = solid;
-		((X3DGeometry3D*)ne)->NumIndices = 3;
-		// check for X3DMetadataObject childs.
-		if(!mReader->isEmptyElement())
-			ParseNode_Metadata(ne, "Cone");
-		else
-			mNodeElementCur->Child.push_back(ne);// add made object as child to current element
-
-		NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
-	}// if(!use.empty()) else
-}
-
-// <Cylinder
-// DEF=""        ID
-// USE=""        IDREF
-// bottom="true" SFBool [initializeOnly]
-// height="2"    SFloat [initializeOnly]
-// radius="1"    SFloat [initializeOnly]
-// side="true"   SFBool [initializeOnly]
-// solid="true"  SFBool [initializeOnly]
-// top="true"    SFBool [initializeOnly]
-// />
-void X3DImporter::ParseNode_Geometry3D_Cylinder()
-{
-    std::string use, def;
-    bool bottom = true;
-    float height = 2;
-    float radius = 1;
-    bool side = true;
-    bool solid = true;
-    bool top = true;
-    X3DNodeElementBase* ne( nullptr );
-
-	MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
-		MACRO_ATTRREAD_CHECK_RET("radius", radius, XML_ReadNode_GetAttrVal_AsFloat);
-		MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_RET("bottom", bottom, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_RET("top", top, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_RET("side", side, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_RET("height", height, XML_ReadNode_GetAttrVal_AsFloat);
-	MACRO_ATTRREAD_LOOPEND;
-
-	// if "USE" defined then find already defined element.
-	if(!use.empty())
-	{
-		MACRO_USE_CHECKANDAPPLY(def, use, ENET_Cylinder, ne);
-	}
-	else
-	{
-		const unsigned int tess = 30;///TODO: IME tessellation factor through ai_property
-
-		std::vector<aiVector3D> tside;// temp array for vertices of side.
-		std::vector<aiVector3D> tcir;// temp array for vertices of circle.
-
-		// create and if needed - define new geometry object.
-		ne = new X3DGeometry3D(X3DNodeElementBase::ENET_Cylinder, mNodeElementCur);
-		if(!def.empty()) ne->ID = def;
-
-		// make cilynder or parts according to flags.
-		if(side) StandardShapes::MakeCone(height, radius, radius, tess, tside, true);
-
-		height /= 2;// height defined for whole cylinder, when creating top and bottom circle we are using just half of height.
-		if(top || bottom) StandardShapes::MakeCircle(radius, tess, tcir);
-		// copy data from temp arrays
-		std::list<aiVector3D>& vlist = ((X3DGeometry3D*)ne)->Vertices;// just short alias.
-
-		for(std::vector<aiVector3D>::iterator it = tside.begin(); it != tside.end(); ++it) vlist.push_back(*it);
-
-		if(top)
-		{
-			for(std::vector<aiVector3D>::iterator it = tcir.begin(); it != tcir.end(); ++it)
-			{
-				(*it).y = height;// y - because circle made in oXZ.
-				vlist.push_back(*it);
-			}
-		}// if(top)
-
-		if(bottom)
-		{
-			for(std::vector<aiVector3D>::iterator it = tcir.begin(); it != tcir.end(); ++it)
-			{
-				(*it).y = -height;// y - because circle made in oXZ.
-				vlist.push_back(*it);
-			}
-		}// if(top)
-
-		((X3DGeometry3D*)ne)->Solid = solid;
-		((X3DGeometry3D*)ne)->NumIndices = 3;
-		// check for X3DMetadataObject childs.
-		if(!mReader->isEmptyElement())
-			ParseNode_Metadata(ne, "Cylinder");
-		else
-			mNodeElementCur->Child.push_back(ne);// add made object as child to current element
-
-		NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
-	}// if(!use.empty()) else
-}
-
-// <ElevationGrid
-// DEF=""                 ID
-// USE=""                 IDREF
-// ccw="true"             SFBool  [initializeOnly]
-// colorPerVertex="true"  SFBool  [initializeOnly]
-// creaseAngle="0"        SFloat  [initializeOnly]
-// height=""              MFloat  [initializeOnly]
-// normalPerVertex="true" SFBool  [initializeOnly]
-// solid="true"           SFBool  [initializeOnly]
-// xDimension="0"         SFInt32 [initializeOnly]
-// xSpacing="1.0"         SFloat  [initializeOnly]
-// zDimension="0"         SFInt32 [initializeOnly]
-// zSpacing="1.0"         SFloat  [initializeOnly]
-// >
-//   <!-- ColorNormalTexCoordContentModel -->
-// ColorNormalTexCoordContentModel can contain Color (or ColorRGBA), Normal and TextureCoordinate, in any order. No more than one instance of any single
-// node type is allowed. A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
-// </ElevationGrid>
-// The ElevationGrid node specifies a uniform rectangular grid of varying height in the Y=0 plane of the local coordinate system. The geometry is described
-// by a scalar array of height values that specify the height of a surface above each point of the grid. The xDimension and zDimension fields indicate
-// the number of elements of the grid height array in the X and Z directions. Both xDimension and zDimension shall be greater than or equal to zero.
-// If either the xDimension or the zDimension is less than two, the ElevationGrid contains no quadrilaterals.
-void X3DImporter::ParseNode_Geometry3D_ElevationGrid()
-{
-    std::string use, def;
-    bool ccw = true;
-    bool colorPerVertex = true;
-    float creaseAngle = 0;
-    std::vector<float> height;
-    bool normalPerVertex = true;
-    bool solid = true;
-    int32_t xDimension = 0;
-    float xSpacing = 1;
-    int32_t zDimension = 0;
-    float zSpacing = 1;
-    X3DNodeElementBase* ne( nullptr );
-
-	MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
-		MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_RET("creaseAngle", creaseAngle, XML_ReadNode_GetAttrVal_AsFloat);
-		MACRO_ATTRREAD_CHECK_REF("height", height, XML_ReadNode_GetAttrVal_AsArrF);
-		MACRO_ATTRREAD_CHECK_RET("xDimension", xDimension, XML_ReadNode_GetAttrVal_AsI32);
-		MACRO_ATTRREAD_CHECK_RET("xSpacing", xSpacing, XML_ReadNode_GetAttrVal_AsFloat);
-		MACRO_ATTRREAD_CHECK_RET("zDimension", zDimension, XML_ReadNode_GetAttrVal_AsI32);
-		MACRO_ATTRREAD_CHECK_RET("zSpacing", zSpacing, XML_ReadNode_GetAttrVal_AsFloat);
-	MACRO_ATTRREAD_LOOPEND;
-
-	// if "USE" defined then find already defined element.
-	if(!use.empty())
-	{
-		MACRO_USE_CHECKANDAPPLY(def, use, ENET_ElevationGrid, ne);
-	}
-	else
-	{
-		if((xSpacing == 0.0f) || (zSpacing == 0.0f)) throw DeadlyImportError("Spacing in <ElevationGrid> must be grater than zero.");
-		if((xDimension <= 0) || (zDimension <= 0)) throw DeadlyImportError("Dimension in <ElevationGrid> must be grater than zero.");
-		if((size_t)(xDimension * zDimension) != height.size()) Throw_IncorrectAttrValue("Heights count must be equal to \"xDimension * zDimension\"");
-
-		// create and if needed - define new geometry object.
-		ne = new X3DElevationGrid(X3DNodeElementBase::ENET_ElevationGrid, mNodeElementCur);
-		if(!def.empty()) ne->ID = def;
-
-		X3DElevationGrid& grid_alias = *((X3DElevationGrid*)ne);// create alias for conveience
-
-		{// create grid vertices list
-			std::vector<float>::const_iterator he_it = height.begin();
-
-			for(int32_t zi = 0; zi < zDimension; zi++)// rows
-			{
-				for(int32_t xi = 0; xi < xDimension; xi++)// columns
-				{
-					aiVector3D tvec(xSpacing * xi, *he_it, zSpacing * zi);
-
-					grid_alias.Vertices.push_back(tvec);
-					++he_it;
-				}
-			}
-		}// END: create grid vertices list
-		//
-		// create faces list. In "coordIdx" format
-		//
-		// check if we have quads
-		if((xDimension < 2) || (zDimension < 2))// only one element in dimension is set, create line set.
-		{
-			((X3DElevationGrid*)ne)->NumIndices = 2;// will be holded as line set.
-			for(size_t i = 0, i_e = (grid_alias.Vertices.size() - 1); i < i_e; i++)
-			{
-				grid_alias.CoordIdx.push_back(static_cast<int32_t>(i));
-				grid_alias.CoordIdx.push_back(static_cast<int32_t>(i + 1));
-				grid_alias.CoordIdx.push_back(-1);
-			}
-		}
-		else// two or more elements in every dimension is set. create quad set.
-		{
-			((X3DElevationGrid*)ne)->NumIndices = 4;
-			for(int32_t fzi = 0, fzi_e = (zDimension - 1); fzi < fzi_e; fzi++)// rows
-			{
-				for(int32_t fxi = 0, fxi_e = (xDimension - 1); fxi < fxi_e; fxi++)// columns
-				{
-					// points direction in face.
-					if(ccw)
-					{
-						// CCW:
-						//	3 2
-						//	0 1
-						grid_alias.CoordIdx.push_back((fzi + 1) * xDimension + fxi);
-						grid_alias.CoordIdx.push_back((fzi + 1) * xDimension + (fxi + 1));
-						grid_alias.CoordIdx.push_back(fzi * xDimension + (fxi + 1));
-						grid_alias.CoordIdx.push_back(fzi * xDimension + fxi);
-					}
-					else
-					{
-						// CW:
-						//	0 1
-						//	3 2
-						grid_alias.CoordIdx.push_back(fzi * xDimension + fxi);
-						grid_alias.CoordIdx.push_back(fzi * xDimension + (fxi + 1));
-						grid_alias.CoordIdx.push_back((fzi + 1) * xDimension + (fxi + 1));
-						grid_alias.CoordIdx.push_back((fzi + 1) * xDimension + fxi);
-					}// if(ccw) else
-
-					grid_alias.CoordIdx.push_back(-1);
-				}// for(int32_t fxi = 0, fxi_e = (xDimension - 1); fxi < fxi_e; fxi++)
-			}// for(int32_t fzi = 0, fzi_e = (zDimension - 1); fzi < fzi_e; fzi++)
-		}// if((xDimension < 2) || (zDimension < 2)) else
-
-		grid_alias.ColorPerVertex = colorPerVertex;
-		grid_alias.NormalPerVertex = normalPerVertex;
-		grid_alias.CreaseAngle = creaseAngle;
-		grid_alias.Solid = solid;
-        // check for child nodes
-        if(!mReader->isEmptyElement())
-        {
-			ParseHelper_Node_Enter(ne);
-			MACRO_NODECHECK_LOOPBEGIN("ElevationGrid");
-				// check for X3DComposedGeometryNodes
-				if(XML_CheckNode_NameEqual("Color")) { ParseNode_Rendering_Color(); continue; }
-				if(XML_CheckNode_NameEqual("ColorRGBA")) { ParseNode_Rendering_ColorRGBA(); continue; }
-				if(XML_CheckNode_NameEqual("Normal")) { ParseNode_Rendering_Normal(); continue; }
-				if(XML_CheckNode_NameEqual("TextureCoordinate")) { ParseNode_Texturing_TextureCoordinate(); continue; }
-				// check for X3DMetadataObject
-				if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("ElevationGrid");
-
-			MACRO_NODECHECK_LOOPEND("ElevationGrid");
-			ParseHelper_Node_Exit();
-		}// if(!mReader->isEmptyElement())
-		else
-		{
-			mNodeElementCur->Child.push_back(ne);// add made object as child to current element
-		}// if(!mReader->isEmptyElement()) else
-
-		NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
-	}// if(!use.empty()) else
-}
-
-template<typename TVector>
-static void GeometryHelper_Extrusion_CurveIsClosed(std::vector<TVector>& pCurve, const bool pDropTail, const bool pRemoveLastPoint, bool& pCurveIsClosed)
-{
-    size_t cur_sz = pCurve.size();
-
-	pCurveIsClosed = false;
-	// for curve with less than four points checking is have no sense,
-	if(cur_sz < 4) return;
-
-	for(size_t s = 3, s_e = cur_sz; s < s_e; s++)
-	{
-		// search for first point of duplicated part.
-		if(pCurve[0] == pCurve[s])
-		{
-			bool found = true;
-
-			// check if tail(indexed by b2) is duplicate of head(indexed by b1).
-			for(size_t b1 = 1, b2 = (s + 1); b2 < cur_sz; b1++, b2++)
-			{
-				if(pCurve[b1] != pCurve[b2])
-				{// points not match: clear flag and break loop.
-					found = false;
-
-					break;
-				}
-			}// for(size_t b1 = 1, b2 = (s + 1); b2 < cur_sz; b1++, b2++)
-
-			// if duplicate tail is found then drop or not it depending on flags.
-			if(found)
-			{
-				pCurveIsClosed = true;
-				if(pDropTail)
-				{
-					if(!pRemoveLastPoint) s++;// prepare value for iterator's arithmetics.
-
-					pCurve.erase(pCurve.begin() + s, pCurve.end());// remove tail
-				}
-
-				break;
-			}// if(found)
-		}// if(pCurve[0] == pCurve[s])
-	}// for(size_t s = 3, s_e = (cur_sz - 1); s < s_e; s++)
-}
-
-static aiVector3D GeometryHelper_Extrusion_GetNextY(const size_t pSpine_PointIdx, const std::vector<aiVector3D>& pSpine, const bool pSpine_Closed)
-{
-    const size_t spine_idx_last = pSpine.size() - 1;
-    aiVector3D tvec;
-
-	if((pSpine_PointIdx == 0) || (pSpine_PointIdx == spine_idx_last))// at first special cases
-	{
-		if(pSpine_Closed)
-		{// If the spine curve is closed: The SCP for the first and last points is the same and is found using (spine[1] - spine[n - 2]) to compute the Y-axis.
-			// As we even for closed spine curve last and first point in pSpine are not the same: duplicates(spine[n - 1] which are equivalent to spine[0])
-			// in tail are removed.
-			// So, last point in pSpine is a spine[n - 2]
-			tvec = pSpine[1] - pSpine[spine_idx_last];
-		}
-		else if(pSpine_PointIdx == 0)
-		{// The Y-axis used for the first point is the vector from spine[0] to spine[1]
-			tvec = pSpine[1] - pSpine[0];
-		}
-		else
-		{// The Y-axis used for the last point it is the vector from spine[n-2] to spine[n-1]. In our case(see above about dropping tail) spine[n - 1] is
-			// the spine[0].
-			tvec = pSpine[spine_idx_last] - pSpine[spine_idx_last - 1];
-		}
-	}// if((pSpine_PointIdx == 0) || (pSpine_PointIdx == spine_idx_last))
-	else
-	{// For all points other than the first or last: The Y-axis for spine[i] is found by normalizing the vector defined by (spine[i+1] - spine[i-1]).
-		tvec = pSpine[pSpine_PointIdx + 1] - pSpine[pSpine_PointIdx - 1];
-	}// if((pSpine_PointIdx == 0) || (pSpine_PointIdx == spine_idx_last)) else
-
-	return tvec.Normalize();
-}
-
-static aiVector3D GeometryHelper_Extrusion_GetNextZ(const size_t pSpine_PointIdx, const std::vector<aiVector3D>& pSpine, const bool pSpine_Closed,
-													const aiVector3D pVecZ_Prev)
-{
-    const aiVector3D zero_vec(0);
-    const size_t spine_idx_last = pSpine.size() - 1;
-
-    aiVector3D tvec;
-
-	// at first special cases
-	if(pSpine.size() < 3)// spine have not enough points for vector calculations.
-	{
-		tvec.Set(0, 0, 1);
-	}
-	else if(pSpine_PointIdx == 0)// special case: first point
-	{
-		if(pSpine_Closed)// for calculating use previous point in curve s[n - 2]. In list it's a last point, because point s[n - 1] was removed as duplicate.
-		{
-			tvec = (pSpine[1] - pSpine[0]) ^ (pSpine[spine_idx_last] - pSpine[0]);
-		}
-		else // for not closed curve first and next point(s[0] and s[1]) has the same vector Z.
-		{
-			bool found = false;
-
-			// As said: "If the Z-axis of the first point is undefined (because the spine is not closed and the first two spine segments are collinear)
-			// then the Z-axis for the first spine point with a defined Z-axis is used."
-			// Walk through spine and find Z.
-			for(size_t next_point = 2; (next_point <= spine_idx_last) && !found; next_point++)
-			{
-				// (pSpine[2] - pSpine[1]) ^ (pSpine[0] - pSpine[1])
-				tvec = (pSpine[next_point] - pSpine[next_point - 1]) ^ (pSpine[next_point - 2] - pSpine[next_point - 1]);
-				found = !tvec.Equal(zero_vec);
-			}
-
-			// if entire spine are collinear then use OZ axis.
-			if(!found) tvec.Set(0, 0, 1);
-		}// if(pSpine_Closed) else
-	}// else if(pSpine_PointIdx == 0)
-	else if(pSpine_PointIdx == spine_idx_last)// special case: last point
-	{
-		if(pSpine_Closed)
-		{// do not forget that real last point s[n - 1] is removed as duplicated. And in this case we are calculating vector Z for point s[n - 2].
-			tvec = (pSpine[0] - pSpine[pSpine_PointIdx]) ^ (pSpine[pSpine_PointIdx - 1] - pSpine[pSpine_PointIdx]);
-			// if taken spine vectors are collinear then use previous vector Z.
-			if(tvec.Equal(zero_vec)) tvec = pVecZ_Prev;
-		}
-		else
-		{// vector Z for last point of not closed curve is previous vector Z.
-			tvec = pVecZ_Prev;
-		}
-	}
-	else// regular point
-	{
-		tvec = (pSpine[pSpine_PointIdx + 1] - pSpine[pSpine_PointIdx]) ^ (pSpine[pSpine_PointIdx - 1] - pSpine[pSpine_PointIdx]);
-		// if taken spine vectors are collinear then use previous vector Z.
-		if(tvec.Equal(zero_vec)) tvec = pVecZ_Prev;
-	}
-
-	// After determining the Z-axis, its dot product with the Z-axis of the previous spine point is computed. If this value is negative, the Z-axis
-	// is flipped (multiplied by -1).
-	if((tvec * pVecZ_Prev) < 0) tvec = -tvec;
-
-	return tvec.Normalize();
-}
-
-// <Extrusion
-// DEF=""                                 ID
-// USE=""                                 IDREF
-// beginCap="true"                        SFBool     [initializeOnly]
-// ccw="true"                             SFBool     [initializeOnly]
-// convex="true"                          SFBool     [initializeOnly]
-// creaseAngle="0.0"                      SFloat     [initializeOnly]
-// crossSection="1 1 1 -1 -1 -1 -1 1 1 1" MFVec2f    [initializeOnly]
-// endCap="true"                          SFBool     [initializeOnly]
-// orientation="0 0 1 0"                  MFRotation [initializeOnly]
-// scale="1 1"                            MFVec2f    [initializeOnly]
-// solid="true"                           SFBool     [initializeOnly]
-// spine="0 0 0 0 1 0"                    MFVec3f    [initializeOnly]
-// />
-void X3DImporter::ParseNode_Geometry3D_Extrusion()
-{
-    std::string use, def;
-    bool beginCap = true;
-    bool ccw = true;
-    bool convex = true;
-    float creaseAngle = 0;
-    std::vector<aiVector2D> crossSection;
-    bool endCap = true;
-    std::vector<float> orientation;
-    std::vector<aiVector2D> scale;
-    bool solid = true;
-    std::vector<aiVector3D> spine;
-    X3DNodeElementBase* ne( nullptr );
-
-	MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
-		MACRO_ATTRREAD_CHECK_RET("beginCap", beginCap, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_RET("convex", convex, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_RET("creaseAngle", creaseAngle, XML_ReadNode_GetAttrVal_AsFloat);
-		MACRO_ATTRREAD_CHECK_REF("crossSection", crossSection, XML_ReadNode_GetAttrVal_AsArrVec2f);
-		MACRO_ATTRREAD_CHECK_RET("endCap", endCap, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_REF("orientation", orientation, XML_ReadNode_GetAttrVal_AsArrF);
-		MACRO_ATTRREAD_CHECK_REF("scale", scale, XML_ReadNode_GetAttrVal_AsArrVec2f);
-		MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_REF("spine", spine, XML_ReadNode_GetAttrVal_AsArrVec3f);
-	MACRO_ATTRREAD_LOOPEND;
-
-	// if "USE" defined then find already defined element.
-	if(!use.empty())
-	{
-		MACRO_USE_CHECKANDAPPLY(def, use, ENET_Extrusion, ne);
-	}
-	else
-	{
-		//
-		// check if default values must be assigned
-		//
-		if(spine.size() == 0)
-		{
-			spine.resize(2);
-			spine[0].Set(0, 0, 0), spine[1].Set(0, 1, 0);
-		}
-		else if(spine.size() == 1)
-		{
-			throw DeadlyImportError("ParseNode_Geometry3D_Extrusion. Spine must have at least two points.");
-		}
-
-		if(crossSection.size() == 0)
-		{
-			crossSection.resize(5);
-			crossSection[0].Set(1, 1), crossSection[1].Set(1, -1), crossSection[2].Set(-1, -1), crossSection[3].Set(-1, 1), crossSection[4].Set(1, 1);
-		}
-
-		{// orientation
-			size_t ori_size = orientation.size() / 4;
-
-			if(ori_size < spine.size())
-			{
-				float add_ori[4];// values that will be added
-
-				if(ori_size == 1)// if "orientation" has one element(means one MFRotation with four components) then use it value for all spine points.
-				{
-					add_ori[0] = orientation[0], add_ori[1] = orientation[1], add_ori[2] = orientation[2], add_ori[3] = orientation[3];
-				}
-				else// else - use default values
-				{
-					add_ori[0] = 0, add_ori[1] = 0, add_ori[2] = 1, add_ori[3] = 0;
-				}
-
-				orientation.reserve(spine.size() * 4);
-				for(size_t i = 0, i_e = (spine.size() - ori_size); i < i_e; i++)
-					orientation.push_back(add_ori[0]), orientation.push_back(add_ori[1]), orientation.push_back(add_ori[2]), orientation.push_back(add_ori[3]);
-			}
-
-			if(orientation.size() % 4) throw DeadlyImportError("Attribute \"orientation\" in <Extrusion> must has multiple four quantity of numbers.");
-		}// END: orientation
-
-		{// scale
-			if(scale.size() < spine.size())
-			{
-				aiVector2D add_sc;
-
-				if(scale.size() == 1)// if "scale" has one element then use it value for all spine points.
-					add_sc = scale[0];
-				else// else - use default values
-					add_sc.Set(1, 1);
-
-				scale.reserve(spine.size());
-				for(size_t i = 0, i_e = (spine.size() - scale.size()); i < i_e; i++) scale.push_back(add_sc);
-			}
-		}// END: scale
-		//
-		// create and if needed - define new geometry object.
-		//
-		ne = new X3DIndexedSet(X3DNodeElementBase::ENET_Extrusion, mNodeElementCur);
-		if(!def.empty()) ne->ID = def;
-
-		X3DIndexedSet& ext_alias = *((X3DIndexedSet*)ne);// create alias for conveience
-		// assign part of input data
-		ext_alias.CCW = ccw;
-		ext_alias.Convex = convex;
-		ext_alias.CreaseAngle = creaseAngle;
-		ext_alias.Solid = solid;
-
-		//
-		// How we done it at all?
-		// 1. At first we will calculate array of basises for every point in spine(look SCP in ISO-dic). Also "orientation" vector
-		// are applied vor every basis.
-		// 2. After that we can create array of point sets: which are scaled, transferred to basis of relative basis and at final translated to real position
-		// using relative spine point.
-		// 3. Next step is creating CoordIdx array(do not forget "-1" delimiter). While creating CoordIdx also created faces for begin and end caps, if
-		// needed. While createing CootdIdx is taking in account CCW flag.
-		// 4. The last step: create Vertices list.
-		//
-        bool spine_closed;// flag: true if spine curve is closed.
-        bool cross_closed;// flag: true if cross curve is closed.
-        std::vector<aiMatrix3x3> basis_arr;// array of basises. ROW_a - X, ROW_b - Y, ROW_c - Z.
-        std::vector<std::vector<aiVector3D> > pointset_arr;// array of point sets: cross curves.
-
-        // detect closed curves
-        GeometryHelper_Extrusion_CurveIsClosed(crossSection, true, true, cross_closed);// true - drop tail, true - remove duplicate end.
-        GeometryHelper_Extrusion_CurveIsClosed(spine, true, true, spine_closed);// true - drop tail, true - remove duplicate end.
-        // If both cap are requested and spine curve is closed then we can make only one cap. Because second cap will be the same surface.
-        if(spine_closed)
-        {
-			beginCap |= endCap;
-			endCap = false;
-		}
-
-        {// 1. Calculate array of basises.
-			aiMatrix4x4 rotmat;
-			aiVector3D vecX(0), vecY(0), vecZ(0);
-
-			basis_arr.resize(spine.size());
-			for(size_t i = 0, i_e = spine.size(); i < i_e; i++)
-			{
-				aiVector3D tvec;
-
-				// get axises of basis.
-				vecY = GeometryHelper_Extrusion_GetNextY(i, spine, spine_closed);
-				vecZ = GeometryHelper_Extrusion_GetNextZ(i, spine, spine_closed, vecZ);
-				vecX = (vecY ^ vecZ).Normalize();
-				// get rotation matrix and apply "orientation" to basis
-				aiMatrix4x4::Rotation(orientation[i * 4 + 3], aiVector3D(orientation[i * 4], orientation[i * 4 + 1], orientation[i * 4 + 2]), rotmat);
-				tvec = vecX, tvec *= rotmat, basis_arr[i].a1 = tvec.x, basis_arr[i].a2 = tvec.y, basis_arr[i].a3 = tvec.z;
-				tvec = vecY, tvec *= rotmat, basis_arr[i].b1 = tvec.x, basis_arr[i].b2 = tvec.y, basis_arr[i].b3 = tvec.z;
-				tvec = vecZ, tvec *= rotmat, basis_arr[i].c1 = tvec.x, basis_arr[i].c2 = tvec.y, basis_arr[i].c3 = tvec.z;
-			}// for(size_t i = 0, i_e = spine.size(); i < i_e; i++)
-		}// END: 1. Calculate array of basises
-
-		{// 2. Create array of point sets.
-			aiMatrix4x4 scmat;
-			std::vector<aiVector3D> tcross(crossSection.size());
-
-			pointset_arr.resize(spine.size());
-			for(size_t spi = 0, spi_e = spine.size(); spi < spi_e; spi++)
-			{
-				aiVector3D tc23vec;
-
-				tc23vec.Set(scale[spi].x, 0, scale[spi].y);
-				aiMatrix4x4::Scaling(tc23vec, scmat);
-				for(size_t cri = 0, cri_e = crossSection.size(); cri < cri_e; cri++)
-				{
-					aiVector3D tvecX, tvecY, tvecZ;
-
-					tc23vec.Set(crossSection[cri].x, 0, crossSection[cri].y);
-					// apply scaling to point
-					tcross[cri] = scmat * tc23vec;
-					//
-					// transfer point to new basis
-					// calculate coordinate in new basis
-					tvecX.Set(basis_arr[spi].a1, basis_arr[spi].a2, basis_arr[spi].a3), tvecX *= tcross[cri].x;
-					tvecY.Set(basis_arr[spi].b1, basis_arr[spi].b2, basis_arr[spi].b3), tvecY *= tcross[cri].y;
-					tvecZ.Set(basis_arr[spi].c1, basis_arr[spi].c2, basis_arr[spi].c3), tvecZ *= tcross[cri].z;
-					// apply new coordinates and translate it to spine point.
-					tcross[cri] = tvecX + tvecY + tvecZ + spine[spi];
-				}// for(size_t cri = 0, cri_e = crossSection.size(); cri < cri_e; i++)
-
-				pointset_arr[spi] = tcross;// store transferred point set
-			}// for(size_t spi = 0, spi_e = spine.size(); spi < spi_e; i++)
-		}// END: 2. Create array of point sets.
-
-		{// 3. Create CoordIdx.
-			// add caps if needed
-			if(beginCap)
-			{
-				// add cap as polygon. vertices of cap are places at begin, so just add numbers from zero.
-				for(size_t i = 0, i_e = crossSection.size(); i < i_e; i++) ext_alias.CoordIndex.push_back(static_cast<int32_t>(i));
-
-				// add delimiter
-				ext_alias.CoordIndex.push_back(-1);
-			}// if(beginCap)
-
-			if(endCap)
-			{
-				// add cap as polygon. vertices of cap are places at end, as for beginCap use just sequence of numbers but with offset.
-				size_t beg = (pointset_arr.size() - 1) * crossSection.size();
-
-				for(size_t i = beg, i_e = (beg + crossSection.size()); i < i_e; i++) ext_alias.CoordIndex.push_back(static_cast<int32_t>(i));
-
-				// add delimiter
-				ext_alias.CoordIndex.push_back(-1);
-			}// if(beginCap)
-
-			// add quads
-			for(size_t spi = 0, spi_e = (spine.size() - 1); spi <= spi_e; spi++)
-			{
-				const size_t cr_sz = crossSection.size();
-				const size_t cr_last = crossSection.size() - 1;
-
-				size_t right_col;// hold index basis for points of quad placed in right column;
-
-				if(spi != spi_e)
-					right_col = spi + 1;
-				else if(spine_closed)// if spine curve is closed then one more quad is needed: between first and last points of curve.
-					right_col = 0;
-				else
-					break;// if spine curve is not closed then break the loop, because spi is out of range for that type of spine.
-
-				for(size_t cri = 0; cri < cr_sz; cri++)
-				{
-					if(cri != cr_last)
-					{
-						MACRO_FACE_ADD_QUAD(ccw, ext_alias.CoordIndex,
-											static_cast<int32_t>(spi * cr_sz + cri), 
-                                            static_cast<int32_t>(right_col * cr_sz + cri), 
-                                            static_cast<int32_t>(right_col * cr_sz + cri + 1), 
-                                            static_cast<int32_t>(spi * cr_sz + cri + 1));
-						// add delimiter
-						ext_alias.CoordIndex.push_back(-1);
-					}
-					else if(cross_closed)// if cross curve is closed then one more quad is needed: between first and last points of curve.
-					{
-						MACRO_FACE_ADD_QUAD(ccw, ext_alias.CoordIndex,
-                                            static_cast<int32_t>(spi * cr_sz + cri), 
-                                            static_cast<int32_t>(right_col * cr_sz + cri), 
-                                            static_cast<int32_t>(right_col * cr_sz + 0), 
-                                            static_cast<int32_t>(spi * cr_sz + 0));
-						// add delimiter
-						ext_alias.CoordIndex.push_back(-1);
-					}
-				}// for(size_t cri = 0; cri < cr_sz; cri++)
-			}// for(size_t spi = 0, spi_e = (spine.size() - 2); spi < spi_e; spi++)
-		}// END: 3. Create CoordIdx.
-
-		{// 4. Create vertices list.
-			// just copy all vertices
-			for(size_t spi = 0, spi_e = spine.size(); spi < spi_e; spi++)
-			{
-				for(size_t cri = 0, cri_e = crossSection.size(); cri < cri_e; cri++)
-				{
-					ext_alias.Vertices.push_back(pointset_arr[spi][cri]);
-				}
-			}
-		}// END: 4. Create vertices list.
-//PrintVectorSet("Ext. CoordIdx", ext_alias.CoordIndex);
-//PrintVectorSet("Ext. Vertices", ext_alias.Vertices);
-		// check for child nodes
-		if(!mReader->isEmptyElement())
-			ParseNode_Metadata(ne, "Extrusion");
-		else
-			mNodeElementCur->Child.push_back(ne);// add made object as child to current element
-
-		NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
-	}// if(!use.empty()) else
-}
-
-// <IndexedFaceSet
-// DEF=""                         ID
-// USE=""                         IDREF
-// ccw="true"             SFBool  [initializeOnly]
-// colorIndex=""          MFInt32 [initializeOnly]
-// colorPerVertex="true"  SFBool  [initializeOnly]
-// convex="true"          SFBool  [initializeOnly]
-// coordIndex=""          MFInt32 [initializeOnly]
-// creaseAngle="0"        SFFloat [initializeOnly]
-// normalIndex=""         MFInt32 [initializeOnly]
-// normalPerVertex="true" SFBool  [initializeOnly]
-// solid="true"           SFBool  [initializeOnly]
-// texCoordIndex=""       MFInt32 [initializeOnly]
-// >
-//    <!-- ComposedGeometryContentModel -->
-// ComposedGeometryContentModel is the child-node content model corresponding to X3DComposedGeometryNodes. It can contain Color (or ColorRGBA), Coordinate,
-// Normal and TextureCoordinate, in any order. No more than one instance of these nodes is allowed. Multiple VertexAttribute (FloatVertexAttribute,
-// Matrix3VertexAttribute, Matrix4VertexAttribute) nodes can also be contained.
-// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
-// </IndexedFaceSet>
-void X3DImporter::ParseNode_Geometry3D_IndexedFaceSet()
-{
-    std::string use, def;
-    bool ccw = true;
-    std::vector<int32_t> colorIndex;
-    bool colorPerVertex = true;
-    bool convex = true;
-    std::vector<int32_t> coordIndex;
-    float creaseAngle = 0;
-    std::vector<int32_t> normalIndex;
-    bool normalPerVertex = true;
-    bool solid = true;
-    std::vector<int32_t> texCoordIndex;
-    X3DNodeElementBase* ne( nullptr );
-
-	MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
-		MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_REF("colorIndex", colorIndex, XML_ReadNode_GetAttrVal_AsArrI32);
-		MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_RET("convex", convex, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_REF("coordIndex", coordIndex, XML_ReadNode_GetAttrVal_AsArrI32);
-		MACRO_ATTRREAD_CHECK_RET("creaseAngle", creaseAngle, XML_ReadNode_GetAttrVal_AsFloat);
-		MACRO_ATTRREAD_CHECK_REF("normalIndex", normalIndex, XML_ReadNode_GetAttrVal_AsArrI32);
-		MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_REF("texCoordIndex", texCoordIndex, XML_ReadNode_GetAttrVal_AsArrI32);
-	MACRO_ATTRREAD_LOOPEND;
-
-	// if "USE" defined then find already defined element.
-	if(!use.empty())
-	{
-		MACRO_USE_CHECKANDAPPLY(def, use, ENET_IndexedFaceSet, ne);
-	}
-	else
-	{
-		// check data
-		if(coordIndex.size() == 0) throw DeadlyImportError("IndexedFaceSet must contain not empty \"coordIndex\" attribute.");
-
-		// create and if needed - define new geometry object.
-		ne = new X3DIndexedSet(X3DNodeElementBase::ENET_IndexedFaceSet, mNodeElementCur);
-		if(!def.empty()) ne->ID = def;
-
-		X3DIndexedSet& ne_alias = *((X3DIndexedSet*)ne);
-
-		ne_alias.CCW = ccw;
-		ne_alias.ColorIndex = colorIndex;
-		ne_alias.ColorPerVertex = colorPerVertex;
-		ne_alias.Convex = convex;
-		ne_alias.CoordIndex = coordIndex;
-		ne_alias.CreaseAngle = creaseAngle;
-		ne_alias.NormalIndex = normalIndex;
-		ne_alias.NormalPerVertex = normalPerVertex;
-		ne_alias.Solid = solid;
-		ne_alias.TexCoordIndex = texCoordIndex;
-        // check for child nodes
-        if(!mReader->isEmptyElement())
-        {
-			ParseHelper_Node_Enter(ne);
-			MACRO_NODECHECK_LOOPBEGIN("IndexedFaceSet");
-				// check for X3DComposedGeometryNodes
-				if(XML_CheckNode_NameEqual("Color")) { ParseNode_Rendering_Color(); continue; }
-				if(XML_CheckNode_NameEqual("ColorRGBA")) { ParseNode_Rendering_ColorRGBA(); continue; }
-				if(XML_CheckNode_NameEqual("Coordinate")) { ParseNode_Rendering_Coordinate(); continue; }
-				if(XML_CheckNode_NameEqual("Normal")) { ParseNode_Rendering_Normal(); continue; }
-				if(XML_CheckNode_NameEqual("TextureCoordinate")) { ParseNode_Texturing_TextureCoordinate(); continue; }
-				// check for X3DMetadataObject
-				if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("IndexedFaceSet");
-
-			MACRO_NODECHECK_LOOPEND("IndexedFaceSet");
-			ParseHelper_Node_Exit();
-		}// if(!mReader->isEmptyElement())
-		else
-		{
-			mNodeElementCur->Child.push_back(ne);// add made object as child to current element
-		}
-
-		NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
-	}// if(!use.empty()) else
-}
-
-// <Sphere
-// DEF=""       ID
-// USE=""       IDREF
-// radius="1"   SFloat [initializeOnly]
-// solid="true" SFBool [initializeOnly]
-// />
-void X3DImporter::ParseNode_Geometry3D_Sphere()
-{
-    std::string use, def;
-    ai_real radius = 1;
-    bool solid = true;
-    X3DNodeElementBase* ne( nullptr );
-
-	MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
-		MACRO_ATTRREAD_CHECK_RET("radius", radius, XML_ReadNode_GetAttrVal_AsFloat);
-		MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
-	MACRO_ATTRREAD_LOOPEND;
-
-	// if "USE" defined then find already defined element.
-	if(!use.empty())
-	{
-		MACRO_USE_CHECKANDAPPLY(def, use, ENET_Sphere, ne);
-	}
-	else
-	{
-		const unsigned int tess = 3;///TODO: IME tessellation factor through ai_property
-
-		std::vector<aiVector3D> tlist;
-
-		// create and if needed - define new geometry object.
-		ne = new X3DGeometry3D(X3DNodeElementBase::ENET_Sphere, mNodeElementCur);
-		if(!def.empty()) ne->ID = def;
-
-		StandardShapes::MakeSphere(tess, tlist);
-		// copy data from temp array and apply scale
-		for(std::vector<aiVector3D>::iterator it = tlist.begin(); it != tlist.end(); ++it)
-		{
-			((X3DGeometry3D*)ne)->Vertices.push_back(*it * radius);
-		}
-
-		((X3DGeometry3D*)ne)->Solid = solid;
-		((X3DGeometry3D*)ne)->NumIndices = 3;
-		// check for X3DMetadataObject childs.
-		if(!mReader->isEmptyElement())
-			ParseNode_Metadata(ne, "Sphere");
-		else
-			mNodeElementCur->Child.push_back(ne);// add made object as child to current element
-
-		NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
-	}// if(!use.empty()) else
-}
-
-}// namespace Assimp
-
-#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER

+ 0 - 393
code/AssetLib/X3D/X3DImporter_Group.cpp

@@ -1,393 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2020, 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_Group.cpp
-/// \brief  Parsing data from nodes of "Grouping" set of X3D.
-/// \date   2015-2016
-/// \author [email protected]
-
-#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
-
-#include "X3DImporter.hpp"
-#include "X3DImporter_Macro.hpp"
-
-#include <assimp/ParsingUtils.h>
-
-namespace Assimp
-{
-
-// <Group
-// DEF=""              ID
-// USE=""              IDREF
-// bboxCenter="0 0 0"  SFVec3f [initializeOnly]
-// bboxSize="-1 -1 -1" SFVec3f [initializeOnly]
-// >
-//    <!-- ChildContentModel -->
-// ChildContentModel is the child-node content model corresponding to X3DChildNode, combining all profiles. ChildContentModel can contain most nodes,
-// other Grouping nodes, Prototype declarations and ProtoInstances in any order and any combination. When the assigned profile is less than Full, the
-// precise palette of legal nodes that are available depends on assigned profile and components.
-// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
-// </Group>
-// A Group node contains children nodes without introducing a new transformation. It is equivalent to a Transform node containing an identity transform.
-void X3DImporter::ParseNode_Grouping_Group(XmlNode &node) {
-    //std::string def, use;
-
-    std::string def = node.attribute("DEF").as_string();
-    std::string use = node.attribute("USE").as_string();
-	/*MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
-	MACRO_ATTRREAD_LOOPEND;*/
-
-	// if "USE" defined then find already defined element.
-	if(!use.empty())
-	{
-		X3DNodeElementBase *ne = nullptr;
-        if (def.empty()) {
-            Throw_DEF_And_USE(node.name());
-        }
-        if (!FindNodeElement(use, X3DNodeElementBase::ENET_Group, &ne)) {
-            Throw_USE_NotFound(node.name(), use);
-        }
-        mNodeElementCur->Child.push_back(ne);
-       //MACRO_USE_CHECKANDAPPLY(def, use, X3DNodeElementBase::ENET_Group, ne);
-	} else {
-		ParseHelper_Group_Begin();// create new grouping element and go deeper if node has children.
-
-                                  // at this place new group mode created and made current, so we can name it.
-        if (!def.empty()) {
-            mNodeElementCur->ID = def;
-        }
-		// in grouping set of nodes check X3DMetadataObject is not needed, because it is done in <Scene> parser function.
-
-		// for empty element exit from node in that place
-		//if(mReader->isEmptyElement())
-        if (node.empty()) {
-            ParseHelper_Node_Exit();
-        }
-	}// if(!use.empty()) else
-}
-
-void X3DImporter::ParseNode_Grouping_GroupEnd()
-{
-	ParseHelper_Node_Exit();// go up in scene graph
-}
-
-// <StaticGroup
-// DEF=""              ID
-// USE=""              IDREF
-// bboxCenter="0 0 0"  SFVec3f [initializeOnly]
-// bboxSize="-1 -1 -1" SFVec3f [initializeOnly]
-// >
-//    <!-- ChildContentModel -->
-// ChildContentModel is the child-node content model corresponding to X3DChildNode, combining all profiles. ChildContentModel can contain most nodes,
-// other Grouping nodes, Prototype declarations and ProtoInstances in any order and any combination. When the assigned profile is less than Full, the
-// precise palette of legal nodes that are available depends on assigned profile and components.
-// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
-// </StaticGroup>
-// The StaticGroup node contains children nodes which cannot be modified. StaticGroup children are guaranteed to not change, send events, receive events or
-// contain any USE references outside the StaticGroup.
-void X3DImporter::ParseNode_Grouping_StaticGroup(XmlNode &node) {
-//    std::string def, use;
-    std::string def = node.attribute("DEF").as_string();
-    std::string use = node.attribute("USE").as_string();
-
-/*	MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
-	MACRO_ATTRREAD_LOOPEND;*/
-
-	// if "USE" defined then find already defined element.
-	if(!use.empty())
-	{
-		X3DNodeElementBase* ne = nullptr;
-        if (!FindNodeElement(use, X3DNodeElementBase::ENET_Group, &ne)) {
-            Throw_USE_NotFound(node.name(), use);
-        }
-        mNodeElementCur->Child.push_back(ne);
-
-//		MACRO_USE_CHECKANDAPPLY(def, use, ENET_Group, ne);
-	}
-	else
-	{
-		ParseHelper_Group_Begin(true);// create new grouping element and go deeper if node has children.
-		// at this place new group mode created and made current, so we can name it.
-		if(!def.empty()) mNodeElementCur->ID = def;
-		// in grouping set of nodes check X3DMetadataObject is not needed, because it is done in <Scene> parser function.
-
-		// for empty element exit from node in that place
-        if (node.empty()) {
-            ParseHelper_Node_Exit();
-        }
-
-//		if(mReader->isEmptyElement()) ParseHelper_Node_Exit();
-	}// if(!use.empty()) else
-}
-
-void X3DImporter::ParseNode_Grouping_StaticGroupEnd()
-{
-	ParseHelper_Node_Exit();// go up in scene graph
-}
-
-// <Switch
-// DEF=""              ID
-// USE=""              IDREF
-// bboxCenter="0 0 0"  SFVec3f [initializeOnly]
-// bboxSize="-1 -1 -1" SFVec3f [initializeOnly]
-// whichChoice="-1"    SFInt32 [inputOutput]
-// >
-//    <!-- ChildContentModel -->
-// ChildContentModel is the child-node content model corresponding to X3DChildNode, combining all profiles. ChildContentModel can contain most nodes,
-// other Grouping nodes, Prototype declarations and ProtoInstances in any order and any combination. When the assigned profile is less than Full, the
-// precise palette of legal nodes that are available depends on assigned profile and components.
-// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
-// </Switch>
-// The Switch grouping node traverses zero or one of the nodes specified in the children field. The whichChoice field specifies the index of the child
-// to traverse, with the first child having index 0. If whichChoice is less than zero or greater than the number of nodes in the children field, nothing
-// is chosen.
-void X3DImporter::ParseNode_Grouping_Switch(XmlNode &node) {
-//    std::string def, use;
-    int32_t whichChoice = -1;
-    std::string def = node.attribute("DEF").as_string();
-    std::string use = node.attribute("USE").as_string();
-    pugi::xml_attribute attr = node.attribute("whichChoise");
-    whichChoice = attr.as_int();
-    /*MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
-		MACRO_ATTRREAD_CHECK_RET("whichChoice", whichChoice, XML_ReadNode_GetAttrVal_AsI32);
-	MACRO_ATTRREAD_LOOPEND;*/
-
-	// if "USE" defined then find already defined element.
-	if(!use.empty())
-	{
-		X3DNodeElementBase* ne = nullptr;
-        if (!FindNodeElement(use, X3DNodeElementBase::ENET_Group, &ne)) {
-            Throw_USE_NotFound(node.name(), use);
-        }
-        mNodeElementCur->Child.push_back(ne);
-
-
-//		MACRO_USE_CHECKANDAPPLY(def, use, ENET_Group, ne);
-	}
-	else
-	{
-		ParseHelper_Group_Begin();// create new grouping element and go deeper if node has children.
-		// at this place new group mode created and made current, so we can name it.
-		if(!def.empty()) mNodeElementCur->ID = def;
-
-		// also set values specific to this type of group
-		((X3DGroup*)mNodeElementCur)->UseChoice = true;
-		((X3DGroup*)mNodeElementCur)->Choice = whichChoice;
-		// in grouping set of nodes check X3DMetadataObject is not needed, because it is done in <Scene> parser function.
-
-		// for empty element exit from node in that place
-//		if(mReader->isEmptyElement()) ParseHelper_Node_Exit();
-        if (node.empty()) {
-            ParseHelper_Node_Exit();
-        }
-
-	}// if(!use.empty()) else
-}
-
-void X3DImporter::ParseNode_Grouping_SwitchEnd()
-{
-	// just exit from node. Defined choice will be accepted at post-processing stage.
-	ParseHelper_Node_Exit();// go up in scene graph
-}
-
-void ReadAttrAsVec3f(pugi::xml_node &node, const std::string &attrName, aiVector3D &vec) {
-    const pugi::xml_attribute &attr = node.attribute(attrName.c_str());
-    if (attr.empty()) {
-        return;
-    }
-
-    std::string data = attr.as_string();
-    std::vector<std::string> token;
-    tokenize<std::string>(data, token, " ");
-    vec.x = (ai_real)std::atof(token[0].c_str());
-    vec.y = (ai_real)std::atof(token[1].c_str());
-    vec.z = (ai_real)std::atof(token[2].c_str());
-}
-
-
-void ReadAttrAsFloatArray(pugi::xml_node &node, const std::string &attrName, size_t numComponents, std::vector<float> &tvec) {
-    pugi::xml_attribute attr = node.attribute(attrName.c_str());
-    std::string data = attr.as_string();
-    std::vector<std::string> token;
-    tokenize<std::string>(data, token, " ");
-    if (token.size() != numComponents) throw DeadlyImportError("<Transform>: rotation vector must have 4 elements.");
-    for (size_t i = 0; i < numComponents; ++i) {
-        tvec.push_back((ai_real)std::atof(token[i].c_str()));
-    }
-}
-
-// <Transform
-// DEF=""                     ID
-// USE=""                     IDREF
-// bboxCenter="0 0 0"         SFVec3f    [initializeOnly]
-// bboxSize="-1 -1 -1"        SFVec3f    [initializeOnly]
-// center="0 0 0"             SFVec3f    [inputOutput]
-// rotation="0 0 1 0"         SFRotation [inputOutput]
-// scale="1 1 1"              SFVec3f    [inputOutput]
-// scaleOrientation="0 0 1 0" SFRotation [inputOutput]
-// translation="0 0 0"        SFVec3f    [inputOutput]
-// >
-//    <!-- ChildContentModel -->
-// ChildContentModel is the child-node content model corresponding to X3DChildNode, combining all profiles. ChildContentModel can contain most nodes,
-// other Grouping nodes, Prototype declarations and ProtoInstances in any order and any combination. When the assigned profile is less than Full, the
-// precise palette of legal nodes that are available depends on assigned profile and components.
-// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
-// </Transform>
-// The Transform node is a grouping node that defines a coordinate system for its children that is relative to the coordinate systems of its ancestors.
-// Given a 3-dimensional point P and Transform node, P is transformed into point P' in its parent's coordinate system by a series of intermediate
-// transformations. In matrix transformation notation, where C (center), SR (scaleOrientation), T (translation), R (rotation), and S (scale) are the
-// equivalent transformation matrices,
-//   P' = T * C * R * SR * S * -SR * -C * P
-void X3DImporter::ParseNode_Grouping_Transform(XmlNode &node) {
-    aiVector3D center(0, 0, 0);
-    float rotation[4] = { 0, 0, 1, 0 };
-    aiVector3D scale(1, 1, 1); // A value of zero indicates that any child geometry shall not be displayed
-    float scale_orientation[4] = { 0, 0, 1, 0 };
-    aiVector3D translation(0, 0, 0);
-    aiMatrix4x4 matr, tmatr;
-    //std::string use, def;
-
-    //MACRO_ATTRREAD_LOOPBEG;
-    std::string def = node.attribute("DEF").as_string();
-    std::string use = node.attribute("USE").as_string();
-
-    //MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
-    ReadAttrAsVec3f(node, "center", center);
-    ReadAttrAsVec3f(node, "scale", scale);
-    ReadAttrAsVec3f(node, "translation", translation);
-    /*MACRO_ATTRREAD_CHECK_REF("center", center, XML_ReadNode_GetAttrVal_AsVec3f);
-		MACRO_ATTRREAD_CHECK_REF("scale", scale, XML_ReadNode_GetAttrVal_AsVec3f);
-		MACRO_ATTRREAD_CHECK_REF("translation", translation, XML_ReadNode_GetAttrVal_AsVec3f);*/
-    if (hasAttribute(node, "rotation")) {
-        std::vector<float> tvec;
-        ReadAttrAsFloatArray(node, "rotation", 4, tvec);
-        memcpy(rotation, tvec.data(), sizeof(rotation));
-    }
-    if (hasAttribute(node, "scaleOrientation")) {
-        std::vector<float> tvec;
-        ReadAttrAsFloatArray(node, "rotation", 4, tvec);
-        ::memcpy(scale_orientation, tvec.data(), sizeof(scale_orientation));
-    }
-    /*if(an == "rotation")
-		{
-			std::vector<float> tvec;
-
-			XML_ReadNode_GetAttrVal_AsArrF(idx, tvec);
-			if(tvec.size() != 4) throw DeadlyImportError("<Transform>: rotation vector must have 4 elements.");
-
-			memcpy(rotation, tvec.data(), sizeof(rotation));
-
-			continue;
-		}
-
-		if(an == "scaleOrientation"){
-
-			std::vector<float> tvec;
-			XML_ReadNode_GetAttrVal_AsArrF(idx, tvec);
-            if ( tvec.size() != 4 )
-            {
-                throw DeadlyImportError( "<Transform>: scaleOrientation vector must have 4 elements." );
-            }
-
-			::memcpy(scale_orientation, tvec.data(), sizeof(scale_orientation) );
-
-			continue;
-		}
-
-	MACRO_ATTRREAD_LOOPEND;*/
-
-	// if "USE" defined then find already defined element.
-	if(!use.empty()) {
-		X3DNodeElementBase* ne = nullptr;
-        if (!FindNodeElement(use, X3DNodeElementBase::ENET_Group, &ne)) {
-            Throw_USE_NotFound(node.name(), use);
-        }
-        mNodeElementCur->Child.push_back(ne);
-
-		//MACRO_USE_CHECKANDAPPLY(def, use, ENET_Group, ne);
-	}
-	else
-	{
-		ParseHelper_Group_Begin();// create new grouping element and go deeper if node has children.
-		// at this place new group mode created and made current, so we can name it.
-        if ( !def.empty() )
-        {
-            mNodeElementCur->ID = def;
-        }
-
-		//
-		// also set values specific to this type of group
-		//
-		// calculate transformation matrix
-		aiMatrix4x4::Translation(translation, matr);// T
-		aiMatrix4x4::Translation(center, tmatr);// C
-		matr *= tmatr;
-		aiMatrix4x4::Rotation(rotation[3], aiVector3D(rotation[0], rotation[1], rotation[2]), tmatr);// R
-		matr *= tmatr;
-		aiMatrix4x4::Rotation(scale_orientation[3], aiVector3D(scale_orientation[0], scale_orientation[1], scale_orientation[2]), tmatr);// SR
-		matr *= tmatr;
-		aiMatrix4x4::Scaling(scale, tmatr);// S
-		matr *= tmatr;
-		aiMatrix4x4::Rotation(-scale_orientation[3], aiVector3D(scale_orientation[0], scale_orientation[1], scale_orientation[2]), tmatr);// -SR
-		matr *= tmatr;
-		aiMatrix4x4::Translation(-center, tmatr);// -C
-		matr *= tmatr;
-		// and assign it
-		((X3DGroup*)mNodeElementCur)->Transformation = matr;
-		// in grouping set of nodes check X3DMetadataObject is not needed, because it is done in <Scene> parser function.
-
-		// for empty element exit from node in that place
-        if ( node.empty() ) {
-            ParseHelper_Node_Exit();
-        }
-	}// if(!use.empty()) else
-}
-
-void X3DImporter::ParseNode_Grouping_TransformEnd()
-{
-	ParseHelper_Node_Exit();// go up in scene graph
-}
-
-}// namespace Assimp
-
-#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER

+ 0 - 290
code/AssetLib/X3D/X3DImporter_Light.cpp

@@ -1,290 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2020, 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_Light.cpp
-/// \brief  Parsing data from nodes of "Lighting" set of X3D.
-/// \date   2015-2016
-/// \author [email protected]
-
-#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
-
-#include "X3DImporter.hpp"
-#include "X3DImporter_Macro.hpp"
-#include <assimp/StringUtils.h>
-
-namespace Assimp {
-
-// <DirectionalLight
-// DEF=""               ID
-// USE=""               IDREF
-// ambientIntensity="0" SFFloat [inputOutput]
-// color="1 1 1"        SFColor [inputOutput]
-// direction="0 0 -1"   SFVec3f [inputOutput]
-// global="false"       SFBool  [inputOutput]
-// intensity="1"        SFFloat [inputOutput]
-// on="true"            SFBool  [inputOutput]
-// />
-void X3DImporter::ParseNode_Lighting_DirectionalLight()
-{
-    std::string def, use;
-    float ambientIntensity = 0;
-    aiColor3D color(1, 1, 1);
-    aiVector3D direction(0, 0, -1);
-    bool global = false;
-    float intensity = 1;
-    bool on = true;
-    X3DNodeElementBase* ne( nullptr );
-
-	MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
-		MACRO_ATTRREAD_CHECK_RET("ambientIntensity", ambientIntensity, XML_ReadNode_GetAttrVal_AsFloat);
-		MACRO_ATTRREAD_CHECK_REF("color", color, XML_ReadNode_GetAttrVal_AsCol3f);
-		MACRO_ATTRREAD_CHECK_REF("direction", direction, XML_ReadNode_GetAttrVal_AsVec3f);
-		MACRO_ATTRREAD_CHECK_RET("global", global, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_RET("intensity", intensity, XML_ReadNode_GetAttrVal_AsFloat);
-		MACRO_ATTRREAD_CHECK_RET("on", on, XML_ReadNode_GetAttrVal_AsBool);
-	MACRO_ATTRREAD_LOOPEND;
-
-	// if "USE" defined then find already defined element.
-	if(!use.empty())
-	{
-		MACRO_USE_CHECKANDAPPLY(def, use, ENET_DirectionalLight, ne);
-	}
-	else
-	{
-		if(on)
-		{
-			// create and if needed - define new geometry object.
-			ne = new X3DLight(X3DNodeElementBase::ENET_DirectionalLight, mNodeElementCur);
-			if(!def.empty())
-				ne->ID = def;
-			else
-				ne->ID = "DirectionalLight_" + to_string((size_t)ne);// make random name
-
-			((X3DLight*)ne)->AmbientIntensity = ambientIntensity;
-			((X3DLight*)ne)->Color = color;
-			((X3DLight*)ne)->Direction = direction;
-			((X3DLight*)ne)->Global = global;
-			((X3DLight*)ne)->Intensity = intensity;
-			// Assimp want a node with name similar to a light. "Why? I don't no." )
-			ParseHelper_Group_Begin(false);
-
-			mNodeElementCur->ID = ne->ID;// assign name to node and return to light element.
-			ParseHelper_Node_Exit();
-			// check for child nodes
-			if(!mReader->isEmptyElement())
-				ParseNode_Metadata(ne, "DirectionalLight");
-			else
-				mNodeElementCur->Child.push_back(ne);// add made object as child to current element
-
-			NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
-		}// if(on)
-	}// if(!use.empty()) else
-}
-
-// <PointLight
-// DEF=""               ID
-// USE=""               IDREF
-// ambientIntensity="0" SFFloat [inputOutput]
-// attenuation="1 0 0"  SFVec3f [inputOutput]
-// color="1 1 1"        SFColor [inputOutput]
-// global="true"        SFBool  [inputOutput]
-// intensity="1"        SFFloat [inputOutput]
-// location="0 0 0"     SFVec3f [inputOutput]
-// on="true"            SFBool  [inputOutput]
-// radius="100"         SFFloat [inputOutput]
-// />
-void X3DImporter::ParseNode_Lighting_PointLight()
-{
-    std::string def, use;
-    float ambientIntensity = 0;
-    aiVector3D attenuation( 1, 0, 0 );
-    aiColor3D color( 1, 1, 1 );
-    bool global = true;
-    float intensity = 1;
-    aiVector3D location( 0, 0, 0 );
-    bool on = true;
-    float radius = 100;
-    X3DNodeElementBase* ne( nullptr );
-
-	MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
-		MACRO_ATTRREAD_CHECK_RET("ambientIntensity", ambientIntensity, XML_ReadNode_GetAttrVal_AsFloat);
-		MACRO_ATTRREAD_CHECK_REF("attenuation", attenuation, XML_ReadNode_GetAttrVal_AsVec3f);
-		MACRO_ATTRREAD_CHECK_REF("color", color, XML_ReadNode_GetAttrVal_AsCol3f);
-		MACRO_ATTRREAD_CHECK_RET("global", global, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_RET("intensity", intensity, XML_ReadNode_GetAttrVal_AsFloat);
-		MACRO_ATTRREAD_CHECK_REF("location", location, XML_ReadNode_GetAttrVal_AsVec3f);
-		MACRO_ATTRREAD_CHECK_RET("on", on, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_RET("radius", radius, XML_ReadNode_GetAttrVal_AsFloat);
-	MACRO_ATTRREAD_LOOPEND;
-
-	// if "USE" defined then find already defined element.
-	if(!use.empty())
-	{
-		MACRO_USE_CHECKANDAPPLY(def, use, ENET_PointLight, ne);
-	}
-	else
-	{
-		if(on)
-		{
-			// create and if needed - define new geometry object.
-			ne = new X3DLight(X3DNodeElementBase::ENET_PointLight, mNodeElementCur);
-			if(!def.empty()) ne->ID = def;
-
-			((X3DLight*)ne)->AmbientIntensity = ambientIntensity;
-			((X3DLight*)ne)->Attenuation = attenuation;
-			((X3DLight*)ne)->Color = color;
-			((X3DLight*)ne)->Global = global;
-			((X3DLight*)ne)->Intensity = intensity;
-			((X3DLight*)ne)->Location = location;
-			((X3DLight*)ne)->Radius = radius;
-			// Assimp want a node with name similar to a light. "Why? I don't no." )
-			ParseHelper_Group_Begin(false);
-			// make random name
-			if(ne->ID.empty()) ne->ID = "PointLight_" + to_string((size_t)ne);
-
-			mNodeElementCur->ID = ne->ID;// assign name to node and return to light element.
-			ParseHelper_Node_Exit();
-			// check for child nodes
-			if(!mReader->isEmptyElement())
-				ParseNode_Metadata(ne, "PointLight");
-			else
-				mNodeElementCur->Child.push_back(ne);// add made object as child to current element
-
-			NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
-		}// if(on)
-	}// if(!use.empty()) else
-}
-
-// <SpotLight
-// DEF=""                 ID
-// USE=""                 IDREF
-// ambientIntensity="0"   SFFloat [inputOutput]
-// attenuation="1 0 0"    SFVec3f [inputOutput]
-// beamWidth="0.7854"     SFFloat [inputOutput]
-// color="1 1 1"          SFColor [inputOutput]
-// cutOffAngle="1.570796" SFFloat [inputOutput]
-// direction="0 0 -1"     SFVec3f [inputOutput]
-// global="true"          SFBool  [inputOutput]
-// intensity="1"          SFFloat [inputOutput]
-// location="0 0 0"       SFVec3f [inputOutput]
-// on="true"              SFBool  [inputOutput]
-// radius="100"           SFFloat [inputOutput]
-// />
-void X3DImporter::ParseNode_Lighting_SpotLight()
-{
-    std::string def, use;
-    float ambientIntensity = 0;
-    aiVector3D attenuation( 1, 0, 0 );
-    float beamWidth = 0.7854f;
-    aiColor3D color( 1, 1, 1 );
-    float cutOffAngle = 1.570796f;
-    aiVector3D direction( 0, 0, -1 );
-    bool global = true;
-    float intensity = 1;
-    aiVector3D location( 0, 0, 0 );
-    bool on = true;
-    float radius = 100;
-    X3DNodeElementBase* ne( nullptr );
-
-	MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
-		MACRO_ATTRREAD_CHECK_RET("ambientIntensity", ambientIntensity, XML_ReadNode_GetAttrVal_AsFloat);
-		MACRO_ATTRREAD_CHECK_REF("attenuation", attenuation, XML_ReadNode_GetAttrVal_AsVec3f);
-		MACRO_ATTRREAD_CHECK_RET("beamWidth", beamWidth, XML_ReadNode_GetAttrVal_AsFloat);
-		MACRO_ATTRREAD_CHECK_REF("color", color, XML_ReadNode_GetAttrVal_AsCol3f);
-		MACRO_ATTRREAD_CHECK_RET("cutOffAngle", cutOffAngle, XML_ReadNode_GetAttrVal_AsFloat);
-		MACRO_ATTRREAD_CHECK_REF("direction", direction, XML_ReadNode_GetAttrVal_AsVec3f);
-		MACRO_ATTRREAD_CHECK_RET("global", global, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_RET("intensity", intensity, XML_ReadNode_GetAttrVal_AsFloat);
-		MACRO_ATTRREAD_CHECK_REF("location", location, XML_ReadNode_GetAttrVal_AsVec3f);
-		MACRO_ATTRREAD_CHECK_RET("on", on, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_RET("radius", radius, XML_ReadNode_GetAttrVal_AsFloat);
-	MACRO_ATTRREAD_LOOPEND;
-
-	// if "USE" defined then find already defined element.
-	if(!use.empty())
-	{
-		MACRO_USE_CHECKANDAPPLY(def, use, ENET_SpotLight, ne);
-	}
-	else
-	{
-		if(on)
-		{
-			// create and if needed - define new geometry object.
-			ne = new X3DLight(X3DNodeElementBase::ENET_SpotLight, mNodeElementCur);
-			if(!def.empty()) ne->ID = def;
-
-			if(beamWidth > cutOffAngle) beamWidth = cutOffAngle;
-
-			((X3DLight*)ne)->AmbientIntensity = ambientIntensity;
-			((X3DLight*)ne)->Attenuation = attenuation;
-			((X3DLight*)ne)->BeamWidth = beamWidth;
-			((X3DLight*)ne)->Color = color;
-			((X3DLight*)ne)->CutOffAngle = cutOffAngle;
-			((X3DLight*)ne)->Direction = direction;
-			((X3DLight*)ne)->Global = global;
-			((X3DLight*)ne)->Intensity = intensity;
-			((X3DLight*)ne)->Location = location;
-			((X3DLight*)ne)->Radius = radius;
-
-			// Assimp want a node with name similar to a light. "Why? I don't no." )
-			ParseHelper_Group_Begin(false);
-			// make random name
-			if(ne->ID.empty()) ne->ID = "SpotLight_" + to_string((size_t)ne);
-
-			mNodeElementCur->ID = ne->ID;// assign name to node and return to light element.
-			ParseHelper_Node_Exit();
-			// check for child nodes
-			if(!mReader->isEmptyElement())
-				ParseNode_Metadata(ne, "SpotLight");
-			else
-				mNodeElementCur->Child.push_back(ne);// add made object as child to current element
-
-			NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
-		}// if(on)
-	}// if(!use.empty()) else
-}
-
-}// namespace Assimp
-
-#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER

+ 0 - 195
code/AssetLib/X3D/X3DImporter_Macro.hpp

@@ -1,195 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2020, 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_Macro.hpp
-/// \brief Useful macrodefines.
-/// \date 2015-2016
-/// \author [email protected]
-
-#ifndef X3DIMPORTER_MACRO_HPP_INCLUDED
-#define X3DIMPORTER_MACRO_HPP_INCLUDED
-
-/// \def MACRO_USE_CHECKANDAPPLY(pDEF, pUSE, pNE)
-/// Used for regular checking while attribute "USE" is defined.
-/// \param [in] pDEF - string holding "DEF" value.
-/// \param [in] pUSE - string holding "USE" value.
-/// \param [in] pType - type of element to find.
-/// \param [out] pNE - pointer to found node element.
-#define MACRO_USE_CHECKANDAPPLY(pDEF, pUSE, pType, pNE) \
-	do { \
-	XML_CheckNode_MustBeEmpty(); \
-	if(!pDEF.empty()) Throw_DEF_And_USE(); \
-	if(!FindNodeElement(pUSE, CX3DImporter_NodeElement::pType, &pNE)) Throw_USE_NotFound(pUSE); \
-	 \
-	NodeElement_Cur->Child.push_back(pNE);/* add found object as child to current element */ \
-	} while(false)
-
-/// \def MACRO_ATTRREAD_LOOPBEG
-/// Begin of loop that read attributes values.
-#define MACRO_ATTRREAD_LOOPBEG \
-	for(int idx = 0, idx_end = mReader->getAttributeCount(); idx < idx_end; idx++) \
-	{ \
-		std::string an(mReader->getAttributeName(idx));
-
-/// \def MACRO_ATTRREAD_LOOPEND
-/// End of loop that read attributes values.
-#define MACRO_ATTRREAD_LOOPEND \
-		Throw_IncorrectAttr(an); \
-	}
-
-/// \def MACRO_ATTRREAD_CHECK_REF
-/// Check current attribute name and if it equal to requested then read value. Result write to output variable by reference. If result was read then
-/// "continue" will called.
-/// \param [in] pAttrName - attribute name.
-/// \param [out] pVarName - output variable name.
-/// \param [in] pFunction - function which read attribute value and write it to pVarName.
-#define MACRO_ATTRREAD_CHECK_REF(pAttrName, pVarName, pFunction) \
-	if(an == pAttrName) \
-	{ \
-		pFunction(idx, pVarName); \
-		continue; \
-	}
-
-/// \def MACRO_ATTRREAD_CHECK_RET
-/// Check current attribute name and if it equal to requested then read value. Result write to output variable using return value of \ref pFunction.
-/// If result was read then  "continue" will called.
-/// \param [in] pAttrName - attribute name.
-/// \param [out] pVarName - output variable name.
-/// \param [in] pFunction - function which read attribute value and write it to pVarName.
-#define MACRO_ATTRREAD_CHECK_RET(pAttrName, pVarName, pFunction) \
-	if(an == pAttrName) \
-	{ \
-		pVarName = pFunction(idx); \
-		continue; \
-	}
-
-/// \def MACRO_ATTRREAD_CHECKUSEDEF_RET
-/// Compact variant for checking "USE" and "DEF". Also skip bbox attributes: "bboxCenter", "bboxSize".
-/// If result was read then  "continue" will called.
-/// \param [out] pDEF_Var - output variable name for "DEF" value.
-/// \param [out] pUSE_Var - output variable name for "USE" value.
-#define MACRO_ATTRREAD_CHECKUSEDEF_RET(pDEF_Var, pUSE_Var) \
-	MACRO_ATTRREAD_CHECK_RET("DEF", pDEF_Var, mReader->getAttributeValue); \
-	MACRO_ATTRREAD_CHECK_RET("USE", pUSE_Var, mReader->getAttributeValue); \
-	if(an == "bboxCenter") continue; \
-	if(an == "bboxSize") continue; \
-	if(an == "containerField") continue; \
-	do {} while(false)
-
-/// \def MACRO_NODECHECK_LOOPBEGIN(pNodeName)
-/// Begin of loop of parsing child nodes. Do not add ';' at end.
-/// \param [in] pNodeName - current node name.
-#define MACRO_NODECHECK_LOOPBEGIN(pNodeName) \
-	do { \
-	bool close_found = false; \
-	 \
-	while(mReader->read()) \
-	{ \
-		if(mReader->getNodeType() == irr::io::EXN_ELEMENT) \
-		{
-
-/// \def MACRO_NODECHECK_LOOPEND(pNodeName)
-/// End of loop of parsing child nodes.
-/// \param [in] pNodeName - current node name.
-#define MACRO_NODECHECK_LOOPEND(pNodeName) \
-		}/* if(mReader->getNodeType() == irr::io::EXN_ELEMENT) */ \
-		else if(mReader->getNodeType() == irr::io::EXN_ELEMENT_END) \
-		{ \
-			if(XML_CheckNode_NameEqual(pNodeName)) \
-			{ \
-				close_found = true; \
-	 \
-				break; \
-			} \
-		}/* else if(mReader->getNodeType() == irr::io::EXN_ELEMENT_END) */ \
-	}/* while(mReader->read()) */ \
-	 \
-	if(!close_found) Throw_CloseNotFound(pNodeName); \
-	 \
-	} while(false)
-
-#define MACRO_NODECHECK_METADATA(pNodeName) \
-	MACRO_NODECHECK_LOOPBEGIN(pNodeName) \
-			/* and childs must be metadata nodes */ \
-			if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported(pNodeName); \
-	 MACRO_NODECHECK_LOOPEND(pNodeName)
-
-/// \def MACRO_FACE_ADD_QUAD_FA(pCCW, pOut, pIn, pP1, pP2, pP3, pP4)
-/// Add points as quad. Means that pP1..pP4 set in CCW order.
-#define MACRO_FACE_ADD_QUAD_FA(pCCW, pOut, pIn, pP1, pP2, pP3, pP4) \
-	do { \
-	if(pCCW) \
-	{ \
-		pOut.push_back(pIn[pP1]); \
-		pOut.push_back(pIn[pP2]); \
-		pOut.push_back(pIn[pP3]); \
-		pOut.push_back(pIn[pP4]); \
-	} \
-	else \
-	{ \
-		pOut.push_back(pIn[pP4]); \
-		pOut.push_back(pIn[pP3]); \
-		pOut.push_back(pIn[pP2]); \
-		pOut.push_back(pIn[pP1]); \
-	} \
-	} while(false)
-
-/// \def MACRO_FACE_ADD_QUAD(pCCW, pOut, pP1, pP2, pP3, pP4)
-/// Add points as quad. Means that pP1..pP4 set in CCW order.
-#define MACRO_FACE_ADD_QUAD(pCCW, pOut, pP1, pP2, pP3, pP4) \
-	do { \
-	if(pCCW) \
-	{ \
-		pOut.push_back(pP1); \
-		pOut.push_back(pP2); \
-		pOut.push_back(pP3); \
-		pOut.push_back(pP4); \
-	} \
-	else \
-	{ \
-		pOut.push_back(pP4); \
-		pOut.push_back(pP3); \
-		pOut.push_back(pP2); \
-		pOut.push_back(pP1); \
-	} \
-	} while(false)
-
-#endif // X3DIMPORTER_MACRO_HPP_INCLUDED

+ 0 - 277
code/AssetLib/X3D/X3DImporter_Metadata.cpp

@@ -1,277 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2020, 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_Metadata.cpp
-/// \brief  Parsing data from nodes of "Metadata" set of X3D.
-/// \date   2015-2016
-/// \author [email protected]
-
-#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
-
-#include "X3DImporter.hpp"
-#include "X3DImporter_Macro.hpp"
-
-namespace Assimp
-{
-
-/// \def MACRO_METADATA_FINDCREATE(pDEF_Var, pUSE_Var, pReference, pValue, pNE, pMetaName)
-/// Find element by "USE" or create new one.
-/// \param [in] pDEF_Var - variable name with "DEF" value.
-/// \param [in] pUSE_Var - variable name with "USE" value.
-/// \param [in] pReference - variable name with "reference" value.
-/// \param [in] pValue - variable name with "value" value.
-/// \param [in, out] pNE - pointer to node element.
-/// \param [in] pMetaClass - Class of node.
-/// \param [in] pMetaName - Name of node.
-/// \param [in] pType - type of element to find.
-#define MACRO_METADATA_FINDCREATE(pDEF_Var, pUSE_Var, pReference, pValue, pNE, pMetaClass, pMetaName, pType) \
-	/* if "USE" defined then find already defined element. */ \
-	if(!pUSE_Var.empty()) \
-	{ \
-		MACRO_USE_CHECKANDAPPLY(pDEF_Var, pUSE_Var, pType, pNE); \
-	} \
-	else \
-	{ \
-		pNE = new pMetaClass(NodeElement_Cur); \
-		if(!pDEF_Var.empty()) pNE->ID = pDEF_Var; \
-	 \
-		((pMetaClass*)pNE)->Reference = pReference; \
-		((pMetaClass*)pNE)->Value = pValue; \
-		/* also metadata node can contain childs */ \
-		if(!mReader->isEmptyElement()) \
-			ParseNode_Metadata(pNE, pMetaName);/* in that case node element will be added to child elements list of current node. */ \
-		else \
-			NodeElement_Cur->Child.push_back(pNE);/* else - add element to child list manually */ \
-	 \
-		NodeElement_List.push_back(pNE);/* add new element to elements list. */ \
-	}/* if(!pUSE_Var.empty()) else */ \
-	 \
-	do {} while(false)
-
-bool X3DImporter::ParseHelper_CheckRead_X3DMetadataObject()
-{
-	if(XML_CheckNode_NameEqual("MetadataBoolean"))
-		ParseNode_MetadataBoolean();
-	else if(XML_CheckNode_NameEqual("MetadataDouble"))
-		ParseNode_MetadataDouble();
-	else if(XML_CheckNode_NameEqual("MetadataFloat"))
-		ParseNode_MetadataFloat();
-	else if(XML_CheckNode_NameEqual("MetadataInteger"))
-		ParseNode_MetadataInteger();
-	else if(XML_CheckNode_NameEqual("MetadataSet"))
-		ParseNode_MetadataSet();
-	else if(XML_CheckNode_NameEqual("MetadataString"))
-		ParseNode_MetadataString();
-	else
-		return false;
-
-	return true;
-}
-
-void X3DImporter::ParseNode_Metadata(X3DNodeElementBase* pParentElement, const std::string& /*pNodeName*/)
-{
-	ParseHelper_Node_Enter(pParentElement);
-	MACRO_NODECHECK_METADATA(mReader->getNodeName());
-	ParseHelper_Node_Exit();
-}
-
-// <MetadataBoolean
-// DEF=""       ID
-// USE=""       IDREF
-// name=""      SFString [inputOutput]
-// reference="" SFString [inputOutput]
-// value=""     MFBool   [inputOutput]
-// />
-void X3DImporter::ParseNode_MetadataBoolean()
-{
-    std::string def, use;
-    std::string name, reference;
-    std::vector<bool> value;
-    X3DNodeElementBase* ne( nullptr );
-
-	MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
-		MACRO_ATTRREAD_CHECK_RET("name", name, mReader->getAttributeValue);
-		MACRO_ATTRREAD_CHECK_RET("reference", reference, mReader->getAttributeValue);
-		MACRO_ATTRREAD_CHECK_REF("value", value, XML_ReadNode_GetAttrVal_AsArrB);
-	MACRO_ATTRREAD_LOOPEND;
-
-	MACRO_METADATA_FINDCREATE(def, use, reference, value, ne, X3DMetaBoolean, "MetadataBoolean", ENET_MetaBoolean);
-}
-
-// <MetadataDouble
-// DEF=""       ID
-// USE=""       IDREF
-// name=""      SFString [inputOutput]
-// reference="" SFString [inputOutput]
-// value=""     MFDouble [inputOutput]
-// />
-void X3DImporter::ParseNode_MetadataDouble()
-{
-    std::string def, use;
-    std::string name, reference;
-    std::vector<double> value;
-    X3DNodeElementBase* ne( nullptr );
-
-	MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
-		MACRO_ATTRREAD_CHECK_RET("name", name, mReader->getAttributeValue);
-		MACRO_ATTRREAD_CHECK_RET("reference", reference, mReader->getAttributeValue);
-		MACRO_ATTRREAD_CHECK_REF("value", value, XML_ReadNode_GetAttrVal_AsArrD);
-	MACRO_ATTRREAD_LOOPEND;
-
-	MACRO_METADATA_FINDCREATE(def, use, reference, value, ne, X3DMetaDouble, "MetadataDouble", ENET_MetaDouble);
-}
-
-// <MetadataFloat
-// DEF=""       ID
-// USE=""       IDREF
-// name=""      SFString [inputOutput]
-// reference="" SFString [inputOutput]
-// value=""     MFFloat  [inputOutput]
-// />
-void X3DImporter::ParseNode_MetadataFloat()
-{
-    std::string def, use;
-    std::string name, reference;
-    std::vector<float> value;
-    X3DNodeElementBase* ne( nullptr );
-
-	MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
-		MACRO_ATTRREAD_CHECK_RET("name", name, mReader->getAttributeValue);
-		MACRO_ATTRREAD_CHECK_RET("reference", reference, mReader->getAttributeValue);
-		MACRO_ATTRREAD_CHECK_REF("value", value, XML_ReadNode_GetAttrVal_AsArrF);
-	MACRO_ATTRREAD_LOOPEND;
-
-	MACRO_METADATA_FINDCREATE(def, use, reference, value, ne, X3DMetaFloat, "MetadataFloat", ENET_MetaFloat);
-}
-
-// <MetadataInteger
-// DEF=""       ID
-// USE=""       IDREF
-// name=""      SFString  [inputOutput]
-// reference="" SFString  [inputOutput]
-// value=""     MFInteger [inputOutput]
-// />
-void X3DImporter::ParseNode_MetadataInteger()
-{
-    std::string def, use;
-    std::string name, reference;
-    std::vector<int32_t> value;
-    X3DNodeElementBase* ne( nullptr );
-
-	MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
-		MACRO_ATTRREAD_CHECK_RET("name", name, mReader->getAttributeValue);
-		MACRO_ATTRREAD_CHECK_RET("reference", reference, mReader->getAttributeValue);
-		MACRO_ATTRREAD_CHECK_REF("value", value, XML_ReadNode_GetAttrVal_AsArrI32);
-	MACRO_ATTRREAD_LOOPEND;
-
-	MACRO_METADATA_FINDCREATE(def, use, reference, value, ne, X3DMetaInteger, "MetadataInteger", ENET_MetaInteger);
-}
-
-// <MetadataSet
-// DEF=""       ID
-// USE=""       IDREF
-// name=""      SFString [inputOutput]
-// reference="" SFString [inputOutput]
-// />
-void X3DImporter::ParseNode_MetadataSet()
-{
-    std::string def, use;
-    std::string name, reference;
-    X3DNodeElementBase* ne( nullptr );
-
-	MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
-		MACRO_ATTRREAD_CHECK_RET("name", name, mReader->getAttributeValue);
-		MACRO_ATTRREAD_CHECK_RET("reference", reference, mReader->getAttributeValue);
-	MACRO_ATTRREAD_LOOPEND;
-
-	// if "USE" defined then find already defined element.
-	if(!use.empty())
-	{
-		MACRO_USE_CHECKANDAPPLY(def, use, ENET_MetaSet, ne);
-	}
-	else
-	{
-		ne = new X3DMetaSet(mNodeElementCur);
-		if(!def.empty()) ne->ID = def;
-
-		((X3DMetaSet*)ne)->Reference = reference;
-		// also metadata node can contain childs
-		if(!mReader->isEmptyElement())
-			ParseNode_Metadata(ne, "MetadataSet");
-		else
-			mNodeElementCur->Child.push_back(ne);// made object as child to current element
-
-		NodeElement_List.push_back(ne);// add new element to elements list.
-	}// if(!use.empty()) else
-}
-
-// <MetadataString
-// DEF=""       ID
-// USE=""       IDREF
-// name=""      SFString [inputOutput]
-// reference="" SFString [inputOutput]
-// value=""     MFString [inputOutput]
-// />
-void X3DImporter::ParseNode_MetadataString()
-{
-    std::string def, use;
-    std::string name, reference;
-    std::list<std::string> value;
-    X3DNodeElementBase* ne( nullptr );
-
-	MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
-		MACRO_ATTRREAD_CHECK_RET("name", name, mReader->getAttributeValue);
-		MACRO_ATTRREAD_CHECK_RET("reference", reference, mReader->getAttributeValue);
-		MACRO_ATTRREAD_CHECK_REF("value", value, XML_ReadNode_GetAttrVal_AsListS);
-	MACRO_ATTRREAD_LOOPEND;
-
-	MACRO_METADATA_FINDCREATE(def, use, reference, value, ne, X3DMetaString, "MetadataString", ENET_MetaString);
-}
-
-}// namespace Assimp
-
-#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER

+ 0 - 134
code/AssetLib/X3D/X3DImporter_Networking.cpp

@@ -1,134 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2020, 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_Networking.cpp
-/// \brief  Parsing data from nodes of "Networking" set of X3D.
-/// \date   2015-2016
-/// \author [email protected]
-
-#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
-
-#include "X3DImporter.hpp"
-#include "X3DImporter_Macro.hpp"
-
-// Header files, Assimp.
-#include <assimp/DefaultIOSystem.h>
-
-//#include <regex>
-
-namespace Assimp
-{
-
-//static std::regex pattern_parentDir(R"((^|/)[^/]+/../)");
-static std::string parentDir("/../");
-
-// <Inline
-// DEF=""              ID
-// USE=""              IDREF
-// bboxCenter="0 0 0"  SFVec3f  [initializeOnly]
-// bboxSize="-1 -1 -1" SFVec3f  [initializeOnly]
-// load="true"         SFBool   [inputOutput]
-// url=""              MFString [inputOutput]
-// />
-void X3DImporter::ParseNode_Networking_Inline()
-{
-    std::string def, use;
-    bool load = true;
-    std::list<std::string> url;
-
-	MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
-		MACRO_ATTRREAD_CHECK_RET("load", load, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_REF("url", url, XML_ReadNode_GetAttrVal_AsListS);
-	MACRO_ATTRREAD_LOOPEND;
-
-	// if "USE" defined then find already defined element.
-	if(!use.empty())
-	{
-		X3DNodeElementBase* ne;
-
-		MACRO_USE_CHECKANDAPPLY(def, use, ENET_Group, ne);
-	}
-	else
-	{
-		ParseHelper_Group_Begin(true);// create new grouping element and go deeper if node has children.
-		// at this place new group mode created and made current, so we can name it.
-		if(!def.empty()) mNodeElementCur->ID = def;
-
-		if(load && !url.empty())
-		{
-			std::string full_path = mpIOHandler->CurrentDirectory() + url.front();
-
-			//full_path = std::regex_replace(full_path, pattern_parentDir, "$1");
-			for (std::string::size_type pos = full_path.find(parentDir); pos != std::string::npos; pos = full_path.find(parentDir, pos)) {
-				if (pos > 0) {
-					std::string::size_type pos2 = full_path.rfind('/', pos - 1);
-					if (pos2 != std::string::npos) {
-						full_path.erase(pos2, pos - pos2 + 3);
-						pos = pos2;
-					}
-					else {
-						full_path.erase(0, pos + 4);
-						pos = 0;
-					}
-				}
-				else {
-					pos += 3;
-				}
-			}
-			// Attribute "url" can contain list of strings. But we need only one - first.
-			std::string::size_type slashPos = full_path.find_last_of("\\/");
-			mpIOHandler->PushDirectory(slashPos == std::string::npos ? std::string() : full_path.substr(0, slashPos + 1));
-			ParseFile(full_path, mpIOHandler);
-			mpIOHandler->PopDirectory();
-		}
-
-		// check for X3DMetadataObject childs.
-		if(!mReader->isEmptyElement()) ParseNode_Metadata(mNodeElementCur, "Inline");
-
-		// exit from node in that place
-		ParseHelper_Node_Exit();
-	}// if(!use.empty()) else
-}
-
-}// namespace Assimp
-
-#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER

+ 0 - 507
code/AssetLib/X3D/X3DImporter_Node.hpp

@@ -1,507 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2020, 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_Node.hpp
-/// \brief  Elements of scene graph.
-/// \date   2015-2016
-/// \author [email protected]
-
-#ifndef INCLUDED_AI_X3D_IMPORTER_NODE_H
-#define INCLUDED_AI_X3D_IMPORTER_NODE_H
-
-// Header files, Assimp.
-#include <assimp/scene.h>
-#include <assimp/types.h>
-
-// Header files, stdlib.
-#include <list>
-#include <string>
-#include <vector>
-
-/// Base class for elements of nodes.
-class X3DNodeElementBase {
-public:
-    /// Define what data type contain node element.
-    enum EType {
-        ENET_Group, ///< Element has type "Group".
-        ENET_MetaBoolean, ///< Element has type "Metadata boolean".
-        ENET_MetaDouble, ///< Element has type "Metadata double".
-        ENET_MetaFloat, ///< Element has type "Metadata float".
-        ENET_MetaInteger, ///< Element has type "Metadata integer".
-        ENET_MetaSet, ///< Element has type "Metadata set".
-        ENET_MetaString, ///< Element has type "Metadata string".
-        ENET_Arc2D, ///< Element has type "Arc2D".
-        ENET_ArcClose2D, ///< Element has type "ArcClose2D".
-        ENET_Circle2D, ///< Element has type "Circle2D".
-        ENET_Disk2D, ///< Element has type "Disk2D".
-        ENET_Polyline2D, ///< Element has type "Polyline2D".
-        ENET_Polypoint2D, ///< Element has type "Polypoint2D".
-        ENET_Rectangle2D, ///< Element has type "Rectangle2D".
-        ENET_TriangleSet2D, ///< Element has type "TriangleSet2D".
-        ENET_Box, ///< Element has type "Box".
-        ENET_Cone, ///< Element has type "Cone".
-        ENET_Cylinder, ///< Element has type "Cylinder".
-        ENET_Sphere, ///< Element has type "Sphere".
-        ENET_ElevationGrid, ///< Element has type "ElevationGrid".
-        ENET_Extrusion, ///< Element has type "Extrusion".
-        ENET_Coordinate, ///< Element has type "Coordinate".
-        ENET_Normal, ///< Element has type "Normal".
-        ENET_TextureCoordinate, ///< Element has type "TextureCoordinate".
-        ENET_IndexedFaceSet, ///< Element has type "IndexedFaceSet".
-        ENET_IndexedLineSet, ///< Element has type "IndexedLineSet".
-        ENET_IndexedTriangleSet, ///< Element has type "IndexedTriangleSet".
-        ENET_IndexedTriangleFanSet, ///< Element has type "IndexedTriangleFanSet".
-        ENET_IndexedTriangleStripSet, ///< Element has type "IndexedTriangleStripSet".
-        ENET_LineSet, ///< Element has type "LineSet".
-        ENET_PointSet, ///< Element has type "PointSet".
-        ENET_TriangleSet, ///< Element has type "TriangleSet".
-        ENET_TriangleFanSet, ///< Element has type "TriangleFanSet".
-        ENET_TriangleStripSet, ///< Element has type "TriangleStripSet".
-        ENET_Color, ///< Element has type "Color".
-        ENET_ColorRGBA, ///< Element has type "ColorRGBA".
-        ENET_Shape, ///< Element has type "Shape".
-        ENET_Appearance, ///< Element has type "Appearance".
-        ENET_Material, ///< Element has type "Material".
-        ENET_ImageTexture, ///< Element has type "ImageTexture".
-        ENET_TextureTransform, ///< Element has type "TextureTransform".
-        ENET_DirectionalLight, ///< Element has type "DirectionalLight".
-        ENET_PointLight, ///< Element has type "PointLight".
-        ENET_SpotLight, ///< Element has type "SpotLight".
-
-        ENET_Invalid ///< Element has invalid type and possible contain invalid data.
-    };
-
-    const EType Type;
-
-    std::string ID; ///< ID of the element. Can be empty. In X3D synonym for "ID" attribute.
-    X3DNodeElementBase *Parent; ///< Parent element. If nullptr then this node is root.
-    std::list<X3DNodeElementBase *> Child; ///< Child elements.
-
-    /// @brief  The destructor, virtual.
-    virtual ~X3DNodeElementBase() {
-        // empty
-    }
-
-protected:
-    /// In constructor inheritor must set element type.
-    /// \param [in] pType - element type.
-    /// \param [in] pParent - parent element.
-    X3DNodeElementBase(const EType pType, X3DNodeElementBase *pParent) :
-            Type(pType), Parent(pParent) {}
-
-    X3DNodeElementBase(const X3DNodeElementBase &pNodeElement) = delete;
-    X3DNodeElementBase &operator=(const X3DNodeElementBase &pNodeElement) = delete;
-    X3DNodeElementBase() = delete;
-}; // class IX3DImporter_NodeElement
-
-/// \class CX3DImporter_NodeElement_Group
-/// Class that define grouping node. Define transformation matrix for children.
-/// Also can select which child will be kept and others are removed.
-class X3DGroup : public X3DNodeElementBase {
-public:
-    aiMatrix4x4 Transformation; ///< Transformation matrix.
-
-    /// \var bool Static
-    /// As you know node elements can use already defined node elements when attribute "USE" is defined.
-    /// Standard search when looking for an element in the whole scene graph, existing at this moment.
-    /// If a node is marked as static, the children(or lower) can not search for elements in the nodes upper then static.
-    bool Static;
-
-    bool UseChoice; ///< Flag: if true then use number from \ref Choice to choose what the child will be kept.
-    int32_t Choice; ///< Number of the child which will be kept.
-
-public:
-    /// Constructor.
-    /// \param [in] pParent - pointer to parent node.
-    /// \param [in] pStatic - static node flag.
-    X3DGroup(X3DNodeElementBase *pParent, const bool pStatic = false) :
-            X3DNodeElementBase(ENET_Group, pParent),
-            Static(pStatic),
-            UseChoice(false) {
-        // empty
-    }
-}; // class CX3DImporter_NodeElement_Group
-
-/// This struct describe meta-value.
-class X3DMeta : public X3DNodeElementBase {
-public:
-    std::string Name; ///< Name of metadata object.
-
-    /// If provided, it identifies the metadata standard or other specification that defines the name field. If the reference field is not provided or is
-    /// empty, the meaning of the name field is considered implicit to the characters in the string.
-    std::string Reference;
-
-    /// In constructor inheritor must set element type.
-    /// \param [in] pType - element type.
-    /// \param [in] pParent - pointer to parent node.
-    X3DMeta(const EType pType, X3DNodeElementBase *pParent) :
-            X3DNodeElementBase(pType, pParent) {}
-}; // class CX3DImporter_NodeElement_Meta
-
-/// \struct CX3DImporter_NodeElement_MetaBoolean
-/// This struct describe metavalue of type boolean.
-struct X3DMetaBoolean : public X3DMeta {
-    std::vector<bool> Value; ///< Stored value.
-
-    /// \fn CX3DImporter_NodeElement_MetaBoolean(CX3DImporter_NodeElement* pParent)
-    /// Constructor
-    /// \param [in] pParent - pointer to parent node.
-    X3DMetaBoolean(X3DNodeElementBase *pParent) :
-            X3DMeta(ENET_MetaBoolean, pParent) {}
-
-}; // struct CX3DImporter_NodeElement_MetaBoolean
-
-/// \struct CX3DImporter_NodeElement_MetaDouble
-/// This struct describe metavalue of type double.
-struct X3DMetaDouble : public X3DMeta {
-    std::vector<double> Value; ///< Stored value.
-
-    /// Constructor
-    /// \param [in] pParent - pointer to parent node.
-    X3DMetaDouble(X3DNodeElementBase *pParent) :
-            X3DMeta(ENET_MetaDouble, pParent) {}
-
-}; // struct CX3DImporter_NodeElement_MetaDouble
-
-/// This struct describe metavalue of type float.
-struct X3DMetaFloat : public X3DMeta {
-    std::vector<float> Value; ///< Stored value.
-
-    /// Constructor
-    /// \param [in] pParent - pointer to parent node.
-    X3DMetaFloat(X3DNodeElementBase *pParent) :
-            X3DMeta(ENET_MetaFloat, pParent) {}
-
-}; // struct CX3DImporter_NodeElement_MetaFloat
-
-/// This struct describe metavalue of type integer.
-struct X3DMetaInteger : public X3DMeta {
-    std::vector<int32_t> Value; ///< Stored value.
-
-    /// Constructor
-    /// \param [in] pParent - pointer to parent node.
-    X3DMetaInteger(X3DNodeElementBase *pParent) :
-            X3DMeta(ENET_MetaInteger, pParent) {}
-
-}; // struct CX3DImporter_NodeElement_MetaInteger
-
-/// This struct describe container for metaobjects.
-struct X3DMetaSet : public X3DMeta {
-    std::list<X3DMeta> Value; ///< Stored value.
-
-    /// Constructor
-    /// \param [in] pParent - pointer to parent node.
-    X3DMetaSet(X3DNodeElementBase *pParent) :
-            X3DMeta(ENET_MetaSet, pParent) {}
-
-}; // struct CX3DImporter_NodeElement_MetaSet
-
-/// This struct describe metavalue of type string.
-struct X3DMetaString : public X3DMeta {
-    std::list<std::string> Value; ///< Stored value.
-
-    /// Constructor
-    /// \param [in] pParent - pointer to parent node.
-    X3DMetaString(X3DNodeElementBase *pParent) :
-            X3DMeta(ENET_MetaString, pParent) {}
-
-}; // struct CX3DImporter_NodeElement_MetaString
-
-/// This struct hold <Color> value.
-struct X3DColor : public X3DNodeElementBase {
-    std::list<aiColor3D> Value; ///< Stored value.
-
-    /// Constructor
-    /// \param [in] pParent - pointer to parent node.
-    X3DColor(X3DNodeElementBase *pParent) :
-            X3DNodeElementBase(ENET_Color, pParent) {}
-
-}; // struct CX3DImporter_NodeElement_Color
-
-/// This struct hold <ColorRGBA> value.
-struct X3DColorRGBA : public X3DNodeElementBase {
-    std::list<aiColor4D> Value; ///< Stored value.
-
-    /// Constructor
-    /// \param [in] pParent - pointer to parent node.
-    X3DColorRGBA(X3DNodeElementBase *pParent) :
-            X3DNodeElementBase(ENET_ColorRGBA, pParent) {}
-
-}; // struct CX3DImporter_NodeElement_ColorRGBA
-
-/// This struct hold <Coordinate> value.
-struct X3DCoordinate : public X3DNodeElementBase {
-    std::list<aiVector3D> Value; ///< Stored value.
-
-    /// Constructor
-    /// \param [in] pParent - pointer to parent node.
-    X3DCoordinate(X3DNodeElementBase *pParent) :
-            X3DNodeElementBase(ENET_Coordinate, pParent) {}
-
-}; // struct CX3DImporter_NodeElement_Coordinate
-
-/// This struct hold <Normal> value.
-struct X3DNormal : public X3DNodeElementBase {
-    std::list<aiVector3D> Value; ///< Stored value.
-
-    /// Constructor
-    /// \param [in] pParent - pointer to parent node.
-    X3DNormal(X3DNodeElementBase *pParent) :
-            X3DNodeElementBase(ENET_Normal, pParent) {}
-
-}; // struct CX3DImporter_NodeElement_Normal
-
-/// This struct hold <TextureCoordinate> value.
-struct X3DTextureCoordinate : public X3DNodeElementBase {
-    std::list<aiVector2D> Value; ///< Stored value.
-
-    /// Constructor
-    /// \param [in] pParent - pointer to parent node.
-    X3DTextureCoordinate(X3DNodeElementBase *pParent) :
-            X3DNodeElementBase(ENET_TextureCoordinate, pParent) {}
-
-}; // struct CX3DImporter_NodeElement_TextureCoordinate
-
-/// Two-dimensional figure.
-class X3DGeometry2D : public X3DNodeElementBase {
-public:
-    std::list<aiVector3D> Vertices; ///< Vertices list.
-    size_t NumIndices; ///< Number of indices in one face.
-    bool Solid; ///< Flag: if true then render must use back-face culling, else render must draw both sides of object.
-
-    /// Constructor.
-    /// \param [in] pParent - pointer to parent node.
-    /// \param [in] pType - type of geometry object.
-    X3DGeometry2D(const EType pType, X3DNodeElementBase *pParent) :
-            X3DNodeElementBase(pType, pParent), Solid(true) {}
-
-}; // class CX3DImporter_NodeElement_Geometry2D
-
-/// Three-dimensional body.
-class X3DGeometry3D : public X3DNodeElementBase {
-public:
-    std::list<aiVector3D> Vertices; ///< Vertices list.
-    size_t NumIndices; ///< Number of indices in one face.
-    bool Solid; ///< Flag: if true then render must use back-face culling, else render must draw both sides of object.
-
-    /// Constructor.
-    /// \param [in] pParent - pointer to parent node.
-    /// \param [in] pType - type of geometry object.
-    X3DGeometry3D(const EType pType, X3DNodeElementBase *pParent) :
-            X3DNodeElementBase(pType, pParent), Vertices(), NumIndices(0), Solid(true) {
-        // empty
-    }
-}; // class CX3DImporter_NodeElement_Geometry3D
-
-/// \class CX3DImporter_NodeElement_ElevationGrid
-/// Uniform rectangular grid of varying height.
-class X3DElevationGrid : public X3DGeometry3D {
-public:
-    bool NormalPerVertex; ///< If true then normals are defined for every vertex, else for every face(line).
-    bool ColorPerVertex; ///< If true then colors are defined for every vertex, else for every face(line).
-    /// If the angle between the geometric normals of two adjacent faces is less than the crease angle, normals shall be calculated so that the faces are
-    /// shaded smoothly across the edge; otherwise, normals shall be calculated so that a lighting discontinuity across the edge is produced.
-    float CreaseAngle;
-    std::vector<int32_t> CoordIdx; ///< Coordinates list by faces. In X3D format: "-1" - delimiter for faces.
-
-    /// Constructor.
-    /// \param [in] pParent - pointer to parent node.
-    /// \param [in] pType - type of geometry object.
-    X3DElevationGrid(const EType pType, X3DNodeElementBase *pParent) :
-            X3DGeometry3D(pType, pParent) {}
-
-}; // class CX3DImporter_NodeElement_IndexedSet
-
-/// Shape with indexed vertices.
-class X3DIndexedSet : public X3DGeometry3D {
-public:
-    /// The ccw field defines the ordering of the vertex coordinates of the geometry with respect to user-given or automatically generated normal vectors
-    /// used in the lighting model equations. If ccw is TRUE, the normals shall follow the right hand rule; the orientation of each normal with respect to
-    /// the vertices (taken in order) shall be such that the vertices appear to be oriented in a counterclockwise order when the vertices are viewed (in the
-    /// local coordinate system of the Shape) from the opposite direction as the normal. If ccw is FALSE, the normals shall be oriented in the opposite
-    /// direction. If normals are not generated but are supplied using a Normal node, and the orientation of the normals does not match the setting of the
-    /// ccw field, results are undefined.
-    bool CCW;
-    std::vector<int32_t> ColorIndex; ///< Field to specify the polygonal faces by indexing into the <Color> or <ColorRGBA>.
-    bool ColorPerVertex; ///< If true then colors are defined for every vertex, else for every face(line).
-    /// The convex field indicates whether all polygons in the shape are convex (TRUE). A polygon is convex if it is planar, does not intersect itself,
-    /// and all of the interior angles at its vertices are less than 180 degrees. Non planar and self intersecting polygons may produce undefined results
-    /// even if the convex field is FALSE.
-    bool Convex;
-    std::vector<int32_t> CoordIndex; ///< Field to specify the polygonal faces by indexing into the <Coordinate>.
-    /// If the angle between the geometric normals of two adjacent faces is less than the crease angle, normals shall be calculated so that the faces are
-    /// shaded smoothly across the edge; otherwise, normals shall be calculated so that a lighting discontinuity across the edge is produced.
-    float CreaseAngle;
-    std::vector<int32_t> NormalIndex; ///< Field to specify the polygonal faces by indexing into the <Normal>.
-    bool NormalPerVertex; ///< If true then normals are defined for every vertex, else for every face(line).
-    std::vector<int32_t> TexCoordIndex; ///< Field to specify the polygonal faces by indexing into the <TextureCoordinate>.
-
-    /// Constructor.
-    /// \param [in] pParent - pointer to parent node.
-    /// \param [in] pType - type of geometry object.
-    X3DIndexedSet(const EType pType, X3DNodeElementBase *pParent) :
-            X3DGeometry3D(pType, pParent) {}
-
-}; // class CX3DImporter_NodeElement_IndexedSet
-
-/// Shape with set of vertices.
-class X3DSet : public X3DGeometry3D {
-public:
-    /// The ccw field defines the ordering of the vertex coordinates of the geometry with respect to user-given or automatically generated normal vectors
-    /// used in the lighting model equations. If ccw is TRUE, the normals shall follow the right hand rule; the orientation of each normal with respect to
-    /// the vertices (taken in order) shall be such that the vertices appear to be oriented in a counterclockwise order when the vertices are viewed (in the
-    /// local coordinate system of the Shape) from the opposite direction as the normal. If ccw is FALSE, the normals shall be oriented in the opposite
-    /// direction. If normals are not generated but are supplied using a Normal node, and the orientation of the normals does not match the setting of the
-    /// ccw field, results are undefined.
-    bool CCW;
-    bool ColorPerVertex; ///< If true then colors are defined for every vertex, else for every face(line).
-    bool NormalPerVertex; ///< If true then normals are defined for every vertex, else for every face(line).
-    std::vector<int32_t> CoordIndex; ///< Field to specify the polygonal faces by indexing into the <Coordinate>.
-    std::vector<int32_t> NormalIndex; ///< Field to specify the polygonal faces by indexing into the <Normal>.
-    std::vector<int32_t> TexCoordIndex; ///< Field to specify the polygonal faces by indexing into the <TextureCoordinate>.
-    std::vector<int32_t> VertexCount; ///< Field describes how many vertices are to be used in each polyline(polygon) from the <Coordinate> field.
-
-    /// Constructor.
-    /// \param [in] pParent - pointer to parent node.
-    /// \param [in] pType - type of geometry object.
-    X3DSet(const EType pType, X3DNodeElementBase *pParent) :
-            X3DGeometry3D(pType, pParent) {}
-
-}; // class CX3DImporter_NodeElement_Set
-
-/// This struct hold <Shape> value.
-struct X3DShape : public X3DNodeElementBase {
-    /// Constructor
-    /// \param [in] pParent - pointer to parent node.
-    X3DShape(X3DNodeElementBase *pParent) :
-            X3DNodeElementBase(ENET_Shape, pParent) {}
-
-}; // struct CX3DImporter_NodeElement_Shape
-
-/// This struct hold <Appearance> value.
-struct X3DAppearance : public X3DNodeElementBase {
-    /// Constructor
-    /// \param [in] pParent - pointer to parent node.
-    X3DAppearance(X3DNodeElementBase *pParent) :
-            X3DNodeElementBase(ENET_Appearance, pParent) {}
-
-}; // struct CX3DImporter_NodeElement_Appearance
-
-/// Material.
-class X3DMaterial : public X3DNodeElementBase {
-public:
-    float AmbientIntensity; ///< Specifies how much ambient light from light sources this surface shall reflect.
-    aiColor3D DiffuseColor; ///< Reflects all X3D light sources depending on the angle of the surface with respect to the light source.
-    aiColor3D EmissiveColor; ///< Models "glowing" objects. This can be useful for displaying pre-lit models.
-    float Shininess; ///< Lower shininess values produce soft glows, while higher values result in sharper, smaller highlights.
-    aiColor3D SpecularColor; ///< The specularColor and shininess fields determine the specular highlights.
-    float Transparency; ///< Specifies how "clear" an object is, with 1.0 being completely transparent, and 0.0 completely opaque.
-
-    /// Constructor.
-    /// \param [in] pParent - pointer to parent node.
-    /// \param [in] pType - type of geometry object.
-    X3DMaterial(X3DNodeElementBase *pParent) :
-            X3DNodeElementBase(ENET_Material, pParent),
-            AmbientIntensity(0.0f),
-            DiffuseColor(),
-            EmissiveColor(),
-            Shininess(0.0f),
-            SpecularColor(),
-            Transparency(1.0f) {
-        // empty
-    }
-}; // class CX3DImporter_NodeElement_Material
-
-/// This struct hold <ImageTexture> value.
-struct X3DImageTexture : public X3DNodeElementBase {
-    /// RepeatS and RepeatT, that specify how the texture wraps in the S and T directions. If repeatS is TRUE (the default), the texture map is repeated
-    /// outside the [0.0, 1.0] texture coordinate range in the S direction so that it fills the shape. If repeatS is FALSE, the texture coordinates are
-    /// clamped in the S direction to lie within the [0.0, 1.0] range. The repeatT field is analogous to the repeatS field.
-    bool RepeatS;
-    bool RepeatT; ///< See \ref RepeatS.
-    std::string URL; ///< URL of the texture.
-
-    /// Constructor
-    /// \param [in] pParent - pointer to parent node.
-    X3DImageTexture(X3DNodeElementBase *pParent) :
-            X3DNodeElementBase(ENET_ImageTexture, pParent) {}
-}; // struct CX3DImporter_NodeElement_ImageTexture
-
-/// This struct hold <TextureTransform> value.
-struct X3DTextureTransform : public X3DNodeElementBase {
-    aiVector2D Center; ///< Specifies a translation offset in texture coordinate space about which the rotation and scale fields are applied.
-    float Rotation; ///< Specifies a rotation in angle base units of the texture coordinates about the center point after the scale has been applied.
-    aiVector2D Scale; ///< Specifies a scaling factor in S and T of the texture coordinates about the center point.
-    aiVector2D Translation; ///<  Specifies a translation of the texture coordinates.
-
-    /// Constructor
-    /// \param [in] pParent - pointer to parent node.
-    X3DTextureTransform(X3DNodeElementBase *pParent) :
-            X3DNodeElementBase(ENET_TextureTransform, pParent) {}
-
-}; // struct CX3DImporter_NodeElement_TextureTransform
-
-/// This struct hold <TextureTransform> value.
-struct X3DLight : public X3DNodeElementBase {
-    float AmbientIntensity; ///< Specifies the intensity of the ambient emission from the light.
-    aiColor3D Color; ///< specifies the spectral colour properties of both the direct and ambient light emission as an RGB value.
-    aiVector3D Direction; ///< Specifies the direction vector of the illumination emanating from the light source in the local coordinate system.
-    /// Field that determines whether the light is global or scoped. Global lights illuminate all objects that fall within their volume of lighting influence.
-    /// Scoped lights only illuminate objects that are in the same transformation hierarchy as the light.
-    bool Global;
-    float Intensity; ///< Specifies the brightness of the direct emission from the light.
-
-    /// PointLight node's illumination falls off with distance as specified by three attenuation coefficients. The attenuation factor
-    /// is: "1 / max(attenuation[0] + attenuation[1] * r + attenuation[2] * r2, 1)", where r is the distance from the light to the surface being illuminated.
-    aiVector3D Attenuation;
-    aiVector3D Location; ///< Specifies a translation offset of the centre point of the light source from the light's local coordinate system origin.
-    float Radius; ///< Specifies the radial extent of the solid angle and the maximum distance from location that may be illuminated by the light source.
-    float BeamWidth; ///< Specifies an inner solid angle in which the light source emits light at uniform full intensity.
-    float CutOffAngle; ///< The light source's emission intensity drops off from the inner solid angle (beamWidth) to the outer solid angle (cutOffAngle).
-
-    /// Constructor
-    /// \param [in] pParent - pointer to parent node.
-    /// \param [in] pLightType - type of the light source.
-    X3DLight(EType pLightType, X3DNodeElementBase *pParent) :
-            X3DNodeElementBase(pLightType, pParent) {}
-
-}; // struct CX3DImporter_NodeElement_Light
-
-#endif // INCLUDED_AI_X3D_IMPORTER_NODE_H

+ 0 - 829
code/AssetLib/X3D/X3DImporter_Postprocess.cpp

@@ -1,829 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2020, 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 [email protected]
-
-#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
-
-#include "X3DImporter.hpp"
-
-// Header files, Assimp.
-#include <assimp/ai_assert.h>
-#include <assimp/StandardShapes.h>
-#include <assimp/StringUtils.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 == X3DNodeElementBase::ENET_Group) matr.push_back(((X3DGroup*)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.Child.begin(); el_it != pNodeElement.Child.end(); ++el_it)
-	{
-		if(((*el_it)->Type == X3DNodeElementBase::ENET_MetaBoolean) || ((*el_it)->Type == X3DNodeElementBase::ENET_MetaDouble) ||
-			((*el_it)->Type == X3DNodeElementBase::ENET_MetaFloat) || ((*el_it)->Type == X3DNodeElementBase::ENET_MetaInteger) ||
-			((*el_it)->Type == X3DNodeElementBase::ENET_MetaString))
-		{
-			pList.push_back(*el_it);
-		}
-		else if((*el_it)->Type == X3DNodeElementBase::ENET_MetaSet)
-		{
-			PostprocessHelper_CollectMetadata(**el_it, pList);
-		}
-	}// for(std::list<CX3DImporter_NodeElement*>::const_iterator el_it = pNodeElement.Child.begin(); el_it != pNodeElement.Child.end(); el_it++)
-}
-
-bool X3DImporter::PostprocessHelper_ElementIsMetadata(const X3DNodeElementBase::EType pType) const
-{
-	if((pType == X3DNodeElementBase::ENET_MetaBoolean) || (pType == X3DNodeElementBase::ENET_MetaDouble) ||
-		(pType == X3DNodeElementBase::ENET_MetaFloat) || (pType == X3DNodeElementBase::ENET_MetaInteger) ||
-		(pType == X3DNodeElementBase::ENET_MetaString) || (pType == X3DNodeElementBase::ENET_MetaSet))
-	{
-		return true;
-	}
-	else
-	{
-		return false;
-	}
-}
-
-bool X3DImporter::PostprocessHelper_ElementIsMesh(const X3DNodeElementBase::EType pType) const
-{
-	if((pType == X3DNodeElementBase::ENET_Arc2D) || (pType == X3DNodeElementBase::ENET_ArcClose2D) ||
-		(pType == X3DNodeElementBase::ENET_Box) || (pType == X3DNodeElementBase::ENET_Circle2D) ||
-		(pType == X3DNodeElementBase::ENET_Cone) || (pType == X3DNodeElementBase::ENET_Cylinder) ||
-		(pType == X3DNodeElementBase::ENET_Disk2D) || (pType == X3DNodeElementBase::ENET_ElevationGrid) ||
-		(pType == X3DNodeElementBase::ENET_Extrusion) || (pType == X3DNodeElementBase::ENET_IndexedFaceSet) ||
-		(pType == X3DNodeElementBase::ENET_IndexedLineSet) || (pType == X3DNodeElementBase::ENET_IndexedTriangleFanSet) ||
-		(pType == X3DNodeElementBase::ENET_IndexedTriangleSet) || (pType == X3DNodeElementBase::ENET_IndexedTriangleStripSet) ||
-		(pType == X3DNodeElementBase::ENET_PointSet) || (pType == X3DNodeElementBase::ENET_LineSet) ||
-		(pType == X3DNodeElementBase::ENET_Polyline2D) || (pType == X3DNodeElementBase::ENET_Polypoint2D) ||
-		(pType == X3DNodeElementBase::ENET_Rectangle2D) || (pType == X3DNodeElementBase::ENET_Sphere) ||
-		(pType == X3DNodeElementBase::ENET_TriangleFanSet) || (pType == X3DNodeElementBase::ENET_TriangleSet) ||
-		(pType == X3DNodeElementBase::ENET_TriangleSet2D) || (pType == X3DNodeElementBase::ENET_TriangleStripSet))
-	{
-		return true;
-	}
-	else
-	{
-		return false;
-	}
-}
-
-void X3DImporter::Postprocess_BuildLight(const X3DNodeElementBase& pNodeElement, std::list<aiLight*>& pSceneLightList) const
-{
-    const X3DLight& ne = *( ( X3DLight* ) &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 X3DNodeElementBase::ENET_DirectionalLight:
-			new_light->mType = aiLightSource_DIRECTIONAL;
-			new_light->mDirection = ne.Direction, new_light->mDirection *= transform_matr;
-
-			break;
-		case X3DNodeElementBase::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 X3DNodeElementBase::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: " + 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.Child.begin(); el_it != pNodeElement.Child.end(); ++el_it)
-	{
-		if((*el_it)->Type == X3DNodeElementBase::ENET_Material)
-		{
-			aiColor3D tcol3;
-			float tvalf;
-			X3DMaterial& tnemat = *((X3DMaterial*)*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 == CX3DImporter_NodeElement::ENET_Material)
-		else if((*el_it)->Type == X3DNodeElementBase::ENET_ImageTexture)
-		{
-			X3DImageTexture& tnetex = *((X3DImageTexture*)*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 == CX3DImporter_NodeElement::ENET_ImageTexture)
-		else if((*el_it)->Type == X3DNodeElementBase::ENET_TextureTransform)
-		{
-			aiUVTransform trans;
-			X3DTextureTransform& tnetextr = *((X3DTextureTransform*)*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 == CX3DImporter_NodeElement::ENET_TextureTransform)
-	}// for(std::list<CX3DImporter_NodeElement*>::const_iterator el_it = pNodeElement.Child.begin(); el_it != pNodeElement.Child.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 == X3DNodeElementBase::ENET_Arc2D) || (pNodeElement.Type == X3DNodeElementBase::ENET_ArcClose2D) ||
-		(pNodeElement.Type == X3DNodeElementBase::ENET_Circle2D) || (pNodeElement.Type == X3DNodeElementBase::ENET_Disk2D) ||
-		(pNodeElement.Type == X3DNodeElementBase::ENET_Polyline2D) || (pNodeElement.Type == X3DNodeElementBase::ENET_Polypoint2D) ||
-		(pNodeElement.Type == X3DNodeElementBase::ENET_Rectangle2D) || (pNodeElement.Type == X3DNodeElementBase::ENET_TriangleSet2D))
-	{
-		X3DGeometry2D& tnemesh = *((X3DGeometry2D*)&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 == X3DNodeElementBase::ENET_Box) || (pNodeElement.Type == X3DNodeElementBase::ENET_Cone) ||
-		(pNodeElement.Type == X3DNodeElementBase::ENET_Cylinder) || (pNodeElement.Type == X3DNodeElementBase::ENET_Sphere))
-	{
-		X3DGeometry3D& tnemesh = *((X3DGeometry3D*)&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 == X3DNodeElementBase::ENET_ElevationGrid)
-	{
-		X3DElevationGrid& tnemesh = *((X3DElevationGrid*)&pNodeElement);// create alias for convenience
-
-		// at first create mesh from existing vertices.
-		*pMesh = GeometryHelper_MakeMesh(tnemesh.CoordIdx, tnemesh.Vertices);
-		// copy additional information from children
-		for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
-		{
-			if((*ch_it)->Type == X3DNodeElementBase::ENET_Color)
-				MeshGeometry_AddColor(**pMesh, ((X3DColor*)*ch_it)->Value, tnemesh.ColorPerVertex);
-			else if((*ch_it)->Type == X3DNodeElementBase::ENET_ColorRGBA)
-				MeshGeometry_AddColor(**pMesh, ((X3DColorRGBA*)*ch_it)->Value, tnemesh.ColorPerVertex);
-			else if((*ch_it)->Type == X3DNodeElementBase::ENET_Normal)
-				MeshGeometry_AddNormal(**pMesh,  ((X3DNormal*)*ch_it)->Value, tnemesh.NormalPerVertex);
-			else if((*ch_it)->Type == X3DNodeElementBase::ENET_TextureCoordinate)
-				MeshGeometry_AddTexCoord(**pMesh, ((X3DTextureCoordinate*)*ch_it)->Value);
-			else
-				throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of ElevationGrid: " + to_string((*ch_it)->Type) + ".");
-		}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
-
-		return;// mesh is build, nothing to do anymore.
-	}// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_ElevationGrid)
-	//
-	// Indexed primitives sets
-	//
-	if(pNodeElement.Type == X3DNodeElementBase::ENET_IndexedFaceSet)
-	{
-		X3DIndexedSet& tnemesh = *((X3DIndexedSet*)&pNodeElement);// create alias for convenience
-
-		// at first search for <Coordinate> node and create mesh.
-		for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
-		{
-			if((*ch_it)->Type == X3DNodeElementBase::ENET_Coordinate)
-			{
-				*pMesh = GeometryHelper_MakeMesh(tnemesh.CoordIndex, ((X3DCoordinate*)*ch_it)->Value);
-			}
-		}
-
-		// copy additional information from children
-		for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
-		{
-			if((*ch_it)->Type == X3DNodeElementBase::ENET_Color)
-				MeshGeometry_AddColor(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((X3DColor*)*ch_it)->Value, tnemesh.ColorPerVertex);
-			else if((*ch_it)->Type == X3DNodeElementBase::ENET_ColorRGBA)
-				MeshGeometry_AddColor(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((X3DColorRGBA*)*ch_it)->Value,
-										tnemesh.ColorPerVertex);
-			else if((*ch_it)->Type == X3DNodeElementBase::ENET_Coordinate)
-				{} // skip because already read when mesh created.
-			else if((*ch_it)->Type == X3DNodeElementBase::ENET_Normal)
-				MeshGeometry_AddNormal(**pMesh, tnemesh.CoordIndex, tnemesh.NormalIndex, ((X3DNormal*)*ch_it)->Value,
-										tnemesh.NormalPerVertex);
-			else if((*ch_it)->Type == X3DNodeElementBase::ENET_TextureCoordinate)
-				MeshGeometry_AddTexCoord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((X3DTextureCoordinate*)*ch_it)->Value);
-			else
-				throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of IndexedFaceSet: " + to_string((*ch_it)->Type) + ".");
-		}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
-
-		return;// mesh is build, nothing to do anymore.
-	}// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_IndexedFaceSet)
-
-	if(pNodeElement.Type == X3DNodeElementBase::ENET_IndexedLineSet)
-	{
-		X3DIndexedSet& tnemesh = *((X3DIndexedSet*)&pNodeElement);// create alias for convenience
-
-		// at first search for <Coordinate> node and create mesh.
-		for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
-		{
-			if((*ch_it)->Type == X3DNodeElementBase::ENET_Coordinate)
-			{
-				*pMesh = GeometryHelper_MakeMesh(tnemesh.CoordIndex, ((X3DCoordinate*)*ch_it)->Value);
-			}
-		}
-
-		// copy additional information from children
-		for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
-		{
-			ai_assert(*pMesh);
-			if((*ch_it)->Type == X3DNodeElementBase::ENET_Color)
-				MeshGeometry_AddColor(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((X3DColor*)*ch_it)->Value, tnemesh.ColorPerVertex);
-			else if((*ch_it)->Type == X3DNodeElementBase::ENET_ColorRGBA)
-				MeshGeometry_AddColor(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((X3DColorRGBA*)*ch_it)->Value,
-										tnemesh.ColorPerVertex);
-			else if((*ch_it)->Type == X3DNodeElementBase::ENET_Coordinate)
-				{} // skip because already read when mesh created.
-			else
-				throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of IndexedLineSet: " + to_string((*ch_it)->Type) + ".");
-		}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
-
-		return;// mesh is build, nothing to do anymore.
-	}// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_IndexedLineSet)
-
-	if((pNodeElement.Type == X3DNodeElementBase::ENET_IndexedTriangleSet) ||
-		(pNodeElement.Type == X3DNodeElementBase::ENET_IndexedTriangleFanSet) ||
-		(pNodeElement.Type == X3DNodeElementBase::ENET_IndexedTriangleStripSet))
-	{
-		X3DIndexedSet& tnemesh = *((X3DIndexedSet*)&pNodeElement);// create alias for convenience
-
-		// at first search for <Coordinate> node and create mesh.
-		for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
-		{
-			if((*ch_it)->Type == X3DNodeElementBase::ENET_Coordinate)
-			{
-				*pMesh = GeometryHelper_MakeMesh(tnemesh.CoordIndex, ((X3DCoordinate*)*ch_it)->Value);
-			}
-		}
-
-		// copy additional information from children
-		for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
-		{
-			ai_assert(*pMesh);
-			if((*ch_it)->Type == X3DNodeElementBase::ENET_Color)
-				MeshGeometry_AddColor(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((X3DColor*)*ch_it)->Value, tnemesh.ColorPerVertex);
-			else if((*ch_it)->Type == X3DNodeElementBase::ENET_ColorRGBA)
-				MeshGeometry_AddColor(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((X3DColorRGBA*)*ch_it)->Value,
-										tnemesh.ColorPerVertex);
-			else if((*ch_it)->Type == X3DNodeElementBase::ENET_Coordinate)
-				{} // skip because already read when mesh created.
-			else if((*ch_it)->Type == X3DNodeElementBase::ENET_Normal)
-				MeshGeometry_AddNormal(**pMesh, tnemesh.CoordIndex, tnemesh.NormalIndex, ((X3DNormal*)*ch_it)->Value,
-										tnemesh.NormalPerVertex);
-			else if((*ch_it)->Type == X3DNodeElementBase::ENET_TextureCoordinate)
-				MeshGeometry_AddTexCoord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((X3DTextureCoordinate*)*ch_it)->Value);
-			else
-				throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of IndexedTriangleSet or IndexedTriangleFanSet, or \
-																	IndexedTriangleStripSet: " + to_string((*ch_it)->Type) + ".");
-		}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
-
-		return;// mesh is build, nothing to do anymore.
-	}// if((pNodeElement.Type == CX3DImporter_NodeElement::ENET_IndexedTriangleFanSet) || (pNodeElement.Type == CX3DImporter_NodeElement::ENET_IndexedTriangleStripSet))
-
-	if(pNodeElement.Type == X3DNodeElementBase::ENET_Extrusion)
-	{
-		X3DIndexedSet& tnemesh = *((X3DIndexedSet*)&pNodeElement);// create alias for convenience
-
-		*pMesh = GeometryHelper_MakeMesh(tnemesh.CoordIndex, tnemesh.Vertices);
-
-		return;// mesh is build, nothing to do anymore.
-	}// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_Extrusion)
-
-	//
-	// Primitives sets
-	//
-	if(pNodeElement.Type == X3DNodeElementBase::ENET_PointSet)
-	{
-		X3DSet& tnemesh = *((X3DSet*)&pNodeElement);// create alias for convenience
-
-		// at first search for <Coordinate> node and create mesh.
-		for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
-		{
-			if((*ch_it)->Type == X3DNodeElementBase::ENET_Coordinate)
-			{
-				std::vector<aiVector3D> vec_copy;
-
-				vec_copy.reserve(((X3DCoordinate*)*ch_it)->Value.size());
-				for(std::list<aiVector3D>::const_iterator it = ((X3DCoordinate*)*ch_it)->Value.begin();
-					it != ((X3DCoordinate*)*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.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
-		{
-			ai_assert(*pMesh);
-			if((*ch_it)->Type == X3DNodeElementBase::ENET_Color)
-				MeshGeometry_AddColor(**pMesh, ((X3DColor*)*ch_it)->Value, true);
-			else if((*ch_it)->Type == X3DNodeElementBase::ENET_ColorRGBA)
-				MeshGeometry_AddColor(**pMesh, ((X3DColorRGBA*)*ch_it)->Value, true);
-			else if((*ch_it)->Type == X3DNodeElementBase::ENET_Coordinate)
-				{} // skip because already read when mesh created.
-			else
-				throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of PointSet: " + to_string((*ch_it)->Type) + ".");
-		}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
-
-		return;// mesh is build, nothing to do anymore.
-	}// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_PointSet)
-
-	if(pNodeElement.Type == X3DNodeElementBase::ENET_LineSet)
-	{
-		X3DSet& tnemesh = *((X3DSet*)&pNodeElement);// create alias for convenience
-
-		// at first search for <Coordinate> node and create mesh.
-		for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
-		{
-			if((*ch_it)->Type == X3DNodeElementBase::ENET_Coordinate)
-			{
-				*pMesh = GeometryHelper_MakeMesh(tnemesh.CoordIndex, ((X3DCoordinate*)*ch_it)->Value);
-			}
-		}
-
-		// copy additional information from children
-		for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
-		{
-			ai_assert(*pMesh);
-			if((*ch_it)->Type == X3DNodeElementBase::ENET_Color)
-				MeshGeometry_AddColor(**pMesh, ((X3DColor*)*ch_it)->Value, true);
-			else if((*ch_it)->Type == X3DNodeElementBase::ENET_ColorRGBA)
-				MeshGeometry_AddColor(**pMesh, ((X3DColorRGBA*)*ch_it)->Value, true);
-			else if((*ch_it)->Type == X3DNodeElementBase::ENET_Coordinate)
-				{} // skip because already read when mesh created.
-			else
-				throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of LineSet: " + to_string((*ch_it)->Type) + ".");
-		}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
-
-		return;// mesh is build, nothing to do anymore.
-	}// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_LineSet)
-
-	if(pNodeElement.Type == X3DNodeElementBase::ENET_TriangleFanSet)
-	{
-		X3DSet& tnemesh = *((X3DSet*)&pNodeElement);// create alias for convenience
-
-		// at first search for <Coordinate> node and create mesh.
-		for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
-		{
-			if((*ch_it)->Type == X3DNodeElementBase::ENET_Coordinate)
-			{
-				*pMesh = GeometryHelper_MakeMesh(tnemesh.CoordIndex, ((X3DCoordinate*)*ch_it)->Value);
-			}
-		}
-
-		// copy additional information from children
-		for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
-		{
-			if ( nullptr == *pMesh ) {
-				break;
-			}
-			if((*ch_it)->Type == X3DNodeElementBase::ENET_Color)
-				MeshGeometry_AddColor(**pMesh, ((X3DColor*)*ch_it)->Value,tnemesh.ColorPerVertex);
-			else if((*ch_it)->Type == X3DNodeElementBase::ENET_ColorRGBA)
-				MeshGeometry_AddColor(**pMesh, ((X3DColorRGBA*)*ch_it)->Value, tnemesh.ColorPerVertex);
-			else if((*ch_it)->Type == X3DNodeElementBase::ENET_Coordinate)
-				{} // skip because already read when mesh created.
-			else if((*ch_it)->Type == X3DNodeElementBase::ENET_Normal)
-				MeshGeometry_AddNormal(**pMesh, tnemesh.CoordIndex, tnemesh.NormalIndex, ((X3DNormal*)*ch_it)->Value,
-										tnemesh.NormalPerVertex);
-			else if((*ch_it)->Type == X3DNodeElementBase::ENET_TextureCoordinate)
-				MeshGeometry_AddTexCoord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((X3DTextureCoordinate*)*ch_it)->Value);
-			else
-				throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of TrianlgeFanSet: " + to_string((*ch_it)->Type) + ".");
-		}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
-
-		return;// mesh is build, nothing to do anymore.
-	}// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_TriangleFanSet)
-
-	if(pNodeElement.Type == X3DNodeElementBase::ENET_TriangleSet)
-	{
-		X3DSet& tnemesh = *((X3DSet*)&pNodeElement);// create alias for convenience
-
-		// at first search for <Coordinate> node and create mesh.
-		for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
-		{
-			if((*ch_it)->Type == X3DNodeElementBase::ENET_Coordinate)
-			{
-				std::vector<aiVector3D> vec_copy;
-
-				vec_copy.reserve(((X3DCoordinate*)*ch_it)->Value.size());
-				for(std::list<aiVector3D>::const_iterator it = ((X3DCoordinate*)*ch_it)->Value.begin();
-					it != ((X3DCoordinate*)*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.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
-		{
-			ai_assert(*pMesh);
-			if((*ch_it)->Type == X3DNodeElementBase::ENET_Color)
-				MeshGeometry_AddColor(**pMesh, ((X3DColor*)*ch_it)->Value, tnemesh.ColorPerVertex);
-			else if((*ch_it)->Type == X3DNodeElementBase::ENET_ColorRGBA)
-				MeshGeometry_AddColor(**pMesh, ((X3DColorRGBA*)*ch_it)->Value, tnemesh.ColorPerVertex);
-			else if((*ch_it)->Type == X3DNodeElementBase::ENET_Coordinate)
-				{} // skip because already read when mesh created.
-			else if((*ch_it)->Type == X3DNodeElementBase::ENET_Normal)
-				MeshGeometry_AddNormal(**pMesh, tnemesh.CoordIndex, tnemesh.NormalIndex, ((X3DNormal*)*ch_it)->Value,
-										tnemesh.NormalPerVertex);
-			else if((*ch_it)->Type == X3DNodeElementBase::ENET_TextureCoordinate)
-				MeshGeometry_AddTexCoord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((X3DTextureCoordinate*)*ch_it)->Value);
-			else
-				throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of TrianlgeSet: " + to_string((*ch_it)->Type) + ".");
-		}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
-
-		return;// mesh is build, nothing to do anymore.
-	}// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_TriangleSet)
-
-	if(pNodeElement.Type == X3DNodeElementBase::ENET_TriangleStripSet)
-	{
-		X3DSet& tnemesh = *((X3DSet*)&pNodeElement);// create alias for convenience
-
-		// at first search for <Coordinate> node and create mesh.
-		for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
-		{
-			if((*ch_it)->Type == X3DNodeElementBase::ENET_Coordinate)
-			{
-				*pMesh = GeometryHelper_MakeMesh(tnemesh.CoordIndex, ((X3DCoordinate*)*ch_it)->Value);
-			}
-		}
-
-		// copy additional information from children
-		for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
-		{
-			ai_assert(*pMesh);
-			if((*ch_it)->Type == X3DNodeElementBase::ENET_Color)
-				MeshGeometry_AddColor(**pMesh, ((X3DColor*)*ch_it)->Value, tnemesh.ColorPerVertex);
-			else if((*ch_it)->Type == X3DNodeElementBase::ENET_ColorRGBA)
-				MeshGeometry_AddColor(**pMesh, ((X3DColorRGBA*)*ch_it)->Value, tnemesh.ColorPerVertex);
-			else if((*ch_it)->Type == X3DNodeElementBase::ENET_Coordinate)
-				{} // skip because already read when mesh created.
-			else if((*ch_it)->Type == X3DNodeElementBase::ENET_Normal)
-				MeshGeometry_AddNormal(**pMesh, tnemesh.CoordIndex, tnemesh.NormalIndex, ((X3DNormal*)*ch_it)->Value,
-										tnemesh.NormalPerVertex);
-			else if((*ch_it)->Type == X3DNodeElementBase::ENET_TextureCoordinate)
-				MeshGeometry_AddTexCoord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((X3DTextureCoordinate*)*ch_it)->Value);
-			else
-				throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of TriangleStripSet: " + to_string((*ch_it)->Type) + ".");
-		}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
-
-		return;// mesh is build, nothing to do anymore.
-	}// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_TriangleStripSet)
-
-	throw DeadlyImportError("Postprocess_BuildMesh. Unknown mesh type: " + 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.Child.begin();
-    std::list<X3DNodeElementBase*>::const_iterator chit_end = pNodeElement.Child.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 == X3DNodeElementBase::ENET_Group)
-	{
-		const X3DGroup& tne_group = *((X3DGroup*)&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.Child.size()))
-			{
-				chit_begin = pNodeElement.Child.end();
-				chit_end = pNodeElement.Child.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 == CX3DImporter_NodeElement::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 == X3DNodeElementBase::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 == X3DNodeElementBase::ENET_Shape)
-		{
-			// shape can contain only one geometry and one appearance nodes.
-			Postprocess_BuildShape(*((X3DShape*)*it), SceneNode_Mesh, pSceneMeshList, pSceneMaterialList);
-		}
-		else if(((*it)->Type == X3DNodeElementBase::ENET_DirectionalLight) || ((*it)->Type == X3DNodeElementBase::ENET_PointLight) ||
-				((*it)->Type == X3DNodeElementBase::ENET_SpotLight))
-		{
-			Postprocess_BuildLight(*((X3DLight*)*it), pSceneLightList);
-		}
-		else if(!PostprocessHelper_ElementIsMetadata((*it)->Type))// skip metadata
-		{
-			throw DeadlyImportError("Postprocess_BuildNode. Unknown type: " + to_string((*it)->Type) + ".");
-		}
-	}// for(std::list<CX3DImporter_NodeElement*>::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 X3DShape& pShapeNodeElement, std::list<unsigned int>& pNodeMeshInd,
-							std::list<aiMesh*>& pSceneMeshList, std::list<aiMaterial*>& pSceneMaterialList) const
-{
-    aiMaterial* tmat = nullptr;
-    aiMesh* tmesh = nullptr;
-    X3DNodeElementBase::EType mesh_type = X3DNodeElementBase::ENET_Invalid;
-    unsigned int mat_ind = 0;
-
-	for(std::list<X3DNodeElementBase*>::const_iterator it = pShapeNodeElement.Child.begin(); it != pShapeNodeElement.Child.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 == X3DNodeElementBase::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<CX3DImporter_NodeElement*>::const_iterator it = pShapeNodeElement.Child.begin(); it != pShapeNodeElement.Child.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 X3DNodeElementBase::ENET_Box:
-					tm = aiTextureMapping_BOX;
-					break;
-				case X3DNodeElementBase::ENET_Cone:
-				case X3DNodeElementBase::ENET_Cylinder:
-					tm = aiTextureMapping_CYLINDER;
-					break;
-				case X3DNodeElementBase::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)
-		{
-			X3DMeta* cur_meta = (X3DMeta*)*it;
-
-			// due to limitations we can add only first element of value list.
-			// Add an element according to its type.
-			if((*it)->Type == X3DNodeElementBase::ENET_MetaBoolean)
-			{
-				if(((X3DMetaBoolean*)cur_meta)->Value.size() > 0) {
-					const bool v = (bool) *( ( (X3DMetaBoolean*) cur_meta )->Value.begin());
-                    pSceneNode.mMetaData->Set(static_cast<unsigned int>(meta_idx), cur_meta->Name, v);
-                }
-			}
-			else if((*it)->Type == X3DNodeElementBase::ENET_MetaDouble)
-			{
-				if(((X3DMetaDouble*)cur_meta)->Value.size() > 0)
-					pSceneNode.mMetaData->Set(static_cast<unsigned int>(meta_idx), cur_meta->Name, (float)*(((X3DMetaDouble*)cur_meta)->Value.begin()));
-			}
-			else if((*it)->Type == X3DNodeElementBase::ENET_MetaFloat)
-			{
-				if(((X3DMetaFloat*)cur_meta)->Value.size() > 0)
-					pSceneNode.mMetaData->Set(static_cast<unsigned int>(meta_idx), cur_meta->Name, *(((X3DMetaFloat*)cur_meta)->Value.begin()));
-			}
-			else if((*it)->Type == X3DNodeElementBase::ENET_MetaInteger)
-			{
-				if(((X3DMetaInteger*)cur_meta)->Value.size() > 0)
-					pSceneNode.mMetaData->Set(static_cast<unsigned int>(meta_idx), cur_meta->Name, *(((X3DMetaInteger*)cur_meta)->Value.begin()));
-			}
-			else if((*it)->Type == X3DNodeElementBase::ENET_MetaString)
-			{
-				if(((X3DMetaString*)cur_meta)->Value.size() > 0)
-				{
-					aiString tstr(((X3DMetaString*)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 == CX3DImporter_NodeElement::ENET_Meta*) else
-		}// for(std::list<CX3DImporter_NodeElement*>::const_iterator it = meta_list.begin(); it != meta_list.end(); it++)
-	}// if( !meta_list.empty() )
-}
-
-}// namespace Assimp
-
-#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER

+ 0 - 1071
code/AssetLib/X3D/X3DImporter_Rendering.cpp

@@ -1,1071 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2020, 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_Rendering.cpp
-/// \brief  Parsing data from nodes of "Rendering" set of X3D.
-/// \date   2015-2016
-/// \author [email protected]
-
-#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
-
-#include "X3DImporter.hpp"
-#include "X3DImporter_Macro.hpp"
-
-namespace Assimp
-{
-
-// <Color
-// DEF=""           ID
-// USE=""           IDREF
-// color="" MFColor [inputOutput]
-// />
-void X3DImporter::ParseNode_Rendering_Color()
-{
-    std::string use, def;
-    std::list<aiColor3D> color;
-    X3DNodeElementBase* ne( nullptr );
-
-	MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
-		MACRO_ATTRREAD_CHECK_REF("color", color, XML_ReadNode_GetAttrVal_AsListCol3f);
-	MACRO_ATTRREAD_LOOPEND;
-
-	// if "USE" defined then find already defined element.
-	if(!use.empty())
-	{
-		MACRO_USE_CHECKANDAPPLY(def, use, ENET_Color, ne);
-	}
-	else
-	{
-		// create and if needed - define new geometry object.
-		ne = new X3DColor(mNodeElementCur);
-		if(!def.empty()) ne->ID = def;
-
-		((X3DColor*)ne)->Value = color;
-		// check for X3DMetadataObject childs.
-		if(!mReader->isEmptyElement())
-			ParseNode_Metadata(ne, "Color");
-		else
-			mNodeElementCur->Child.push_back(ne);// add made object as child to current element
-
-		NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
-	}// if(!use.empty()) else
-}
-
-// <ColorRGBA
-// DEF=""               ID
-// USE=""               IDREF
-// color="" MFColorRGBA [inputOutput]
-// />
-void X3DImporter::ParseNode_Rendering_ColorRGBA()
-{
-    std::string use, def;
-    std::list<aiColor4D> color;
-    X3DNodeElementBase* ne( nullptr );
-
-	MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
-		MACRO_ATTRREAD_CHECK_REF("color", color, XML_ReadNode_GetAttrVal_AsListCol4f);
-	MACRO_ATTRREAD_LOOPEND;
-
-	// if "USE" defined then find already defined element.
-	if(!use.empty())
-	{
-		MACRO_USE_CHECKANDAPPLY(def, use, ENET_ColorRGBA, ne);
-	}
-	else
-	{
-		// create and if needed - define new geometry object.
-		ne = new X3DColorRGBA(mNodeElementCur);
-		if(!def.empty()) ne->ID = def;
-
-		((X3DColorRGBA*)ne)->Value = color;
-		// check for X3DMetadataObject childs.
-		if(!mReader->isEmptyElement())
-			ParseNode_Metadata(ne, "ColorRGBA");
-		else
-			mNodeElementCur->Child.push_back(ne);// add made object as child to current element
-
-		NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
-	}// if(!use.empty()) else
-}
-
-// <Coordinate
-// DEF=""      ID
-// USE=""      IDREF
-// point=""    MFVec3f [inputOutput]
-// />
-void X3DImporter::ParseNode_Rendering_Coordinate()
-{
-    std::string use, def;
-    std::list<aiVector3D> point;
-    X3DNodeElementBase* ne( nullptr );
-
-	MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
-		MACRO_ATTRREAD_CHECK_REF("point", point, XML_ReadNode_GetAttrVal_AsListVec3f);
-	MACRO_ATTRREAD_LOOPEND;
-
-	// if "USE" defined then find already defined element.
-	if(!use.empty())
-	{
-		MACRO_USE_CHECKANDAPPLY(def, use, ENET_Coordinate, ne);
-	}
-	else
-	{
-		// create and if needed - define new geometry object.
-		ne = new X3DCoordinate(mNodeElementCur);
-		if(!def.empty()) ne->ID = def;
-
-		((X3DCoordinate*)ne)->Value = point;
-		// check for X3DMetadataObject childs.
-		if(!mReader->isEmptyElement())
-			ParseNode_Metadata(ne, "Coordinate");
-		else
-			mNodeElementCur->Child.push_back(ne);// add made object as child to current element
-
-		NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
-	}// if(!use.empty()) else
-}
-
-// <IndexedLineSet
-// DEF=""                ID
-// USE=""                IDREF
-// colorIndex=""         MFInt32 [initializeOnly]
-// colorPerVertex="true" SFBool  [initializeOnly]
-// coordIndex=""         MFInt32 [initializeOnly]
-// >
-//    <!-- ColorCoordinateContentModel -->
-// ColorCoordinateContentModel is the child-node content model corresponding to IndexedLineSet, LineSet and PointSet. ColorCoordinateContentModel can
-// contain any-order Coordinate node with Color (or ColorRGBA) node. No more than one instance of any single node type is allowed.
-// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
-// </IndexedLineSet>
-void X3DImporter::ParseNode_Rendering_IndexedLineSet()
-{
-    std::string use, def;
-    std::vector<int32_t> colorIndex;
-    bool colorPerVertex = true;
-    std::vector<int32_t> coordIndex;
-    X3DNodeElementBase* ne( nullptr );
-
-	MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
-		MACRO_ATTRREAD_CHECK_REF("colorIndex", colorIndex, XML_ReadNode_GetAttrVal_AsArrI32);
-		MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_REF("coordIndex", coordIndex, XML_ReadNode_GetAttrVal_AsArrI32);
-	MACRO_ATTRREAD_LOOPEND;
-
-	// if "USE" defined then find already defined element.
-	if(!use.empty())
-	{
-		MACRO_USE_CHECKANDAPPLY(def, use, ENET_IndexedLineSet, ne);
-	}
-	else
-	{
-		// check data
-		if((coordIndex.size() < 2) || ((coordIndex.back() == (-1)) && (coordIndex.size() < 3)))
-			throw DeadlyImportError("IndexedLineSet must contain not empty \"coordIndex\" attribute.");
-
-		// create and if needed - define new geometry object.
-		ne = new X3DIndexedSet(X3DNodeElementBase::ENET_IndexedLineSet, mNodeElementCur);
-		if(!def.empty()) ne->ID = def;
-
-		X3DIndexedSet& ne_alias = *((X3DIndexedSet*)ne);
-
-		ne_alias.ColorIndex = colorIndex;
-		ne_alias.ColorPerVertex = colorPerVertex;
-		ne_alias.CoordIndex = coordIndex;
-        // check for child nodes
-        if(!mReader->isEmptyElement())
-        {
-			ParseHelper_Node_Enter(ne);
-			MACRO_NODECHECK_LOOPBEGIN("IndexedLineSet");
-				// check for Color and Coordinate nodes
-				if(XML_CheckNode_NameEqual("Color")) { ParseNode_Rendering_Color(); continue; }
-				if(XML_CheckNode_NameEqual("ColorRGBA")) { ParseNode_Rendering_ColorRGBA(); continue; }
-				if(XML_CheckNode_NameEqual("Coordinate")) { ParseNode_Rendering_Coordinate(); continue; }
-				// check for X3DMetadataObject
-				if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("IndexedLineSet");
-
-			MACRO_NODECHECK_LOOPEND("IndexedLineSet");
-			ParseHelper_Node_Exit();
-		}// if(!mReader->isEmptyElement())
-		else
-		{
-			mNodeElementCur->Child.push_back(ne);// add made object as child to current element
-		}
-
-		NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
-	}// if(!use.empty()) else
-}
-
-// <IndexedTriangleFanSet
-// DEF=""                 ID
-// USE=""                 IDREF
-// ccw="true"             SFBool  [initializeOnly]
-// colorPerVertex="true"  SFBool  [initializeOnly]
-// index=""               MFInt32 [initializeOnly]
-// normalPerVertex="true" SFBool  [initializeOnly]
-// solid="true"           SFBool  [initializeOnly]
-// >
-//    <!-- ComposedGeometryContentModel -->
-// ComposedGeometryContentModel is the child-node content model corresponding to X3DComposedGeometryNodes. It can contain Color (or ColorRGBA), Coordinate,
-// Normal and TextureCoordinate, in any order. No more than one instance of these nodes is allowed. Multiple VertexAttribute (FloatVertexAttribute,
-// Matrix3VertexAttribute, Matrix4VertexAttribute) nodes can also be contained.
-// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
-// </IndexedTriangleFanSet>
-void X3DImporter::ParseNode_Rendering_IndexedTriangleFanSet()
-{
-    std::string use, def;
-    bool ccw = true;
-    bool colorPerVertex = true;
-    std::vector<int32_t> index;
-    bool normalPerVertex = true;
-    bool solid = true;
-    X3DNodeElementBase* ne( nullptr );
-
-	MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
-		MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_REF("index", index, XML_ReadNode_GetAttrVal_AsArrI32);
-		MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
-	MACRO_ATTRREAD_LOOPEND;
-
-	// if "USE" defined then find already defined element.
-	if(!use.empty())
-	{
-		MACRO_USE_CHECKANDAPPLY(def, use, ENET_IndexedTriangleFanSet, ne);
-	}
-	else
-	{
-		// check data
-		if(index.size() == 0) throw DeadlyImportError("IndexedTriangleFanSet must contain not empty \"index\" attribute.");
-
-		// create and if needed - define new geometry object.
-		ne = new X3DIndexedSet(X3DNodeElementBase::ENET_IndexedTriangleFanSet, mNodeElementCur);
-		if(!def.empty()) ne->ID = def;
-
-		X3DIndexedSet& ne_alias = *((X3DIndexedSet*)ne);
-
-		ne_alias.CCW = ccw;
-		ne_alias.ColorPerVertex = colorPerVertex;
-		ne_alias.NormalPerVertex = normalPerVertex;
-		ne_alias.Solid = solid;
-
-		ne_alias.CoordIndex.clear();
-		int counter = 0;
-		int32_t idx[3];
-		for(std::vector<int32_t>::const_iterator idx_it = index.begin(); idx_it != index.end(); ++idx_it)
-		{
-			idx[2] = *idx_it;
-			if (idx[2] < 0)
-			{
-				counter = 0;
-			}
-			else
-			{
-				if (counter >= 2)
-				{
-					if(ccw)
-					{
-						ne_alias.CoordIndex.push_back(idx[0]);
-						ne_alias.CoordIndex.push_back(idx[1]);
-						ne_alias.CoordIndex.push_back(idx[2]);
-					}
-					else
-					{
-						ne_alias.CoordIndex.push_back(idx[0]);
-						ne_alias.CoordIndex.push_back(idx[2]);
-						ne_alias.CoordIndex.push_back(idx[1]);
-					}
-					ne_alias.CoordIndex.push_back(-1);
-					idx[1] = idx[2];
-				}
-				else
-				{
-					idx[counter] = idx[2];
-				}
-				++counter;
-			}
-		}// for(std::list<int32_t>::const_iterator idx_it = index.begin(); idx_it != ne_alias.index.end(); idx_it++)
-
-        // check for child nodes
-        if(!mReader->isEmptyElement())
-        {
-			ParseHelper_Node_Enter(ne);
-			MACRO_NODECHECK_LOOPBEGIN("IndexedTriangleFanSet");
-				// check for X3DComposedGeometryNodes
-				if(XML_CheckNode_NameEqual("Color")) { ParseNode_Rendering_Color(); continue; }
-				if(XML_CheckNode_NameEqual("ColorRGBA")) { ParseNode_Rendering_ColorRGBA(); continue; }
-				if(XML_CheckNode_NameEqual("Coordinate")) { ParseNode_Rendering_Coordinate(); continue; }
-				if(XML_CheckNode_NameEqual("Normal")) { ParseNode_Rendering_Normal(); continue; }
-				if(XML_CheckNode_NameEqual("TextureCoordinate")) { ParseNode_Texturing_TextureCoordinate(); continue; }
-				// check for X3DMetadataObject
-				if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("IndexedTriangleFanSet");
-
-			MACRO_NODECHECK_LOOPEND("IndexedTriangleFanSet");
-			ParseHelper_Node_Exit();
-		}// if(!mReader->isEmptyElement())
-		else
-		{
-			mNodeElementCur->Child.push_back(ne);// add made object as child to current element
-		}
-
-		NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
-	}// if(!use.empty()) else
-}
-
-// <IndexedTriangleSet
-// DEF=""                 ID
-// USE=""                 IDREF
-// ccw="true"             SFBool  [initializeOnly]
-// colorPerVertex="true"  SFBool  [initializeOnly]
-// index=""               MFInt32 [initializeOnly]
-// normalPerVertex="true" SFBool  [initializeOnly]
-// solid="true"           SFBool  [initializeOnly]
-// >
-//    <!-- ComposedGeometryContentModel -->
-// ComposedGeometryContentModel is the child-node content model corresponding to X3DComposedGeometryNodes. It can contain Color (or ColorRGBA), Coordinate,
-// Normal and TextureCoordinate, in any order. No more than one instance of these nodes is allowed. Multiple VertexAttribute (FloatVertexAttribute,
-// Matrix3VertexAttribute, Matrix4VertexAttribute) nodes can also be contained.
-// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
-// </IndexedTriangleSet>
-void X3DImporter::ParseNode_Rendering_IndexedTriangleSet()
-{
-    std::string use, def;
-    bool ccw = true;
-    bool colorPerVertex = true;
-    std::vector<int32_t> index;
-    bool normalPerVertex = true;
-    bool solid = true;
-    X3DNodeElementBase* ne( nullptr );
-
-	MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
-		MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_REF("index", index, XML_ReadNode_GetAttrVal_AsArrI32);
-		MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
-	MACRO_ATTRREAD_LOOPEND;
-
-	// if "USE" defined then find already defined element.
-	if(!use.empty())
-	{
-		MACRO_USE_CHECKANDAPPLY(def, use, ENET_IndexedTriangleSet, ne);
-	}
-	else
-	{
-		// check data
-		if(index.size() == 0) throw DeadlyImportError("IndexedTriangleSet must contain not empty \"index\" attribute.");
-
-		// create and if needed - define new geometry object.
-		ne = new X3DIndexedSet(X3DNodeElementBase::ENET_IndexedTriangleSet, mNodeElementCur);
-		if(!def.empty()) ne->ID = def;
-
-		X3DIndexedSet& ne_alias = *((X3DIndexedSet*)ne);
-
-		ne_alias.CCW = ccw;
-		ne_alias.ColorPerVertex = colorPerVertex;
-		ne_alias.NormalPerVertex = normalPerVertex;
-		ne_alias.Solid = solid;
-
-		ne_alias.CoordIndex.clear();
-		int counter = 0;
-		int32_t idx[3];
-		for(std::vector<int32_t>::const_iterator idx_it = index.begin(); idx_it != index.end(); ++idx_it)
-		{
-			idx[counter++] = *idx_it;
-			if (counter > 2)
-			{
-				counter = 0;
-				if(ccw)
-				{
-					ne_alias.CoordIndex.push_back(idx[0]);
-					ne_alias.CoordIndex.push_back(idx[1]);
-					ne_alias.CoordIndex.push_back(idx[2]);
-				}
-				else
-				{
-					ne_alias.CoordIndex.push_back(idx[0]);
-					ne_alias.CoordIndex.push_back(idx[2]);
-					ne_alias.CoordIndex.push_back(idx[1]);
-				}
-				ne_alias.CoordIndex.push_back(-1);
-			}
-		}// for(std::list<int32_t>::const_iterator idx_it = index.begin(); idx_it != ne_alias.index.end(); idx_it++)
-
-        // check for child nodes
-        if(!mReader->isEmptyElement())
-        {
-			ParseHelper_Node_Enter(ne);
-			MACRO_NODECHECK_LOOPBEGIN("IndexedTriangleSet");
-				// check for X3DComposedGeometryNodes
-				if(XML_CheckNode_NameEqual("Color")) { ParseNode_Rendering_Color(); continue; }
-				if(XML_CheckNode_NameEqual("ColorRGBA")) { ParseNode_Rendering_ColorRGBA(); continue; }
-				if(XML_CheckNode_NameEqual("Coordinate")) { ParseNode_Rendering_Coordinate(); continue; }
-				if(XML_CheckNode_NameEqual("Normal")) { ParseNode_Rendering_Normal(); continue; }
-				if(XML_CheckNode_NameEqual("TextureCoordinate")) { ParseNode_Texturing_TextureCoordinate(); continue; }
-				// check for X3DMetadataObject
-				if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("IndexedTriangleSet");
-
-			MACRO_NODECHECK_LOOPEND("IndexedTriangleSet");
-			ParseHelper_Node_Exit();
-		}// if(!mReader->isEmptyElement())
-		else
-		{
-			mNodeElementCur->Child.push_back(ne);// add made object as child to current element
-		}
-
-		NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
-	}// if(!use.empty()) else
-}
-
-// <IndexedTriangleStripSet
-// DEF=""                 ID
-// USE=""                 IDREF
-// ccw="true"             SFBool  [initializeOnly]
-// colorPerVertex="true"  SFBool  [initializeOnly]
-// index=""               MFInt32 [initializeOnly]
-// normalPerVertex="true" SFBool  [initializeOnly]
-// solid="true"           SFBool  [initializeOnly]
-// >
-//    <!-- ComposedGeometryContentModel -->
-// ComposedGeometryContentModel is the child-node content model corresponding to X3DComposedGeometryNodes. It can contain Color (or ColorRGBA), Coordinate,
-// Normal and TextureCoordinate, in any order. No more than one instance of these nodes is allowed. Multiple VertexAttribute (FloatVertexAttribute,
-// Matrix3VertexAttribute, Matrix4VertexAttribute) nodes can also be contained.
-// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
-// </IndexedTriangleStripSet>
-void X3DImporter::ParseNode_Rendering_IndexedTriangleStripSet()
-{
-    std::string use, def;
-    bool ccw = true;
-    bool colorPerVertex = true;
-    std::vector<int32_t> index;
-    bool normalPerVertex = true;
-    bool solid = true;
-    X3DNodeElementBase* ne( nullptr );
-
-	MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
-		MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_REF("index", index, XML_ReadNode_GetAttrVal_AsArrI32);
-		MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
-	MACRO_ATTRREAD_LOOPEND;
-
-	// if "USE" defined then find already defined element.
-	if(!use.empty())
-	{
-		MACRO_USE_CHECKANDAPPLY(def, use, ENET_IndexedTriangleStripSet, ne);
-	}
-	else
-	{
-		// check data
-		if(index.size() == 0) throw DeadlyImportError("IndexedTriangleStripSet must contain not empty \"index\" attribute.");
-
-		// create and if needed - define new geometry object.
-		ne = new X3DIndexedSet(X3DNodeElementBase::ENET_IndexedTriangleStripSet, mNodeElementCur);
-		if(!def.empty()) ne->ID = def;
-
-		X3DIndexedSet& ne_alias = *((X3DIndexedSet*)ne);
-
-		ne_alias.CCW = ccw;
-		ne_alias.ColorPerVertex = colorPerVertex;
-		ne_alias.NormalPerVertex = normalPerVertex;
-		ne_alias.Solid = solid;
-
-		ne_alias.CoordIndex.clear();
-		int counter = 0;
-		int32_t idx[3];
-		for(std::vector<int32_t>::const_iterator idx_it = index.begin(); idx_it != index.end(); ++idx_it)
-		{
-			idx[2] = *idx_it;
-			if (idx[2] < 0)
-			{
-				counter = 0;
-			}
-			else
-			{
-				if (counter >= 2)
-				{
-					if(ccw)
-					{
-						ne_alias.CoordIndex.push_back(idx[0]);
-						ne_alias.CoordIndex.push_back(idx[1]);
-						ne_alias.CoordIndex.push_back(idx[2]);
-					}
-					else
-					{
-						ne_alias.CoordIndex.push_back(idx[0]);
-						ne_alias.CoordIndex.push_back(idx[2]);
-						ne_alias.CoordIndex.push_back(idx[1]);
-					}
-					ne_alias.CoordIndex.push_back(-1);
-				}
-				idx[counter & 1] = idx[2];
-				++counter;
-			}
-		}// for(std::list<int32_t>::const_iterator idx_it = index.begin(); idx_it != ne_alias.index.end(); idx_it++)
-
-        // check for child nodes
-        if(!mReader->isEmptyElement())
-        {
-			ParseHelper_Node_Enter(ne);
-			MACRO_NODECHECK_LOOPBEGIN("IndexedTriangleStripSet");
-				// check for X3DComposedGeometryNodes
-				if(XML_CheckNode_NameEqual("Color")) { ParseNode_Rendering_Color(); continue; }
-				if(XML_CheckNode_NameEqual("ColorRGBA")) { ParseNode_Rendering_ColorRGBA(); continue; }
-				if(XML_CheckNode_NameEqual("Coordinate")) { ParseNode_Rendering_Coordinate(); continue; }
-				if(XML_CheckNode_NameEqual("Normal")) { ParseNode_Rendering_Normal(); continue; }
-				if(XML_CheckNode_NameEqual("TextureCoordinate")) { ParseNode_Texturing_TextureCoordinate(); continue; }
-				// check for X3DMetadataObject
-				if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("IndexedTriangleStripSet");
-
-			MACRO_NODECHECK_LOOPEND("IndexedTriangleStripSet");
-			ParseHelper_Node_Exit();
-		}// if(!mReader->isEmptyElement())
-		else
-		{
-			mNodeElementCur->Child.push_back(ne);// add made object as child to current element
-		}
-
-		NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
-	}// if(!use.empty()) else
-}
-
-// <LineSet
-// DEF=""         ID
-// USE=""         IDREF
-// vertexCount="" MFInt32 [initializeOnly]
-// >
-//    <!-- ColorCoordinateContentModel -->
-// ColorCoordinateContentModel is the child-node content model corresponding to IndexedLineSet, LineSet and PointSet. ColorCoordinateContentModel can
-// contain any-order Coordinate node with Color (or ColorRGBA) node. No more than one instance of any single node type is allowed.
-// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
-// </LineSet>
-void X3DImporter::ParseNode_Rendering_LineSet()
-{
-    std::string use, def;
-    std::vector<int32_t> vertexCount;
-    X3DNodeElementBase* ne( nullptr );
-
-	MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
-		MACRO_ATTRREAD_CHECK_REF("vertexCount", vertexCount, XML_ReadNode_GetAttrVal_AsArrI32);
-	MACRO_ATTRREAD_LOOPEND;
-
-	// if "USE" defined then find already defined element.
-	if(!use.empty())
-	{
-		MACRO_USE_CHECKANDAPPLY(def, use, ENET_LineSet, ne);
-	}
-	else
-	{
-		// check data
-		if(vertexCount.size() == 0) throw DeadlyImportError("LineSet must contain not empty \"vertexCount\" attribute.");
-
-		// create and if needed - define new geometry object.
-		ne = new X3DSet(X3DNodeElementBase::ENET_LineSet, mNodeElementCur);
-		if(!def.empty()) ne->ID = def;
-
-		X3DSet& ne_alias = *((X3DSet*)ne);
-
-		ne_alias.VertexCount = vertexCount;
-		// create CoordIdx
-		size_t coord_num = 0;
-
-		ne_alias.CoordIndex.clear();
-		for(std::vector<int32_t>::const_iterator vc_it = ne_alias.VertexCount.begin(); vc_it != ne_alias.VertexCount.end(); ++vc_it)
-		{
-			if(*vc_it < 2) throw DeadlyImportError("LineSet. vertexCount shall be greater than or equal to two.");
-
-			for(int32_t i = 0; i < *vc_it; i++) ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num++));// add vertices indices
-
-			 ne_alias.CoordIndex.push_back(-1);// add face delimiter.
-		}
-
-        // check for child nodes
-        if(!mReader->isEmptyElement())
-        {
-			ParseHelper_Node_Enter(ne);
-			MACRO_NODECHECK_LOOPBEGIN("LineSet");
-				// check for X3DComposedGeometryNodes
-				if(XML_CheckNode_NameEqual("Color")) { ParseNode_Rendering_Color(); continue; }
-				if(XML_CheckNode_NameEqual("ColorRGBA")) { ParseNode_Rendering_ColorRGBA(); continue; }
-				if(XML_CheckNode_NameEqual("Coordinate")) { ParseNode_Rendering_Coordinate(); continue; }
-				// check for X3DMetadataObject
-				if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("LineSet");
-
-			MACRO_NODECHECK_LOOPEND("LineSet");
-			ParseHelper_Node_Exit();
-		}// if(!mReader->isEmptyElement())
-		else
-		{
-			mNodeElementCur->Child.push_back(ne);// add made object as child to current element
-		}
-
-		NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
-	}// if(!use.empty()) else
-}
-
-// <PointSet
-// DEF="" ID
-// USE="" IDREF
-// >
-//    <!-- ColorCoordinateContentModel -->
-// ColorCoordinateContentModel is the child-node content model corresponding to IndexedLineSet, LineSet and PointSet. ColorCoordinateContentModel can
-// contain any-order Coordinate node with Color (or ColorRGBA) node. No more than one instance of any single node type is allowed.
-// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
-// </PointSet>
-void X3DImporter::ParseNode_Rendering_PointSet()
-{
-    std::string use, def;
-    X3DNodeElementBase* ne( nullptr );
-
-	MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
-	MACRO_ATTRREAD_LOOPEND;
-
-	// if "USE" defined then find already defined element.
-	if(!use.empty())
-	{
-		MACRO_USE_CHECKANDAPPLY(def, use, ENET_PointSet, ne);
-	}
-	else
-	{
-		// create and if needed - define new geometry object.
-		ne = new X3DIndexedSet(X3DNodeElementBase::ENET_PointSet, mNodeElementCur);
-		if(!def.empty()) ne->ID = def;
-
-        // check for child nodes
-        if(!mReader->isEmptyElement())
-        {
-			ParseHelper_Node_Enter(ne);
-			MACRO_NODECHECK_LOOPBEGIN("PointSet");
-				// check for X3DComposedGeometryNodes
-				if(XML_CheckNode_NameEqual("Color")) { ParseNode_Rendering_Color(); continue; }
-				if(XML_CheckNode_NameEqual("ColorRGBA")) { ParseNode_Rendering_ColorRGBA(); continue; }
-				if(XML_CheckNode_NameEqual("Coordinate")) { ParseNode_Rendering_Coordinate(); continue; }
-				// check for X3DMetadataObject
-				if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("PointSet");
-
-			MACRO_NODECHECK_LOOPEND("PointSet");
-			ParseHelper_Node_Exit();
-		}// if(!mReader->isEmptyElement())
-		else
-		{
-			mNodeElementCur->Child.push_back(ne);// add made object as child to current element
-		}
-
-		NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
-	}// if(!use.empty()) else
-}
-
-// <TriangleFanSet
-// DEF=""                 ID
-// USE=""                 IDREF
-// ccw="true"             SFBool  [initializeOnly]
-// colorPerVertex="true"  SFBool  [initializeOnly]
-// fanCount=""            MFInt32 [inputOutput]
-// normalPerVertex="true" SFBool  [initializeOnly]
-// solid="true"           SFBool  [initializeOnly]
-// >
-//    <!-- ComposedGeometryContentModel -->
-// ComposedGeometryContentModel is the child-node content model corresponding to X3DComposedGeometryNodes. It can contain Color (or ColorRGBA), Coordinate,
-// Normal and TextureCoordinate, in any order. No more than one instance of these nodes is allowed. Multiple VertexAttribute (FloatVertexAttribute,
-// Matrix3VertexAttribute, Matrix4VertexAttribute) nodes can also be contained.
-// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
-// </TriangleFanSet>
-void X3DImporter::ParseNode_Rendering_TriangleFanSet()
-{
-    std::string use, def;
-    bool ccw = true;
-    bool colorPerVertex = true;
-    std::vector<int32_t> fanCount;
-    bool normalPerVertex = true;
-    bool solid = true;
-    X3DNodeElementBase* ne( nullptr );
-
-	MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
-		MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_REF("fanCount", fanCount, XML_ReadNode_GetAttrVal_AsArrI32);
-		MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
-	MACRO_ATTRREAD_LOOPEND;
-
-	// if "USE" defined then find already defined element.
-	if(!use.empty())
-	{
-		MACRO_USE_CHECKANDAPPLY(def, use, ENET_TriangleFanSet, ne);
-	}
-	else
-	{
-		// check data
-		if(fanCount.size() == 0) throw DeadlyImportError("TriangleFanSet must contain not empty \"fanCount\" attribute.");
-
-		// create and if needed - define new geometry object.
-		ne = new X3DSet(X3DNodeElementBase::ENET_TriangleFanSet, mNodeElementCur);
-		if(!def.empty()) ne->ID = def;
-
-		X3DSet& ne_alias = *((X3DSet*)ne);
-
-		ne_alias.CCW = ccw;
-		ne_alias.ColorPerVertex = colorPerVertex;
-		ne_alias.VertexCount = fanCount;
-		ne_alias.NormalPerVertex = normalPerVertex;
-		ne_alias.Solid = solid;
-		// create CoordIdx
-		size_t coord_num_first, coord_num_prev;
-
-		ne_alias.CoordIndex.clear();
-		// assign indices for first triangle
-		coord_num_first = 0;
-		coord_num_prev = 1;
-		for(std::vector<int32_t>::const_iterator vc_it = ne_alias.VertexCount.begin(); vc_it != ne_alias.VertexCount.end(); ++vc_it)
-		{
-			if(*vc_it < 3) throw DeadlyImportError("TriangleFanSet. fanCount shall be greater than or equal to three.");
-
-			for(int32_t vc = 2; vc < *vc_it; vc++)
-			{
-				if(ccw)
-				{
-					// 2 1
-					//  0
-					ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num_first));// first vertex is a center and always is [0].
-					ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num_prev++));
-					ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num_prev));
-				}
-				else
-				{
-					// 1 2
-					//  0
-					ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num_first));// first vertex is a center and always is [0].
-					ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num_prev + 1));
-					ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num_prev++));
-				}// if(ccw) else
-
-				ne_alias.CoordIndex.push_back(-1);// add face delimiter.
-			}// for(int32_t vc = 2; vc < *vc_it; vc++)
-
-			coord_num_prev++;// that index will be center of next fan
-			coord_num_first = coord_num_prev++;// forward to next point - second point of fan
-		}// for(std::list<int32_t>::const_iterator vc_it = ne_alias.VertexCount.begin(); vc_it != ne_alias.VertexCount.end(); vc_it++)
-        // check for child nodes
-        if(!mReader->isEmptyElement())
-        {
-			ParseHelper_Node_Enter(ne);
-			MACRO_NODECHECK_LOOPBEGIN("TriangleFanSet");
-				// check for X3DComposedGeometryNodes
-				if(XML_CheckNode_NameEqual("Color")) { ParseNode_Rendering_Color(); continue; }
-				if(XML_CheckNode_NameEqual("ColorRGBA")) { ParseNode_Rendering_ColorRGBA(); continue; }
-				if(XML_CheckNode_NameEqual("Coordinate")) { ParseNode_Rendering_Coordinate(); continue; }
-				if(XML_CheckNode_NameEqual("Normal")) { ParseNode_Rendering_Normal(); continue; }
-				if(XML_CheckNode_NameEqual("TextureCoordinate")) { ParseNode_Texturing_TextureCoordinate(); continue; }
-				// check for X3DMetadataObject
-				if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("TriangleFanSet");
-
-			MACRO_NODECHECK_LOOPEND("TriangleFanSet");
-			ParseHelper_Node_Exit();
-		}// if(!mReader->isEmptyElement())
-		else
-		{
-			mNodeElementCur->Child.push_back(ne);// add made object as child to current element
-		}
-
-		NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
-	}// if(!use.empty()) else
-}
-
-// <TriangleSet
-// DEF=""                 ID
-// USE=""                 IDREF
-// ccw="true"             SFBool  [initializeOnly]
-// colorPerVertex="true"  SFBool  [initializeOnly]
-// normalPerVertex="true" SFBool  [initializeOnly]
-// solid="true"           SFBool  [initializeOnly]
-// >
-//    <!-- ComposedGeometryContentModel -->
-// ComposedGeometryContentModel is the child-node content model corresponding to X3DComposedGeometryNodes. It can contain Color (or ColorRGBA), Coordinate,
-// Normal and TextureCoordinate, in any order. No more than one instance of these nodes is allowed. Multiple VertexAttribute (FloatVertexAttribute,
-// Matrix3VertexAttribute, Matrix4VertexAttribute) nodes can also be contained.
-// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
-// </TriangleSet>
-void X3DImporter::ParseNode_Rendering_TriangleSet()
-{
-    std::string use, def;
-    bool ccw = true;
-    bool colorPerVertex = true;
-    bool normalPerVertex = true;
-    bool solid = true;
-    X3DNodeElementBase* ne( nullptr );
-
-	MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
-		MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
-	MACRO_ATTRREAD_LOOPEND;
-
-	// if "USE" defined then find already defined element.
-	if(!use.empty())
-	{
-		MACRO_USE_CHECKANDAPPLY(def, use, ENET_TriangleSet, ne);
-	}
-	else
-	{
-		// create and if needed - define new geometry object.
-		ne = new X3DIndexedSet(X3DNodeElementBase::ENET_TriangleSet, mNodeElementCur);
-		if(!def.empty()) ne->ID = def;
-
-		X3DSet& ne_alias = *((X3DSet*)ne);
-
-		ne_alias.CCW = ccw;
-		ne_alias.ColorPerVertex = colorPerVertex;
-		ne_alias.NormalPerVertex = normalPerVertex;
-		ne_alias.Solid = solid;
-        // check for child nodes
-        if(!mReader->isEmptyElement())
-        {
-			ParseHelper_Node_Enter(ne);
-			MACRO_NODECHECK_LOOPBEGIN("TriangleSet");
-				// check for X3DComposedGeometryNodes
-				if(XML_CheckNode_NameEqual("Color")) { ParseNode_Rendering_Color(); continue; }
-				if(XML_CheckNode_NameEqual("ColorRGBA")) { ParseNode_Rendering_ColorRGBA(); continue; }
-				if(XML_CheckNode_NameEqual("Coordinate")) { ParseNode_Rendering_Coordinate(); continue; }
-				if(XML_CheckNode_NameEqual("Normal")) { ParseNode_Rendering_Normal(); continue; }
-				if(XML_CheckNode_NameEqual("TextureCoordinate")) { ParseNode_Texturing_TextureCoordinate(); continue; }
-				// check for X3DMetadataObject
-				if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("TriangleSet");
-
-			MACRO_NODECHECK_LOOPEND("TriangleSet");
-			ParseHelper_Node_Exit();
-		}// if(!mReader->isEmptyElement())
-		else
-		{
-			mNodeElementCur->Child.push_back(ne);// add made object as child to current element
-		}
-
-		NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
-	}// if(!use.empty()) else
-}
-
-// <TriangleStripSet
-// DEF=""                 ID
-// USE=""                 IDREF
-// ccw="true"             SFBool  [initializeOnly]
-// colorPerVertex="true"  SFBool  [initializeOnly]
-// normalPerVertex="true" SFBool  [initializeOnly]
-// solid="true"           SFBool  [initializeOnly]
-// stripCount=""          MFInt32 [inputOutput]
-// >
-//    <!-- ComposedGeometryContentModel -->
-// ComposedGeometryContentModel is the child-node content model corresponding to X3DComposedGeometryNodes. It can contain Color (or ColorRGBA), Coordinate,
-// Normal and TextureCoordinate, in any order. No more than one instance of these nodes is allowed. Multiple VertexAttribute (FloatVertexAttribute,
-// Matrix3VertexAttribute, Matrix4VertexAttribute) nodes can also be contained.
-// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
-// </TriangleStripSet>
-void X3DImporter::ParseNode_Rendering_TriangleStripSet()
-{
-    std::string use, def;
-    bool ccw = true;
-    bool colorPerVertex = true;
-    std::vector<int32_t> stripCount;
-    bool normalPerVertex = true;
-    bool solid = true;
-    X3DNodeElementBase* ne( nullptr );
-
-	MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
-		MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_REF("stripCount", stripCount, XML_ReadNode_GetAttrVal_AsArrI32);
-		MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool);
-	MACRO_ATTRREAD_LOOPEND;
-
-	// if "USE" defined then find already defined element.
-	if(!use.empty())
-	{
-		MACRO_USE_CHECKANDAPPLY(def, use, ENET_TriangleStripSet, ne);
-	}
-	else
-	{
-		// check data
-		if(stripCount.size() == 0) throw DeadlyImportError("TriangleStripSet must contain not empty \"stripCount\" attribute.");
-
-		// create and if needed - define new geometry object.
-		ne = new X3DSet(X3DNodeElementBase::ENET_TriangleStripSet, mNodeElementCur);
-		if(!def.empty()) ne->ID = def;
-
-		X3DSet& ne_alias = *((X3DSet*)ne);
-
-		ne_alias.CCW = ccw;
-		ne_alias.ColorPerVertex = colorPerVertex;
-		ne_alias.VertexCount = stripCount;
-		ne_alias.NormalPerVertex = normalPerVertex;
-		ne_alias.Solid = solid;
-		// create CoordIdx
-		size_t coord_num0, coord_num1, coord_num2;// indices of current triangle
-		bool odd_tri;// sequence of current triangle
-		size_t coord_num_sb;// index of first point of strip
-
-		ne_alias.CoordIndex.clear();
-		coord_num_sb = 0;
-		for(std::vector<int32_t>::const_iterator vc_it = ne_alias.VertexCount.begin(); vc_it != ne_alias.VertexCount.end(); ++vc_it)
-		{
-			if(*vc_it < 3) throw DeadlyImportError("TriangleStripSet. stripCount shall be greater than or equal to three.");
-
-			// set initial values for first triangle
-			coord_num0 = coord_num_sb;
-			coord_num1 = coord_num_sb + 1;
-			coord_num2 = coord_num_sb + 2;
-			odd_tri = true;
-
-			for(int32_t vc = 2; vc < *vc_it; vc++)
-			{
-				if(ccw)
-				{
-					// 0 2
-					//  1
-					ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num0));
-					ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num1));
-					ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num2));
-				}
-				else
-				{
-					// 0 1
-					//  2
-					ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num0));
-					ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num2));
-					ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num1));
-				}// if(ccw) else
-
-				ne_alias.CoordIndex.push_back(-1);// add face delimiter.
-				// prepare values for next triangle
-				if(odd_tri)
-				{
-					coord_num0 = coord_num2;
-					coord_num2++;
-				}
-				else
-				{
-					coord_num1 = coord_num2;
-					coord_num2 = coord_num1 + 1;
-				}
-
-				odd_tri = !odd_tri;
-				coord_num_sb = coord_num2;// that index will be start of next strip
-			}// for(int32_t vc = 2; vc < *vc_it; vc++)
-		}// for(std::list<int32_t>::const_iterator vc_it = ne_alias.VertexCount.begin(); vc_it != ne_alias.VertexCount.end(); vc_it++)
-        // check for child nodes
-        if(!mReader->isEmptyElement())
-        {
-			ParseHelper_Node_Enter(ne);
-			MACRO_NODECHECK_LOOPBEGIN("TriangleStripSet");
-				// check for X3DComposedGeometryNodes
-				if(XML_CheckNode_NameEqual("Color")) { ParseNode_Rendering_Color(); continue; }
-				if(XML_CheckNode_NameEqual("ColorRGBA")) { ParseNode_Rendering_ColorRGBA(); continue; }
-				if(XML_CheckNode_NameEqual("Coordinate")) { ParseNode_Rendering_Coordinate(); continue; }
-				if(XML_CheckNode_NameEqual("Normal")) { ParseNode_Rendering_Normal(); continue; }
-				if(XML_CheckNode_NameEqual("TextureCoordinate")) { ParseNode_Texturing_TextureCoordinate(); continue; }
-				// check for X3DMetadataObject
-				if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("TriangleStripSet");
-
-			MACRO_NODECHECK_LOOPEND("TriangleStripSet");
-			ParseHelper_Node_Exit();
-		}// if(!mReader->isEmptyElement())
-		else
-		{
-			mNodeElementCur->Child.push_back(ne);// add made object as child to current element
-		}
-
-		NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
-	}// if(!use.empty()) else
-}
-
-// <Normal
-// DEF=""      ID
-// USE=""      IDREF
-// vector=""   MFVec3f [inputOutput]
-// />
-void X3DImporter::ParseNode_Rendering_Normal()
-{
-std::string use, def;
-std::list<aiVector3D> vector;
-X3DNodeElementBase* ne;
-
-	MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
-		MACRO_ATTRREAD_CHECK_REF("vector", vector, XML_ReadNode_GetAttrVal_AsListVec3f);
-	MACRO_ATTRREAD_LOOPEND;
-
-	// if "USE" defined then find already defined element.
-	if(!use.empty())
-	{
-		MACRO_USE_CHECKANDAPPLY(def, use, ENET_Normal, ne);
-	}
-	else
-	{
-		// create and if needed - define new geometry object.
-		ne = new X3DNormal(mNodeElementCur);
-		if(!def.empty()) ne->ID = def;
-
-		((X3DNormal*)ne)->Value = vector;
-		// check for X3DMetadataObject childs.
-		if(!mReader->isEmptyElement())
-			ParseNode_Metadata(ne, "Normal");
-		else
-			mNodeElementCur->Child.push_back(ne);// add made object as child to current element
-
-		NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
-	}// if(!use.empty()) else
-}
-
-}// namespace Assimp
-
-#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER

+ 0 - 250
code/AssetLib/X3D/X3DImporter_Shape.cpp

@@ -1,250 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2020, 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_Shape.cpp
-/// \brief  Parsing data from nodes of "Shape" set of X3D.
-/// \date   2015-2016
-/// \author [email protected]
-
-#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
-
-#include "X3DImporter.hpp"
-#include "X3DImporter_Macro.hpp"
-
-namespace Assimp
-{
-
-// <Shape
-// DEF=""              ID
-// USE=""              IDREF
-// bboxCenter="0 0 0"  SFVec3f [initializeOnly]
-// bboxSize="-1 -1 -1" SFVec3f [initializeOnly]
-// >
-//    <!-- ShapeChildContentModel -->
-// "ShapeChildContentModel is the child-node content model corresponding to X3DShapeNode. ShapeChildContentModel can contain a single Appearance node and a
-// single geometry node, in any order.
-// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model."
-// </Shape>
-// A Shape node is unlit if either of the following is true:
-//     The shape's appearance field is nullptr (default).
-//     The material field in the Appearance node is nullptr (default).
-// NOTE Geometry nodes that represent lines or points do not support lighting.
-void X3DImporter::ParseNode_Shape_Shape()
-{
-    std::string use, def;
-    X3DNodeElementBase* ne( nullptr );
-
-	MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
-	MACRO_ATTRREAD_LOOPEND;
-
-	// if "USE" defined then find already defined element.
-	if(!use.empty())
-	{
-		MACRO_USE_CHECKANDAPPLY(def, use, ENET_Shape, ne);
-	}
-	else
-	{
-		// create and if needed - define new geometry object.
-		ne = new X3DShape(mNodeElementCur);
-		if(!def.empty()) ne->ID = def;
-
-        // check for child nodes
-        if(!mReader->isEmptyElement())
-        {
-			ParseHelper_Node_Enter(ne);
-			MACRO_NODECHECK_LOOPBEGIN("Shape");
-				// check for appearance node
-				if(XML_CheckNode_NameEqual("Appearance")) { ParseNode_Shape_Appearance(); continue; }
-				// check for X3DGeometryNodes
-				if(XML_CheckNode_NameEqual("Arc2D")) { ParseNode_Geometry2D_Arc2D(); continue; }
-				if(XML_CheckNode_NameEqual("ArcClose2D")) { ParseNode_Geometry2D_ArcClose2D(); continue; }
-				if(XML_CheckNode_NameEqual("Circle2D")) { ParseNode_Geometry2D_Circle2D(); continue; }
-				if(XML_CheckNode_NameEqual("Disk2D")) { ParseNode_Geometry2D_Disk2D(); continue; }
-				if(XML_CheckNode_NameEqual("Polyline2D")) { ParseNode_Geometry2D_Polyline2D(); continue; }
-				if(XML_CheckNode_NameEqual("Polypoint2D")) { ParseNode_Geometry2D_Polypoint2D(); continue; }
-				if(XML_CheckNode_NameEqual("Rectangle2D")) { ParseNode_Geometry2D_Rectangle2D(); continue; }
-				if(XML_CheckNode_NameEqual("TriangleSet2D")) { ParseNode_Geometry2D_TriangleSet2D(); continue; }
-				if(XML_CheckNode_NameEqual("Box")) { ParseNode_Geometry3D_Box(); continue; }
-				if(XML_CheckNode_NameEqual("Cone")) { ParseNode_Geometry3D_Cone(); continue; }
-				if(XML_CheckNode_NameEqual("Cylinder")) { ParseNode_Geometry3D_Cylinder(); continue; }
-				if(XML_CheckNode_NameEqual("ElevationGrid")) { ParseNode_Geometry3D_ElevationGrid(); continue; }
-				if(XML_CheckNode_NameEqual("Extrusion")) { ParseNode_Geometry3D_Extrusion(); continue; }
-				if(XML_CheckNode_NameEqual("IndexedFaceSet")) { ParseNode_Geometry3D_IndexedFaceSet(); continue; }
-				if(XML_CheckNode_NameEqual("Sphere")) { ParseNode_Geometry3D_Sphere(); continue; }
-				if(XML_CheckNode_NameEqual("IndexedLineSet")) { ParseNode_Rendering_IndexedLineSet(); continue; }
-				if(XML_CheckNode_NameEqual("LineSet")) { ParseNode_Rendering_LineSet(); continue; }
-				if(XML_CheckNode_NameEqual("PointSet")) { ParseNode_Rendering_PointSet(); continue; }
-				if(XML_CheckNode_NameEqual("IndexedTriangleFanSet")) { ParseNode_Rendering_IndexedTriangleFanSet(); continue; }
-				if(XML_CheckNode_NameEqual("IndexedTriangleSet")) { ParseNode_Rendering_IndexedTriangleSet(); continue; }
-				if(XML_CheckNode_NameEqual("IndexedTriangleStripSet")) { ParseNode_Rendering_IndexedTriangleStripSet(); continue; }
-				if(XML_CheckNode_NameEqual("TriangleFanSet")) { ParseNode_Rendering_TriangleFanSet(); continue; }
-				if(XML_CheckNode_NameEqual("TriangleSet")) { ParseNode_Rendering_TriangleSet(); continue; }
-				if(XML_CheckNode_NameEqual("TriangleStripSet")) { ParseNode_Rendering_TriangleStripSet(); continue; }
-				// check for X3DMetadataObject
-				if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("Shape");
-
-			MACRO_NODECHECK_LOOPEND("Shape");
-			ParseHelper_Node_Exit();
-		}// if(!mReader->isEmptyElement())
-		else
-		{
-			mNodeElementCur->Child.push_back(ne);// add made object as child to current element
-		}
-
-		NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
-	}// if(!use.empty()) else
-}
-
-// <Appearance
-// DEF="" ID
-// USE="" IDREF
-// >
-// <!-- AppearanceChildContentModel -->
-// "Child-node content model corresponding to X3DAppearanceChildNode. Appearance can contain FillProperties, LineProperties, Material, any Texture node and
-// any TextureTransform node, in any order. No more than one instance of these nodes is allowed. Appearance may also contain multiple shaders (ComposedShader,
-// PackagedShader, ProgramShader).
-// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model."
-// </Appearance>
-void X3DImporter::ParseNode_Shape_Appearance()
-{
-    std::string use, def;
-    X3DNodeElementBase* ne( nullptr );
-
-	MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
-	MACRO_ATTRREAD_LOOPEND;
-
-	// if "USE" defined then find already defined element.
-	if(!use.empty())
-	{
-		MACRO_USE_CHECKANDAPPLY(def, use, ENET_Appearance, ne);
-	}
-	else
-	{
-		// create and if needed - define new geometry object.
-		ne = new X3DAppearance(mNodeElementCur);
-		if(!def.empty()) ne->ID = def;
-
-        // check for child nodes
-        if(!mReader->isEmptyElement())
-        {
-			ParseHelper_Node_Enter(ne);
-			MACRO_NODECHECK_LOOPBEGIN("Appearance");
-				if(XML_CheckNode_NameEqual("Material")) { ParseNode_Shape_Material(); continue; }
-				if(XML_CheckNode_NameEqual("ImageTexture")) { ParseNode_Texturing_ImageTexture(); continue; }
-				if(XML_CheckNode_NameEqual("TextureTransform")) { ParseNode_Texturing_TextureTransform(); continue; }
-				// check for X3DMetadataObject
-				if(!ParseHelper_CheckRead_X3DMetadataObject()) XML_CheckNode_SkipUnsupported("Appearance");
-
-			MACRO_NODECHECK_LOOPEND("Appearance");
-			ParseHelper_Node_Exit();
-		}// if(!mReader->isEmptyElement())
-		else
-		{
-			mNodeElementCur->Child.push_back(ne);// add made object as child to current element
-		}
-
-		NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
-	}// if(!use.empty()) else
-}
-
-// <Material
-// DEF=""                     ID
-// USE=""                     IDREF
-// ambientIntensity="0.2"     SFFloat [inputOutput]
-// diffuseColor="0.8 0.8 0.8" SFColor [inputOutput]
-// emissiveColor="0 0 0"      SFColor [inputOutput]
-// shininess="0.2"            SFFloat [inputOutput]
-// specularColor="0 0 0"      SFColor [inputOutput]
-// transparency="0"           SFFloat [inputOutput]
-// />
-void X3DImporter::ParseNode_Shape_Material()
-{
-    std::string use, def;
-    float ambientIntensity = 0.2f;
-    float shininess = 0.2f;
-    float transparency = 0;
-    aiColor3D diffuseColor(0.8f, 0.8f, 0.8f);
-    aiColor3D emissiveColor(0, 0, 0);
-    aiColor3D specularColor(0, 0, 0);
-    X3DNodeElementBase* ne( nullptr );
-
-	MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
-		MACRO_ATTRREAD_CHECK_RET("ambientIntensity", ambientIntensity, XML_ReadNode_GetAttrVal_AsFloat);
-		MACRO_ATTRREAD_CHECK_RET("shininess", shininess, XML_ReadNode_GetAttrVal_AsFloat);
-		MACRO_ATTRREAD_CHECK_RET("transparency", transparency, XML_ReadNode_GetAttrVal_AsFloat);
-		MACRO_ATTRREAD_CHECK_REF("diffuseColor", diffuseColor, XML_ReadNode_GetAttrVal_AsCol3f);
-		MACRO_ATTRREAD_CHECK_REF("emissiveColor", emissiveColor, XML_ReadNode_GetAttrVal_AsCol3f);
-		MACRO_ATTRREAD_CHECK_REF("specularColor", specularColor, XML_ReadNode_GetAttrVal_AsCol3f);
-	MACRO_ATTRREAD_LOOPEND;
-
-	// if "USE" defined then find already defined element.
-	if(!use.empty())
-	{
-		MACRO_USE_CHECKANDAPPLY(def, use, ENET_Material, ne);
-	}
-	else
-	{
-		// create and if needed - define new geometry object.
-		ne = new X3DMaterial(mNodeElementCur);
-		if(!def.empty()) ne->ID = def;
-
-		((X3DMaterial*)ne)->AmbientIntensity = ambientIntensity;
-		((X3DMaterial*)ne)->Shininess = shininess;
-		((X3DMaterial*)ne)->Transparency = transparency;
-		((X3DMaterial*)ne)->DiffuseColor = diffuseColor;
-		((X3DMaterial*)ne)->EmissiveColor = emissiveColor;
-		((X3DMaterial*)ne)->SpecularColor = specularColor;
-        // check for child nodes
-		if(!mReader->isEmptyElement())
-			ParseNode_Metadata(ne, "Material");
-		else
-			mNodeElementCur->Child.push_back(ne);// add made object as child to current element
-
-		NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
-	}// if(!use.empty()) else
-}
-
-}// namespace Assimp
-
-#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER

+ 0 - 197
code/AssetLib/X3D/X3DImporter_Texturing.cpp

@@ -1,197 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2020, 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_Texturing.cpp
-/// \brief  Parsing data from nodes of "Texturing" set of X3D.
-/// \date   2015-2016
-/// \author [email protected]
-
-#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
-
-#include "X3DImporter.hpp"
-#include "X3DImporter_Macro.hpp"
-
-namespace Assimp
-{
-
-// <ImageTexture
-// DEF=""         ID
-// USE=""         IDREF
-// repeatS="true" SFBool
-// repeatT="true" SFBool
-// url=""         MFString
-// />
-// When the url field contains no values ([]), texturing is disabled.
-void X3DImporter::ParseNode_Texturing_ImageTexture()
-{
-    std::string use, def;
-    bool repeatS = true;
-    bool repeatT = true;
-    std::list<std::string> url;
-    X3DNodeElementBase* ne( nullptr );
-
-	MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
-		MACRO_ATTRREAD_CHECK_RET("repeatS", repeatS, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_RET("repeatT", repeatT, XML_ReadNode_GetAttrVal_AsBool);
-		MACRO_ATTRREAD_CHECK_REF("url", url, XML_ReadNode_GetAttrVal_AsListS);
-	MACRO_ATTRREAD_LOOPEND;
-
-	// if "USE" defined then find already defined element.
-	if(!use.empty())
-	{
-		MACRO_USE_CHECKANDAPPLY(def, use, ENET_ImageTexture, ne);
-	}
-	else
-	{
-		// create and if needed - define new geometry object.
-		ne = new X3DImageTexture(mNodeElementCur);
-		if(!def.empty()) ne->ID = def;
-
-		((X3DImageTexture*)ne)->RepeatS = repeatS;
-		((X3DImageTexture*)ne)->RepeatT = repeatT;
-		// Attribute "url" can contain list of strings. But we need only one - first.
-		if(!url.empty())
-			((X3DImageTexture*)ne)->URL = url.front();
-		else
-			((X3DImageTexture*)ne)->URL = "";
-
-		// check for X3DMetadataObject childs.
-		if(!mReader->isEmptyElement())
-			ParseNode_Metadata(ne, "ImageTexture");
-		else
-			mNodeElementCur->Child.push_back(ne);// add made object as child to current element
-
-		NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
-	}// if(!use.empty()) else
-}
-
-// <TextureCoordinate
-// DEF=""      ID
-// USE=""      IDREF
-// point=""    MFVec3f [inputOutput]
-// />
-void X3DImporter::ParseNode_Texturing_TextureCoordinate()
-{
-    std::string use, def;
-    std::list<aiVector2D> point;
-    X3DNodeElementBase* ne( nullptr );
-
-	MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
-		MACRO_ATTRREAD_CHECK_REF("point", point, XML_ReadNode_GetAttrVal_AsListVec2f);
-	MACRO_ATTRREAD_LOOPEND;
-
-	// if "USE" defined then find already defined element.
-	if(!use.empty())
-	{
-		MACRO_USE_CHECKANDAPPLY(def, use, ENET_TextureCoordinate, ne);
-	}
-	else
-	{
-		// create and if needed - define new geometry object.
-		ne = new X3DTextureCoordinate(mNodeElementCur);
-		if(!def.empty()) ne->ID = def;
-
-		((X3DTextureCoordinate*)ne)->Value = point;
-		// check for X3DMetadataObject childs.
-		if(!mReader->isEmptyElement())
-			ParseNode_Metadata(ne, "TextureCoordinate");
-		else
-			mNodeElementCur->Child.push_back(ne);// add made object as child to current element
-
-		NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
-	}// if(!use.empty()) else
-}
-
-// <TextureTransform
-// DEF=""            ID
-// USE=""            IDREF
-// center="0 0"      SFVec2f [inputOutput]
-// rotation="0"      SFFloat [inputOutput]
-// scale="1 1"       SFVec2f [inputOutput]
-// translation="0 0" SFVec2f [inputOutput]
-// />
-void X3DImporter::ParseNode_Texturing_TextureTransform()
-{
-    std::string use, def;
-    aiVector2D center(0, 0);
-    float rotation = 0;
-    aiVector2D scale(1, 1);
-    aiVector2D translation(0, 0);
-    X3DNodeElementBase* ne( nullptr );
-
-	MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use);
-		MACRO_ATTRREAD_CHECK_REF("center", center, XML_ReadNode_GetAttrVal_AsVec2f);
-		MACRO_ATTRREAD_CHECK_RET("rotation", rotation, XML_ReadNode_GetAttrVal_AsFloat);
-		MACRO_ATTRREAD_CHECK_REF("scale", scale, XML_ReadNode_GetAttrVal_AsVec2f);
-		MACRO_ATTRREAD_CHECK_REF("translation", translation, XML_ReadNode_GetAttrVal_AsVec2f);
-	MACRO_ATTRREAD_LOOPEND;
-
-	// if "USE" defined then find already defined element.
-	if(!use.empty())
-	{
-		MACRO_USE_CHECKANDAPPLY(def, use, ENET_TextureTransform, ne);
-	}
-	else
-	{
-		// create and if needed - define new geometry object.
-		ne = new X3DTextureTransform(mNodeElementCur);
-		if(!def.empty()) ne->ID = def;
-
-		((X3DTextureTransform*)ne)->Center = center;
-		((X3DTextureTransform*)ne)->Rotation = rotation;
-		((X3DTextureTransform*)ne)->Scale = scale;
-		((X3DTextureTransform*)ne)->Translation = translation;
-		// check for X3DMetadataObject childs.
-		if(!mReader->isEmptyElement())
-			ParseNode_Metadata(ne, "TextureTransform");
-		else
-			mNodeElementCur->Child.push_back(ne);// add made object as child to current element
-
-		NodeElement_List.push_back(ne);// add element to node element list because its a new object in graph
-	}// if(!use.empty()) else
-}
-
-}// namespace Assimp
-
-#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER

+ 0 - 1677
code/AssetLib/X3D/X3DVocabulary.cpp

@@ -1,1677 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-Copyright (c) 2006-2020, 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   X3DVocabulary.cpp
-/// \brief  Vocabulary for Fast Infoset encoded binary X3D files.
-/// \date   2017
-/// \author Patrick Daehne
-
-#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
-
-#include "FIReader.hpp"
-
-#include <memory>
-
-namespace Assimp {
-
-static const char *encodingAlgorithmTable_3_2[] = {
-    "encoder://web3d.org/QuantizedFloatArrayEncoder",
-    "encoder://web3d.org/DeltazlibIntArrayEncoder",
-    "encoder://web3d.org/QuantizedzlibFloatArrayEncoder",
-    "encoder://web3d.org/zlibFloatArrayEncoder",
-    "encoder://web3d.org/QuantizedDoubleArrayEncoder",
-    "encoder://web3d.org/zlibDoubleArrayEncoder",
-    "encoder://web3d.org/QuantizedzlibDoubleArrayEncoder",
-    "encoder://web3d.org/RangeIntArrayEncoder"
-};
-
-static const std::shared_ptr<const FIValue> attributeValueTable_3_2[] = {
-    FIStringValue::create("false"),
-    FIStringValue::create("true")
-};
-
-static const FIQName elementNameTable_3_2[] = {
-    { "Shape", nullptr, nullptr },
-    { "Appearance", nullptr, nullptr },
-    { "Material", nullptr, nullptr },
-    { "IndexedFaceSet", nullptr, nullptr },
-    { "ProtoInstance", nullptr, nullptr },
-    { "Transform", nullptr, nullptr },
-    { "ImageTexture", nullptr, nullptr },
-    { "TextureTransform", nullptr, nullptr },
-    { "Coordinate", nullptr, nullptr },
-    { "Normal", nullptr, nullptr },
-    { "Color", nullptr, nullptr },
-    { "ColorRGBA", nullptr, nullptr },
-    { "TextureCoordinate", nullptr, nullptr },
-    { "ROUTE", nullptr, nullptr },
-    { "fieldValue", nullptr, nullptr },
-    { "Group", nullptr, nullptr },
-    { "LOD", nullptr, nullptr },
-    { "Switch", nullptr, nullptr },
-    { "Script", nullptr, nullptr },
-    { "IndexedTriangleFanSet", nullptr, nullptr },
-    { "IndexedTriangleSet", nullptr, nullptr },
-    { "IndexedTriangleStripSet", nullptr, nullptr },
-    { "MultiTexture", nullptr, nullptr },
-    { "MultiTextureCoordinate", nullptr, nullptr },
-    { "MultiTextureTransform", nullptr, nullptr },
-    { "IndexedLineSet", nullptr, nullptr },
-    { "PointSet", nullptr, nullptr },
-    { "StaticGroup", nullptr, nullptr },
-    { "Sphere", nullptr, nullptr },
-    { "Box", nullptr, nullptr },
-    { "Cone", nullptr, nullptr },
-    { "Anchor", nullptr, nullptr },
-    { "Arc2D", nullptr, nullptr },
-    { "ArcClose2D", nullptr, nullptr },
-    { "AudioClip", nullptr, nullptr },
-    { "Background", nullptr, nullptr },
-    { "Billboard", nullptr, nullptr },
-    { "BooleanFilter", nullptr, nullptr },
-    { "BooleanSequencer", nullptr, nullptr },
-    { "BooleanToggle", nullptr, nullptr },
-    { "BooleanTrigger", nullptr, nullptr },
-    { "Circle2D", nullptr, nullptr },
-    { "Collision", nullptr, nullptr },
-    { "ColorInterpolator", nullptr, nullptr },
-    { "Contour2D", nullptr, nullptr },
-    { "ContourPolyline2D", nullptr, nullptr },
-    { "CoordinateDouble", nullptr, nullptr },
-    { "CoordinateInterpolator", nullptr, nullptr },
-    { "CoordinateInterpolator2D", nullptr, nullptr },
-    { "Cylinder", nullptr, nullptr },
-    { "CylinderSensor", nullptr, nullptr },
-    { "DirectionalLight", nullptr, nullptr },
-    { "Disk2D", nullptr, nullptr },
-    { "EXPORT", nullptr, nullptr },
-    { "ElevationGrid", nullptr, nullptr },
-    { "EspduTransform", nullptr, nullptr },
-    { "ExternProtoDeclare", nullptr, nullptr },
-    { "Extrusion", nullptr, nullptr },
-    { "FillProperties", nullptr, nullptr },
-    { "Fog", nullptr, nullptr },
-    { "FontStyle", nullptr, nullptr },
-    { "GeoCoordinate", nullptr, nullptr },
-    { "GeoElevationGrid", nullptr, nullptr },
-    { "GeoLOD", nullptr, nullptr },
-    { "GeoLocation", nullptr, nullptr },
-    { "GeoMetadata", nullptr, nullptr },
-    { "GeoOrigin", nullptr, nullptr },
-    { "GeoPositionInterpolator", nullptr, nullptr },
-    { "GeoTouchSensor", nullptr, nullptr },
-    { "GeoViewpoint", nullptr, nullptr },
-    { "HAnimDisplacer", nullptr, nullptr },
-    { "HAnimHumanoid", nullptr, nullptr },
-    { "HAnimJoint", nullptr, nullptr },
-    { "HAnimSegment", nullptr, nullptr },
-    { "HAnimSite", nullptr, nullptr },
-    { "IMPORT", nullptr, nullptr },
-    { "IS", nullptr, nullptr },
-    { "Inline", nullptr, nullptr },
-    { "IntegerSequencer", nullptr, nullptr },
-    { "IntegerTrigger", nullptr, nullptr },
-    { "KeySensor", nullptr, nullptr },
-    { "LineProperties", nullptr, nullptr },
-    { "LineSet", nullptr, nullptr },
-    { "LoadSensor", nullptr, nullptr },
-    { "MetadataDouble", nullptr, nullptr },
-    { "MetadataFloat", nullptr, nullptr },
-    { "MetadataInteger", nullptr, nullptr },
-    { "MetadataSet", nullptr, nullptr },
-    { "MetadataString", nullptr, nullptr },
-    { "MovieTexture", nullptr, nullptr },
-    { "NavigationInfo", nullptr, nullptr },
-    { "NormalInterpolator", nullptr, nullptr },
-    { "NurbsCurve", nullptr, nullptr },
-    { "NurbsCurve2D", nullptr, nullptr },
-    { "NurbsOrientationInterpolator", nullptr, nullptr },
-    { "NurbsPatchSurface", nullptr, nullptr },
-    { "NurbsPositionInterpolator", nullptr, nullptr },
-    { "NurbsSet", nullptr, nullptr },
-    { "NurbsSurfaceInterpolator", nullptr, nullptr },
-    { "NurbsSweptSurface", nullptr, nullptr },
-    { "NurbsSwungSurface", nullptr, nullptr },
-    { "NurbsTextureCoordinate", nullptr, nullptr },
-    { "NurbsTrimmedSurface", nullptr, nullptr },
-    { "OrientationInterpolator", nullptr, nullptr },
-    { "PixelTexture", nullptr, nullptr },
-    { "PlaneSensor", nullptr, nullptr },
-    { "PointLight", nullptr, nullptr },
-    { "Polyline2D", nullptr, nullptr },
-    { "Polypoint2D", nullptr, nullptr },
-    { "PositionInterpolator", nullptr, nullptr },
-    { "PositionInterpolator2D", nullptr, nullptr },
-    { "ProtoBody", nullptr, nullptr },
-    { "ProtoDeclare", nullptr, nullptr },
-    { "ProtoInterface", nullptr, nullptr },
-    { "ProximitySensor", nullptr, nullptr },
-    { "ReceiverPdu", nullptr, nullptr },
-    { "Rectangle2D", nullptr, nullptr },
-    { "ScalarInterpolator", nullptr, nullptr },
-    { "Scene", nullptr, nullptr },
-    { "SignalPdu", nullptr, nullptr },
-    { "Sound", nullptr, nullptr },
-    { "SphereSensor", nullptr, nullptr },
-    { "SpotLight", nullptr, nullptr },
-    { "StringSensor", nullptr, nullptr },
-    { "Text", nullptr, nullptr },
-    { "TextureBackground", nullptr, nullptr },
-    { "TextureCoordinateGenerator", nullptr, nullptr },
-    { "TimeSensor", nullptr, nullptr },
-    { "TimeTrigger", nullptr, nullptr },
-    { "TouchSensor", nullptr, nullptr },
-    { "TransmitterPdu", nullptr, nullptr },
-    { "TriangleFanSet", nullptr, nullptr },
-    { "TriangleSet", nullptr, nullptr },
-    { "TriangleSet2D", nullptr, nullptr },
-    { "TriangleStripSet", nullptr, nullptr },
-    { "Viewpoint", nullptr, nullptr },
-    { "VisibilitySensor", nullptr, nullptr },
-    { "WorldInfo", nullptr, nullptr },
-    { "X3D", nullptr, nullptr },
-    { "component", nullptr, nullptr },
-    { "connect", nullptr, nullptr },
-    { "field", nullptr, nullptr },
-    { "head", nullptr, nullptr },
-    { "humanoidBodyType", nullptr, nullptr },
-    { "meta", nullptr, nullptr },
-    { "CADAssembly", nullptr, nullptr },
-    { "CADFace", nullptr, nullptr },
-    { "CADLayer", nullptr, nullptr },
-    { "CADPart", nullptr, nullptr },
-    { "ComposedCubeMapTexture", nullptr, nullptr },
-    { "ComposedShader", nullptr, nullptr },
-    { "ComposedTexture3D", nullptr, nullptr },
-    { "FloatVertexAttribute", nullptr, nullptr },
-    { "FogCoordinate", nullptr, nullptr },
-    { "GeneratedCubeMapTexture", nullptr, nullptr },
-    { "ImageCubeMapTexture", nullptr, nullptr },
-    { "ImageTexture3D", nullptr, nullptr },
-    { "IndexedQuadSet", nullptr, nullptr },
-    { "LocalFog", nullptr, nullptr },
-    { "Matrix3VertexAttribute", nullptr, nullptr },
-    { "Matrix4VertexAttribute", nullptr, nullptr },
-    { "PackagedShader", nullptr, nullptr },
-    { "PixelTexture3D", nullptr, nullptr },
-    { "ProgramShader", nullptr, nullptr },
-    { "QuadSet", nullptr, nullptr },
-    { "ShaderPart", nullptr, nullptr },
-    { "ShaderProgram", nullptr, nullptr },
-    { "TextureCoordinate3D", nullptr, nullptr },
-    { "TextureCoordinate4D", nullptr, nullptr },
-    { "TextureTransform3D", nullptr, nullptr },
-    { "TextureTransformMatrix3D", nullptr, nullptr },
-    { "BallJoint", nullptr, nullptr },
-    { "BoundedPhysicsModel", nullptr, nullptr },
-    { "ClipPlane", nullptr, nullptr },
-    { "CollidableOffset", nullptr, nullptr },
-    { "CollidableShape", nullptr, nullptr },
-    { "CollisionCollection", nullptr, nullptr },
-    { "CollisionSensor", nullptr, nullptr },
-    { "CollisionSpace", nullptr, nullptr },
-    { "ColorDamper", nullptr, nullptr },
-    { "ConeEmitter", nullptr, nullptr },
-    { "Contact", nullptr, nullptr },
-    { "CoordinateDamper", nullptr, nullptr },
-    { "DISEntityManager", nullptr, nullptr },
-    { "DISEntityTypeMapping", nullptr, nullptr },
-    { "DoubleAxisHingeJoint", nullptr, nullptr },
-    { "EaseInEaseOut", nullptr, nullptr },
-    { "ExplosionEmitter", nullptr, nullptr },
-    { "ForcePhysicsModel", nullptr, nullptr },
-    { "GeoProximitySensor", nullptr, nullptr },
-    { "GeoTransform", nullptr, nullptr },
-    { "Layer", nullptr, nullptr },
-    { "LayerSet", nullptr, nullptr },
-    { "Layout", nullptr, nullptr },
-    { "LayoutGroup", nullptr, nullptr },
-    { "LayoutLayer", nullptr, nullptr },
-    { "LinePickSensor", nullptr, nullptr },
-    { "MotorJoint", nullptr, nullptr },
-    { "OrientationChaser", nullptr, nullptr },
-    { "OrientationDamper", nullptr, nullptr },
-    { "OrthoViewpoint", nullptr, nullptr },
-    { "ParticleSystem", nullptr, nullptr },
-    { "PickableGroup", nullptr, nullptr },
-    { "PointEmitter", nullptr, nullptr },
-    { "PointPickSensor", nullptr, nullptr },
-    { "PolylineEmitter", nullptr, nullptr },
-    { "PositionChaser", nullptr, nullptr },
-    { "PositionChaser2D", nullptr, nullptr },
-    { "PositionDamper", nullptr, nullptr },
-    { "PositionDamper2D", nullptr, nullptr },
-    { "PrimitivePickSensor", nullptr, nullptr },
-    { "RigidBody", nullptr, nullptr },
-    { "RigidBodyCollection", nullptr, nullptr },
-    { "ScalarChaser", nullptr, nullptr },
-    { "ScreenFontStyle", nullptr, nullptr },
-    { "ScreenGroup", nullptr, nullptr },
-    { "SingleAxisHingeJoint", nullptr, nullptr },
-    { "SliderJoint", nullptr, nullptr },
-    { "SplinePositionInterpolator", nullptr, nullptr },
-    { "SplinePositionInterpolator2D", nullptr, nullptr },
-    { "SplineScalarInterpolator", nullptr, nullptr },
-    { "SquadOrientationInterpolator", nullptr, nullptr },
-    { "SurfaceEmitter", nullptr, nullptr },
-    { "TexCoordDamper", nullptr, nullptr },
-    { "TextureProperties", nullptr, nullptr },
-    { "TransformSensor", nullptr, nullptr },
-    { "TwoSidedMaterial", nullptr, nullptr },
-    { "UniversalJoint", nullptr, nullptr },
-    { "ViewpointGroup", nullptr, nullptr },
-    { "Viewport", nullptr, nullptr },
-    { "VolumeEmitter", nullptr, nullptr },
-    { "VolumePickSensor", nullptr, nullptr },
-    { "WindPhysicsModel", nullptr, nullptr }
-};
-
-static const FIQName attributeNameTable_3_2[] = {
-    { "DEF", nullptr, nullptr },
-    { "USE", nullptr, nullptr },
-    { "containerField", nullptr, nullptr },
-    { "fromNode", nullptr, nullptr },
-    { "fromField", nullptr, nullptr },
-    { "toNode", nullptr, nullptr },
-    { "toField", nullptr, nullptr },
-    { "name", nullptr, nullptr },
-    { "value", nullptr, nullptr },
-    { "color", nullptr, nullptr },
-    { "colorIndex", nullptr, nullptr },
-    { "coordIndex", nullptr, nullptr },
-    { "texCoordIndex", nullptr, nullptr },
-    { "normalIndex", nullptr, nullptr },
-    { "colorPerVertex", nullptr, nullptr },
-    { "normalPerVertex", nullptr, nullptr },
-    { "rotation", nullptr, nullptr },
-    { "scale", nullptr, nullptr },
-    { "center", nullptr, nullptr },
-    { "scaleOrientation", nullptr, nullptr },
-    { "translation", nullptr, nullptr },
-    { "url", nullptr, nullptr },
-    { "repeatS", nullptr, nullptr },
-    { "repeatT", nullptr, nullptr },
-    { "point", nullptr, nullptr },
-    { "vector", nullptr, nullptr },
-    { "range", nullptr, nullptr },
-    { "ambientIntensity", nullptr, nullptr },
-    { "diffuseColor", nullptr, nullptr },
-    { "emissiveColor", nullptr, nullptr },
-    { "shininess", nullptr, nullptr },
-    { "specularColor", nullptr, nullptr },
-    { "transparency", nullptr, nullptr },
-    { "whichChoice", nullptr, nullptr },
-    { "index", nullptr, nullptr },
-    { "mode", nullptr, nullptr },
-    { "source", nullptr, nullptr },
-    { "function", nullptr, nullptr },
-    { "alpha", nullptr, nullptr },
-    { "vertexCount", nullptr, nullptr },
-    { "radius", nullptr, nullptr },
-    { "size", nullptr, nullptr },
-    { "height", nullptr, nullptr },
-    { "solid", nullptr, nullptr },
-    { "ccw", nullptr, nullptr },
-    { "key", nullptr, nullptr },
-    { "keyValue", nullptr, nullptr },
-    { "enabled", nullptr, nullptr },
-    { "direction", nullptr, nullptr },
-    { "position", nullptr, nullptr },
-    { "orientation", nullptr, nullptr },
-    { "bboxCenter", nullptr, nullptr },
-    { "bboxSize", nullptr, nullptr },
-    { "AS", nullptr, nullptr },
-    { "InlineDEF", nullptr, nullptr },
-    { "accessType", nullptr, nullptr },
-    { "actionKeyPress", nullptr, nullptr },
-    { "actionKeyRelease", nullptr, nullptr },
-    { "address", nullptr, nullptr },
-    { "altKey", nullptr, nullptr },
-    { "antennaLocation", nullptr, nullptr },
-    { "antennaPatternLength", nullptr, nullptr },
-    { "antennaPatternType", nullptr, nullptr },
-    { "applicationID", nullptr, nullptr },
-    { "articulationParameterArray", nullptr, nullptr },
-    { "articulationParameterChangeIndicatorArray", nullptr, nullptr },
-    { "articulationParameterCount", nullptr, nullptr },
-    { "articulationParameterDesignatorArray", nullptr, nullptr },
-    { "articulationParameterIdPartAttachedArray", nullptr, nullptr },
-    { "articulationParameterTypeArray", nullptr, nullptr },
-    { "attenuation", nullptr, nullptr },
-    { "autoOffset", nullptr, nullptr },
-    { "avatarSize", nullptr, nullptr },
-    { "axisOfRotation", nullptr, nullptr },
-    { "backUrl", nullptr, nullptr },
-    { "beamWidth", nullptr, nullptr },
-    { "beginCap", nullptr, nullptr },
-    { "bindTime", nullptr, nullptr },
-    { "bottom", nullptr, nullptr },
-    { "bottomRadius", nullptr, nullptr },
-    { "bottomUrl", nullptr, nullptr },
-    { "centerOfMass", nullptr, nullptr },
-    { "centerOfRotation", nullptr, nullptr },
-    { "child1Url", nullptr, nullptr },
-    { "child2Url", nullptr, nullptr },
-    { "child3Url", nullptr, nullptr },
-    { "child4Url", nullptr, nullptr },
-    { "class", nullptr, nullptr },
-    { "closureType", nullptr, nullptr },
-    { "collideTime", nullptr, nullptr },
-    { "content", nullptr, nullptr },
-    { "controlKey", nullptr, nullptr },
-    { "controlPoint", nullptr, nullptr },
-    { "convex", nullptr, nullptr },
-    { "coordinateSystem", nullptr, nullptr },
-    { "copyright", nullptr, nullptr },
-    { "creaseAngle", nullptr, nullptr },
-    { "crossSection", nullptr, nullptr },
-    { "cryptoKeyID", nullptr, nullptr },
-    { "cryptoSystem", nullptr, nullptr },
-    { "cutOffAngle", nullptr, nullptr },
-    { "cycleInterval", nullptr, nullptr },
-    { "cycleTime", nullptr, nullptr },
-    { "data", nullptr, nullptr },
-    { "dataFormat", nullptr, nullptr },
-    { "dataLength", nullptr, nullptr },
-    { "dataUrl", nullptr, nullptr },
-    { "date", nullptr, nullptr },
-    { "deadReckoning", nullptr, nullptr },
-    { "deletionAllowed", nullptr, nullptr },
-    { "description", nullptr, nullptr },
-    { "detonateTime", nullptr, nullptr },
-    { "dir", nullptr, nullptr },
-    { "directOutput", nullptr, nullptr },
-    { "diskAngle", nullptr, nullptr },
-    { "displacements", nullptr, nullptr },
-    { "documentation", nullptr, nullptr },
-    { "elapsedTime", nullptr, nullptr },
-    { "ellipsoid", nullptr, nullptr },
-    { "encodingScheme", nullptr, nullptr },
-    { "endAngle", nullptr, nullptr },
-    { "endCap", nullptr, nullptr },
-    { "enterTime", nullptr, nullptr },
-    { "enteredText", nullptr, nullptr },
-    { "entityCategory", nullptr, nullptr },
-    { "entityCountry", nullptr, nullptr },
-    { "entityDomain", nullptr, nullptr },
-    { "entityExtra", nullptr, nullptr },
-    { "entityID", nullptr, nullptr },
-    { "entityKind", nullptr, nullptr },
-    { "entitySpecific", nullptr, nullptr },
-    { "entitySubCategory", nullptr, nullptr },
-    { "exitTime", nullptr, nullptr },
-    { "extent", nullptr, nullptr },
-    { "family", nullptr, nullptr },
-    { "fanCount", nullptr, nullptr },
-    { "fieldOfView", nullptr, nullptr },
-    { "filled", nullptr, nullptr },
-    { "finalText", nullptr, nullptr },
-    { "fireMissionIndex", nullptr, nullptr },
-    { "fired1", nullptr, nullptr },
-    { "fired2", nullptr, nullptr },
-    { "firedTime", nullptr, nullptr },
-    { "firingRange", nullptr, nullptr },
-    { "firingRate", nullptr, nullptr },
-    { "fogType", nullptr, nullptr },
-    { "forceID", nullptr, nullptr },
-    { "frequency", nullptr, nullptr },
-    { "frontUrl", nullptr, nullptr },
-    { "fuse", nullptr, nullptr },
-    { "geoCoords", nullptr, nullptr },
-    { "geoGridOrigin", nullptr, nullptr },
-    { "geoSystem", nullptr, nullptr },
-    { "groundAngle", nullptr, nullptr },
-    { "groundColor", nullptr, nullptr },
-    { "hatchColor", nullptr, nullptr },
-    { "hatchStyle", nullptr, nullptr },
-    { "hatched", nullptr, nullptr },
-    { "headlight", nullptr, nullptr },
-    { "horizontal", nullptr, nullptr },
-    { "horizontalDatum", nullptr, nullptr },
-    { "http-equiv", nullptr, nullptr },
-    { "image", nullptr, nullptr },
-    { "importedDEF", nullptr, nullptr },
-    { "info", nullptr, nullptr },
-    { "innerRadius", nullptr, nullptr },
-    { "inputFalse", nullptr, nullptr },
-    { "inputNegate", nullptr, nullptr },
-    { "inputSource", nullptr, nullptr },
-    { "inputTrue", nullptr, nullptr },
-    { "integerKey", nullptr, nullptr },
-    { "intensity", nullptr, nullptr },
-    { "jump", nullptr, nullptr },
-    { "justify", nullptr, nullptr },
-    { "keyPress", nullptr, nullptr },
-    { "keyRelease", nullptr, nullptr },
-    { "knot", nullptr, nullptr },
-    { "lang", nullptr, nullptr },
-    { "language", nullptr, nullptr },
-    { "leftToRight", nullptr, nullptr },
-    { "leftUrl", nullptr, nullptr },
-    { "length", nullptr, nullptr },
-    { "lengthOfModulationParameters", nullptr, nullptr },
-    { "level", nullptr, nullptr },
-    { "limitOrientation", nullptr, nullptr },
-    { "lineSegments", nullptr, nullptr },
-    { "linearAcceleration", nullptr, nullptr },
-    { "linearVelocity", nullptr, nullptr },
-    { "linetype", nullptr, nullptr },
-    { "linewidthScaleFactor", nullptr, nullptr },
-    { "llimit", nullptr, nullptr },
-    { "load", nullptr, nullptr },
-    { "loadTime", nullptr, nullptr },
-    { "localDEF", nullptr, nullptr },
-    { "location", nullptr, nullptr },
-    { "loop", nullptr, nullptr },
-    { "marking", nullptr, nullptr },
-    { "mass", nullptr, nullptr },
-    { "maxAngle", nullptr, nullptr },
-    { "maxBack", nullptr, nullptr },
-    { "maxExtent", nullptr, nullptr },
-    { "maxFront", nullptr, nullptr },
-    { "maxPosition", nullptr, nullptr },
-    { "metadataFormat", nullptr, nullptr },
-    { "minAngle", nullptr, nullptr },
-    { "minBack", nullptr, nullptr },
-    { "minFront", nullptr, nullptr },
-    { "minPosition", nullptr, nullptr },
-    { "modulationTypeDetail", nullptr, nullptr },
-    { "modulationTypeMajor", nullptr, nullptr },
-    { "modulationTypeSpreadSpectrum", nullptr, nullptr },
-    { "modulationTypeSystem", nullptr, nullptr },
-    { "momentsOfInertia", nullptr, nullptr },
-    { "multicastRelayHost", nullptr, nullptr },
-    { "multicastRelayPort", nullptr, nullptr },
-    { "munitionApplicationID", nullptr, nullptr },
-    { "munitionEndPoint", nullptr, nullptr },
-    { "munitionEntityID", nullptr, nullptr },
-    { "munitionQuantity", nullptr, nullptr },
-    { "munitionSiteID", nullptr, nullptr },
-    { "munitionStartPoint", nullptr, nullptr },
-    { "mustEvaluate", nullptr, nullptr },
-    { "navType", nullptr, nullptr },
-    { "networkMode", nullptr, nullptr },
-    { "next", nullptr, nullptr },
-    { "nodeField", nullptr, nullptr },
-    { "offset", nullptr, nullptr },
-    { "on", nullptr, nullptr },
-    { "order", nullptr, nullptr },
-    { "originator", nullptr, nullptr },
-    { "outerRadius", nullptr, nullptr },
-    { "parameter", nullptr, nullptr },
-    { "pauseTime", nullptr, nullptr },
-    { "pitch", nullptr, nullptr },
-    { "points", nullptr, nullptr },
-    { "port", nullptr, nullptr },
-    { "power", nullptr, nullptr },
-    { "previous", nullptr, nullptr },
-    { "priority", nullptr, nullptr },
-    { "profile", nullptr, nullptr },
-    { "progress", nullptr, nullptr },
-    { "protoField", nullptr, nullptr },
-    { "radioEntityTypeCategory", nullptr, nullptr },
-    { "radioEntityTypeCountry", nullptr, nullptr },
-    { "radioEntityTypeDomain", nullptr, nullptr },
-    { "radioEntityTypeKind", nullptr, nullptr },
-    { "radioEntityTypeNomenclature", nullptr, nullptr },
-    { "radioEntityTypeNomenclatureVersion", nullptr, nullptr },
-    { "radioID", nullptr, nullptr },
-    { "readInterval", nullptr, nullptr },
-    { "receivedPower", nullptr, nullptr },
-    { "receiverState", nullptr, nullptr },
-    { "reference", nullptr, nullptr },
-    { "relativeAntennaLocation", nullptr, nullptr },
-    { "resolution", nullptr, nullptr },
-    { "resumeTime", nullptr, nullptr },
-    { "rightUrl", nullptr, nullptr },
-    { "rootUrl", nullptr, nullptr },
-    { "rotateYUp", nullptr, nullptr },
-    { "rtpHeaderExpected", nullptr, nullptr },
-    { "sampleRate", nullptr, nullptr },
-    { "samples", nullptr, nullptr },
-    { "shiftKey", nullptr, nullptr },
-    { "side", nullptr, nullptr },
-    { "siteID", nullptr, nullptr },
-    { "skinCoordIndex", nullptr, nullptr },
-    { "skinCoordWeight", nullptr, nullptr },
-    { "skyAngle", nullptr, nullptr },
-    { "skyColor", nullptr, nullptr },
-    { "spacing", nullptr, nullptr },
-    { "spatialize", nullptr, nullptr },
-    { "speed", nullptr, nullptr },
-    { "speedFactor", nullptr, nullptr },
-    { "spine", nullptr, nullptr },
-    { "startAngle", nullptr, nullptr },
-    { "startTime", nullptr, nullptr },
-    { "stiffness", nullptr, nullptr },
-    { "stopTime", nullptr, nullptr },
-    { "string", nullptr, nullptr },
-    { "stripCount", nullptr, nullptr },
-    { "style", nullptr, nullptr },
-    { "summary", nullptr, nullptr },
-    { "tdlType", nullptr, nullptr },
-    { "tessellation", nullptr, nullptr },
-    { "tessellationScale", nullptr, nullptr },
-    { "time", nullptr, nullptr },
-    { "timeOut", nullptr, nullptr },
-    { "timestamp", nullptr, nullptr },
-    { "title", nullptr, nullptr },
-    { "toggle", nullptr, nullptr },
-    { "top", nullptr, nullptr },
-    { "topToBottom", nullptr, nullptr },
-    { "topUrl", nullptr, nullptr },
-    { "touchTime", nullptr, nullptr },
-    { "transmitFrequencyBandwidth", nullptr, nullptr },
-    { "transmitState", nullptr, nullptr },
-    { "transmitterApplicationID", nullptr, nullptr },
-    { "transmitterEntityID", nullptr, nullptr },
-    { "transmitterRadioID", nullptr, nullptr },
-    { "transmitterSiteID", nullptr, nullptr },
-    { "transparent", nullptr, nullptr },
-    { "triggerTime", nullptr, nullptr },
-    { "triggerTrue", nullptr, nullptr },
-    { "triggerValue", nullptr, nullptr },
-    { "type", nullptr, nullptr },
-    { "uDimension", nullptr, nullptr },
-    { "uKnot", nullptr, nullptr },
-    { "uOrder", nullptr, nullptr },
-    { "uTessellation", nullptr, nullptr },
-    { "ulimit", nullptr, nullptr },
-    { "vDimension", nullptr, nullptr },
-    { "vKnot", nullptr, nullptr },
-    { "vOrder", nullptr, nullptr },
-    { "vTessellation", nullptr, nullptr },
-    { "version", nullptr, nullptr },
-    { "verticalDatum", nullptr, nullptr },
-    { "vertices", nullptr, nullptr },
-    { "visibilityLimit", nullptr, nullptr },
-    { "visibilityRange", nullptr, nullptr },
-    { "warhead", nullptr, nullptr },
-    { "weight", nullptr, nullptr },
-    { "whichGeometry", nullptr, nullptr },
-    { "writeInterval", nullptr, nullptr },
-    { "xDimension", nullptr, nullptr },
-    { "xSpacing", nullptr, nullptr },
-    { "yScale", nullptr, nullptr },
-    { "zDimension", nullptr, nullptr },
-    { "zSpacing", nullptr, nullptr },
-    { "visible", nullptr, nullptr },
-    { "repeatR", nullptr, nullptr },
-    { "texture", nullptr, nullptr },
-    { "back", nullptr, nullptr },
-    { "front", nullptr, nullptr },
-    { "left", nullptr, nullptr },
-    { "right", nullptr, nullptr },
-    { "parts", nullptr, nullptr },
-    { "isSelected", nullptr, nullptr },
-    { "isValid", nullptr, nullptr },
-    { "numComponents", nullptr, nullptr },
-    { "depth", nullptr, nullptr },
-    { "update", nullptr, nullptr },
-    { "fogCoord", nullptr, nullptr },
-    { "texCoord", nullptr, nullptr },
-    { "activate", nullptr, nullptr },
-    { "programs", nullptr, nullptr },
-    { "matrix", nullptr, nullptr },
-    { "anchorPoint", nullptr, nullptr },
-    { "body1", nullptr, nullptr },
-    { "body2", nullptr, nullptr },
-    { "mustOutput", nullptr, nullptr },
-    { "body1AnchorPoint", nullptr, nullptr },
-    { "body2AnchorPoint", nullptr, nullptr },
-    { "plane", nullptr, nullptr },
-    { "appliedParameters", nullptr, nullptr },
-    { "bounce", nullptr, nullptr },
-    { "frictionCoefficients", nullptr, nullptr },
-    { "minBounceSpeed", nullptr, nullptr },
-    { "slipFactors", nullptr, nullptr },
-    { "softnessConstantForceMix", nullptr, nullptr },
-    { "softnessErrorCorrection", nullptr, nullptr },
-    { "surfaceSpeed", nullptr, nullptr },
-    { "isActive", nullptr, nullptr },
-    { "useGeometry", nullptr, nullptr },
-    { "set_destination", nullptr, nullptr },
-    { "set_value", nullptr, nullptr },
-    { "tau", nullptr, nullptr },
-    { "tolerance", nullptr, nullptr },
-    { "value_changed", nullptr, nullptr },
-    { "initialDestination", nullptr, nullptr },
-    { "initialValue", nullptr, nullptr },
-    { "angle", nullptr, nullptr },
-    { "variation", nullptr, nullptr },
-    { "surfaceArea", nullptr, nullptr },
-    { "frictionDirection", nullptr, nullptr },
-    { "slipCoefficients", nullptr, nullptr },
-    { "category", nullptr, nullptr },
-    { "country", nullptr, nullptr },
-    { "domain", nullptr, nullptr },
-    { "extra", nullptr, nullptr },
-    { "kind", nullptr, nullptr },
-    { "specific", nullptr, nullptr },
-    { "subcategory", nullptr, nullptr },
-    { "axis1", nullptr, nullptr },
-    { "axis2", nullptr, nullptr },
-    { "desiredAngularVelocity1", nullptr, nullptr },
-    { "desiredAngularVelocity2", nullptr, nullptr },
-    { "maxAngle1", nullptr, nullptr },
-    { "maxTorque1", nullptr, nullptr },
-    { "maxTorque2", nullptr, nullptr },
-    { "minAngle1", nullptr, nullptr },
-    { "stopBounce1", nullptr, nullptr },
-    { "stopConstantForceMix1", nullptr, nullptr },
-    { "stopErrorCorrection1", nullptr, nullptr },
-    { "suspensionErrorCorrection", nullptr, nullptr },
-    { "suspensionForce", nullptr, nullptr },
-    { "body1Axis", nullptr, nullptr },
-    { "body2Axis", nullptr, nullptr },
-    { "hinge1Angle", nullptr, nullptr },
-    { "hinge1AngleRate", nullptr, nullptr },
-    { "hinge2Angle", nullptr, nullptr },
-    { "hinge2AngleRate", nullptr, nullptr },
-    { "set_fraction", nullptr, nullptr },
-    { "easeInEaseOut", nullptr, nullptr },
-    { "modifiedFraction_changed", nullptr, nullptr },
-    { "force", nullptr, nullptr },
-    { "geoCenter", nullptr, nullptr },
-    { "centerOfRotation_changed", nullptr, nullptr },
-    { "geoCoord_changed", nullptr, nullptr },
-    { "orientation_changed", nullptr, nullptr },
-    { "position_changed", nullptr, nullptr },
-    { "isPickable", nullptr, nullptr },
-    { "viewport", nullptr, nullptr },
-    { "activeLayer", nullptr, nullptr },
-    { "align", nullptr, nullptr },
-    { "offsetUnits", nullptr, nullptr },
-    { "scaleMode", nullptr, nullptr },
-    { "sizeUnits", nullptr, nullptr },
-    { "layout", nullptr, nullptr },
-    { "objectType", nullptr, nullptr },
-    { "pickedNormal", nullptr, nullptr },
-    { "pickedPoint", nullptr, nullptr },
-    { "pickedTextureCoordinate", nullptr, nullptr },
-    { "intersectionType", nullptr, nullptr },
-    { "sortOrder", nullptr, nullptr },
-    { "axis1Angle", nullptr, nullptr },
-    { "axis1Torque", nullptr, nullptr },
-    { "axis2Angle", nullptr, nullptr },
-    { "axis2Torque", nullptr, nullptr },
-    { "axis3Angle", nullptr, nullptr },
-    { "axis3Torque", nullptr, nullptr },
-    { "enabledAxies", nullptr, nullptr },
-    { "motor1Axis", nullptr, nullptr },
-    { "motor2Axis", nullptr, nullptr },
-    { "motor3Axis", nullptr, nullptr },
-    { "stop1Bounce", nullptr, nullptr },
-    { "stop1ErrorCorrection", nullptr, nullptr },
-    { "stop2Bounce", nullptr, nullptr },
-    { "stop2ErrorCorrection", nullptr, nullptr },
-    { "stop3Bounce", nullptr, nullptr },
-    { "stop3ErrorCorrection", nullptr, nullptr },
-    { "motor1Angle", nullptr, nullptr },
-    { "motor1AngleRate", nullptr, nullptr },
-    { "motor2Angle", nullptr, nullptr },
-    { "motor2AngleRate", nullptr, nullptr },
-    { "motor3Angle", nullptr, nullptr },
-    { "motor3AngleRate", nullptr, nullptr },
-    { "autoCalc", nullptr, nullptr },
-    { "duration", nullptr, nullptr },
-    { "retainUserOffsets", nullptr, nullptr },
-    { "isBound", nullptr, nullptr },
-    { "appearance", nullptr, nullptr },
-    { "createParticles", nullptr, nullptr },
-    { "lifetimeVariation", nullptr, nullptr },
-    { "maxParticles", nullptr, nullptr },
-    { "particleLifetime", nullptr, nullptr },
-    { "particleSize", nullptr, nullptr },
-    { "colorKey", nullptr, nullptr },
-    { "geometryType", nullptr, nullptr },
-    { "texCoordKey", nullptr, nullptr },
-    { "pickable", nullptr, nullptr },
-    { "angularDampingFactor", nullptr, nullptr },
-    { "angularVelocity", nullptr, nullptr },
-    { "autoDamp", nullptr, nullptr },
-    { "autoDisable", nullptr, nullptr },
-    { "disableAngularSpeed", nullptr, nullptr },
-    { "disableLinearSpeed", nullptr, nullptr },
-    { "disableTime", nullptr, nullptr },
-    { "finiteRotationAxis", nullptr, nullptr },
-    { "fixed", nullptr, nullptr },
-    { "forces", nullptr, nullptr },
-    { "inertia", nullptr, nullptr },
-    { "linearDampingFactor", nullptr, nullptr },
-    { "torques", nullptr, nullptr },
-    { "useFiniteRotation", nullptr, nullptr },
-    { "useGlobalForce", nullptr, nullptr },
-    { "constantForceMix", nullptr, nullptr },
-    { "constantSurfaceThickness", nullptr, nullptr },
-    { "errorCorrection", nullptr, nullptr },
-    { "iterations", nullptr, nullptr },
-    { "maxCorrectionSpeed", nullptr, nullptr },
-    { "preferAccuracy", nullptr, nullptr },
-    { "pointSize", nullptr, nullptr },
-    { "stopBounce", nullptr, nullptr },
-    { "stopErrorCorrection", nullptr, nullptr },
-    { "angleRate", nullptr, nullptr },
-    { "maxSeparation", nullptr, nullptr },
-    { "minSeparation", nullptr, nullptr },
-    { "separation", nullptr, nullptr },
-    { "separationRate", nullptr, nullptr },
-    { "closed", nullptr, nullptr },
-    { "keyVelocity", nullptr, nullptr },
-    { "normalizeVelocity", nullptr, nullptr },
-    { "surface", nullptr, nullptr },
-    { "anisotropicDegree", nullptr, nullptr },
-    { "borderColor", nullptr, nullptr },
-    { "borderWidth", nullptr, nullptr },
-    { "boundaryModeS", nullptr, nullptr },
-    { "boundaryModeT", nullptr, nullptr },
-    { "boundaryModeR", nullptr, nullptr },
-    { "magnificationFilter", nullptr, nullptr },
-    { "minificationFilter", nullptr, nullptr },
-    { "textureCompression", nullptr, nullptr },
-    { "texturePriority", nullptr, nullptr },
-    { "generateMipMaps", nullptr, nullptr },
-    { "targetObject", nullptr, nullptr },
-    { "backAmbientIntensity", nullptr, nullptr },
-    { "backDiffuseColor", nullptr, nullptr },
-    { "backEmissiveColor", nullptr, nullptr },
-    { "backShininess", nullptr, nullptr },
-    { "backSpecularColor", nullptr, nullptr },
-    { "separateBackColor", nullptr, nullptr },
-    { "displayed", nullptr, nullptr },
-    { "clipBoundary", nullptr, nullptr },
-    { "internal", nullptr, nullptr },
-    { "gustiness", nullptr, nullptr },
-    { "turbulence", nullptr, nullptr }
-};
-
-FIVocabulary X3D_vocabulary_3_2 = {
-    nullptr, 0,
-    encodingAlgorithmTable_3_2, 8,
-    nullptr, 0,
-    nullptr, 0,
-    nullptr, 0,
-    nullptr, 0,
-    nullptr, 0,
-    attributeValueTable_3_2, 2,
-    nullptr, 0,
-    nullptr, 0,
-    elementNameTable_3_2, 233,
-    attributeNameTable_3_2, 516
-};
-
-static const char *encodingAlgorithmTable_3_3[] = {
-    "encoder://web3d.org/QuantizedFloatArrayEncoder",
-    "encoder://web3d.org/DeltazlibIntArrayEncoder",
-    "encoder://web3d.org/QuantizedzlibFloatArrayEncoder",
-    "encoder://web3d.org/zlibFloatArrayEncoder",
-    "encoder://web3d.org/QuantizedDoubleArrayEncoder",
-    "encoder://web3d.org/zlibDoubleArrayEncoder",
-    "encoder://web3d.org/QuantizedzlibDoubleArrayEncoder",
-    "encoder://web3d.org/RangeIntArrayEncoder"
-};
-
-static const std::shared_ptr<const FIValue> attributeValueTable_3_3[] = {
-    FIStringValue::create("false"),
-    FIStringValue::create("true")
-};
-
-static const FIQName elementNameTable_3_3[] = {
-    { "Shape", nullptr, nullptr },
-    { "Appearance", nullptr, nullptr },
-    { "Material", nullptr, nullptr },
-    { "IndexedFaceSet", nullptr, nullptr },
-    { "ProtoInstance", nullptr, nullptr },
-    { "Transform", nullptr, nullptr },
-    { "ImageTexture", nullptr, nullptr },
-    { "TextureTransform", nullptr, nullptr },
-    { "Coordinate", nullptr, nullptr },
-    { "Normal", nullptr, nullptr },
-    { "Color", nullptr, nullptr },
-    { "ColorRGBA", nullptr, nullptr },
-    { "TextureCoordinate", nullptr, nullptr },
-    { "ROUTE", nullptr, nullptr },
-    { "fieldValue", nullptr, nullptr },
-    { "Group", nullptr, nullptr },
-    { "LOD", nullptr, nullptr },
-    { "Switch", nullptr, nullptr },
-    { "Script", nullptr, nullptr },
-    { "IndexedTriangleFanSet", nullptr, nullptr },
-    { "IndexedTriangleSet", nullptr, nullptr },
-    { "IndexedTriangleStripSet", nullptr, nullptr },
-    { "MultiTexture", nullptr, nullptr },
-    { "MultiTextureCoordinate", nullptr, nullptr },
-    { "MultiTextureTransform", nullptr, nullptr },
-    { "IndexedLineSet", nullptr, nullptr },
-    { "PointSet", nullptr, nullptr },
-    { "StaticGroup", nullptr, nullptr },
-    { "Sphere", nullptr, nullptr },
-    { "Box", nullptr, nullptr },
-    { "Cone", nullptr, nullptr },
-    { "Anchor", nullptr, nullptr },
-    { "Arc2D", nullptr, nullptr },
-    { "ArcClose2D", nullptr, nullptr },
-    { "AudioClip", nullptr, nullptr },
-    { "Background", nullptr, nullptr },
-    { "Billboard", nullptr, nullptr },
-    { "BooleanFilter", nullptr, nullptr },
-    { "BooleanSequencer", nullptr, nullptr },
-    { "BooleanToggle", nullptr, nullptr },
-    { "BooleanTrigger", nullptr, nullptr },
-    { "Circle2D", nullptr, nullptr },
-    { "Collision", nullptr, nullptr },
-    { "ColorInterpolator", nullptr, nullptr },
-    { "Contour2D", nullptr, nullptr },
-    { "ContourPolyline2D", nullptr, nullptr },
-    { "CoordinateDouble", nullptr, nullptr },
-    { "CoordinateInterpolator", nullptr, nullptr },
-    { "CoordinateInterpolator2D", nullptr, nullptr },
-    { "Cylinder", nullptr, nullptr },
-    { "CylinderSensor", nullptr, nullptr },
-    { "DirectionalLight", nullptr, nullptr },
-    { "Disk2D", nullptr, nullptr },
-    { "EXPORT", nullptr, nullptr },
-    { "ElevationGrid", nullptr, nullptr },
-    { "EspduTransform", nullptr, nullptr },
-    { "ExternProtoDeclare", nullptr, nullptr },
-    { "Extrusion", nullptr, nullptr },
-    { "FillProperties", nullptr, nullptr },
-    { "Fog", nullptr, nullptr },
-    { "FontStyle", nullptr, nullptr },
-    { "GeoCoordinate", nullptr, nullptr },
-    { "GeoElevationGrid", nullptr, nullptr },
-    { "GeoLOD", nullptr, nullptr },
-    { "GeoLocation", nullptr, nullptr },
-    { "GeoMetadata", nullptr, nullptr },
-    { "GeoOrigin", nullptr, nullptr },
-    { "GeoPositionInterpolator", nullptr, nullptr },
-    { "GeoTouchSensor", nullptr, nullptr },
-    { "GeoViewpoint", nullptr, nullptr },
-    { "HAnimDisplacer", nullptr, nullptr },
-    { "HAnimHumanoid", nullptr, nullptr },
-    { "HAnimJoint", nullptr, nullptr },
-    { "HAnimSegment", nullptr, nullptr },
-    { "HAnimSite", nullptr, nullptr },
-    { "IMPORT", nullptr, nullptr },
-    { "IS", nullptr, nullptr },
-    { "Inline", nullptr, nullptr },
-    { "IntegerSequencer", nullptr, nullptr },
-    { "IntegerTrigger", nullptr, nullptr },
-    { "KeySensor", nullptr, nullptr },
-    { "LineProperties", nullptr, nullptr },
-    { "LineSet", nullptr, nullptr },
-    { "LoadSensor", nullptr, nullptr },
-    { "MetadataDouble", nullptr, nullptr },
-    { "MetadataFloat", nullptr, nullptr },
-    { "MetadataInteger", nullptr, nullptr },
-    { "MetadataSet", nullptr, nullptr },
-    { "MetadataString", nullptr, nullptr },
-    { "MovieTexture", nullptr, nullptr },
-    { "NavigationInfo", nullptr, nullptr },
-    { "NormalInterpolator", nullptr, nullptr },
-    { "NurbsCurve", nullptr, nullptr },
-    { "NurbsCurve2D", nullptr, nullptr },
-    { "NurbsOrientationInterpolator", nullptr, nullptr },
-    { "NurbsPatchSurface", nullptr, nullptr },
-    { "NurbsPositionInterpolator", nullptr, nullptr },
-    { "NurbsSet", nullptr, nullptr },
-    { "NurbsSurfaceInterpolator", nullptr, nullptr },
-    { "NurbsSweptSurface", nullptr, nullptr },
-    { "NurbsSwungSurface", nullptr, nullptr },
-    { "NurbsTextureCoordinate", nullptr, nullptr },
-    { "NurbsTrimmedSurface", nullptr, nullptr },
-    { "OrientationInterpolator", nullptr, nullptr },
-    { "PixelTexture", nullptr, nullptr },
-    { "PlaneSensor", nullptr, nullptr },
-    { "PointLight", nullptr, nullptr },
-    { "Polyline2D", nullptr, nullptr },
-    { "Polypoint2D", nullptr, nullptr },
-    { "PositionInterpolator", nullptr, nullptr },
-    { "PositionInterpolator2D", nullptr, nullptr },
-    { "ProtoBody", nullptr, nullptr },
-    { "ProtoDeclare", nullptr, nullptr },
-    { "ProtoInterface", nullptr, nullptr },
-    { "ProximitySensor", nullptr, nullptr },
-    { "ReceiverPdu", nullptr, nullptr },
-    { "Rectangle2D", nullptr, nullptr },
-    { "ScalarInterpolator", nullptr, nullptr },
-    { "Scene", nullptr, nullptr },
-    { "SignalPdu", nullptr, nullptr },
-    { "Sound", nullptr, nullptr },
-    { "SphereSensor", nullptr, nullptr },
-    { "SpotLight", nullptr, nullptr },
-    { "StringSensor", nullptr, nullptr },
-    { "Text", nullptr, nullptr },
-    { "TextureBackground", nullptr, nullptr },
-    { "TextureCoordinateGenerator", nullptr, nullptr },
-    { "TimeSensor", nullptr, nullptr },
-    { "TimeTrigger", nullptr, nullptr },
-    { "TouchSensor", nullptr, nullptr },
-    { "TransmitterPdu", nullptr, nullptr },
-    { "TriangleFanSet", nullptr, nullptr },
-    { "TriangleSet", nullptr, nullptr },
-    { "TriangleSet2D", nullptr, nullptr },
-    { "TriangleStripSet", nullptr, nullptr },
-    { "Viewpoint", nullptr, nullptr },
-    { "VisibilitySensor", nullptr, nullptr },
-    { "WorldInfo", nullptr, nullptr },
-    { "X3D", nullptr, nullptr },
-    { "component", nullptr, nullptr },
-    { "connect", nullptr, nullptr },
-    { "field", nullptr, nullptr },
-    { "head", nullptr, nullptr },
-    { "humanoidBodyType", nullptr, nullptr },
-    { "meta", nullptr, nullptr },
-    { "CADAssembly", nullptr, nullptr },
-    { "CADFace", nullptr, nullptr },
-    { "CADLayer", nullptr, nullptr },
-    { "CADPart", nullptr, nullptr },
-    { "ComposedCubeMapTexture", nullptr, nullptr },
-    { "ComposedShader", nullptr, nullptr },
-    { "ComposedTexture3D", nullptr, nullptr },
-    { "FloatVertexAttribute", nullptr, nullptr },
-    { "FogCoordinate", nullptr, nullptr },
-    { "GeneratedCubeMapTexture", nullptr, nullptr },
-    { "ImageCubeMapTexture", nullptr, nullptr },
-    { "ImageTexture3D", nullptr, nullptr },
-    { "IndexedQuadSet", nullptr, nullptr },
-    { "LocalFog", nullptr, nullptr },
-    { "Matrix3VertexAttribute", nullptr, nullptr },
-    { "Matrix4VertexAttribute", nullptr, nullptr },
-    { "PackagedShader", nullptr, nullptr },
-    { "PixelTexture3D", nullptr, nullptr },
-    { "ProgramShader", nullptr, nullptr },
-    { "QuadSet", nullptr, nullptr },
-    { "ShaderPart", nullptr, nullptr },
-    { "ShaderProgram", nullptr, nullptr },
-    { "TextureCoordinate3D", nullptr, nullptr },
-    { "TextureCoordinate4D", nullptr, nullptr },
-    { "TextureTransform3D", nullptr, nullptr },
-    { "TextureTransformMatrix3D", nullptr, nullptr },
-    { "BallJoint", nullptr, nullptr },
-    { "BoundedPhysicsModel", nullptr, nullptr },
-    { "ClipPlane", nullptr, nullptr },
-    { "CollidableOffset", nullptr, nullptr },
-    { "CollidableShape", nullptr, nullptr },
-    { "CollisionCollection", nullptr, nullptr },
-    { "CollisionSensor", nullptr, nullptr },
-    { "CollisionSpace", nullptr, nullptr },
-    { "ColorDamper", nullptr, nullptr },
-    { "ConeEmitter", nullptr, nullptr },
-    { "Contact", nullptr, nullptr },
-    { "CoordinateDamper", nullptr, nullptr },
-    { "DISEntityManager", nullptr, nullptr },
-    { "DISEntityTypeMapping", nullptr, nullptr },
-    { "DoubleAxisHingeJoint", nullptr, nullptr },
-    { "EaseInEaseOut", nullptr, nullptr },
-    { "ExplosionEmitter", nullptr, nullptr },
-    { "ForcePhysicsModel", nullptr, nullptr },
-    { "GeoProximitySensor", nullptr, nullptr },
-    { "GeoTransform", nullptr, nullptr },
-    { "Layer", nullptr, nullptr },
-    { "LayerSet", nullptr, nullptr },
-    { "Layout", nullptr, nullptr },
-    { "LayoutGroup", nullptr, nullptr },
-    { "LayoutLayer", nullptr, nullptr },
-    { "LinePickSensor", nullptr, nullptr },
-    { "MotorJoint", nullptr, nullptr },
-    { "OrientationChaser", nullptr, nullptr },
-    { "OrientationDamper", nullptr, nullptr },
-    { "OrthoViewpoint", nullptr, nullptr },
-    { "ParticleSystem", nullptr, nullptr },
-    { "PickableGroup", nullptr, nullptr },
-    { "PointEmitter", nullptr, nullptr },
-    { "PointPickSensor", nullptr, nullptr },
-    { "PolylineEmitter", nullptr, nullptr },
-    { "PositionChaser", nullptr, nullptr },
-    { "PositionChaser2D", nullptr, nullptr },
-    { "PositionDamper", nullptr, nullptr },
-    { "PositionDamper2D", nullptr, nullptr },
-    { "PrimitivePickSensor", nullptr, nullptr },
-    { "RigidBody", nullptr, nullptr },
-    { "RigidBodyCollection", nullptr, nullptr },
-    { "ScalarChaser", nullptr, nullptr },
-    { "ScreenFontStyle", nullptr, nullptr },
-    { "ScreenGroup", nullptr, nullptr },
-    { "SingleAxisHingeJoint", nullptr, nullptr },
-    { "SliderJoint", nullptr, nullptr },
-    { "SplinePositionInterpolator", nullptr, nullptr },
-    { "SplinePositionInterpolator2D", nullptr, nullptr },
-    { "SplineScalarInterpolator", nullptr, nullptr },
-    { "SquadOrientationInterpolator", nullptr, nullptr },
-    { "SurfaceEmitter", nullptr, nullptr },
-    { "TexCoordDamper2D", nullptr, nullptr },
-    { "TextureProperties", nullptr, nullptr },
-    { "TransformSensor", nullptr, nullptr },
-    { "TwoSidedMaterial", nullptr, nullptr },
-    { "UniversalJoint", nullptr, nullptr },
-    { "ViewpointGroup", nullptr, nullptr },
-    { "Viewport", nullptr, nullptr },
-    { "VolumeEmitter", nullptr, nullptr },
-    { "VolumePickSensor", nullptr, nullptr },
-    { "WindPhysicsModel", nullptr, nullptr },
-    { "BlendedVolumeStyle", nullptr, nullptr },
-    { "BoundaryEnhancementVolumeStyle", nullptr, nullptr },
-    { "CartoonVolumeStyle", nullptr, nullptr },
-    { "ComposedVolumeStyle", nullptr, nullptr },
-    { "EdgeEnhancementVolumeStyle", nullptr, nullptr },
-    { "IsoSurfaceVolumeData", nullptr, nullptr },
-    { "MetadataBoolean", nullptr, nullptr },
-    { "OpacityMapVolumeStyle", nullptr, nullptr },
-    { "ProjectionVolumeStyle", nullptr, nullptr },
-    { "SegmentedVolumeData", nullptr, nullptr },
-    { "ShadedVolumeStyle", nullptr, nullptr },
-    { "SilhouetteEnhancementVolumeStyle", nullptr, nullptr },
-    { "ToneMappedVolumeStyle", nullptr, nullptr },
-    { "VolumeData", nullptr, nullptr },
-    { "ColorChaser", nullptr, nullptr },
-    { "CoordinateChaser", nullptr, nullptr },
-    { "ScalarDamper", nullptr, nullptr },
-    { "TexCoordChaser2D", nullptr, nullptr },
-    { "unit", nullptr, nullptr }
-};
-
-static const FIQName attributeNameTable_3_3[] = {
-    { "DEF", nullptr, nullptr },
-    { "USE", nullptr, nullptr },
-    { "containerField", nullptr, nullptr },
-    { "fromNode", nullptr, nullptr },
-    { "fromField", nullptr, nullptr },
-    { "toNode", nullptr, nullptr },
-    { "toField", nullptr, nullptr },
-    { "name", nullptr, nullptr },
-    { "value", nullptr, nullptr },
-    { "color", nullptr, nullptr },
-    { "colorIndex", nullptr, nullptr },
-    { "coordIndex", nullptr, nullptr },
-    { "texCoordIndex", nullptr, nullptr },
-    { "normalIndex", nullptr, nullptr },
-    { "colorPerVertex", nullptr, nullptr },
-    { "normalPerVertex", nullptr, nullptr },
-    { "rotation", nullptr, nullptr },
-    { "scale", nullptr, nullptr },
-    { "center", nullptr, nullptr },
-    { "scaleOrientation", nullptr, nullptr },
-    { "translation", nullptr, nullptr },
-    { "url", nullptr, nullptr },
-    { "repeatS", nullptr, nullptr },
-    { "repeatT", nullptr, nullptr },
-    { "point", nullptr, nullptr },
-    { "vector", nullptr, nullptr },
-    { "range", nullptr, nullptr },
-    { "ambientIntensity", nullptr, nullptr },
-    { "diffuseColor", nullptr, nullptr },
-    { "emissiveColor", nullptr, nullptr },
-    { "shininess", nullptr, nullptr },
-    { "specularColor", nullptr, nullptr },
-    { "transparency", nullptr, nullptr },
-    { "whichChoice", nullptr, nullptr },
-    { "index", nullptr, nullptr },
-    { "mode", nullptr, nullptr },
-    { "source", nullptr, nullptr },
-    { "function", nullptr, nullptr },
-    { "alpha", nullptr, nullptr },
-    { "vertexCount", nullptr, nullptr },
-    { "radius", nullptr, nullptr },
-    { "size", nullptr, nullptr },
-    { "height", nullptr, nullptr },
-    { "solid", nullptr, nullptr },
-    { "ccw", nullptr, nullptr },
-    { "key", nullptr, nullptr },
-    { "keyValue", nullptr, nullptr },
-    { "enabled", nullptr, nullptr },
-    { "direction", nullptr, nullptr },
-    { "position", nullptr, nullptr },
-    { "orientation", nullptr, nullptr },
-    { "bboxCenter", nullptr, nullptr },
-    { "bboxSize", nullptr, nullptr },
-    { "AS", nullptr, nullptr },
-    { "InlineDEF", nullptr, nullptr },
-    { "accessType", nullptr, nullptr },
-    { "actionKeyPress", nullptr, nullptr },
-    { "actionKeyRelease", nullptr, nullptr },
-    { "address", nullptr, nullptr },
-    { "altKey", nullptr, nullptr },
-    { "antennaLocation", nullptr, nullptr },
-    { "antennaPatternLength", nullptr, nullptr },
-    { "antennaPatternType", nullptr, nullptr },
-    { "applicationID", nullptr, nullptr },
-    { "articulationParameterArray", nullptr, nullptr },
-    { "articulationParameterChangeIndicatorArray", nullptr, nullptr },
-    { "articulationParameterCount", nullptr, nullptr },
-    { "articulationParameterDesignatorArray", nullptr, nullptr },
-    { "articulationParameterIdPartAttachedArray", nullptr, nullptr },
-    { "articulationParameterTypeArray", nullptr, nullptr },
-    { "attenuation", nullptr, nullptr },
-    { "autoOffset", nullptr, nullptr },
-    { "avatarSize", nullptr, nullptr },
-    { "axisOfRotation", nullptr, nullptr },
-    { "backUrl", nullptr, nullptr },
-    { "beamWidth", nullptr, nullptr },
-    { "beginCap", nullptr, nullptr },
-    { "bindTime", nullptr, nullptr },
-    { "bottom", nullptr, nullptr },
-    { "bottomRadius", nullptr, nullptr },
-    { "bottomUrl", nullptr, nullptr },
-    { "centerOfMass", nullptr, nullptr },
-    { "centerOfRotation", nullptr, nullptr },
-    { "child1Url", nullptr, nullptr },
-    { "child2Url", nullptr, nullptr },
-    { "child3Url", nullptr, nullptr },
-    { "child4Url", nullptr, nullptr },
-    { "class", nullptr, nullptr },
-    { "closureType", nullptr, nullptr },
-    { "collideTime", nullptr, nullptr },
-    { "content", nullptr, nullptr },
-    { "controlKey", nullptr, nullptr },
-    { "controlPoint", nullptr, nullptr },
-    { "convex", nullptr, nullptr },
-    { "coordinateSystem", nullptr, nullptr },
-    { "copyright", nullptr, nullptr },
-    { "creaseAngle", nullptr, nullptr },
-    { "crossSection", nullptr, nullptr },
-    { "cryptoKeyID", nullptr, nullptr },
-    { "cryptoSystem", nullptr, nullptr },
-    { "cutOffAngle", nullptr, nullptr },
-    { "cycleInterval", nullptr, nullptr },
-    { "cycleTime", nullptr, nullptr },
-    { "data", nullptr, nullptr },
-    { "dataFormat", nullptr, nullptr },
-    { "dataLength", nullptr, nullptr },
-    { "dataUrl", nullptr, nullptr },
-    { "date", nullptr, nullptr },
-    { "deadReckoning", nullptr, nullptr },
-    { "deletionAllowed", nullptr, nullptr },
-    { "description", nullptr, nullptr },
-    { "detonateTime", nullptr, nullptr },
-    { "dir", nullptr, nullptr },
-    { "directOutput", nullptr, nullptr },
-    { "diskAngle", nullptr, nullptr },
-    { "displacements", nullptr, nullptr },
-    { "documentation", nullptr, nullptr },
-    { "elapsedTime", nullptr, nullptr },
-    { "ellipsoid", nullptr, nullptr },
-    { "encodingScheme", nullptr, nullptr },
-    { "endAngle", nullptr, nullptr },
-    { "endCap", nullptr, nullptr },
-    { "enterTime", nullptr, nullptr },
-    { "enteredText", nullptr, nullptr },
-    { "entityCategory", nullptr, nullptr },
-    { "entityCountry", nullptr, nullptr },
-    { "entityDomain", nullptr, nullptr },
-    { "entityExtra", nullptr, nullptr },
-    { "entityID", nullptr, nullptr },
-    { "entityKind", nullptr, nullptr },
-    { "entitySpecific", nullptr, nullptr },
-    { "entitySubCategory", nullptr, nullptr },
-    { "exitTime", nullptr, nullptr },
-    { "extent", nullptr, nullptr },
-    { "family", nullptr, nullptr },
-    { "fanCount", nullptr, nullptr },
-    { "fieldOfView", nullptr, nullptr },
-    { "filled", nullptr, nullptr },
-    { "finalText", nullptr, nullptr },
-    { "fireMissionIndex", nullptr, nullptr },
-    { "fired1", nullptr, nullptr },
-    { "fired2", nullptr, nullptr },
-    { "firedTime", nullptr, nullptr },
-    { "firingRange", nullptr, nullptr },
-    { "firingRate", nullptr, nullptr },
-    { "fogType", nullptr, nullptr },
-    { "forceID", nullptr, nullptr },
-    { "frequency", nullptr, nullptr },
-    { "frontUrl", nullptr, nullptr },
-    { "fuse", nullptr, nullptr },
-    { "geoCoords", nullptr, nullptr },
-    { "geoGridOrigin", nullptr, nullptr },
-    { "geoSystem", nullptr, nullptr },
-    { "groundAngle", nullptr, nullptr },
-    { "groundColor", nullptr, nullptr },
-    { "hatchColor", nullptr, nullptr },
-    { "hatchStyle", nullptr, nullptr },
-    { "hatched", nullptr, nullptr },
-    { "headlight", nullptr, nullptr },
-    { "horizontal", nullptr, nullptr },
-    { "horizontalDatum", nullptr, nullptr },
-    { "http-equiv", nullptr, nullptr },
-    { "image", nullptr, nullptr },
-    { "importedDEF", nullptr, nullptr },
-    { "info", nullptr, nullptr },
-    { "innerRadius", nullptr, nullptr },
-    { "inputFalse", nullptr, nullptr },
-    { "inputNegate", nullptr, nullptr },
-    { "inputSource", nullptr, nullptr },
-    { "inputTrue", nullptr, nullptr },
-    { "integerKey", nullptr, nullptr },
-    { "intensity", nullptr, nullptr },
-    { "jump", nullptr, nullptr },
-    { "justify", nullptr, nullptr },
-    { "keyPress", nullptr, nullptr },
-    { "keyRelease", nullptr, nullptr },
-    { "knot", nullptr, nullptr },
-    { "lang", nullptr, nullptr },
-    { "language", nullptr, nullptr },
-    { "leftToRight", nullptr, nullptr },
-    { "leftUrl", nullptr, nullptr },
-    { "length", nullptr, nullptr },
-    { "lengthOfModulationParameters", nullptr, nullptr },
-    { "level", nullptr, nullptr },
-    { "limitOrientation", nullptr, nullptr },
-    { "lineSegments", nullptr, nullptr },
-    { "linearAcceleration", nullptr, nullptr },
-    { "linearVelocity", nullptr, nullptr },
-    { "linetype", nullptr, nullptr },
-    { "linewidthScaleFactor", nullptr, nullptr },
-    { "llimit", nullptr, nullptr },
-    { "load", nullptr, nullptr },
-    { "loadTime", nullptr, nullptr },
-    { "localDEF", nullptr, nullptr },
-    { "location", nullptr, nullptr },
-    { "loop", nullptr, nullptr },
-    { "marking", nullptr, nullptr },
-    { "mass", nullptr, nullptr },
-    { "maxAngle", nullptr, nullptr },
-    { "maxBack", nullptr, nullptr },
-    { "maxExtent", nullptr, nullptr },
-    { "maxFront", nullptr, nullptr },
-    { "maxPosition", nullptr, nullptr },
-    { "metadataFormat", nullptr, nullptr },
-    { "minAngle", nullptr, nullptr },
-    { "minBack", nullptr, nullptr },
-    { "minFront", nullptr, nullptr },
-    { "minPosition", nullptr, nullptr },
-    { "modulationTypeDetail", nullptr, nullptr },
-    { "modulationTypeMajor", nullptr, nullptr },
-    { "modulationTypeSpreadSpectrum", nullptr, nullptr },
-    { "modulationTypeSystem", nullptr, nullptr },
-    { "momentsOfInertia", nullptr, nullptr },
-    { "multicastRelayHost", nullptr, nullptr },
-    { "multicastRelayPort", nullptr, nullptr },
-    { "munitionApplicationID", nullptr, nullptr },
-    { "munitionEndPoint", nullptr, nullptr },
-    { "munitionEntityID", nullptr, nullptr },
-    { "munitionQuantity", nullptr, nullptr },
-    { "munitionSiteID", nullptr, nullptr },
-    { "munitionStartPoint", nullptr, nullptr },
-    { "mustEvaluate", nullptr, nullptr },
-    { "navType", nullptr, nullptr },
-    { "networkMode", nullptr, nullptr },
-    { "next", nullptr, nullptr },
-    { "nodeField", nullptr, nullptr },
-    { "offset", nullptr, nullptr },
-    { "on", nullptr, nullptr },
-    { "order", nullptr, nullptr },
-    { "originator", nullptr, nullptr },
-    { "outerRadius", nullptr, nullptr },
-    { "parameter", nullptr, nullptr },
-    { "pauseTime", nullptr, nullptr },
-    { "pitch", nullptr, nullptr },
-    { "points", nullptr, nullptr },
-    { "port", nullptr, nullptr },
-    { "power", nullptr, nullptr },
-    { "previous", nullptr, nullptr },
-    { "priority", nullptr, nullptr },
-    { "profile", nullptr, nullptr },
-    { "progress", nullptr, nullptr },
-    { "protoField", nullptr, nullptr },
-    { "radioEntityTypeCategory", nullptr, nullptr },
-    { "radioEntityTypeCountry", nullptr, nullptr },
-    { "radioEntityTypeDomain", nullptr, nullptr },
-    { "radioEntityTypeKind", nullptr, nullptr },
-    { "radioEntityTypeNomenclature", nullptr, nullptr },
-    { "radioEntityTypeNomenclatureVersion", nullptr, nullptr },
-    { "radioID", nullptr, nullptr },
-    { "readInterval", nullptr, nullptr },
-    { "receivedPower", nullptr, nullptr },
-    { "receiverState", nullptr, nullptr },
-    { "reference", nullptr, nullptr },
-    { "relativeAntennaLocation", nullptr, nullptr },
-    { "resolution", nullptr, nullptr },
-    { "resumeTime", nullptr, nullptr },
-    { "rightUrl", nullptr, nullptr },
-    { "rootUrl", nullptr, nullptr },
-    { "rotateYUp", nullptr, nullptr },
-    { "rtpHeaderExpected", nullptr, nullptr },
-    { "sampleRate", nullptr, nullptr },
-    { "samples", nullptr, nullptr },
-    { "shiftKey", nullptr, nullptr },
-    { "side", nullptr, nullptr },
-    { "siteID", nullptr, nullptr },
-    { "skinCoordIndex", nullptr, nullptr },
-    { "skinCoordWeight", nullptr, nullptr },
-    { "skyAngle", nullptr, nullptr },
-    { "skyColor", nullptr, nullptr },
-    { "spacing", nullptr, nullptr },
-    { "spatialize", nullptr, nullptr },
-    { "speed", nullptr, nullptr },
-    { "speedFactor", nullptr, nullptr },
-    { "spine", nullptr, nullptr },
-    { "startAngle", nullptr, nullptr },
-    { "startTime", nullptr, nullptr },
-    { "stiffness", nullptr, nullptr },
-    { "stopTime", nullptr, nullptr },
-    { "string", nullptr, nullptr },
-    { "stripCount", nullptr, nullptr },
-    { "style", nullptr, nullptr },
-    { "summary", nullptr, nullptr },
-    { "tdlType", nullptr, nullptr },
-    { "tessellation", nullptr, nullptr },
-    { "tessellationScale", nullptr, nullptr },
-    { "time", nullptr, nullptr },
-    { "timeOut", nullptr, nullptr },
-    { "timestamp", nullptr, nullptr },
-    { "title", nullptr, nullptr },
-    { "toggle", nullptr, nullptr },
-    { "top", nullptr, nullptr },
-    { "topToBottom", nullptr, nullptr },
-    { "topUrl", nullptr, nullptr },
-    { "touchTime", nullptr, nullptr },
-    { "transmitFrequencyBandwidth", nullptr, nullptr },
-    { "transmitState", nullptr, nullptr },
-    { "transmitterApplicationID", nullptr, nullptr },
-    { "transmitterEntityID", nullptr, nullptr },
-    { "transmitterRadioID", nullptr, nullptr },
-    { "transmitterSiteID", nullptr, nullptr },
-    { "transparent", nullptr, nullptr },
-    { "triggerTime", nullptr, nullptr },
-    { "triggerTrue", nullptr, nullptr },
-    { "triggerValue", nullptr, nullptr },
-    { "type", nullptr, nullptr },
-    { "uDimension", nullptr, nullptr },
-    { "uKnot", nullptr, nullptr },
-    { "uOrder", nullptr, nullptr },
-    { "uTessellation", nullptr, nullptr },
-    { "ulimit", nullptr, nullptr },
-    { "vDimension", nullptr, nullptr },
-    { "vKnot", nullptr, nullptr },
-    { "vOrder", nullptr, nullptr },
-    { "vTessellation", nullptr, nullptr },
-    { "version", nullptr, nullptr },
-    { "verticalDatum", nullptr, nullptr },
-    { "vertices", nullptr, nullptr },
-    { "visibilityLimit", nullptr, nullptr },
-    { "visibilityRange", nullptr, nullptr },
-    { "warhead", nullptr, nullptr },
-    { "weight", nullptr, nullptr },
-    { "whichGeometry", nullptr, nullptr },
-    { "writeInterval", nullptr, nullptr },
-    { "xDimension", nullptr, nullptr },
-    { "xSpacing", nullptr, nullptr },
-    { "yScale", nullptr, nullptr },
-    { "zDimension", nullptr, nullptr },
-    { "zSpacing", nullptr, nullptr },
-    { "visible", nullptr, nullptr },
-    { "repeatR", nullptr, nullptr },
-    { "texture", nullptr, nullptr },
-    { "back", nullptr, nullptr },
-    { "front", nullptr, nullptr },
-    { "left", nullptr, nullptr },
-    { "right", nullptr, nullptr },
-    { "parts", nullptr, nullptr },
-    { "isSelected", nullptr, nullptr },
-    { "isValid", nullptr, nullptr },
-    { "numComponents", nullptr, nullptr },
-    { "depth", nullptr, nullptr },
-    { "update", nullptr, nullptr },
-    { "fogCoord", nullptr, nullptr },
-    { "texCoord", nullptr, nullptr },
-    { "activate", nullptr, nullptr },
-    { "programs", nullptr, nullptr },
-    { "matrix", nullptr, nullptr },
-    { "anchorPoint", nullptr, nullptr },
-    { "body1", nullptr, nullptr },
-    { "body2", nullptr, nullptr },
-    { "forceOutput", nullptr, nullptr },
-    { "body1AnchorPoint", nullptr, nullptr },
-    { "body2AnchorPoint", nullptr, nullptr },
-    { "plane", nullptr, nullptr },
-    { "appliedParameters", nullptr, nullptr },
-    { "bounce", nullptr, nullptr },
-    { "frictionCoefficients", nullptr, nullptr },
-    { "minBounceSpeed", nullptr, nullptr },
-    { "slipFactors", nullptr, nullptr },
-    { "softnessConstantForceMix", nullptr, nullptr },
-    { "softnessErrorCorrection", nullptr, nullptr },
-    { "surfaceSpeed", nullptr, nullptr },
-    { "isActive", nullptr, nullptr },
-    { "useGeometry", nullptr, nullptr },
-    { "set_destination", nullptr, nullptr },
-    { "set_value", nullptr, nullptr },
-    { "tau", nullptr, nullptr },
-    { "tolerance", nullptr, nullptr },
-    { "value_changed", nullptr, nullptr },
-    { "initialDestination", nullptr, nullptr },
-    { "initialValue", nullptr, nullptr },
-    { "angle", nullptr, nullptr },
-    { "variation", nullptr, nullptr },
-    { "surfaceArea", nullptr, nullptr },
-    { "frictionDirection", nullptr, nullptr },
-    { "slipCoefficients", nullptr, nullptr },
-    { "category", nullptr, nullptr },
-    { "country", nullptr, nullptr },
-    { "domain", nullptr, nullptr },
-    { "extra", nullptr, nullptr },
-    { "kind", nullptr, nullptr },
-    { "specific", nullptr, nullptr },
-    { "subcategory", nullptr, nullptr },
-    { "axis1", nullptr, nullptr },
-    { "axis2", nullptr, nullptr },
-    { "desiredAngularVelocity1", nullptr, nullptr },
-    { "desiredAngularVelocity2", nullptr, nullptr },
-    { "maxAngle1", nullptr, nullptr },
-    { "maxTorque1", nullptr, nullptr },
-    { "maxTorque2", nullptr, nullptr },
-    { "minAngle1", nullptr, nullptr },
-    { "stopBounce1", nullptr, nullptr },
-    { "stopConstantForceMix1", nullptr, nullptr },
-    { "stopErrorCorrection1", nullptr, nullptr },
-    { "suspensionErrorCorrection", nullptr, nullptr },
-    { "suspensionForce", nullptr, nullptr },
-    { "body1Axis", nullptr, nullptr },
-    { "body2Axis", nullptr, nullptr },
-    { "hinge1Angle", nullptr, nullptr },
-    { "hinge1AngleRate", nullptr, nullptr },
-    { "hinge2Angle", nullptr, nullptr },
-    { "hinge2AngleRate", nullptr, nullptr },
-    { "set_fraction", nullptr, nullptr },
-    { "easeInEaseOut", nullptr, nullptr },
-    { "modifiedFraction_changed", nullptr, nullptr },
-    { "force", nullptr, nullptr },
-    { "geoCenter", nullptr, nullptr },
-    { "centerOfRotation_changed", nullptr, nullptr },
-    { "geoCoord_changed", nullptr, nullptr },
-    { "orientation_changed", nullptr, nullptr },
-    { "position_changed", nullptr, nullptr },
-    { "isPickable", nullptr, nullptr },
-    { "viewport", nullptr, nullptr },
-    { "activeLayer", nullptr, nullptr },
-    { "align", nullptr, nullptr },
-    { "offsetUnits", nullptr, nullptr },
-    { "scaleMode", nullptr, nullptr },
-    { "sizeUnits", nullptr, nullptr },
-    { "layout", nullptr, nullptr },
-    { "objectType", nullptr, nullptr },
-    { "pickedNormal", nullptr, nullptr },
-    { "pickedPoint", nullptr, nullptr },
-    { "pickedTextureCoordinate", nullptr, nullptr },
-    { "intersectionType", nullptr, nullptr },
-    { "sortOrder", nullptr, nullptr },
-    { "axis1Angle", nullptr, nullptr },
-    { "axis1Torque", nullptr, nullptr },
-    { "axis2Angle", nullptr, nullptr },
-    { "axis2Torque", nullptr, nullptr },
-    { "axis3Angle", nullptr, nullptr },
-    { "axis3Torque", nullptr, nullptr },
-    { "enabledAxies", nullptr, nullptr },
-    { "motor1Axis", nullptr, nullptr },
-    { "motor2Axis", nullptr, nullptr },
-    { "motor3Axis", nullptr, nullptr },
-    { "stop1Bounce", nullptr, nullptr },
-    { "stop1ErrorCorrection", nullptr, nullptr },
-    { "stop2Bounce", nullptr, nullptr },
-    { "stop2ErrorCorrection", nullptr, nullptr },
-    { "stop3Bounce", nullptr, nullptr },
-    { "stop3ErrorCorrection", nullptr, nullptr },
-    { "motor1Angle", nullptr, nullptr },
-    { "motor1AngleRate", nullptr, nullptr },
-    { "motor2Angle", nullptr, nullptr },
-    { "motor2AngleRate", nullptr, nullptr },
-    { "motor3Angle", nullptr, nullptr },
-    { "motor3AngleRate", nullptr, nullptr },
-    { "autoCalc", nullptr, nullptr },
-    { "duration", nullptr, nullptr },
-    { "retainUserOffsets", nullptr, nullptr },
-    { "isBound", nullptr, nullptr },
-    { "appearance", nullptr, nullptr },
-    { "createParticles", nullptr, nullptr },
-    { "lifetimeVariation", nullptr, nullptr },
-    { "maxParticles", nullptr, nullptr },
-    { "particleLifetime", nullptr, nullptr },
-    { "particleSize", nullptr, nullptr },
-    { "colorKey", nullptr, nullptr },
-    { "geometryType", nullptr, nullptr },
-    { "texCoordKey", nullptr, nullptr },
-    { "pickable", nullptr, nullptr },
-    { "angularDampingFactor", nullptr, nullptr },
-    { "angularVelocity", nullptr, nullptr },
-    { "autoDamp", nullptr, nullptr },
-    { "autoDisable", nullptr, nullptr },
-    { "disableAngularSpeed", nullptr, nullptr },
-    { "disableLinearSpeed", nullptr, nullptr },
-    { "disableTime", nullptr, nullptr },
-    { "finiteRotationAxis", nullptr, nullptr },
-    { "fixed", nullptr, nullptr },
-    { "forces", nullptr, nullptr },
-    { "inertia", nullptr, nullptr },
-    { "linearDampingFactor", nullptr, nullptr },
-    { "torques", nullptr, nullptr },
-    { "useFiniteRotation", nullptr, nullptr },
-    { "useGlobalForce", nullptr, nullptr },
-    { "constantForceMix", nullptr, nullptr },
-    { "constantSurfaceThickness", nullptr, nullptr },
-    { "errorCorrection", nullptr, nullptr },
-    { "iterations", nullptr, nullptr },
-    { "maxCorrectionSpeed", nullptr, nullptr },
-    { "preferAccuracy", nullptr, nullptr },
-    { "pointSize", nullptr, nullptr },
-    { "stopBounce", nullptr, nullptr },
-    { "stopErrorCorrection", nullptr, nullptr },
-    { "angleRate", nullptr, nullptr },
-    { "maxSeparation", nullptr, nullptr },
-    { "minSeparation", nullptr, nullptr },
-    { "separation", nullptr, nullptr },
-    { "separationRate", nullptr, nullptr },
-    { "closed", nullptr, nullptr },
-    { "keyVelocity", nullptr, nullptr },
-    { "normalizeVelocity", nullptr, nullptr },
-    { "surface", nullptr, nullptr },
-    { "anisotropicDegree", nullptr, nullptr },
-    { "borderColor", nullptr, nullptr },
-    { "borderWidth", nullptr, nullptr },
-    { "boundaryModeS", nullptr, nullptr },
-    { "boundaryModeT", nullptr, nullptr },
-    { "boundaryModeR", nullptr, nullptr },
-    { "magnificationFilter", nullptr, nullptr },
-    { "minificationFilter", nullptr, nullptr },
-    { "textureCompression", nullptr, nullptr },
-    { "texturePriority", nullptr, nullptr },
-    { "generateMipMaps", nullptr, nullptr },
-    { "targetObject", nullptr, nullptr },
-    { "backAmbientIntensity", nullptr, nullptr },
-    { "backDiffuseColor", nullptr, nullptr },
-    { "backEmissiveColor", nullptr, nullptr },
-    { "backShininess", nullptr, nullptr },
-    { "backSpecularColor", nullptr, nullptr },
-    { "separateBackColor", nullptr, nullptr },
-    { "displayed", nullptr, nullptr },
-    { "clipBoundary", nullptr, nullptr },
-    { "internal", nullptr, nullptr },
-    { "gustiness", nullptr, nullptr },
-    { "turbulence", nullptr, nullptr },
-    { "unitCategory", nullptr, nullptr },
-    { "unitName", nullptr, nullptr },
-    { "unitConversionFactor", nullptr, nullptr },
-    { "weightConstant1", nullptr, nullptr },
-    { "weightConstant2", nullptr, nullptr },
-    { "weightFunction1", nullptr, nullptr },
-    { "weightFunction2", nullptr, nullptr },
-    { "boundaryOpacity", nullptr, nullptr },
-    { "opacityFactor", nullptr, nullptr },
-    { "retainedOpacity", nullptr, nullptr },
-    { "colorSteps", nullptr, nullptr },
-    { "orthogonalColor", nullptr, nullptr },
-    { "parallelColor", nullptr, nullptr },
-    { "ordered", nullptr, nullptr },
-    { "edgeColor", nullptr, nullptr },
-    { "gradientThreshold", nullptr, nullptr },
-    { "contourStepSize", nullptr, nullptr },
-    { "dimensions", nullptr, nullptr },
-    { "surfaceTolerance", nullptr, nullptr },
-    { "surfaceValues", nullptr, nullptr },
-    { "intensityThreshold", nullptr, nullptr },
-    { "segmentEnabled", nullptr, nullptr },
-    { "lighting", nullptr, nullptr },
-    { "shadows", nullptr, nullptr },
-    { "phaseFunction", nullptr, nullptr },
-    { "silhouetteBoundaryOpacity", nullptr, nullptr },
-    { "silhouetteRetainedOpacity", nullptr, nullptr },
-    { "silhouetteSharpness", nullptr, nullptr },
-    { "coolColor", nullptr, nullptr },
-    { "warmColor", nullptr, nullptr }
-};
-
-FIVocabulary X3D_vocabulary_3_3 = {
-    nullptr, 0,
-    encodingAlgorithmTable_3_3, 8,
-    nullptr, 0,
-    nullptr, 0,
-    nullptr, 0,
-    nullptr, 0,
-    nullptr, 0,
-    attributeValueTable_3_3, 2,
-    nullptr, 0,
-    nullptr, 0,
-    elementNameTable_3_3, 252,
-    attributeNameTable_3_3, 546
-};
-
-}// namespace Assimp
-
-#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER

+ 0 - 15
code/CMakeLists.txt

@@ -800,21 +800,6 @@ ADD_ASSIMP_IMPORTER( X
 ADD_ASSIMP_IMPORTER( X3D
   AssetLib/X3D/X3DImporter.cpp
   AssetLib/X3D/X3DImporter.hpp
-  AssetLib/X3D/X3DImporter_Geometry2D.cpp
-  AssetLib/X3D/X3DImporter_Geometry3D.cpp
-  AssetLib/X3D/X3DImporter_Group.cpp
-  AssetLib/X3D/X3DImporter_Light.cpp
-  AssetLib/X3D/X3DImporter_Macro.hpp
-  AssetLib/X3D/X3DImporter_Metadata.cpp
-  AssetLib/X3D/X3DImporter_Networking.cpp
-  AssetLib/X3D/X3DImporter_Node.hpp
-  AssetLib/X3D/X3DImporter_Postprocess.cpp
-  AssetLib/X3D/X3DImporter_Rendering.cpp
-  AssetLib/X3D/X3DImporter_Shape.cpp
-  AssetLib/X3D/X3DImporter_Texturing.cpp
-  #AssetLib/X3D/FIReader.hpp
-  #AssetLib/X3D/FIReader.cpp
-  #AssetLib/X3D/X3DVocabulary.cpp
 )
 
 ADD_ASSIMP_IMPORTER( GLTF

+ 48 - 60
include/assimp/ParsingUtils.h

@@ -39,7 +39,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ----------------------------------------------------------------------
 */
 
-
 /** @file ParsingUtils.h
  *  @brief Defines helper functions for text parsing
  */
@@ -48,12 +47,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #define AI_PARSING_UTILS_H_INC
 
 #ifdef __GNUC__
-#   pragma GCC system_header
+#pragma GCC system_header
 #endif
 
 #include <assimp/StringComparison.h>
 #include <assimp/StringUtils.h>
 #include <assimp/defs.h>
+#include <vector>
 
 namespace Assimp {
 
@@ -71,57 +71,53 @@ static const unsigned int BufferSize = 4096;
 // ---------------------------------------------------------------------------------
 template <class char_t>
 AI_FORCE_INLINE
-char_t ToLower( char_t in ) {
-    return (in >= (char_t)'A' && in <= (char_t)'Z') ? (char_t)(in+0x20) : in;
+        char_t
+        ToLower(char_t in) {
+    return (in >= (char_t)'A' && in <= (char_t)'Z') ? (char_t)(in + 0x20) : in;
 }
 
 // ---------------------------------------------------------------------------------
 template <class char_t>
 AI_FORCE_INLINE
-char_t ToUpper( char_t in) {
-    return (in >= (char_t)'a' && in <= (char_t)'z') ? (char_t)(in-0x20) : in;
+        char_t
+        ToUpper(char_t in) {
+    return (in >= (char_t)'a' && in <= (char_t)'z') ? (char_t)(in - 0x20) : in;
 }
 
 // ---------------------------------------------------------------------------------
 template <class char_t>
-AI_FORCE_INLINE
-bool IsUpper( char_t in) {
+AI_FORCE_INLINE bool IsUpper(char_t in) {
     return (in >= (char_t)'A' && in <= (char_t)'Z');
 }
 
 // ---------------------------------------------------------------------------------
 template <class char_t>
-AI_FORCE_INLINE
-bool IsLower( char_t in) {
+AI_FORCE_INLINE bool IsLower(char_t in) {
     return (in >= (char_t)'a' && in <= (char_t)'z');
 }
 
 // ---------------------------------------------------------------------------------
 template <class char_t>
-AI_FORCE_INLINE
-bool IsSpace( char_t in) {
+AI_FORCE_INLINE bool IsSpace(char_t in) {
     return (in == (char_t)' ' || in == (char_t)'\t');
 }
 
 // ---------------------------------------------------------------------------------
 template <class char_t>
-AI_FORCE_INLINE
-bool IsLineEnd( char_t in) {
-    return (in==(char_t)'\r'||in==(char_t)'\n'||in==(char_t)'\0'||in==(char_t)'\f');
+AI_FORCE_INLINE bool IsLineEnd(char_t in) {
+    return (in == (char_t)'\r' || in == (char_t)'\n' || in == (char_t)'\0' || in == (char_t)'\f');
 }
 
 // ---------------------------------------------------------------------------------
 template <class char_t>
-AI_FORCE_INLINE
-bool IsSpaceOrNewLine( char_t in) {
+AI_FORCE_INLINE bool IsSpaceOrNewLine(char_t in) {
     return IsSpace<char_t>(in) || IsLineEnd<char_t>(in);
 }
 
 // ---------------------------------------------------------------------------------
 template <class char_t>
-AI_FORCE_INLINE
-bool SkipSpaces( const char_t* in, const char_t** out) {
-    while( *in == ( char_t )' ' || *in == ( char_t )'\t' ) {
+AI_FORCE_INLINE bool SkipSpaces(const char_t *in, const char_t **out) {
+    while (*in == (char_t)' ' || *in == (char_t)'\t') {
         ++in;
     }
     *out = in;
@@ -130,21 +126,19 @@ bool SkipSpaces( const char_t* in, const char_t** out) {
 
 // ---------------------------------------------------------------------------------
 template <class char_t>
-AI_FORCE_INLINE
-bool SkipSpaces( const char_t** inout) {
-    return SkipSpaces<char_t>(*inout,inout);
+AI_FORCE_INLINE bool SkipSpaces(const char_t **inout) {
+    return SkipSpaces<char_t>(*inout, inout);
 }
 
 // ---------------------------------------------------------------------------------
 template <class char_t>
-AI_FORCE_INLINE
-bool SkipLine( const char_t* in, const char_t** out) {
-    while( *in != ( char_t )'\r' && *in != ( char_t )'\n' && *in != ( char_t )'\0' ) {
+AI_FORCE_INLINE bool SkipLine(const char_t *in, const char_t **out) {
+    while (*in != (char_t)'\r' && *in != (char_t)'\n' && *in != (char_t)'\0') {
         ++in;
     }
 
     // files are opened in binary mode. Ergo there are both NL and CR
-    while( *in == ( char_t )'\r' || *in == ( char_t )'\n' ) {
+    while (*in == (char_t)'\r' || *in == (char_t)'\n') {
         ++in;
     }
     *out = in;
@@ -153,16 +147,14 @@ bool SkipLine( const char_t* in, const char_t** out) {
 
 // ---------------------------------------------------------------------------------
 template <class char_t>
-AI_FORCE_INLINE
-bool SkipLine( const char_t** inout) {
-    return SkipLine<char_t>(*inout,inout);
+AI_FORCE_INLINE bool SkipLine(const char_t **inout) {
+    return SkipLine<char_t>(*inout, inout);
 }
 
 // ---------------------------------------------------------------------------------
 template <class char_t>
-AI_FORCE_INLINE
-bool SkipSpacesAndLineEnd( const char_t* in, const char_t** out) {
-    while( *in == ( char_t )' ' || *in == ( char_t )'\t' || *in == ( char_t )'\r' || *in == ( char_t )'\n' ) {
+AI_FORCE_INLINE bool SkipSpacesAndLineEnd(const char_t *in, const char_t **out) {
+    while (*in == (char_t)' ' || *in == (char_t)'\t' || *in == (char_t)'\r' || *in == (char_t)'\n') {
         ++in;
     }
     *out = in;
@@ -171,27 +163,25 @@ bool SkipSpacesAndLineEnd( const char_t* in, const char_t** out) {
 
 // ---------------------------------------------------------------------------------
 template <class char_t>
-AI_FORCE_INLINE
-bool SkipSpacesAndLineEnd( const char_t** inout) {
-    return SkipSpacesAndLineEnd<char_t>(*inout,inout);
+AI_FORCE_INLINE bool SkipSpacesAndLineEnd(const char_t **inout) {
+    return SkipSpacesAndLineEnd<char_t>(*inout, inout);
 }
 
 // ---------------------------------------------------------------------------------
 template <class char_t>
-AI_FORCE_INLINE
-bool GetNextLine( const char_t*& buffer, char_t out[ BufferSize ] ) {
-    if( ( char_t )'\0' == *buffer ) {
+AI_FORCE_INLINE bool GetNextLine(const char_t *&buffer, char_t out[BufferSize]) {
+    if ((char_t)'\0' == *buffer) {
         return false;
     }
 
-    char* _out = out;
-    char* const end = _out + BufferSize;
-    while( !IsLineEnd( *buffer ) && _out < end ) {
+    char *_out = out;
+    char *const end = _out + BufferSize;
+    while (!IsLineEnd(*buffer) && _out < end) {
         *_out++ = *buffer++;
     }
     *_out = (char_t)'\0';
 
-    while( IsLineEnd( *buffer ) && '\0' != *buffer ) {
+    while (IsLineEnd(*buffer) && '\0' != *buffer) {
         ++buffer;
     }
 
@@ -200,18 +190,16 @@ bool GetNextLine( const char_t*& buffer, char_t out[ BufferSize ] ) {
 
 // ---------------------------------------------------------------------------------
 template <class char_t>
-AI_FORCE_INLINE bool IsNumeric( char_t in) {
-    return ( in >= '0' && in <= '9' ) || '-' == in || '+' == in;
+AI_FORCE_INLINE bool IsNumeric(char_t in) {
+    return (in >= '0' && in <= '9') || '-' == in || '+' == in;
 }
 
 // ---------------------------------------------------------------------------------
 template <class char_t>
-AI_FORCE_INLINE
-bool TokenMatch(char_t*& in, const char* token, unsigned int len)
-{
-    if (!::strncmp(token,in,len) && IsSpaceOrNewLine(in[len])) {
+AI_FORCE_INLINE bool TokenMatch(char_t *&in, const char *token, unsigned int len) {
+    if (!::strncmp(token, in, len) && IsSpaceOrNewLine(in[len])) {
         if (in[len] != '\0') {
-            in += len+1;
+            in += len + 1;
         } else {
             // If EOF after the token make sure we don't go past end of buffer
             in += len;
@@ -228,9 +216,9 @@ bool TokenMatch(char_t*& in, const char* token, unsigned int len)
  *  @param len Number of characters to check
  */
 AI_FORCE_INLINE
-bool TokenMatchI(const char*& in, const char* token, unsigned int len) {
-    if (!ASSIMP_strincmp(token,in,len) && IsSpaceOrNewLine(in[len])) {
-        in += len+1;
+bool TokenMatchI(const char *&in, const char *token, unsigned int len) {
+    if (!ASSIMP_strincmp(token, in, len) && IsSpaceOrNewLine(in[len])) {
+        in += len + 1;
         return true;
     }
     return false;
@@ -238,22 +226,22 @@ bool TokenMatchI(const char*& in, const char* token, unsigned int len) {
 
 // ---------------------------------------------------------------------------------
 AI_FORCE_INLINE
-void SkipToken(const char*& in) {
+void SkipToken(const char *&in) {
     SkipSpaces(&in);
-    while ( !IsSpaceOrNewLine( *in ) ) {
+    while (!IsSpaceOrNewLine(*in)) {
         ++in;
     }
 }
 
 // ---------------------------------------------------------------------------------
 AI_FORCE_INLINE
-std::string GetNextToken(const char*& in) {
+std::string GetNextToken(const char *&in) {
     SkipSpacesAndLineEnd(&in);
-    const char* cur = in;
-    while ( !IsSpaceOrNewLine( *in ) ) {
+    const char *cur = in;
+    while (!IsSpaceOrNewLine(*in)) {
         ++in;
     }
-    return std::string(cur,(size_t)(in-cur));
+    return std::string(cur, (size_t)(in - cur));
 }
 
 // ---------------------------------------------------------------------------------
@@ -289,6 +277,6 @@ AI_FORCE_INLINE unsigned int tokenize(const string_type &str, std::vector<string
 
 // ---------------------------------------------------------------------------------
 
-} // ! namespace Assimp
+} // namespace Assimp
 
 #endif // ! AI_PARSING_UTILS_H_INC

Some files were not shown because too many files changed in this diff