Jelajahi Sumber

start to migrate colladat and amf

Kim Kulling 5 tahun lalu
induk
melakukan
fb20e15163

+ 49 - 35
code/AssetLib/AMF/AMFImporter.cpp

@@ -5,8 +5,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,
@@ -82,7 +80,7 @@ void AMFImporter::Clear() {
     mTexture_Converted.clear();
     // Delete all elements
     if (!mNodeElement_List.empty()) {
-        for (CAMFImporter_NodeElement *ne : mNodeElement_List) {
+        for (AMFNodeElementBase *ne : mNodeElement_List) {
             delete ne;
         }
 
@@ -90,8 +88,14 @@ void AMFImporter::Clear() {
     }
 }
 
+AMFImporter::AMFImporter() :
+        mNodeElement_Cur(nullptr),
+        mXmlParser(nullptr) {
+    // empty
+}
+
 AMFImporter::~AMFImporter() {
-    if (mReader != nullptr) delete mReader;
+    delete mXmlParser;
     // Clear() is accounting if data already is deleted. So, just check again if all data is deleted.
     Clear();
 }
@@ -100,10 +104,12 @@ AMFImporter::~AMFImporter() {
 /************************************************************ Functions: find set ************************************************************/
 /*********************************************************************************************************************************************/
 
-bool AMFImporter::Find_NodeElement(const std::string &pID, const CAMFImporter_NodeElement::EType pType, CAMFImporter_NodeElement **pNodeElement) const {
-    for (CAMFImporter_NodeElement *ne : mNodeElement_List) {
+bool AMFImporter::Find_NodeElement(const std::string &pID, const AMFNodeElementBase::EType pType, AMFNodeElementBase **pNodeElement) const {
+    for (AMFNodeElementBase *ne : mNodeElement_List) {
         if ((ne->ID == pID) && (ne->Type == pType)) {
-            if (pNodeElement != nullptr) *pNodeElement = ne;
+            if (pNodeElement != nullptr) {
+                *pNodeElement = ne;
+            }
 
             return true;
         }
@@ -117,7 +123,9 @@ bool AMFImporter::Find_ConvertedNode(const std::string &pID, std::list<aiNode *>
 
     for (aiNode *node : pNodeList) {
         if (node->mName == node_name) {
-            if (pNode != nullptr) *pNode = node;
+            if (pNode != nullptr) {
+                *pNode = node;
+            }
 
             return true;
         }
@@ -129,7 +137,9 @@ bool AMFImporter::Find_ConvertedNode(const std::string &pID, std::list<aiNode *>
 bool AMFImporter::Find_ConvertedMaterial(const std::string &pID, const SPP_Material **pConvertedMaterial) const {
     for (const SPP_Material &mat : mMaterial_Converted) {
         if (mat.ID == pID) {
-            if (pConvertedMaterial != nullptr) *pConvertedMaterial = &mat;
+            if (pConvertedMaterial != nullptr) {
+                *pConvertedMaterial = &mat;
+            }
 
             return true;
         }
@@ -142,20 +152,20 @@ bool AMFImporter::Find_ConvertedMaterial(const std::string &pID, const SPP_Mater
 /************************************************************ Functions: throw set ***********************************************************/
 /*********************************************************************************************************************************************/
 
-void AMFImporter::Throw_CloseNotFound(const std::string &pNode) {
-    throw DeadlyImportError("Close tag for node <" + pNode + "> not found. Seems file is corrupt.");
+void AMFImporter::Throw_CloseNotFound(const std::string &nodeName) {
+    throw DeadlyImportError("Close tag for node <" + nodeName + "> not found. Seems file is corrupt.");
 }
 
-void AMFImporter::Throw_IncorrectAttr(const std::string &pAttrName) {
-    throw DeadlyImportError("Node <" + std::string(mReader->getNodeName()) + "> has incorrect attribute \"" + pAttrName + "\".");
+void AMFImporter::Throw_IncorrectAttr(const std::string &nodeName, const std::string &attrName) {
+    throw DeadlyImportError("Node <" + nodeName + "> has incorrect attribute \"" + attrName + "\".");
 }
 
-void AMFImporter::Throw_IncorrectAttrValue(const std::string &pAttrName) {
-    throw DeadlyImportError("Attribute \"" + pAttrName + "\" in node <" + std::string(mReader->getNodeName()) + "> has incorrect value.");
+void AMFImporter::Throw_IncorrectAttrValue(const std::string &nodeName, const std::string &attrName) {
+    throw DeadlyImportError("Attribute \"" + attrName + "\" in node <" + nodeName + "> has incorrect value.");
 }
 
-void AMFImporter::Throw_MoreThanOnceDefined(const std::string &pNodeType, const std::string &pDescription) {
-    throw DeadlyImportError("\"" + pNodeType + "\" node can be used only once in " + mReader->getNodeName() + ". Description: " + pDescription);
+void AMFImporter::Throw_MoreThanOnceDefined(const std::string &nodeName, const std::string &pNodeType, const std::string &pDescription) {
+    throw DeadlyImportError("\"" + pNodeType + "\" node can be used only once in " + nodeName + ". Description: " + pDescription);
 }
 
 void AMFImporter::Throw_ID_NotFound(const std::string &pID) const {
@@ -166,8 +176,10 @@ void AMFImporter::Throw_ID_NotFound(const std::string &pID) const {
 /************************************************************* Functions: XML set ************************************************************/
 /*********************************************************************************************************************************************/
 
-void AMFImporter::XML_CheckNode_MustHaveChildren() {
-    if (mReader->isEmptyElement()) throw DeadlyImportError(std::string("Node <") + mReader->getNodeName() + "> must have children.");
+void AMFImporter::XML_CheckNode_MustHaveChildren(pugi::xml_node &node) {
+    if (node.children().begin() == node.children().end()) {
+        throw DeadlyImportError(std::string("Node <") + node.name() + "> must have children.");
+    }
 }
 
 void AMFImporter::XML_CheckNode_SkipUnsupported(const std::string &pParentNodeName) {
@@ -211,9 +223,10 @@ casu_cres:
     }
 }
 
-bool AMFImporter::XML_SearchNode(const std::string &pNodeName) {
+bool AMFImporter::XML_SearchNode(const std::string &nodeName) {
+    mXmlParser->h(nodeName);
     while (mReader->read()) {
-        if ((mReader->getNodeType() == irr::io::EXN_ELEMENT) && XML_CheckNode_NameEqual(pNodeName)) return true;
+        if ((mReader->getNodeType() == irr::io::EXN_ELEMENT) && XML_CheckNode_NameEqual(nodeName)) return true;
     }
 
     return false;
@@ -366,23 +379,24 @@ void AMFImporter::ParseFile(const std::string &pFile, IOSystem *pIOHandler) {
     std::unique_ptr<IOStream> file(pIOHandler->Open(pFile, "rb"));
 
     // Check whether we can read from the file
-    if (file.get() == NULL) throw DeadlyImportError("Failed to open AMF file " + pFile + ".");
-
-    // generate a XML reader for it
-    std::unique_ptr<CIrrXML_IOStreamReader> mIOWrapper(new CIrrXML_IOStreamReader(file.get()));
-    mReader = irr::io::createIrrXMLReader(mIOWrapper.get());
-    if (!mReader) throw DeadlyImportError("Failed to create XML reader for file" + pFile + ".");
-    //
-    // start reading
-    // search for root tag <amf>
-    if (XML_SearchNode("amf"))
-        ParseNode_Root();
-    else
+    if (file.get() == nullptr) {
+        throw DeadlyImportError("Failed to open AMF file " + pFile + ".");
+    }
+
+    mXmlParser = new XmlParser();
+    if (!mXmlParser->parse( file.get() ) {
+        delete mXmlParser;
+        throw DeadlyImportError("Failed to create XML reader for file" + pFile + ".");
+    }
+
+    // Start reading, search for root tag <amf>
+    if (!mXmlParser->hasNode("amf")) {
         throw DeadlyImportError("Root node \"amf\" not found.");
+    }
+
+    ParseNode_Root();
 
     delete mReader;
-    // restore old XMLreader
-    mReader = OldReader;
 }
 
 // <amf

+ 170 - 167
code/AssetLib/AMF/AMFImporter.hpp

@@ -52,11 +52,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "AMFImporter_Node.hpp"
 
 // Header files, Assimp.
-#include <assimp/DefaultLogger.hpp>
-#include <assimp/importerdesc.h>
 #include "assimp/types.h"
 #include <assimp/BaseImporter.h>
 #include <assimp/XmlParser.h>
+#include <assimp/importerdesc.h>
+#include <assimp/DefaultLogger.hpp>
 
 // Header files, stdlib.
 #include <set>
@@ -99,22 +99,22 @@ namespace Assimp {
 ///
 class AMFImporter : public BaseImporter {
 private:
-    struct SPP_Material;// forward declaration
+    struct SPP_Material; // forward declaration
 
-                        /// \struct SPP_Composite
-                        /// Data type for post-processing step. More suitable container for part of material's composition.
+    /// \struct SPP_Composite
+    /// Data type for post-processing step. More suitable container for part of material's composition.
     struct SPP_Composite {
-        SPP_Material* Material;///< Pointer to material - part of composition.
-        std::string Formula;///< Formula for calculating ratio of \ref Material.
+        SPP_Material *Material; ///< Pointer to material - part of composition.
+        std::string Formula; ///< Formula for calculating ratio of \ref Material.
     };
 
     /// \struct SPP_Material
     /// Data type for post-processing step. More suitable container for material.
     struct SPP_Material {
-        std::string ID;///< Material ID.
-        std::list<AMFMetadata*> Metadata;///< Metadata of material.
-        AMFColor* Color;///< Color of material.
-        std::list<SPP_Composite> Composition;///< List of child materials if current material is composition of few another.
+        std::string ID; ///< Material ID.
+        std::list<AMFMetadata *> Metadata; ///< Metadata of material.
+        AMFColor *Color; ///< Color of material.
+        std::list<SPP_Composite> Composition; ///< List of child materials if current material is composition of few another.
 
         /// Return color calculated for specified coordinate.
         /// \param [in] pX - "x" coordinate.
@@ -127,176 +127,179 @@ private:
     /// Data type for post-processing step. More suitable container for texture.
     struct SPP_Texture {
         std::string ID;
-        size_t      Width, Height, Depth;
-        bool        Tiled;
-        char        FormatHint[9];// 8 for string + 1 for terminator.
-        uint8_t    *Data;
+        size_t Width, Height, Depth;
+        bool Tiled;
+        char FormatHint[9]; // 8 for string + 1 for terminator.
+        uint8_t *Data;
     };
 
     /// Data type for post-processing step. Contain face data.
     struct SComplexFace {
-        aiFace Face;///< Face vertices.
-        const AMFColor* Color;///< Face color. Equal to nullptr if color is not set for the face.
-        const AMFTexMap* TexMap;///< Face texture mapping data. Equal to nullptr if texture mapping is not set for the face.
+        aiFace Face; ///< Face vertices.
+        const AMFColor *Color; ///< Face color. Equal to nullptr if color is not set for the face.
+        const AMFTexMap *TexMap; ///< Face texture mapping data. Equal to nullptr if texture mapping is not set for the face.
     };
 
-	/// Clear all temporary data.
-	void Clear();
-
-	/// Get data stored in <vertices> and place it to arrays.
-	/// \param [in] pNodeElement - reference to node element which kept <object> data.
-	/// \param [in] pVertexCoordinateArray - reference to vertices coordinates kept in <vertices>.
-	/// \param [in] pVertexColorArray - reference to vertices colors for all <vertex's. If color for vertex is not set then corresponding member of array
-	/// contain nullptr.
-	void PostprocessHelper_CreateMeshDataArray(const AMFMesh& pNodeElement, std::vector<aiVector3D>& pVertexCoordinateArray,
-												std::vector<AMFColor*>& pVertexColorArray) const;
-
-	/// Return converted texture ID which related to specified source textures ID's. If converted texture does not exist then it will be created and ID on new
-	/// converted texture will be returned. Conversion: set of textures from \ref CAMFImporter_NodeElement_Texture to one \ref SPP_Texture and place it
-	/// to converted textures list.
-	/// Any of source ID's can be absent(empty string) or even one ID only specified. But at least one ID must be specified.
-	/// \param [in] pID_R - ID of source "red" texture.
-	/// \param [in] pID_G - ID of source "green" texture.
-	/// \param [in] pID_B - ID of source "blue" texture.
-	/// \param [in] pID_A - ID of source "alpha" texture.
-	/// \return index of the texture in array of the converted textures.
-	size_t PostprocessHelper_GetTextureID_Or_Create(const std::string& pID_R, const std::string& pID_G, const std::string& pID_B, const std::string& pID_A);
-
-	/// Separate input list by texture IDs. This step is needed because aiMesh can contain mesh which is use only one texture (or set: diffuse, bump etc).
-	/// \param [in] pInputList - input list with faces. Some of them can contain color or texture mapping, or both of them, or nothing. Will be cleared after
-	/// processing.
-	/// \param [out] pOutputList_Separated - output list of the faces lists. Separated faces list by used texture IDs. Will be cleared before processing.
-	void PostprocessHelper_SplitFacesByTextureID(std::list<SComplexFace>& pInputList, std::list<std::list<SComplexFace> >& pOutputList_Separated);
-
-	/// Check if child elements of node element is metadata and add it to scene node.
-	/// \param [in] pMetadataList - reference to list with collected metadata.
-	/// \param [out] pSceneNode - scene node in which metadata will be added.
-	void Postprocess_AddMetadata(const std::list<AMFMetadata*>& pMetadataList, aiNode& pSceneNode) const;
-
-	/// To create aiMesh and aiNode for it from <object>.
-	/// \param [in] pNodeElement - reference to node element which kept <object> data.
-	/// \param [out] pMeshList - reference to a list with all aiMesh of the scene.
-	/// \param [out] pSceneNode - pointer to place where new aiNode will be created.
-	void Postprocess_BuildNodeAndObject(const AMFObject& pNodeElement, std::list<aiMesh*>& pMeshList, aiNode** pSceneNode);
-
-	/// Create mesh for every <volume> in <mesh>.
-	/// \param [in] pNodeElement - reference to node element which kept <mesh> data.
-	/// \param [in] pVertexCoordinateArray - reference to vertices coordinates for all <volume>'s.
-	/// \param [in] pVertexColorArray - reference to vertices colors for all <volume>'s. If color for vertex is not set then corresponding member of array
-	/// contain nullptr.
-	/// \param [in] pObjectColor - pointer to colors for <object>. If color is not set then argument contain nullptr.
-	/// \param [in] pMaterialList - reference to a list with defined materials.
-	/// \param [out] pMeshList - reference to a list with all aiMesh of the scene.
-	/// \param [out] pSceneNode - reference to aiNode which will own new aiMesh's.
-	void Postprocess_BuildMeshSet(const AMFMesh& pNodeElement, const std::vector<aiVector3D>& pVertexCoordinateArray,
-									const std::vector<AMFColor*>& pVertexColorArray, const AMFColor* pObjectColor,
-									std::list<aiMesh*>& pMeshList, aiNode& pSceneNode);
-
-	/// Convert material from \ref CAMFImporter_NodeElement_Material to \ref SPP_Material.
-	/// \param [in] pMaterial - source CAMFImporter_NodeElement_Material.
-	void Postprocess_BuildMaterial(const AMFMaterial& pMaterial);
-
-	/// Create and add to aiNode's list new part of scene graph defined by <constellation>.
-	/// \param [in] pConstellation - reference to <constellation> node.
-	/// \param [out] pNodeList - reference to aiNode's list.
-	void Postprocess_BuildConstellation(AMFConstellation& pConstellation, std::list<aiNode*>& pNodeList) const;
-
-	/// Build Assimp scene graph in aiScene from collected data.
-	/// \param [out] pScene - pointer to aiScene where tree will be built.
-	void Postprocess_BuildScene(aiScene* pScene);
-
-	/// Decode Base64-encoded data.
-	/// \param [in] pInputBase64 - reference to input Base64-encoded string.
-	/// \param [out] pOutputData - reference to output array for decoded data.
-	void ParseHelper_Decode_Base64(const std::string& pInputBase64, std::vector<uint8_t>& pOutputData) const;
-
-	/// Parse <AMF> node of the file.
-	void ParseNode_Root(XmlNode &root);
-
-	/// Parse <constellation> node of the file.
-	void ParseNode_Constellation(XmlNode &node);
-
-	/// Parse <instance> node of the file.
-	void ParseNode_Instance(XmlNode &node);
-
-	/// Parse <material> node of the file.
-	void ParseNode_Material(XmlNode &node);
-
-	/// Parse <metadata> node.
-	void ParseNode_Metadata(XmlNode &node);
-
-	/// Parse <object> node of the file.
-	void ParseNode_Object(XmlNode &node);
-
-	/// Parse <texture> node of the file.
-	void ParseNode_Texture(XmlNode &node);
-
-	/// Parse <coordinates> node of the file.
-	void ParseNode_Coordinates(XmlNode &node);
-
-	/// Parse <edge> node of the file.
-	void ParseNode_Edge(XmlNode &node);
-
-	/// Parse <mesh> node of the file.
-	void ParseNode_Mesh(XmlNode &node);
-
-	/// Parse <triangle> node of the file.
-	void ParseNode_Triangle(XmlNode &node);
-
-	/// Parse <vertex> node of the file.
-	void ParseNode_Vertex(XmlNode &node);
-
-	/// Parse <vertices> node of the file.
-	void ParseNode_Vertices(XmlNode &node);
-
-	/// Parse <volume> node of the file.
-	void ParseNode_Volume(XmlNode &node);
-
-	/// Parse <color> node of the file.
-	void ParseNode_Color(XmlNode &node);
-
-	/// Parse <texmap> of <map> node of the file.
-	/// \param [in] pUseOldName - if true then use old name of node(and children) - <map>, instead of new name - <texmap>.
-	void ParseNode_TexMap(XmlNode &node, const bool pUseOldName = false);
+    /// Clear all temporary data.
+    void Clear();
+
+    /// Get data stored in <vertices> and place it to arrays.
+    /// \param [in] pNodeElement - reference to node element which kept <object> data.
+    /// \param [in] pVertexCoordinateArray - reference to vertices coordinates kept in <vertices>.
+    /// \param [in] pVertexColorArray - reference to vertices colors for all <vertex's. If color for vertex is not set then corresponding member of array
+    /// contain nullptr.
+    void PostprocessHelper_CreateMeshDataArray(const AMFMesh &pNodeElement, std::vector<aiVector3D> &pVertexCoordinateArray,
+            std::vector<AMFColor *> &pVertexColorArray) const;
+
+    /// Return converted texture ID which related to specified source textures ID's. If converted texture does not exist then it will be created and ID on new
+    /// converted texture will be returned. Conversion: set of textures from \ref CAMFImporter_NodeElement_Texture to one \ref SPP_Texture and place it
+    /// to converted textures list.
+    /// Any of source ID's can be absent(empty string) or even one ID only specified. But at least one ID must be specified.
+    /// \param [in] pID_R - ID of source "red" texture.
+    /// \param [in] pID_G - ID of source "green" texture.
+    /// \param [in] pID_B - ID of source "blue" texture.
+    /// \param [in] pID_A - ID of source "alpha" texture.
+    /// \return index of the texture in array of the converted textures.
+    size_t PostprocessHelper_GetTextureID_Or_Create(const std::string &pID_R, const std::string &pID_G, const std::string &pID_B, const std::string &pID_A);
+
+    /// Separate input list by texture IDs. This step is needed because aiMesh can contain mesh which is use only one texture (or set: diffuse, bump etc).
+    /// \param [in] pInputList - input list with faces. Some of them can contain color or texture mapping, or both of them, or nothing. Will be cleared after
+    /// processing.
+    /// \param [out] pOutputList_Separated - output list of the faces lists. Separated faces list by used texture IDs. Will be cleared before processing.
+    void PostprocessHelper_SplitFacesByTextureID(std::list<SComplexFace> &pInputList, std::list<std::list<SComplexFace>> &pOutputList_Separated);
+
+    /// Check if child elements of node element is metadata and add it to scene node.
+    /// \param [in] pMetadataList - reference to list with collected metadata.
+    /// \param [out] pSceneNode - scene node in which metadata will be added.
+    void Postprocess_AddMetadata(const std::list<AMFMetadata *> &pMetadataList, aiNode &pSceneNode) const;
+
+    /// To create aiMesh and aiNode for it from <object>.
+    /// \param [in] pNodeElement - reference to node element which kept <object> data.
+    /// \param [out] pMeshList - reference to a list with all aiMesh of the scene.
+    /// \param [out] pSceneNode - pointer to place where new aiNode will be created.
+    void Postprocess_BuildNodeAndObject(const AMFObject &pNodeElement, std::list<aiMesh *> &pMeshList, aiNode **pSceneNode);
+
+    /// Create mesh for every <volume> in <mesh>.
+    /// \param [in] pNodeElement - reference to node element which kept <mesh> data.
+    /// \param [in] pVertexCoordinateArray - reference to vertices coordinates for all <volume>'s.
+    /// \param [in] pVertexColorArray - reference to vertices colors for all <volume>'s. If color for vertex is not set then corresponding member of array
+    /// contain nullptr.
+    /// \param [in] pObjectColor - pointer to colors for <object>. If color is not set then argument contain nullptr.
+    /// \param [in] pMaterialList - reference to a list with defined materials.
+    /// \param [out] pMeshList - reference to a list with all aiMesh of the scene.
+    /// \param [out] pSceneNode - reference to aiNode which will own new aiMesh's.
+    void Postprocess_BuildMeshSet(const AMFMesh &pNodeElement, const std::vector<aiVector3D> &pVertexCoordinateArray,
+            const std::vector<AMFColor *> &pVertexColorArray, const AMFColor *pObjectColor,
+            std::list<aiMesh *> &pMeshList, aiNode &pSceneNode);
+
+    /// Convert material from \ref CAMFImporter_NodeElement_Material to \ref SPP_Material.
+    /// \param [in] pMaterial - source CAMFImporter_NodeElement_Material.
+    void Postprocess_BuildMaterial(const AMFMaterial &pMaterial);
+
+    /// Create and add to aiNode's list new part of scene graph defined by <constellation>.
+    /// \param [in] pConstellation - reference to <constellation> node.
+    /// \param [out] pNodeList - reference to aiNode's list.
+    void Postprocess_BuildConstellation(AMFConstellation &pConstellation, std::list<aiNode *> &pNodeList) const;
+
+    /// Build Assimp scene graph in aiScene from collected data.
+    /// \param [out] pScene - pointer to aiScene where tree will be built.
+    void Postprocess_BuildScene(aiScene *pScene);
+
+    /// Decode Base64-encoded data.
+    /// \param [in] pInputBase64 - reference to input Base64-encoded string.
+    /// \param [out] pOutputData - reference to output array for decoded data.
+    void ParseHelper_Decode_Base64(const std::string &pInputBase64, std::vector<uint8_t> &pOutputData) const;
+
+    /// Parse <AMF> node of the file.
+    void ParseNode_Root(XmlNode &root);
+
+    /// Parse <constellation> node of the file.
+    void ParseNode_Constellation(XmlNode &node);
+
+    /// Parse <instance> node of the file.
+    void ParseNode_Instance(XmlNode &node);
+
+    /// Parse <material> node of the file.
+    void ParseNode_Material(XmlNode &node);
+
+    /// Parse <metadata> node.
+    void ParseNode_Metadata(XmlNode &node);
+
+    /// Parse <object> node of the file.
+    void ParseNode_Object(XmlNode &node);
+
+    /// Parse <texture> node of the file.
+    void ParseNode_Texture(XmlNode &node);
+
+    /// Parse <coordinates> node of the file.
+    void ParseNode_Coordinates(XmlNode &node);
+
+    /// Parse <edge> node of the file.
+    void ParseNode_Edge(XmlNode &node);
+
+    /// Parse <mesh> node of the file.
+    void ParseNode_Mesh(XmlNode &node);
+
+    /// Parse <triangle> node of the file.
+    void ParseNode_Triangle(XmlNode &node);
+
+    /// Parse <vertex> node of the file.
+    void ParseNode_Vertex(XmlNode &node);
+
+    /// Parse <vertices> node of the file.
+    void ParseNode_Vertices(XmlNode &node);
+
+    /// Parse <volume> node of the file.
+    void ParseNode_Volume(XmlNode &node);
+
+    /// Parse <color> node of the file.
+    void ParseNode_Color(XmlNode &node);
+
+    /// Parse <texmap> of <map> node of the file.
+    /// \param [in] pUseOldName - if true then use old name of node(and children) - <map>, instead of new name - <texmap>.
+    void ParseNode_TexMap(XmlNode &node, const bool pUseOldName = false);
 
 public:
-	/// Default constructor.
-	AMFImporter() AI_NO_EXCEPT
-    : mNodeElement_Cur(nullptr)
-    , mXmlParser(nullptr) {
-        // empty
-    }
-
-	/// Default destructor.
-	~AMFImporter();
-
-	/// Parse AMF file and fill scene graph. The function has no return value. Result can be found by analyzing the generated graph.
-	/// Also exception can be thrown if trouble will found.
-	/// \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);
-
-	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;
-
-    AMFImporter(const AMFImporter& pScene) = delete;
-    AMFImporter& operator=(const AMFImporter& pScene) = delete;
+    /// Default constructor.
+    AMFImporter() AI_NO_EXCEPT;
+
+    /// Default destructor.
+    ~AMFImporter();
+
+    /// Parse AMF file and fill scene graph. The function has no return value. Result can be found by analyzing the generated graph.
+    /// Also exception can be thrown if trouble will found.
+    /// \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);
+
+    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;
+    bool Find_NodeElement(const std::string &pID, const AMFNodeElementBase::EType pType, AMFNodeElementBase **pNodeElement) const;
+    bool Find_ConvertedNode(const std::string &pID, std::list<aiNode *> &pNodeList, aiNode **pNode) const;
+    bool Find_ConvertedMaterial(const std::string &pID, const SPP_Material **pConvertedMaterial) const;
+    void Throw_CloseNotFound(const std::string &nodeName);
+    void Throw_IncorrectAttr(const std::string &nodeName, const std::string &pAttrName);
+    void Throw_IncorrectAttrValue(const std::string &nodeName, const std::string &pAttrName);
+    void Throw_MoreThanOnceDefined(const std::string &nodeName, const std::string &pNodeType, const std::string &pDescription);
+    void Throw_ID_NotFound(const std::string &pID) const;
+    void XML_CheckNode_MustHaveChildren(pugi::xml_node &node);
+
+    AMFImporter(const AMFImporter &pScene) = delete;
+    AMFImporter &operator=(const AMFImporter &pScene) = delete;
 
 private:
     static const aiImporterDesc Description;
 
-    AMFNodeElementBase* mNodeElement_Cur;///< Current element.
-    std::list<AMFNodeElementBase*> mNodeElement_List;///< All elements of scene graph.
-	XmlParser *mXmlParser;
-    //irr::io::IrrXMLReader* mReader;///< Pointer to XML-reader object
+    AMFNodeElementBase *mNodeElement_Cur; ///< Current element.
+    std::list<AMFNodeElementBase *> mNodeElement_List; ///< All elements of scene graph.
+    XmlParser *mXmlParser;
     std::string mUnit;
-    std::list<SPP_Material> mMaterial_Converted;///< List of converted materials for postprocessing step.
-    std::list<SPP_Texture> mTexture_Converted;///< List of converted textures for postprocessing step.
-
+    std::list<SPP_Material> mMaterial_Converted; ///< List of converted materials for postprocessing step.
+    std::list<SPP_Texture> mTexture_Converted; ///< List of converted textures for postprocessing step.
 };
 
-}// namespace Assimp
+} // namespace Assimp
 
 #endif // INCLUDED_AI_AMF_IMPORTER_H

+ 267 - 227
code/AssetLib/AMF/AMFImporter_Geometry.cpp

@@ -5,8 +5,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,
@@ -51,22 +49,39 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "AMFImporter.hpp"
 #include "AMFImporter_Macro.hpp"
 
-namespace Assimp
-{
+#include <assimp/ParsingUtils.h>
+
+namespace Assimp {
 
 // <mesh>
 // </mesh>
 // A 3D mesh hull.
 // Multi elements - Yes.
 // Parent element - <object>.
-void AMFImporter::ParseNode_Mesh()
-{
-CAMFImporter_NodeElement* ne;
-
-	// create new mesh object.
-	ne = new CAMFImporter_NodeElement_Mesh(mNodeElement_Cur);
-	// Check for child nodes
-	if(!mReader->isEmptyElement())
+void AMFImporter::ParseNode_Mesh(XmlNode &node) {
+    AMFNodeElementBase *ne = nullptr;
+
+    // create new mesh object.
+    ne = new AMFMesh(mNodeElement_Cur);
+    // Check for child nodes
+    if (0 != ASSIMP_stricmp(node.name(), "mesh")) {
+        return;
+    }
+
+    bool found_verts = false, found_volumes = false;
+    pugi::xml_node vertNode = node.child("vertices");
+    if (!vertNode.empty()) {
+        ParseNode_Vertices(vertNode);
+        found_verts = true;
+    }
+
+    pugi::xml_node volumeNode = node.child("volume");
+    if (!volumeNode.empty()) {
+        ParseNode_Volume(volumeNode);
+        found_volumes = true;
+    }
+
+    /*if(!mReader->isEmptyElement())
 	{
 		bool vert_read = false;
 
@@ -87,12 +102,14 @@ CAMFImporter_NodeElement* ne;
 		MACRO_NODECHECK_LOOPEND("mesh");
 		ParseHelper_Node_Exit();
 	}// if(!mReader->isEmptyElement())
-	else
-	{
-		mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
-	}// if(!mReader->isEmptyElement()) else
-
-	mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
+	else*/
+    // Add element to child list of current element
+    if (!found_verts && !found_volumes) {
+        mNodeElement_Cur->Child.push_back(ne);
+    } // if(!mReader->isEmptyElement()) else
+
+    // and to node element list because its a new object in graph.
+    mNodeElement_List.push_back(ne);
 }
 
 // <vertices>
@@ -100,27 +117,34 @@ CAMFImporter_NodeElement* ne;
 // The list of vertices to be used in defining triangles.
 // Multi elements - No.
 // Parent element - <mesh>.
-void AMFImporter::ParseNode_Vertices()
-{
-CAMFImporter_NodeElement* ne;
-
-	// create new mesh object.
-	ne = new CAMFImporter_NodeElement_Vertices(mNodeElement_Cur);
-	// Check for child nodes
-	if(!mReader->isEmptyElement())
-	{
-		ParseHelper_Node_Enter(ne);
-		MACRO_NODECHECK_LOOPBEGIN("vertices");
-			if(XML_CheckNode_NameEqual("vertex")) { ParseNode_Vertex(); continue; }
-		MACRO_NODECHECK_LOOPEND("vertices");
-		ParseHelper_Node_Exit();
-	}// if(!mReader->isEmptyElement())
-	else
-	{
-		mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
-	}// if(!mReader->isEmptyElement()) else
-
-	mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
+void AMFImporter::ParseNode_Vertices(XmlNode &node) {
+    AMFNodeElementBase *ne = nullptr;
+
+    // create new mesh object.
+    ne = new AMFVertices(mNodeElement_Cur);
+    // Check for child nodes
+    pugi::xml_node vertexNode = node.child("vertex");
+    if (!vertexNode.empty()) {
+        ParseNode_Vertex(vertexNode);
+    } else {
+        mNodeElement_Cur->Child.push_back(ne); // Add element to child list of current element
+    } // if(!mReader->isEmptyElement()) else
+
+    /*if (!mReader->isEmptyElement()) {
+            ParseHelper_Node_Enter(ne);
+            MACRO_NODECHECK_LOOPBEGIN("vertices");
+            if (XML_CheckNode_NameEqual("vertex")) {
+                ParseNode_Vertex();
+                continue;
+            }
+            MACRO_NODECHECK_LOOPEND("vertices");
+            ParseHelper_Node_Exit();
+            } // if(!mReader->isEmptyElement())
+        else {
+            mNodeElement_Cur->Child.push_back(ne); // Add element to child list of current element
+        } // if(!mReader->isEmptyElement()) else*/
+
+    mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph.
 }
 
 // <vertex>
@@ -128,52 +152,64 @@ CAMFImporter_NodeElement* ne;
 // A vertex to be referenced in triangles.
 // Multi elements - Yes.
 // Parent element - <vertices>.
-void AMFImporter::ParseNode_Vertex()
-{
-CAMFImporter_NodeElement* ne;
-
-	// create new mesh object.
-	ne = new CAMFImporter_NodeElement_Vertex(mNodeElement_Cur);
-	// Check for child nodes
-	if(!mReader->isEmptyElement())
-	{
-		bool col_read = false;
-		bool coord_read = false;
-
-		ParseHelper_Node_Enter(ne);
-		MACRO_NODECHECK_LOOPBEGIN("vertex");
-			if(XML_CheckNode_NameEqual("color"))
-			{
-				// Check if data already defined.
-				if(col_read) Throw_MoreThanOnceDefined("color", "Only one color can be defined for <vertex>.");
-				// read data and set flag about it
-				ParseNode_Color();
-				col_read = true;
-
-				continue;
-			}
-
-			if(XML_CheckNode_NameEqual("coordinates"))
-			{
-				// Check if data already defined.
-				if(coord_read) Throw_MoreThanOnceDefined("coordinates", "Only one coordinates set can be defined for <vertex>.");
-				// read data and set flag about it
-				ParseNode_Coordinates();
-				coord_read = true;
-
-				continue;
-			}
-
-			if(XML_CheckNode_NameEqual("metadata")) { ParseNode_Metadata(); continue; }
-		MACRO_NODECHECK_LOOPEND("vertex");
-		ParseHelper_Node_Exit();
-	}// if(!mReader->isEmptyElement())
-	else
-	{
-		mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
-	}// if(!mReader->isEmptyElement()) else
-
-	mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
+void AMFImporter::ParseNode_Vertex(XmlNode &node) {
+    AMFNodeElementBase *ne = nullptr;
+
+    // create new mesh object.
+    ne = new AMFVertex(mNodeElement_Cur);
+    pugi::xml_node colorNode = node.child("color");
+    bool col_read = false;
+    bool coord_read = false;
+    if (!colorNode.empty()) {
+        ParseNode_Color(colorNode);
+        col_read = true;
+    }
+    pugi::xml_node coordNode = node.child("coordinates");
+    if (!coordNode.empty()) {
+        ParseNode_Coordinates(coordNode);
+        coord_read = true;
+    }
+    if (!coord_read && !coord_read) {
+        mNodeElement_Cur->Child.push_back(ne); // Add element to child list of current element
+    }
+
+        // Check for child nodes
+/*        if (!mReader->isEmptyElement()) {
+
+            ParseHelper_Node_Enter(ne);
+            MACRO_NODECHECK_LOOPBEGIN("vertex");
+            if (XML_CheckNode_NameEqual("color")) {
+                // Check if data already defined.
+                if (col_read) Throw_MoreThanOnceDefined("color", "Only one color can be defined for <vertex>.");
+                // read data and set flag about it
+                ParseNode_Color();
+                col_read = true;
+
+                continue;
+            }
+
+            if (XML_CheckNode_NameEqual("coordinates")) {
+                // Check if data already defined.
+                if (coord_read) Throw_MoreThanOnceDefined("coordinates", "Only one coordinates set can be defined for <vertex>.");
+                // read data and set flag about it
+                ParseNode_Coordinates();
+                coord_read = true;
+
+                continue;
+            }
+
+            if (XML_CheckNode_NameEqual("metadata")) {
+                ParseNode_Metadata();
+                continue;
+            }
+            MACRO_NODECHECK_LOOPEND("vertex");
+            ParseHelper_Node_Exit();
+        } // if(!mReader->isEmptyElement())
+        else {
+            mNodeElement_Cur->Child.push_back(ne); // Add element to child list of current element
+        } // if(!mReader->isEmptyElement()) else
+        */
+    mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph.
 }
 
 // <coordinates>
@@ -186,37 +222,42 @@ CAMFImporter_NodeElement* ne;
 //   <x>, <y>, <z>
 //   Multi elements - No.
 //   X, Y, or Z coordinate, respectively, of a vertex position in space.
-void AMFImporter::ParseNode_Coordinates()
-{
-CAMFImporter_NodeElement* ne;
-
-	// create new color object.
-	ne = new CAMFImporter_NodeElement_Coordinates(mNodeElement_Cur);
-
-	CAMFImporter_NodeElement_Coordinates& als = *((CAMFImporter_NodeElement_Coordinates*)ne);// alias for convenience
-
-	// Check for child nodes
-	if(!mReader->isEmptyElement())
-	{
-		bool read_flag[3] = { false, false, false };
-
-		ParseHelper_Node_Enter(ne);
-		MACRO_NODECHECK_LOOPBEGIN("coordinates");
-			MACRO_NODECHECK_READCOMP_F("x", read_flag[0], als.Coordinate.x);
-			MACRO_NODECHECK_READCOMP_F("y", read_flag[1], als.Coordinate.y);
-			MACRO_NODECHECK_READCOMP_F("z", read_flag[2], als.Coordinate.z);
-		MACRO_NODECHECK_LOOPEND("coordinates");
-		ParseHelper_Node_Exit();
-		// check that all components was defined
-		if((read_flag[0] && read_flag[1] && read_flag[2]) == 0) throw DeadlyImportError("Not all coordinate's components are defined.");
-
-	}// if(!mReader->isEmptyElement())
-	else
-	{
-		mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
-	}// if(!mReader->isEmptyElement()) else
-
-	mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
+void AMFImporter::ParseNode_Coordinates(XmlNode &node) {
+    AMFNodeElementBase *ne = nullptr;
+
+    // create new color object.
+    ne = new AMFCoordinates(mNodeElement_Cur);
+
+    AMFCoordinates &als = *((AMFCoordinates *)ne); // alias for convenience
+
+    if (node.attributes().begin() != node.attributes().end()) {
+        als.Coordinate.x = (ai_real)node.attribute("x").as_float();
+        als.Coordinate.y = (ai_real)node.attribute("y").as_float();
+        als.Coordinate.z = (ai_real)node.attribute("z").as_float();
+    } else {
+        mNodeElement_Cur->Child.push_back(ne);
+    }
+
+    /*// Check for child nodes
+    if (!mReader->isEmptyElement()) {
+        bool read_flag[3] = { false, false, false };
+
+        ParseHelper_Node_Enter(ne);
+        MACRO_NODECHECK_LOOPBEGIN("coordinates");
+        MACRO_NODECHECK_READCOMP_F("x", read_flag[0], als.Coordinate.x);
+        MACRO_NODECHECK_READCOMP_F("y", read_flag[1], als.Coordinate.y);
+        MACRO_NODECHECK_READCOMP_F("z", read_flag[2], als.Coordinate.z);
+        MACRO_NODECHECK_LOOPEND("coordinates");
+        ParseHelper_Node_Exit();
+        // check that all components was defined
+        if ((read_flag[0] && read_flag[1] && read_flag[2]) == 0) throw DeadlyImportError("Not all coordinate's components are defined.");
+
+    } // if(!mReader->isEmptyElement())
+    else {
+        mNodeElement_Cur->Child.push_back(ne); // Add element to child list of current element
+    } // if(!mReader->isEmptyElement()) else*/
+
+    mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph.
 }
 
 // <volume
@@ -228,52 +269,56 @@ CAMFImporter_NodeElement* ne;
 // Defines a volume from the established vertex list.
 // Multi elements - Yes.
 // Parent element - <mesh>.
-void AMFImporter::ParseNode_Volume()
-{
-std::string materialid;
-std::string type;
-CAMFImporter_NodeElement* ne;
-
-	// Read attributes for node <color>.
-	MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECK_RET("materialid", materialid, mReader->getAttributeValue);
-		MACRO_ATTRREAD_CHECK_RET("type", type, mReader->getAttributeValue);
-	MACRO_ATTRREAD_LOOPEND;
-
-	// create new object.
-	ne = new CAMFImporter_NodeElement_Volume(mNodeElement_Cur);
-	// and assign read data
-	((CAMFImporter_NodeElement_Volume*)ne)->MaterialID = materialid;
-	((CAMFImporter_NodeElement_Volume*)ne)->Type = type;
-	// Check for child nodes
-	if(!mReader->isEmptyElement())
-	{
-		bool col_read = false;
-
-		ParseHelper_Node_Enter(ne);
-		MACRO_NODECHECK_LOOPBEGIN("volume");
-			if(XML_CheckNode_NameEqual("color"))
-			{
-				// Check if data already defined.
-				if(col_read) Throw_MoreThanOnceDefined("color", "Only one color can be defined for <volume>.");
-				// read data and set flag about it
-				ParseNode_Color();
-				col_read = true;
-
-				continue;
-			}
-
-			if(XML_CheckNode_NameEqual("triangle")) { ParseNode_Triangle(); continue; }
-			if(XML_CheckNode_NameEqual("metadata")) { ParseNode_Metadata(); continue; }
-		MACRO_NODECHECK_LOOPEND("volume");
-		ParseHelper_Node_Exit();
-	}// if(!mReader->isEmptyElement())
-	else
-	{
-		mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
-	}// if(!mReader->isEmptyElement()) else
-
-	mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
+void AMFImporter::ParseNode_Volume(XmlNode &node) {
+    std::string materialid;
+    std::string type;
+    AMFNodeElementBase *ne = new AMFVolume(mNodeElement_Cur);
+
+    // Read attributes for node <color>.
+    /*MACRO_ATTRREAD_LOOPBEG;
+    MACRO_ATTRREAD_CHECK_RET("materialid", materialid, mReader->getAttributeValue);
+    MACRO_ATTRREAD_CHECK_RET("type", type, mReader->getAttributeValue);
+    MACRO_ATTRREAD_LOOPEND;*/
+
+    // create new object.
+    //ne = new CAMFImporter_NodeElement_Volume(mNodeElement_Cur);
+    // and assign read data
+   
+    ((AMFVolume *)ne)->MaterialID = node.attribute("materialid").as_string();
+     
+    ((AMFVolume *)ne)->Type = type;
+    // Check for child nodes
+    if (!mReader->isEmptyElement()) {
+        bool col_read = false;
+
+        ParseHelper_Node_Enter(ne);
+        MACRO_NODECHECK_LOOPBEGIN("volume");
+        if (XML_CheckNode_NameEqual("color")) {
+            // Check if data already defined.
+            if (col_read) Throw_MoreThanOnceDefined("color", "Only one color can be defined for <volume>.");
+            // read data and set flag about it
+            ParseNode_Color();
+            col_read = true;
+
+            continue;
+        }
+
+        if (XML_CheckNode_NameEqual("triangle")) {
+            ParseNode_Triangle();
+            continue;
+        }
+        if (XML_CheckNode_NameEqual("metadata")) {
+            ParseNode_Metadata();
+            continue;
+        }
+        MACRO_NODECHECK_LOOPEND("volume");
+        ParseHelper_Node_Exit();
+    } // if(!mReader->isEmptyElement())
+    else {
+        mNodeElement_Cur->Child.push_back(ne); // Add element to child list of current element
+    } // if(!mReader->isEmptyElement()) else
+
+    mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph.
 }
 
 // <triangle>
@@ -286,72 +331,67 @@ CAMFImporter_NodeElement* ne;
 //   <v1>, <v2>, <v3>
 //   Multi elements - No.
 //   Index of the desired vertices in a triangle or edge.
-void AMFImporter::ParseNode_Triangle()
-{
-CAMFImporter_NodeElement* ne;
-
-	// create new color object.
-	ne = new CAMFImporter_NodeElement_Triangle(mNodeElement_Cur);
-
-	CAMFImporter_NodeElement_Triangle& als = *((CAMFImporter_NodeElement_Triangle*)ne);// alias for convenience
-
-	// Check for child nodes
-	if(!mReader->isEmptyElement())
-	{
-		bool col_read = false, tex_read = false;
-		bool read_flag[3] = { false, false, false };
-
-		ParseHelper_Node_Enter(ne);
-		MACRO_NODECHECK_LOOPBEGIN("triangle");
-			if(XML_CheckNode_NameEqual("color"))
-			{
-				// Check if data already defined.
-				if(col_read) Throw_MoreThanOnceDefined("color", "Only one color can be defined for <triangle>.");
-				// read data and set flag about it
-				ParseNode_Color();
-				col_read = true;
-
-				continue;
-			}
-
-			if(XML_CheckNode_NameEqual("texmap"))// new name of node: "texmap".
-			{
-				// Check if data already defined.
-				if(tex_read) Throw_MoreThanOnceDefined("texmap", "Only one texture coordinate can be defined for <triangle>.");
-				// read data and set flag about it
-				ParseNode_TexMap();
-				tex_read = true;
-
-				continue;
-			}
-			else if(XML_CheckNode_NameEqual("map"))// old name of node: "map".
-			{
-				// Check if data already defined.
-				if(tex_read) Throw_MoreThanOnceDefined("map", "Only one texture coordinate can be defined for <triangle>.");
-				// read data and set flag about it
-				ParseNode_TexMap(true);
-				tex_read = true;
-
-				continue;
-			}
-
-			MACRO_NODECHECK_READCOMP_U32("v1", read_flag[0], als.V[0]);
-			MACRO_NODECHECK_READCOMP_U32("v2", read_flag[1], als.V[1]);
-			MACRO_NODECHECK_READCOMP_U32("v3", read_flag[2], als.V[2]);
-		MACRO_NODECHECK_LOOPEND("triangle");
-		ParseHelper_Node_Exit();
-		// check that all components was defined
-		if((read_flag[0] && read_flag[1] && read_flag[2]) == 0) throw DeadlyImportError("Not all vertices of the triangle are defined.");
-
-	}// if(!mReader->isEmptyElement())
-	else
-	{
-		mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
-	}// if(!mReader->isEmptyElement()) else
-
-	mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
+void AMFImporter::ParseNode_Triangle() {
+    CAMFImporter_NodeElement *ne;
+
+    // create new color object.
+    ne = new CAMFImporter_NodeElement_Triangle(mNodeElement_Cur);
+
+    CAMFImporter_NodeElement_Triangle &als = *((CAMFImporter_NodeElement_Triangle *)ne); // alias for convenience
+
+    // Check for child nodes
+    if (!mReader->isEmptyElement()) {
+        bool col_read = false, tex_read = false;
+        bool read_flag[3] = { false, false, false };
+
+        ParseHelper_Node_Enter(ne);
+        MACRO_NODECHECK_LOOPBEGIN("triangle");
+        if (XML_CheckNode_NameEqual("color")) {
+            // Check if data already defined.
+            if (col_read) Throw_MoreThanOnceDefined("color", "Only one color can be defined for <triangle>.");
+            // read data and set flag about it
+            ParseNode_Color();
+            col_read = true;
+
+            continue;
+        }
+
+        if (XML_CheckNode_NameEqual("texmap")) // new name of node: "texmap".
+        {
+            // Check if data already defined.
+            if (tex_read) Throw_MoreThanOnceDefined("texmap", "Only one texture coordinate can be defined for <triangle>.");
+            // read data and set flag about it
+            ParseNode_TexMap();
+            tex_read = true;
+
+            continue;
+        } else if (XML_CheckNode_NameEqual("map")) // old name of node: "map".
+        {
+            // Check if data already defined.
+            if (tex_read) Throw_MoreThanOnceDefined("map", "Only one texture coordinate can be defined for <triangle>.");
+            // read data and set flag about it
+            ParseNode_TexMap(true);
+            tex_read = true;
+
+            continue;
+        }
+
+        MACRO_NODECHECK_READCOMP_U32("v1", read_flag[0], als.V[0]);
+        MACRO_NODECHECK_READCOMP_U32("v2", read_flag[1], als.V[1]);
+        MACRO_NODECHECK_READCOMP_U32("v3", read_flag[2], als.V[2]);
+        MACRO_NODECHECK_LOOPEND("triangle");
+        ParseHelper_Node_Exit();
+        // check that all components was defined
+        if ((read_flag[0] && read_flag[1] && read_flag[2]) == 0) throw DeadlyImportError("Not all vertices of the triangle are defined.");
+
+    } // if(!mReader->isEmptyElement())
+    else {
+        mNodeElement_Cur->Child.push_back(ne); // Add element to child list of current element
+    } // if(!mReader->isEmptyElement()) else
+
+    mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph.
 }
 
-}// namespace Assimp
+} // namespace Assimp
 
 #endif // !ASSIMP_BUILD_NO_AMF_IMPORTER

+ 27 - 24
code/AssetLib/AMF/AMFImporter_Material.cpp

@@ -51,8 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "AMFImporter.hpp"
 //#include "AMFImporter_Macro.hpp"
 
-namespace Assimp
-{
+namespace Assimp {
 
 // <color
 // profile="" - The ICC color space used to interpret the three color channels <r>, <g> and <b>.
@@ -79,18 +78,19 @@ void AMFImporter::ParseNode_Color(XmlNode &node) {
 	if (!node.empty()) {
 		bool read_flag[4] = { false, false, false, false };
 		for (pugi::xml_node &child : node.children()) {
-			if (child.name() == "r") {
+            std::string name = child.name();
+            if ( name == "r") {
 				read_flag[0] = true;
-				als.Color.r = atof(child.value());
-			} else if (child.name() == "g") {
+                als.Color.r = (ai_real)::atof(child.value());
+            } else if (name == "g") {
 				read_flag[1] = true;
-				als.Color.g = atof(child.value());
-			} else if (child.name() == "b") {
+                als.Color.g = (ai_real)::atof(child.value());
+            } else if (name == "b") {
 				read_flag[2] = true;
-				als.Color.b = atof(child.value());
-			} else if (child.name() == "g") {
+                als.Color.b = (ai_real)::atof(child.value());
+            } else if (name == "g") {
 			    read_flag[3] = true;
-		    	als.Color.a = atof(child.value());
+                als.Color.a = (ai_real) ::atof(child.value());
 		    }
         }
 		// check that all components was defined
@@ -127,10 +127,11 @@ void AMFImporter::ParseNode_Material(XmlNode &node) {
 	if (!node.empty()) {
 		bool col_read = false;
         for (pugi::xml_node &child : node.children()) {
-			if (child.name() == "color") {
+            const std::string name = child.name();
+            if (name == "color") {
 				col_read = true;
 				ParseNode_Color(child);
-			} else if (child.name() == "metadata") {
+            } else if (name == "metadata") {
 				ParseNode_Metadata(child);
 			}
 		}
@@ -256,44 +257,46 @@ void AMFImporter::ParseNode_TexMap(XmlNode &node, const bool pUseOldName) {
 
 	if (!pUseOldName) {
 		for (pugi::xml_attribute &attr : node.attributes()) {
-			if (attr.name() == "utex1") {
+            const std::string name = attr.name();
+            if (name == "utex1") {
 				read_flag[0] = true;
 				als.TextureCoordinate[0].x = attr.as_float();
-			} else if (attr.name() == "utex2") {
+            } else if (name == "utex2") {
 				read_flag[1] = true;
 				als.TextureCoordinate[1].x = attr.as_float();
-			} else if (attr.name() == "utex3") {
+            } else if (name == "utex3") {
 				read_flag[2] = true;
 				als.TextureCoordinate[2].x = attr.as_float();
-			} else if (attr.name() == "vtex1") {
+            } else if (name == "vtex1") {
 				read_flag[3] = true;
 				als.TextureCoordinate[0].y = attr.as_float();
-			} else if (attr.name() == "vtex2") {
+            } else if (name == "vtex2") {
 				read_flag[4] = true;
 				als.TextureCoordinate[1].y = attr.as_float();
-			} else if (attr.name() == "vtex3") {
+            } else if (name == "vtex3") {
 				read_flag[5] = true;
 				als.TextureCoordinate[0].y = attr.as_float();
 			}
 		}
 	} else {
 		for (pugi::xml_attribute &attr : node.attributes()) {
-			if (attr.name() == "u") {
+            const std::string name = attr.name();
+            if (name == "u") {
 				read_flag[0] = true;
 				als.TextureCoordinate[0].x = attr.as_float();
-			} else if (attr.name() == "u2") {
+            } else if (name == "u2") {
 				read_flag[1] = true;
 				als.TextureCoordinate[1].x = attr.as_float();
-			} else if (attr.name() == "u3") {
+            } else if (name == "u3") {
 				read_flag[2] = true;
 				als.TextureCoordinate[2].x = attr.as_float();
-			} else if (attr.name() == "v1") {
+            } else if (name == "v1") {
 				read_flag[3] = true;
 				als.TextureCoordinate[0].y = attr.as_float();
-			} else if (attr.name() == "v2") {
+            } else if (name == "v2") {
 				read_flag[4] = true;
 				als.TextureCoordinate[1].y = attr.as_float();
-			} else if (attr.name() == "v3") {
+            } else if (name == "v3") {
 				read_flag[5] = true;
 				als.TextureCoordinate[0].y = attr.as_float();
 			}

+ 0 - 2
code/AssetLib/AMF/AMFImporter_Node.hpp

@@ -5,8 +5,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,

+ 125 - 99
code/AssetLib/AMF/AMFImporter_Postprocess.cpp

@@ -5,8 +5,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,
@@ -83,39 +81,41 @@ aiColor4D AMFImporter::SPP_Material::GetColor(const float /*pX*/, const float /*
     return tcol;
 }
 
-void AMFImporter::PostprocessHelper_CreateMeshDataArray(const CAMFImporter_NodeElement_Mesh &pNodeElement, std::vector<aiVector3D> &pVertexCoordinateArray,
-        std::vector<CAMFImporter_NodeElement_Color *> &pVertexColorArray) const {
-    CAMFImporter_NodeElement_Vertices *vn = nullptr;
+void AMFImporter::PostprocessHelper_CreateMeshDataArray(const AMFMesh &pNodeElement, std::vector<aiVector3D> &pVertexCoordinateArray,
+        std::vector<AMFColor *> &pVertexColorArray) const {
+    AMFVertex *vn = nullptr;
     size_t col_idx;
 
     // All data stored in "vertices", search for it.
-    for (CAMFImporter_NodeElement *ne_child : pNodeElement.Child) {
-        if (ne_child->Type == CAMFImporter_NodeElement::ENET_Vertices) vn = (CAMFImporter_NodeElement_Vertices *)ne_child;
+    for (AMFNodeElementBase *ne_child : pNodeElement.Child) {
+        if (ne_child->Type == AMFNodeElementBase::ENET_Vertices) {
+            vn = (AMFVertex *)ne_child;
+        }
     }
 
     // If "vertices" not found then no work for us.
-    if (vn == nullptr) return;
+    if (vn == nullptr) {
+        return;
+    }
 
     pVertexCoordinateArray.reserve(vn->Child.size()); // all coordinates stored as child and we need to reserve space for future push_back's.
     pVertexColorArray.resize(vn->Child.size()); // colors count equal vertices count.
     col_idx = 0;
     // Inside vertices collect all data and place to arrays
-    for (CAMFImporter_NodeElement *vn_child : vn->Child) {
+    for (AMFNodeElementBase *vn_child : vn->Child) {
         // vertices, colors
-        if (vn_child->Type == CAMFImporter_NodeElement::ENET_Vertex) {
+        if (vn_child->Type == AMFNodeElementBase::ENET_Vertex) {
             // by default clear color for current vertex
             pVertexColorArray[col_idx] = nullptr;
 
-            for (CAMFImporter_NodeElement *vtx : vn_child->Child) {
-                if (vtx->Type == CAMFImporter_NodeElement::ENET_Coordinates) {
-                    pVertexCoordinateArray.push_back(((CAMFImporter_NodeElement_Coordinates *)vtx)->Coordinate);
-
+            for (AMFNodeElementBase *vtx : vn_child->Child) {
+                if (vtx->Type == AMFNodeElementBase::ENET_Coordinates) {
+                    pVertexCoordinateArray.push_back(((AMFCoordinates *)vtx)->Coordinate);
                     continue;
                 }
 
-                if (vtx->Type == CAMFImporter_NodeElement::ENET_Color) {
-                    pVertexColorArray[col_idx] = (CAMFImporter_NodeElement_Color *)vtx;
-
+                if (vtx->Type == AMFNodeElementBase::ENET_Color) {
+                    pVertexColorArray[col_idx] = (AMFColor *)vtx;
                     continue;
                 }
             } // for(CAMFImporter_NodeElement* vtx: vn_child->Child)
@@ -146,59 +146,77 @@ size_t AMFImporter::PostprocessHelper_GetTextureID_Or_Create(const std::string &
         }
     }
 
-    //
     // Converted texture not found, create it.
-    //
-    CAMFImporter_NodeElement_Texture *src_texture[4]{ nullptr };
-    std::vector<CAMFImporter_NodeElement_Texture *> src_texture_4check;
+    AMFTexture *src_texture[4] {
+        nullptr
+    };
+    std::vector<AMFTexture *> src_texture_4check;
     SPP_Texture converted_texture;
 
     { // find all specified source textures
-        CAMFImporter_NodeElement *t_tex;
-
+        AMFNodeElementBase *t_tex;
+        
         // R
         if (!pID_R.empty()) {
-            if (!Find_NodeElement(pID_R, CAMFImporter_NodeElement::ENET_Texture, &t_tex)) Throw_ID_NotFound(pID_R);
+            pugi::xml_node *node = mXmlParser->findNode(pID_R);
+            if (nullptr == node) {
+                throw DeadlyImportError("Id not found " + pID_R + ".");
+            }
+            //if (!Find_NodeElement(pID_R, AMFNodeElementBase::ENET_Texture, &t_tex)) Throw_ID_NotFound(pID_R);
 
-            src_texture[0] = (CAMFImporter_NodeElement_Texture *)t_tex;
-            src_texture_4check.push_back((CAMFImporter_NodeElement_Texture *)t_tex);
+            src_texture[0] = (AMFTexture *)t_tex;
+            src_texture_4check.push_back((AMFTexture *)t_tex);
         } else {
             src_texture[0] = nullptr;
         }
 
         // G
         if (!pID_G.empty()) {
-            if (!Find_NodeElement(pID_G, CAMFImporter_NodeElement::ENET_Texture, &t_tex)) Throw_ID_NotFound(pID_G);
+            pugi::xml_node *node = mXmlParser->findNode(pID_G);
+            if (nullptr == node) {
+                throw DeadlyImportError("Id not found " + pID_G + ".");
+            }
 
-            src_texture[1] = (CAMFImporter_NodeElement_Texture *)t_tex;
-            src_texture_4check.push_back((CAMFImporter_NodeElement_Texture *)t_tex);
+            //if (!Find_NodeElement(pID_G, AMFNodeElementBase::ENET_Texture, &t_tex)) Throw_ID_NotFound(pID_G);
+
+            src_texture[1] = (AMFTexture *)t_tex;
+            src_texture_4check.push_back((AMFTexture *)t_tex);
         } else {
             src_texture[1] = nullptr;
         }
 
         // B
         if (!pID_B.empty()) {
-            if (!Find_NodeElement(pID_B, CAMFImporter_NodeElement::ENET_Texture, &t_tex)) Throw_ID_NotFound(pID_B);
+            //if (!Find_NodeElement(pID_B, AMFNodeElementBase::ENET_Texture, &t_tex)) Throw_ID_NotFound(pID_B);
+            pugi::xml_node *node = mXmlParser->findNode(pID_B);
+            if (nullptr == node) {
+                throw DeadlyImportError("Id not found " + pID_B + ".");
+            }
 
-            src_texture[2] = (CAMFImporter_NodeElement_Texture *)t_tex;
-            src_texture_4check.push_back((CAMFImporter_NodeElement_Texture *)t_tex);
+            src_texture[2] = (AMFTexture *)t_tex;
+            src_texture_4check.push_back((AMFTexture *)t_tex);
         } else {
             src_texture[2] = nullptr;
         }
 
         // A
         if (!pID_A.empty()) {
-            if (!Find_NodeElement(pID_A, CAMFImporter_NodeElement::ENET_Texture, &t_tex)) Throw_ID_NotFound(pID_A);
+            pugi::xml_node *node = mXmlParser->findNode(pID_A);
+            if (nullptr == node) {
+                throw DeadlyImportError("Id not found " + pID_A + ".");
+            }
 
-            src_texture[3] = (CAMFImporter_NodeElement_Texture *)t_tex;
-            src_texture_4check.push_back((CAMFImporter_NodeElement_Texture *)t_tex);
+            //if (!Find_NodeElement(pID_A, AMFNodeElementBase::ENET_Texture, &t_tex)) Throw_ID_NotFound(pID_A);
+
+            src_texture[3] = (AMFTexture *)t_tex;
+            src_texture_4check.push_back((AMFTexture *)t_tex);
         } else {
             src_texture[3] = nullptr;
         }
     } // END: find all specified source textures
 
     // check that all textures has same size
-    if (src_texture_4check.size() > 1) {
+    if (!src_texture_4check.empty() ) {
         for (size_t i = 0, i_e = (src_texture_4check.size() - 1); i < i_e; i++) {
             if ((src_texture_4check[i]->Width != src_texture_4check[i + 1]->Width) || (src_texture_4check[i]->Height != src_texture_4check[i + 1]->Height) ||
                     (src_texture_4check[i]->Depth != src_texture_4check[i + 1]->Depth)) {
@@ -255,7 +273,7 @@ size_t AMFImporter::PostprocessHelper_GetTextureID_Or_Create(const std::string &
     auto CopyTextureData = [&](const std::string &pID, const size_t pOffset, const size_t pStep, const uint8_t pSrcTexNum) -> void {
         if (!pID.empty()) {
             for (size_t idx_target = pOffset, idx_src = 0; idx_target < tex_size; idx_target += pStep, idx_src++) {
-                CAMFImporter_NodeElement_Texture *tex = src_texture[pSrcTexNum];
+                AMFTexture *tex = src_texture[pSrcTexNum];
                 ai_assert(tex);
                 converted_texture.Data[idx_target] = tex->Data.at(idx_src);
             }
@@ -276,7 +294,7 @@ size_t AMFImporter::PostprocessHelper_GetTextureID_Or_Create(const std::string &
 }
 
 void AMFImporter::PostprocessHelper_SplitFacesByTextureID(std::list<SComplexFace> &pInputList, std::list<std::list<SComplexFace>> &pOutputList_Separated) {
-    auto texmap_is_equal = [](const CAMFImporter_NodeElement_TexMap *pTexMap1, const CAMFImporter_NodeElement_TexMap *pTexMap2) -> bool {
+    auto texmap_is_equal = [](const AMFTexMap *pTexMap1, const AMFTexMap *pTexMap2) -> bool {
         if ((pTexMap1 == nullptr) && (pTexMap2 == nullptr)) return true;
         if (pTexMap1 == nullptr) return false;
         if (pTexMap2 == nullptr) return false;
@@ -313,56 +331,61 @@ void AMFImporter::PostprocessHelper_SplitFacesByTextureID(std::list<SComplexFace
     } while (!pInputList.empty());
 }
 
-void AMFImporter::Postprocess_AddMetadata(const std::list<CAMFImporter_NodeElement_Metadata *> &metadataList, aiNode &sceneNode) const {
-    if (!metadataList.empty()) {
-        if (sceneNode.mMetaData != nullptr) throw DeadlyImportError("Postprocess. MetaData member in node are not nullptr. Something went wrong.");
+void AMFImporter::Postprocess_AddMetadata(const std::list<AMFMetadata *> &metadataList, aiNode &sceneNode) const {
+    if (metadataList.empty()) {
+        return;
+    }
+    if (sceneNode.mMetaData != nullptr) {
+        throw DeadlyImportError("Postprocess. MetaData member in node are not nullptr. Something went wrong.");
+    }
 
-        // copy collected metadata to output node.
-        sceneNode.mMetaData = aiMetadata::Alloc(static_cast<unsigned int>(metadataList.size()));
-        size_t meta_idx(0);
+    // copy collected metadata to output node.
+    sceneNode.mMetaData = aiMetadata::Alloc(static_cast<unsigned int>(metadataList.size()));
+    size_t meta_idx(0);
 
-        for (const CAMFImporter_NodeElement_Metadata &metadata : metadataList) {
-            sceneNode.mMetaData->Set(static_cast<unsigned int>(meta_idx++), metadata.Type, aiString(metadata.Value));
-        }
-    } // if(!metadataList.empty())
+    for (const AMFMetadata &metadata : metadataList) {
+        sceneNode.mMetaData->Set(static_cast<unsigned int>(meta_idx++), metadata.Type, aiString(metadata.Value));
+    }
 }
 
-void AMFImporter::Postprocess_BuildNodeAndObject(const CAMFImporter_NodeElement_Object &pNodeElement, std::list<aiMesh *> &pMeshList, aiNode **pSceneNode) {
-    CAMFImporter_NodeElement_Color *object_color = nullptr;
+void AMFImporter::Postprocess_BuildNodeAndObject(const AMFObject &pNodeElement, std::list<aiMesh *> &pMeshList, aiNode **pSceneNode) {
+    AMFColor *object_color = nullptr;
 
     // create new aiNode and set name as <object> has.
     *pSceneNode = new aiNode;
     (*pSceneNode)->mName = pNodeElement.ID;
     // read mesh and color
-    for (const CAMFImporter_NodeElement *ne_child : pNodeElement.Child) {
+    for (const AMFNodeElementBase *ne_child : pNodeElement.Child) {
         std::vector<aiVector3D> vertex_arr;
-        std::vector<CAMFImporter_NodeElement_Color *> color_arr;
+        std::vector<AMFColor *> color_arr;
 
         // color for object
-        if (ne_child->Type == CAMFImporter_NodeElement::ENET_Color) object_color = (CAMFImporter_NodeElement_Color *)ne_child;
+        if (ne_child->Type == AMFNodeElementBase::ENET_Color) {
+            object_color = (AMFColor *) ne_child;
+        }
 
-        if (ne_child->Type == CAMFImporter_NodeElement::ENET_Mesh) {
+        if (ne_child->Type == AMFNodeElementBase::ENET_Mesh) {
             // Create arrays from children of mesh: vertices.
-            PostprocessHelper_CreateMeshDataArray(*((CAMFImporter_NodeElement_Mesh *)ne_child), vertex_arr, color_arr);
+            PostprocessHelper_CreateMeshDataArray(*((AMFMesh *)ne_child), vertex_arr, color_arr);
             // Use this arrays as a source when creating every aiMesh
-            Postprocess_BuildMeshSet(*((CAMFImporter_NodeElement_Mesh *)ne_child), vertex_arr, color_arr, object_color, pMeshList, **pSceneNode);
+            Postprocess_BuildMeshSet(*((AMFMesh *)ne_child), vertex_arr, color_arr, object_color, pMeshList, **pSceneNode);
         }
     } // for(const CAMFImporter_NodeElement* ne_child: pNodeElement)
 }
 
-void AMFImporter::Postprocess_BuildMeshSet(const CAMFImporter_NodeElement_Mesh &pNodeElement, const std::vector<aiVector3D> &pVertexCoordinateArray,
-        const std::vector<CAMFImporter_NodeElement_Color *> &pVertexColorArray,
-        const CAMFImporter_NodeElement_Color *pObjectColor, std::list<aiMesh *> &pMeshList, aiNode &pSceneNode) {
+void AMFImporter::Postprocess_BuildMeshSet(const AMFMesh &pNodeElement, const std::vector<aiVector3D> &pVertexCoordinateArray,
+        const std::vector<AMFColor *> &pVertexColorArray,
+        const AMFColor *pObjectColor, std::list<aiMesh *> &pMeshList, aiNode &pSceneNode) {
     std::list<unsigned int> mesh_idx;
 
     // all data stored in "volume", search for it.
-    for (const CAMFImporter_NodeElement *ne_child : pNodeElement.Child) {
-        const CAMFImporter_NodeElement_Color *ne_volume_color = nullptr;
+    for (const AMFNodeElementBase *ne_child : pNodeElement.Child) {
+        const AMFColor *ne_volume_color = nullptr;
         const SPP_Material *cur_mat = nullptr;
 
-        if (ne_child->Type == CAMFImporter_NodeElement::ENET_Volume) {
+        if (ne_child->Type == AMFNodeElementBase::ENET_Volume) {
             /******************* Get faces *******************/
-            const CAMFImporter_NodeElement_Volume *ne_volume = reinterpret_cast<const CAMFImporter_NodeElement_Volume *>(ne_child);
+            const AMFVolume *ne_volume = reinterpret_cast<const AMFVolume *>(ne_child);
 
             std::list<SComplexFace> complex_faces_list; // List of the faces of the volume.
             std::list<std::list<SComplexFace>> complex_faces_toplist; // List of the face list for every mesh.
@@ -373,13 +396,13 @@ void AMFImporter::Postprocess_BuildMeshSet(const CAMFImporter_NodeElement_Mesh &
             }
 
             // inside "volume" collect all data and place to arrays or create new objects
-            for (const CAMFImporter_NodeElement *ne_volume_child : ne_volume->Child) {
+            for (const AMFNodeElementBase *ne_volume_child : ne_volume->Child) {
                 // color for volume
-                if (ne_volume_child->Type == CAMFImporter_NodeElement::ENET_Color) {
-                    ne_volume_color = reinterpret_cast<const CAMFImporter_NodeElement_Color *>(ne_volume_child);
-                } else if (ne_volume_child->Type == CAMFImporter_NodeElement::ENET_Triangle) // triangles, triangles colors
+                if (ne_volume_child->Type == AMFNodeElementBase::ENET_Color) {
+                    ne_volume_color = reinterpret_cast<const AMFColor *>(ne_volume_child);
+                } else if (ne_volume_child->Type == AMFNodeElementBase::ENET_Triangle) // triangles, triangles colors
                 {
-                    const CAMFImporter_NodeElement_Triangle &tri_al = *reinterpret_cast<const CAMFImporter_NodeElement_Triangle *>(ne_volume_child);
+                    const AMFTriangle &tri_al = *reinterpret_cast<const AMFTriangle *>(ne_volume_child);
 
                     SComplexFace complex_face;
 
@@ -388,11 +411,11 @@ void AMFImporter::Postprocess_BuildMeshSet(const CAMFImporter_NodeElement_Mesh &
                     complex_face.TexMap = nullptr;
                     // get data from triangle children: color, texture coordinates.
                     if (tri_al.Child.size()) {
-                        for (const CAMFImporter_NodeElement *ne_triangle_child : tri_al.Child) {
-                            if (ne_triangle_child->Type == CAMFImporter_NodeElement::ENET_Color)
-                                complex_face.Color = reinterpret_cast<const CAMFImporter_NodeElement_Color *>(ne_triangle_child);
-                            else if (ne_triangle_child->Type == CAMFImporter_NodeElement::ENET_TexMap)
-                                complex_face.TexMap = reinterpret_cast<const CAMFImporter_NodeElement_TexMap *>(ne_triangle_child);
+                        for (const AMFNodeElementBase *ne_triangle_child : tri_al.Child) {
+                            if (ne_triangle_child->Type == AMFNodeElementBase::ENET_Color)
+                                complex_face.Color = reinterpret_cast<const AMFColor *>(ne_triangle_child);
+                            else if (ne_triangle_child->Type == AMFNodeElementBase::ENET_TexMap)
+                                complex_face.TexMap = reinterpret_cast<const AMFTexMap *>(ne_triangle_child);
                         }
                     } // if(tri_al.Child.size())
 
@@ -422,15 +445,18 @@ void AMFImporter::Postprocess_BuildMeshSet(const CAMFImporter_NodeElement_Mesh &
                                 if (face.Face.mIndices[idx_vert] > *pBiggerThan) {
                                     rv = face.Face.mIndices[idx_vert];
                                     found = true;
-
                                     break;
                                 }
                             }
 
-                            if (found) break;
+                            if (found) {
+                                break;
+                            }
                         }
 
-                        if (!found) return *pBiggerThan;
+                        if (!found) {
+                            return *pBiggerThan;
+                        }
                     } else {
                         rv = pFaceList.front().Face.mIndices[0];
                     } // if(pBiggerThan != nullptr) else
@@ -505,9 +531,9 @@ void AMFImporter::Postprocess_BuildMeshSet(const CAMFImporter_NodeElement_Mesh &
                 tmesh->mNumFaces = static_cast<unsigned int>(face_list_cur.size());
                 tmesh->mFaces = new aiFace[tmesh->mNumFaces];
 
-                // Create vertices list and optimize indices. Optimisation mean following.In AMF all volumes use one big list of vertices. And one volume
+                // Create vertices list and optimize indices. Optimization mean following.In AMF all volumes use one big list of vertices. And one volume
                 // can use only part of vertices list, for example: vertices list contain few thousands of vertices and volume use vertices 1, 3, 10.
-                // Do you need all this thousands of garbage? Of course no. So, optimisation step transformate sparse indices set to continuous.
+                // Do you need all this thousands of garbage? Of course no. So, optimization step transform sparse indices set to continuous.
                 size_t VertexCount_Max = tmesh->mNumFaces * 3; // 3 - triangles.
                 std::vector<aiVector3D> vert_arr, texcoord_arr;
                 std::vector<aiColor4D> col_arr;
@@ -566,7 +592,7 @@ void AMFImporter::Postprocess_BuildMeshSet(const CAMFImporter_NodeElement_Mesh &
                     size_t idx_vert_new = vert_arr.size();
                     ///TODO: clean unused vertices. "* 2": in certain cases - mesh full of triangle colors - vert_arr will contain duplicated vertices for
                     /// colored triangles and initial vertices (for colored vertices) which in real became unused. This part need more thinking about
-                    /// optimisation.
+                    /// optimization.
                     bool *idx_vert_used;
 
                     idx_vert_used = new bool[VertexCount_Max * 2];
@@ -639,15 +665,15 @@ void AMFImporter::Postprocess_BuildMeshSet(const CAMFImporter_NodeElement_Mesh &
     } // if(mesh_idx.size() > 0)
 }
 
-void AMFImporter::Postprocess_BuildMaterial(const CAMFImporter_NodeElement_Material &pMaterial) {
+void AMFImporter::Postprocess_BuildMaterial(const AMFMaterial &pMaterial) {
     SPP_Material new_mat;
 
     new_mat.ID = pMaterial.ID;
-    for (const CAMFImporter_NodeElement *mat_child : pMaterial.Child) {
-        if (mat_child->Type == CAMFImporter_NodeElement::ENET_Color) {
-            new_mat.Color = (CAMFImporter_NodeElement_Color *)mat_child;
-        } else if (mat_child->Type == CAMFImporter_NodeElement::ENET_Metadata) {
-            new_mat.Metadata.push_back((CAMFImporter_NodeElement_Metadata *)mat_child);
+    for (const AMFNodeElementBase *mat_child : pMaterial.Child) {
+        if (mat_child->Type == AMFNodeElementBase::ENET_Color) {
+            new_mat.Color = (AMFColor*)mat_child;
+        } else if (mat_child->Type == AMFNodeElementBase::ENET_Metadata) {
+            new_mat.Metadata.push_back((AMFMetadata *)mat_child);
         }
     } // for(const CAMFImporter_NodeElement* mat_child; pMaterial.Child)
 
@@ -655,7 +681,7 @@ void AMFImporter::Postprocess_BuildMaterial(const CAMFImporter_NodeElement_Mater
     mMaterial_Converted.push_back(new_mat);
 }
 
-void AMFImporter::Postprocess_BuildConstellation(CAMFImporter_NodeElement_Constellation &pConstellation, std::list<aiNode *> &pNodeList) const {
+void AMFImporter::Postprocess_BuildConstellation(AMFConstellation &pConstellation, std::list<aiNode *> &pNodeList) const {
     aiNode *con_node;
     std::list<aiNode *> ch_node;
 
@@ -672,8 +698,8 @@ void AMFImporter::Postprocess_BuildConstellation(CAMFImporter_NodeElement_Conste
         aiNode *t_node;
         aiNode *found_node;
 
-        if (ne->Type == CAMFImporter_NodeElement::ENET_Metadata) continue;
-        if (ne->Type != CAMFImporter_NodeElement::ENET_Instance) throw DeadlyImportError("Only <instance> nodes can be in <constellation>.");
+        if (ne->Type == AMFNodeElementBase::ENET_Metadata) continue;
+        if (ne->Type != AMFNodeElementBase::ENET_Instance) throw DeadlyImportError("Only <instance> nodes can be in <constellation>.");
 
         // create alias for conveniance
         CAMFImporter_NodeElement_Instance &als = *((CAMFImporter_NodeElement_Instance *)ne);
@@ -723,10 +749,10 @@ void AMFImporter::Postprocess_BuildScene(aiScene *pScene) {
     pScene->mRootNode->mParent = nullptr;
     pScene->mFlags |= AI_SCENE_FLAGS_ALLOW_SHARED;
     // search for root(<amf>) element
-    CAMFImporter_NodeElement *root_el = nullptr;
+    AMFNodeElementBase *root_el = nullptr;
 
-    for (CAMFImporter_NodeElement *ne : mNodeElement_List) {
-        if (ne->Type != CAMFImporter_NodeElement::ENET_Root) continue;
+    for (AMFNodeElementBase *ne : mNodeElement_List) {
+        if (ne->Type != AMFNodeElementBase::ENET_Root) continue;
 
         root_el = ne;
 
@@ -742,15 +768,15 @@ void AMFImporter::Postprocess_BuildScene(aiScene *pScene) {
     //
     // 1. <material>
     // 2. <texture> will be converted later when processing triangles list. \sa Postprocess_BuildMeshSet
-    for (const CAMFImporter_NodeElement *root_child : root_el->Child) {
-        if (root_child->Type == CAMFImporter_NodeElement::ENET_Material) Postprocess_BuildMaterial(*((CAMFImporter_NodeElement_Material *)root_child));
+    for (const AMFNodeElementBase *root_child : root_el->Child) {
+        if (root_child->Type == AMFNodeElementBase::ENET_Material) Postprocess_BuildMaterial(*((CAMFImporter_NodeElement_Material *)root_child));
     }
 
     // After "appearance" nodes we must read <object> because it will be used in <constellation> -> <instance>.
     //
     // 3. <object>
-    for (const CAMFImporter_NodeElement *root_child : root_el->Child) {
-        if (root_child->Type == CAMFImporter_NodeElement::ENET_Object) {
+    for (const AMFNodeElementBase *root_child : root_el->Child) {
+        if (root_child->Type == AMFNodeElementBase::ENET_Object) {
             aiNode *tnode = nullptr;
 
             // for <object> mesh and node must be built: object ID assigned to aiNode name and will be used in future for <instance>
@@ -761,15 +787,15 @@ void AMFImporter::Postprocess_BuildScene(aiScene *pScene) {
 
     // And finally read rest of nodes.
     //
-    for (const CAMFImporter_NodeElement *root_child : root_el->Child) {
+    for (const AMFNodeElementBase *root_child : root_el->Child) {
         // 4. <constellation>
-        if (root_child->Type == CAMFImporter_NodeElement::ENET_Constellation) {
+        if (root_child->Type == AMFNodeElementBase::ENET_Constellation) {
             // <object> and <constellation> at top of self abstraction use aiNode. So we can use only aiNode list for creating new aiNode's.
-            Postprocess_BuildConstellation(*((CAMFImporter_NodeElement_Constellation *)root_child), node_list);
+            Postprocess_BuildConstellation(*((AMFConstellation *)root_child), node_list);
         }
 
         // 5, <metadata>
-        if (root_child->Type == CAMFImporter_NodeElement::ENET_Metadata) meta_list.push_back((CAMFImporter_NodeElement_Metadata *)root_child);
+        if (root_child->Type == AMFNodeElementBase::ENET_Metadata) meta_list.push_back((CAMFImporter_NodeElement_Metadata *)root_child);
     } // for(const CAMFImporter_NodeElement* root_child: root_el->Child)
 
     // at now we can add collected metadata to root node

File diff ditekan karena terlalu besar
+ 393 - 160
code/AssetLib/Collada/ColladaParser.cpp


+ 54 - 52
code/AssetLib/Collada/ColladaParser.h

@@ -50,9 +50,10 @@
 #include "ColladaHelper.h"
 #include <assimp/TinyFormatter.h>
 #include <assimp/ai_assert.h>
-#include <assimp/irrXMLWrapper.h>
+#include <assimp/XmlParser.h>
 
 namespace Assimp {
+
 class ZipArchiveIOSystem;
 
 // ------------------------------------------------------------------------------------------
@@ -81,25 +82,25 @@ protected:
     static std::string ReadZaeManifest(ZipArchiveIOSystem &zip_archive);
 
     /** Reads the contents of the file */
-    void ReadContents();
+    void ReadContents(XmlNode &node);
 
     /** Reads the structure of the file */
-    void ReadStructure();
+    void ReadStructure(XmlNode &node);
 
     /** Reads asset information such as coordinate system information and legal blah */
-    void ReadAssetInfo();
+    void ReadAssetInfo(XmlNode &node);
 
     /** Reads contributor information such as author and legal blah */
-    void ReadContributorInfo();
+    void ReadContributorInfo(XmlNode &node);
 
     /** Reads generic metadata into provided map and renames keys for Assimp */
-    void ReadMetaDataItem(StringMetaData &metadata);
+    void ReadMetaDataItem(XmlNode &node, StringMetaData &metadata);
 
     /** Reads the animation library */
-    void ReadAnimationLibrary();
+    void ReadAnimationLibrary(XmlNode &node);
 
     /** Reads the animation clip library */
-    void ReadAnimationClipLibrary();
+    void ReadAnimationClipLibrary(XmlNode &node);
 
     /** Unwrap controllers dependency hierarchy */
     void PostProcessControllers();
@@ -108,103 +109,103 @@ protected:
     void PostProcessRootAnimations();
 
     /** Reads an animation into the given parent structure */
-    void ReadAnimation(Collada::Animation *pParent);
+    void ReadAnimation(XmlNode &node, Collada::Animation *pParent);
 
     /** Reads an animation sampler into the given anim channel */
-    void ReadAnimationSampler(Collada::AnimationChannel &pChannel);
+    void ReadAnimationSampler(XmlNode &node, Collada::AnimationChannel &pChannel);
 
     /** Reads the skeleton controller library */
-    void ReadControllerLibrary();
+    void ReadControllerLibrary(XmlNode &node);
 
     /** Reads a controller into the given mesh structure */
-    void ReadController(Collada::Controller &pController);
+    void ReadController(XmlNode &node, Collada::Controller &pController);
 
     /** Reads the joint definitions for the given controller */
-    void ReadControllerJoints(Collada::Controller &pController);
+    void ReadControllerJoints(XmlNode &node, Collada::Controller &pController);
 
     /** Reads the joint weights for the given controller */
-    void ReadControllerWeights(Collada::Controller &pController);
+    void ReadControllerWeights(XmlNode &node, Collada::Controller &pController);
 
     /** Reads the image library contents */
-    void ReadImageLibrary();
+    void ReadImageLibrary(XmlNode &node);
 
     /** Reads an image entry into the given image */
-    void ReadImage(Collada::Image &pImage);
+    void ReadImage(XmlNode &node, Collada::Image &pImage);
 
     /** Reads the material library */
-    void ReadMaterialLibrary();
+    void ReadMaterialLibrary(XmlNode &node);
 
     /** Reads a material entry into the given material */
-    void ReadMaterial(Collada::Material &pMaterial);
+    void ReadMaterial(XmlNode &node, Collada::Material &pMaterial);
 
     /** Reads the camera library */
-    void ReadCameraLibrary();
+    void ReadCameraLibrary(XmlNode &node);
 
     /** Reads a camera entry into the given camera */
-    void ReadCamera(Collada::Camera &pCamera);
+    void ReadCamera(XmlNode &node, Collada::Camera &pCamera);
 
     /** Reads the light library */
-    void ReadLightLibrary();
+    void ReadLightLibrary(XmlNode &node);
 
     /** Reads a light entry into the given light */
-    void ReadLight(Collada::Light &pLight);
+    void ReadLight(XmlNode &node, Collada::Light &pLight);
 
     /** Reads the effect library */
-    void ReadEffectLibrary();
+    void ReadEffectLibrary(XmlNode &node);
 
     /** Reads an effect entry into the given effect*/
-    void ReadEffect(Collada::Effect &pEffect);
+    void ReadEffect(XmlNode &node, Collada::Effect &pEffect);
 
     /** Reads an COMMON effect profile */
-    void ReadEffectProfileCommon(Collada::Effect &pEffect);
+    void ReadEffectProfileCommon(XmlNode &node, Collada::Effect &pEffect);
 
     /** Read sampler properties */
-    void ReadSamplerProperties(Collada::Sampler &pSampler);
+    void ReadSamplerProperties(XmlNode &node, Collada::Sampler &pSampler);
 
     /** Reads an effect entry containing a color or a texture defining that color */
-    void ReadEffectColor(aiColor4D &pColor, Collada::Sampler &pSampler);
+    void ReadEffectColor(XmlNode &node, aiColor4D &pColor, Collada::Sampler &pSampler);
 
     /** Reads an effect entry containing a float */
-    void ReadEffectFloat(ai_real &pFloat);
+    void ReadEffectFloat(XmlNode &node, ai_real &pFloat);
 
     /** Reads an effect parameter specification of any kind */
-    void ReadEffectParam(Collada::EffectParam &pParam);
+    void ReadEffectParam(XmlNode &node, Collada::EffectParam &pParam);
 
     /** Reads the geometry library contents */
-    void ReadGeometryLibrary();
+    void ReadGeometryLibrary(XmlNode &node);
 
     /** Reads a geometry from the geometry library. */
-    void ReadGeometry(Collada::Mesh &pMesh);
+    void ReadGeometry(XmlNode &node, Collada::Mesh &pMesh);
 
     /** Reads a mesh from the geometry library */
-    void ReadMesh(Collada::Mesh &pMesh);
+    void ReadMesh(XmlNode &node, Collada::Mesh &pMesh);
 
     /** Reads a source element - a combination of raw data and an accessor defining
          * things that should not be redefinable. Yes, that's another rant.
          */
-    void ReadSource();
+    void ReadSource(XmlNode &node);
 
     /** Reads a data array holding a number of elements, and stores it in the global library.
          * Currently supported are array of floats and arrays of strings.
          */
-    void ReadDataArray();
+    void ReadDataArray(XmlNode &node);
 
     /** Reads an accessor and stores it in the global library under the given ID -
          * accessors use the ID of the parent <source> element
          */
-    void ReadAccessor(const std::string &pID);
+    void ReadAccessor(XmlNode &node, const std::string &pID);
 
     /** Reads input declarations of per-vertex mesh data into the given mesh */
-    void ReadVertexData(Collada::Mesh &pMesh);
+    void ReadVertexData(XmlNode &node, Collada::Mesh &pMesh);
 
     /** Reads input declarations of per-index mesh data into the given mesh */
-    void ReadIndexData(Collada::Mesh &pMesh);
+    void ReadIndexData(XmlNode &node, Collada::Mesh &pMesh);
 
     /** Reads a single input channel element and stores it in the given array, if valid */
-    void ReadInputChannel(std::vector<Collada::InputChannel> &poChannels);
+    void ReadInputChannel(XmlNode &node, std::vector<Collada::InputChannel> &poChannels);
 
     /** Reads a <p> primitive index list and assembles the mesh data into the given mesh */
-    size_t ReadPrimitives(Collada::Mesh &pMesh, std::vector<Collada::InputChannel> &pPerIndexChannels,
+    size_t ReadPrimitives(XmlNode &node, Collada::Mesh &pMesh, std::vector<Collada::InputChannel> &pPerIndexChannels,
             size_t pNumPrimitives, const std::vector<size_t> &pVCount, Collada::PrimitiveType pPrimType);
 
     /** Copies the data for a single primitive into the mesh, based on the InputChannels */
@@ -220,22 +221,22 @@ protected:
     void ExtractDataObjectFromChannel(const Collada::InputChannel &pInput, size_t pLocalIndex, Collada::Mesh &pMesh);
 
     /** Reads the library of node hierarchies and scene parts */
-    void ReadSceneLibrary();
+    void ReadSceneLibrary(XmlNode &node);
 
     /** Reads a scene node's contents including children and stores it in the given node */
-    void ReadSceneNode(Collada::Node *pNode);
+    void ReadSceneNode(XmlNode &node, Collada::Node *pNode);
 
     /** Reads a node transformation entry of the given type and adds it to the given node's transformation list. */
-    void ReadNodeTransformation(Collada::Node *pNode, Collada::TransformType pType);
+    void ReadNodeTransformation(XmlNode &node, Collada::Node *pNode, Collada::TransformType pType);
 
     /** Reads a mesh reference in a node and adds it to the node's mesh list */
-    void ReadNodeGeometry(Collada::Node *pNode);
+    void ReadNodeGeometry(XmlNode &node, Collada::Node *pNode);
 
     /** Reads the collada scene */
-    void ReadScene();
+    void ReadScene(XmlNode &node);
 
     // Processes bind_vertex_input and bind elements
-    void ReadMaterialVertexInputBinding(Collada::SemanticMappingTable &tbl);
+    void ReadMaterialVertexInputBinding(XmlNode &node, Collada::SemanticMappingTable &tbl);
 
     /** Reads embedded textures from a ZAE archive*/
     void ReadEmbeddedTextures(ZipArchiveIOSystem &zip_archive);
@@ -246,19 +247,19 @@ protected:
     void ReportWarning(const char *msg, ...);
 
     /** Skips all data until the end node of the current element */
-    void SkipElement();
+    //void SkipElement();
 
     /** Skips all data until the end node of the given element */
-    void SkipElement(const char *pElement);
+    //void SkipElement(const char *pElement);
 
     /** Compares the current xml element name to the given string and returns true if equal */
     bool IsElement(const char *pName) const;
 
     /** Tests for the opening tag of the given element, throws an exception if not found */
-    void TestOpening(const char *pName);
+    //void TestOpening(const char *pName);
 
     /** Tests for the closing tag of the given element, throws an exception if not found */
-    void TestClosing(const char *pName);
+    //void TestClosing(const char *pName);
 
     /** Checks the present element for the presence of the attribute, returns its index
          or throws an exception if not found */
@@ -293,11 +294,12 @@ protected:
     const Type &ResolveLibraryReference(const std::map<std::string, Type> &pLibrary, const std::string &pURL) const;
 
 protected:
-    /** Filename, for a verbose error message */
+    // Filename, for a verbose error message
     std::string mFileName;
 
-    /** XML reader, member for everyday use */
-    irr::io::IrrXMLReader *mReader;
+    // XML reader, member for everyday use
+    //irr::io::IrrXMLReader *mReader;
+    XmlParser mXmlParser;
 
     /** All data arrays found in the file by ID. Might be referred to by actually
          everyone. Collada, you are a steaming pile of indirection. */

+ 5 - 1
code/AssetLib/Irr/IRRMeshLoader.cpp

@@ -73,7 +73,11 @@ static const aiImporterDesc desc = {
 
 // ------------------------------------------------------------------------------------------------
 // Constructor to be privately used by Importer
-IRRMeshImporter::IRRMeshImporter() {}
+IRRMeshImporter::IRRMeshImporter() :
+        BaseImporter(),
+        IrrlichtBase() {
+    // empty
+}
 
 // ------------------------------------------------------------------------------------------------
 // Destructor, private as well

+ 8 - 15
code/AssetLib/Irr/IRRMeshLoader.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,
@@ -47,12 +46,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef AI_IRRMESHLOADER_H_INCLUDED
 #define AI_IRRMESHLOADER_H_INCLUDED
 
-#include <assimp/BaseImporter.h>
 #include "IRRShared.h"
+#include <assimp/BaseImporter.h>
 
 #ifndef ASSIMP_BUILD_NO_IRRMESH_IMPORTER
 
-namespace Assimp    {
+namespace Assimp {
 
 // ---------------------------------------------------------------------------
 /** IrrMesh importer class.
@@ -61,37 +60,31 @@ namespace Assimp    {
  * irrEdit. As IrrEdit itself is capable of importing quite many file formats,
  * it might be a good file format for data exchange.
  */
-class IRRMeshImporter : public BaseImporter, public IrrlichtBase
-{
+class IRRMeshImporter : public BaseImporter, public IrrlichtBase {
 public:
     IRRMeshImporter();
     ~IRRMeshImporter();
 
-
-public:
-
     // -------------------------------------------------------------------
     /** Returns whether the class can handle the format of the given file.
      *  See BaseImporter::CanRead() for details.
      */
-    bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
-        bool checkSig) const;
+    bool CanRead(const std::string &pFile, IOSystem *pIOHandler,
+            bool checkSig) const;
 
 protected:
-
     // -------------------------------------------------------------------
     /** Return importer meta information.
      * See #BaseImporter::GetInfo for the details
      */
-    const aiImporterDesc* GetInfo () const;
+    const aiImporterDesc *GetInfo() const;
 
     // -------------------------------------------------------------------
     /** Imports the given file into the given scene structure.
      * See BaseImporter::InternReadFile() for details
      */
-    void InternReadFile( const std::string& pFile, aiScene* pScene,
-        IOSystem* pIOHandler);
-
+    void InternReadFile(const std::string &pFile, aiScene *pScene,
+            IOSystem *pIOHandler);
 };
 
 } // end of namespace Assimp

+ 9 - 11
code/AssetLib/Irr/IRRShared.cpp

@@ -43,8 +43,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *  @brief Shared utilities for the IRR and IRRMESH loaders
  */
 
-
-
 //This section should be excluded only if both the Irrlicht AND the Irrlicht Mesh importers were omitted.
 #if !(defined(ASSIMP_BUILD_NO_IRR_IMPORTER) && defined(ASSIMP_BUILD_NO_IRRMESH_IMPORTER))
 
@@ -57,7 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 using namespace Assimp;
 
 // Transformation matrix to convert from Assimp to IRR space
-static const aiMatrix4x4 Assimp::AI_TO_IRR_MATRIX = aiMatrix4x4 (
+const aiMatrix4x4 Assimp::AI_TO_IRR_MATRIX = aiMatrix4x4 (
     1.0f, 0.0f, 0.0f, 0.0f,
     0.0f, 0.0f, 1.0f, 0.0f,
     0.0f, 1.0f, 0.0f, 0.0f,
@@ -66,7 +64,7 @@ static const aiMatrix4x4 Assimp::AI_TO_IRR_MATRIX = aiMatrix4x4 (
 // ------------------------------------------------------------------------------------------------
 // read a property in hexadecimal format (i.e. ffffffff)
 void IrrlichtBase::ReadHexProperty(HexProperty &out ) {
-	for (pugi::xml_attribute attrib : mNode.attributes()) {
+	for (pugi::xml_attribute attrib : mNode->attributes()) {
         if (!ASSIMP_stricmp(attrib.name(), "name")) {
             out.name = std::string( attrib.value() );
         } else if (!ASSIMP_stricmp(attrib.name(),"value")) {
@@ -79,7 +77,7 @@ void IrrlichtBase::ReadHexProperty(HexProperty &out ) {
 // ------------------------------------------------------------------------------------------------
 // read a decimal property
 void IrrlichtBase::ReadIntProperty(IntProperty & out) {
-	for (pugi::xml_attribute attrib : mNode.attributes()) {
+	for (pugi::xml_attribute attrib : mNode->attributes()) {
 		if (!ASSIMP_stricmp(attrib.name(), "name")) {
 			out.name = std::string(attrib.value());
         } else if (!ASSIMP_stricmp(attrib.value(),"value")) {
@@ -91,8 +89,8 @@ void IrrlichtBase::ReadIntProperty(IntProperty & out) {
 
 // ------------------------------------------------------------------------------------------------
 // read a string property
-void IrrlichtBase::ReadStringProperty (StringProperty& out) {
-	for (pugi::xml_attribute attrib : mNode.attributes()) {
+void IrrlichtBase::ReadStringProperty( StringProperty& out) {
+	for (pugi::xml_attribute attrib : mNode->attributes()) {
 		if (!ASSIMP_stricmp(attrib.name(), "name")) {
 			out.name = std::string(attrib.value());
 		} else if (!ASSIMP_stricmp(attrib.name(), "value")) {
@@ -105,7 +103,7 @@ void IrrlichtBase::ReadStringProperty (StringProperty& out) {
 // ------------------------------------------------------------------------------------------------
 // read a boolean property
 void IrrlichtBase::ReadBoolProperty(BoolProperty &out) {
-	for (pugi::xml_attribute attrib : mNode.attributes()) {
+	for (pugi::xml_attribute attrib : mNode->attributes()) {
 		if (!ASSIMP_stricmp(attrib.name(), "name")){
 			out.name = std::string(attrib.value());
 		} else if (!ASSIMP_stricmp(attrib.name(), "value")) {
@@ -118,7 +116,7 @@ void IrrlichtBase::ReadBoolProperty(BoolProperty &out) {
 // ------------------------------------------------------------------------------------------------
 // read a float property
 void IrrlichtBase::ReadFloatProperty(FloatProperty &out) {
-	for (pugi::xml_attribute attrib : mNode.attributes()) {
+	for (pugi::xml_attribute attrib : mNode->attributes()) {
 		if (!ASSIMP_stricmp(attrib.name(), "name")) {
 			out.name = std::string(attrib.value());
 		} else if (!ASSIMP_stricmp(attrib.name(), "value")) {
@@ -131,7 +129,7 @@ void IrrlichtBase::ReadFloatProperty(FloatProperty &out) {
 // ------------------------------------------------------------------------------------------------
 // read a vector property
 void IrrlichtBase::ReadVectorProperty( VectorProperty &out ) {
-	for (pugi::xml_attribute attrib : mNode.attributes()) {
+	for (pugi::xml_attribute attrib : mNode->attributes()) {
 		if (!ASSIMP_stricmp(attrib.name(), "name")) {
 			out.name = std::string(attrib.value());
 		} else if (!ASSIMP_stricmp(attrib.name(), "value")) {
@@ -181,7 +179,7 @@ aiMaterial* IrrlichtBase::ParseMaterial(unsigned int& matFlags) {
     int cnt  = 0; // number of used texture channels
     unsigned int nd = 0;
 
-    for (pugi::xml_node child : mNode.children()) {
+    for (pugi::xml_node child : mNode->children()) {
 		if (!ASSIMP_stricmp(child.name(), "color")) { // Hex properties
 			HexProperty prop;
 			ReadHexProperty(prop);

+ 44 - 41
code/AssetLib/Irr/IRRShared.h

@@ -7,49 +7,48 @@
 #ifndef INCLUDED_AI_IRRSHARED_H
 #define INCLUDED_AI_IRRSHARED_H
 
-#include <assimp/XmlParser.h>
 #include <assimp/BaseImporter.h>
+#include <assimp/XmlParser.h>
 #include <stdint.h>
 
 struct aiMaterial;
 
-namespace Assimp    {
+namespace Assimp {
 
 /** @brief Matrix to convert from Assimp to IRR and backwards
  */
 extern const aiMatrix4x4 AI_TO_IRR_MATRIX;
 
-
 // Default: 0 = solid, one texture
-#define AI_IRRMESH_MAT_solid_2layer         0x10000
+#define AI_IRRMESH_MAT_solid_2layer 0x10000
 
 // Transparency flags
-#define AI_IRRMESH_MAT_trans_vertex_alpha   0x1
-#define AI_IRRMESH_MAT_trans_add            0x2
+#define AI_IRRMESH_MAT_trans_vertex_alpha 0x1
+#define AI_IRRMESH_MAT_trans_add 0x2
 
 // Lightmapping flags
-#define AI_IRRMESH_MAT_lightmap             0x2
-#define AI_IRRMESH_MAT_lightmap_m2          (AI_IRRMESH_MAT_lightmap|0x4)
-#define AI_IRRMESH_MAT_lightmap_m4          (AI_IRRMESH_MAT_lightmap|0x8)
-#define AI_IRRMESH_MAT_lightmap_light       (AI_IRRMESH_MAT_lightmap|0x10)
-#define AI_IRRMESH_MAT_lightmap_light_m2    (AI_IRRMESH_MAT_lightmap|0x20)
-#define AI_IRRMESH_MAT_lightmap_light_m4    (AI_IRRMESH_MAT_lightmap|0x40)
-#define AI_IRRMESH_MAT_lightmap_add         (AI_IRRMESH_MAT_lightmap|0x80)
+#define AI_IRRMESH_MAT_lightmap 0x2
+#define AI_IRRMESH_MAT_lightmap_m2 (AI_IRRMESH_MAT_lightmap | 0x4)
+#define AI_IRRMESH_MAT_lightmap_m4 (AI_IRRMESH_MAT_lightmap | 0x8)
+#define AI_IRRMESH_MAT_lightmap_light (AI_IRRMESH_MAT_lightmap | 0x10)
+#define AI_IRRMESH_MAT_lightmap_light_m2 (AI_IRRMESH_MAT_lightmap | 0x20)
+#define AI_IRRMESH_MAT_lightmap_light_m4 (AI_IRRMESH_MAT_lightmap | 0x40)
+#define AI_IRRMESH_MAT_lightmap_add (AI_IRRMESH_MAT_lightmap | 0x80)
 
 // Standard NormalMap (or Parallax map, they're treated equally)
-#define AI_IRRMESH_MAT_normalmap_solid      (0x100)
+#define AI_IRRMESH_MAT_normalmap_solid (0x100)
 
 // Normal map combined with vertex alpha
-#define AI_IRRMESH_MAT_normalmap_tva    \
+#define AI_IRRMESH_MAT_normalmap_tva \
     (AI_IRRMESH_MAT_normalmap_solid | AI_IRRMESH_MAT_trans_vertex_alpha)
 
 // Normal map combined with additive transparency
-#define AI_IRRMESH_MAT_normalmap_ta     \
+#define AI_IRRMESH_MAT_normalmap_ta \
     (AI_IRRMESH_MAT_normalmap_solid | AI_IRRMESH_MAT_trans_add)
 
 // Special flag. It indicates a second texture has been found
 // Its type depends ... either a normal textue or a normal map
-#define AI_IRRMESH_EXTRA_2ND_TEXTURE        0x100000
+#define AI_IRRMESH_EXTRA_2ND_TEXTURE 0x100000
 
 // ---------------------------------------------------------------------------
 /** Base class for the Irr and IrrMesh importers.
@@ -57,58 +56,62 @@ extern const aiMatrix4x4 AI_TO_IRR_MATRIX;
  *  Declares some irrlight-related xml parsing utilities and provides tools
  *  to load materials from IRR and IRRMESH files.
  */
-class IrrlichtBase
-{
+class IrrlichtBase {
 protected:
+    IrrlichtBase() :
+            mNode(nullptr) {
+        // empty
+    }
+
+    ~IrrlichtBase() {
+        // empty
+    }
 
     /** @brief Data structure for a simple name-value property
      */
     template <class T>
-    struct Property
-    {
+    struct Property {
         std::string name;
         T value;
     };
 
-    typedef Property<uint32_t>      HexProperty;
-    typedef Property<std::string>   StringProperty;
-    typedef Property<bool>          BoolProperty;
-    typedef Property<float>         FloatProperty;
-    typedef Property<aiVector3D>    VectorProperty;
-    typedef Property<int>           IntProperty;
+    typedef Property<uint32_t> HexProperty;
+    typedef Property<std::string> StringProperty;
+    typedef Property<bool> BoolProperty;
+    typedef Property<float> FloatProperty;
+    typedef Property<aiVector3D> VectorProperty;
+    typedef Property<int> IntProperty;
 
     /// XML reader instance
-	XmlParser mParser;
-	pugi::xml_node &mNode;
+    XmlParser mParser;
+    pugi::xml_node *mNode;
 
     // -------------------------------------------------------------------
     /** Parse a material description from the XML
      *  @return The created material
      *  @param matFlags Receives AI_IRRMESH_MAT_XX flags
      */
-    aiMaterial* ParseMaterial(unsigned int& matFlags);
+    aiMaterial *ParseMaterial(unsigned int &matFlags);
 
     // -------------------------------------------------------------------
     /** Read a property of the specified type from the current XML element.
      *  @param out Receives output data
      */
-    void ReadHexProperty    (HexProperty&    out);
-    void ReadStringProperty (StringProperty& out);
-    void ReadBoolProperty   (BoolProperty&   out);
-    void ReadFloatProperty  (FloatProperty&  out);
-    void ReadVectorProperty (VectorProperty&  out);
-    void ReadIntProperty    (IntProperty&    out);
+    void ReadHexProperty(HexProperty &out);
+    void ReadStringProperty(StringProperty &out);
+    void ReadBoolProperty(BoolProperty &out);
+    void ReadFloatProperty(FloatProperty &out);
+    void ReadVectorProperty(VectorProperty &out);
+    void ReadIntProperty(IntProperty &out);
 };
 
-
 // ------------------------------------------------------------------------------------------------
 // Unpack a hex color, e.g. 0xdcdedfff
-inline
-void ColorFromARGBPacked(uint32_t in, aiColor4D& clr) {
+inline void ColorFromARGBPacked(uint32_t in, aiColor4D &clr) {
     clr.a = ((in >> 24) & 0xff) / 255.f;
     clr.r = ((in >> 16) & 0xff) / 255.f;
-    clr.g = ((in >>  8) & 0xff) / 255.f;
-    clr.b = ((in      ) & 0xff) / 255.f;
+    clr.g = ((in >> 8) & 0xff) / 255.f;
+    clr.b = ((in)&0xff) / 255.f;
 }
 
 } // end namespace Assimp

+ 3 - 1
contrib/pugixml-1.9/src/pugixml.hpp

@@ -1251,6 +1251,8 @@ namespace pugi
 	};
 
 	#ifndef PUGIXML_NO_EXCEPTIONS
+#pragma warning(push)
+#pragma warning( disable: 4275 )
 	// XPath exception class
 	class PUGIXML_CLASS xpath_exception: public std::exception
 	{
@@ -1268,7 +1270,7 @@ namespace pugi
 		const xpath_parse_result& result() const;
 	};
 	#endif
-
+#pragma warning(pop)
 	// XPath node class (either xml_node or xml_attribute)
 	class PUGIXML_CLASS xpath_node
 	{

+ 4 - 0
include/assimp/XmlParser.h

@@ -109,6 +109,10 @@ public:
         return &node;
     }
 
+    bool hasNode( const std::string &name ) const {
+        return nullptr != findNode(name);
+    }
+
     TNodeType *parse(IOStream *stream) {
 		if (nullptr == stream) {
 			return nullptr;

Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini