Quellcode durchsuchen

ogre + collada migration.

Kim Kulling vor 5 Jahren
Ursprung
Commit
21678df589

+ 3 - 236
code/AssetLib/AMF/AMFImporter.cpp

@@ -181,118 +181,10 @@ void AMFImporter::XML_CheckNode_MustHaveChildren(pugi::xml_node &node) {
     }
 }
 
-/*void AMFImporter::XML_CheckNode_SkipUnsupported(const std::string &pParentNodeName) {
-    static const size_t Uns_Skip_Len = 3;
-    const char *Uns_Skip[Uns_Skip_Len] = { "composite", "edge", "normal" };
-
-    static bool skipped_before[Uns_Skip_Len] = { false, false, false };
-
-    std::string nn(mReader->getNodeName());
-    bool found = false;
-    bool close_found = false;
-    size_t sk_idx;
-
-    for (sk_idx = 0; sk_idx < Uns_Skip_Len; sk_idx++) {
-        if (nn != Uns_Skip[sk_idx]) continue;
-
-        found = true;
-        if (mReader->isEmptyElement()) {
-            close_found = true;
-
-            goto casu_cres;
-        }
-
-        while (mReader->read()) {
-            if ((mReader->getNodeType() == irr::io::EXN_ELEMENT_END) && (nn == mReader->getNodeName())) {
-                close_found = true;
-
-                goto casu_cres;
-            }
-        }
-    } // for(sk_idx = 0; sk_idx < Uns_Skip_Len; sk_idx++)
-
-casu_cres:
-
-    if (!found) throw DeadlyImportError("Unknown node \"" + nn + "\" in " + pParentNodeName + ".");
-    if (!close_found) Throw_CloseNotFound(nn);
-
-    if (!skipped_before[sk_idx]) {
-        skipped_before[sk_idx] = true;
-        ASSIMP_LOG_WARN_F("Skipping node \"", nn, "\" in ", pParentNodeName, ".");
-    }
-}*/
-
 bool AMFImporter::XML_SearchNode(const std::string &nodeName) {
     return nullptr != mXmlParser->findNode(nodeName);
 }
 
-/*bool AMFImporter::XML_ReadNode_GetAttrVal_AsBool(const int pAttrIdx) {
-    std::string val(mReader->getAttributeValue(pAttrIdx));
-
-    if ((val == "false") || (val == "0"))
-        return false;
-    else if ((val == "true") || (val == "1"))
-        return true;
-    else
-        throw DeadlyImportError("Bool attribute value can contain \"false\"/\"0\" or \"true\"/\"1\" not the \"" + val + "\"");
-}
-
-float AMFImporter::XML_ReadNode_GetAttrVal_AsFloat(const int pAttrIdx) {
-    std::string val;
-    float tvalf;
-
-    ParseHelper_FixTruncatedFloatString(mReader->getAttributeValue(pAttrIdx), val);
-    fast_atoreal_move(val.c_str(), tvalf, false);
-
-    return tvalf;
-}
-
-uint32_t AMFImporter::XML_ReadNode_GetAttrVal_AsU32(const int pAttrIdx) {
-    return strtoul10(mReader->getAttributeValue(pAttrIdx));
-}
-
-float AMFImporter::XML_ReadNode_GetVal_AsFloat() {
-    std::string val;
-    float tvalf;
-
-    if (!mReader->read()) throw DeadlyImportError("XML_ReadNode_GetVal_AsFloat. No data, seems file is corrupt.");
-    if (mReader->getNodeType() != irr::io::EXN_TEXT) throw DeadlyImportError("XML_ReadNode_GetVal_AsFloat. Invalid type of XML element, seems file is corrupt.");
-
-    ParseHelper_FixTruncatedFloatString(mReader->getNodeData(), val);
-    fast_atoreal_move(val.c_str(), tvalf, false);
-
-    return tvalf;
-}
-
-uint32_t AMFImporter::XML_ReadNode_GetVal_AsU32() {
-    if (!mReader->read()) throw DeadlyImportError("XML_ReadNode_GetVal_AsU32. No data, seems file is corrupt.");
-    if (mReader->getNodeType() != irr::io::EXN_TEXT) throw DeadlyImportError("XML_ReadNode_GetVal_AsU32. Invalid type of XML element, seems file is corrupt.");
-
-    return strtoul10(mReader->getNodeData());
-}
-
-void AMFImporter::XML_ReadNode_GetVal_AsString(std::string &pValue) {
-    if (!mReader->read()) throw DeadlyImportError("XML_ReadNode_GetVal_AsString. No data, seems file is corrupt.");
-    if (mReader->getNodeType() != irr::io::EXN_TEXT)
-        throw DeadlyImportError("XML_ReadNode_GetVal_AsString. Invalid type of XML element, seems file is corrupt.");
-
-    pValue = mReader->getNodeData();
-}*/
-
-/*********************************************************************************************************************************************/
-/************************************************************ Functions: parse set ***********************************************************/
-/*********************************************************************************************************************************************/
-
-/*void AMFImporter::ParseHelper_Node_Enter(CAMFImporter_NodeElement *pNode) {
-    mNodeElement_Cur->Child.push_back(pNode); // add new element to current element child list.
-    mNodeElement_Cur = pNode; // switch current element to new one.
-}
-
-void AMFImporter::ParseHelper_Node_Exit() {
-    // check if we can walk up.
-    if (mNodeElement_Cur != nullptr) mNodeElement_Cur = mNodeElement_Cur->Parent;
-}
-*/
 void AMFImporter::ParseHelper_FixTruncatedFloatString(const char *pInStr, std::string &pOutString) {
     size_t instr_len;
 
@@ -369,7 +261,6 @@ void AMFImporter::ParseHelper_Decode_Base64(const std::string &pInputBase64, std
 }
 
 void AMFImporter::ParseFile(const std::string &pFile, IOSystem *pIOHandler) {
-//    irr::io::IrrXMLReader *OldReader = mReader; // store current XMLreader.
     std::unique_ptr<IOStream> file(pIOHandler->Open(pFile, "rb"));
 
     // Check whether we can read from the file
@@ -388,8 +279,6 @@ void AMFImporter::ParseFile(const std::string &pFile, IOSystem *pIOHandler) {
         throw DeadlyImportError("Root node \"amf\" not found.");
     }
     ParseNode_Root();
-
-    //delete mReader;
 } // namespace Assimp
 
 // <amf
@@ -408,11 +297,6 @@ void AMFImporter::ParseNode_Root() {
     version = root->attribute("version").as_string();
 
     // Read attributes for node <amf>.
-    /*MACRO_ATTRREAD_LOOPBEG;
-    MACRO_ATTRREAD_CHECK_RET("unit", unit, mReader->getAttributeValue);
-    MACRO_ATTRREAD_CHECK_RET("version", version, mReader->getAttributeValue);
-    MACRO_ATTRREAD_LOOPEND_WSKIP;*/
-
     // Check attributes
     if (!mUnit.empty()) {
         if ((mUnit != "inch") && (mUnit != "millimeter") && (mUnit != "meter") && (mUnit != "feet") && (mUnit != "micron")) {
@@ -428,6 +312,7 @@ void AMFImporter::ParseNode_Root() {
     ((AMFRoot *)ne)->Unit = unit;
     ((AMFRoot *)ne)->Version = version;
 
+    // Check for child nodes
     for (pugi::xml_node &currentNode : root->children()) {
         const std::string currentName = currentNode.name();
         if (currentName == "object") {
@@ -443,32 +328,6 @@ void AMFImporter::ParseNode_Root() {
         }
         mNodeElement_Cur = ne; // force restore "current" element
     }
-    // Check for child nodes
-    /*if (!mReader->isEmptyElement()) {
-        MACRO_NODECHECK_LOOPBEGIN("amf");
-        if (XML_CheckNode_NameEqual("object")) {
-            ParseNode_Object();
-            continue;
-        }
-        if (XML_CheckNode_NameEqual("material")) {
-            ParseNode_Material();
-            continue;
-        }
-        if (XML_CheckNode_NameEqual("texture")) {
-            ParseNode_Texture();
-            continue;
-        }
-        if (XML_CheckNode_NameEqual("constellation")) {
-            ParseNode_Constellation();
-            continue;
-        }
-        if (XML_CheckNode_NameEqual("metadata")) {
-            ParseNode_Metadata();
-            continue;
-        }
-        MACRO_NODECHECK_LOOPEND("amf");
-        mNodeElement_Cur = ne; // force restore "current" element
-    } // if(!mReader->isEmptyElement())*/
 
     mNodeElement_List.push_back(ne); // add to node element list because its a new object in graph.
 }
@@ -483,10 +342,6 @@ void AMFImporter::ParseNode_Root() {
 void AMFImporter::ParseNode_Constellation(XmlNode &node) {
     std::string id;
     id = node.attribute("id").as_string();
-    // Read attributes for node <constellation>.
-    /*MACRO_ATTRREAD_LOOPBEG;
-    MACRO_ATTRREAD_CHECK_RET("id", id, mReader->getAttributeValue);
-    MACRO_ATTRREAD_LOOPEND;*/
 
     // create and if needed - define new grouping object.
     AMFNodeElementBase *ne = new AMFConstellation(mNodeElement_Cur);
@@ -497,6 +352,7 @@ void AMFImporter::ParseNode_Constellation(XmlNode &node) {
         als.ID = id;
     }
 
+    // Check for child nodes
     for (pugi::xml_node &currentNode : node.children()) {
         std::string name = currentNode.name();
         if (name == "instance") {
@@ -509,26 +365,6 @@ void AMFImporter::ParseNode_Constellation(XmlNode &node) {
         mNodeElement_Cur->Child.push_back(ne);
     }
     mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph.
-    // Check for child nodes
-    /*if (!mReader->isEmptyElement()) {
-        ParseHelper_Node_Enter(ne);
-        MACRO_NODECHECK_LOOPBEGIN("constellation");
-        if (XML_CheckNode_NameEqual("instance")) {
-            ParseNode_Instance();
-            continue;
-        }
-        if (XML_CheckNode_NameEqual("metadata")) {
-            ParseNode_Metadata();
-            continue;
-        }
-        MACRO_NODECHECK_LOOPEND("constellation");
-        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.*/
 }
 
 // <instance
@@ -542,9 +378,6 @@ void AMFImporter::ParseNode_Instance(XmlNode &node) {
     AMFNodeElementBase *ne(nullptr);
 
     // Read attributes for node <constellation>.
-/*    MACRO_ATTRREAD_LOOPBEG;
-    MACRO_ATTRREAD_CHECK_RET("objectid", objectid, mReader->getAttributeValue);
-    MACRO_ATTRREAD_LOOPEND;*/
     std::string objectid = node.attribute("objectid").as_string();
 
     // used object id must be defined, check that.
@@ -552,9 +385,7 @@ void AMFImporter::ParseNode_Instance(XmlNode &node) {
         throw DeadlyImportError("\"objectid\" in <instance> must be defined.");
     }
     // create and define new grouping object.
-    //ne = new CAMFImporter_NodeElement_Instance(mNodeElement_Cur);
     ne = new AMFInstance(mNodeElement_Cur);
-    //CAMFImporter_NodeElement_Instance &als = *((CAMFImporter_NodeElement_Instance *)ne); // alias for convenience
     AMFInstance &als = *((AMFInstance *)ne);
     als.ObjectID = objectid;
 
@@ -584,29 +415,6 @@ void AMFImporter::ParseNode_Instance(XmlNode &node) {
             als.Delta.z = (ai_real)std::atof(currentNode.value());
         }
     }
-    // Check for child nodes
-    /*if (!mReader->isEmptyElement()) {
-
-        als.Delta.Set(0, 0, 0);
-        als.Rotation.Set(0, 0, 0);
-        ParseHelper_Node_Enter(ne);
-        MACRO_NODECHECK_LOOPBEGIN("instance");
-        MACRO_NODECHECK_READCOMP_F("deltax", read_flag[0], als.Delta.x);
-        MACRO_NODECHECK_READCOMP_F("deltay", read_flag[1], als.Delta.y);
-        MACRO_NODECHECK_READCOMP_F("deltaz", read_flag[2], als.Delta.z);
-        MACRO_NODECHECK_READCOMP_F("rx", read_flag[3], als.Rotation.x);
-        MACRO_NODECHECK_READCOMP_F("ry", read_flag[4], als.Rotation.y);
-        MACRO_NODECHECK_READCOMP_F("rz", read_flag[5], als.Rotation.z);
-        MACRO_NODECHECK_LOOPEND("instance");
-        ParseHelper_Node_Exit();
-        // also convert degrees to radians.
-        als.Rotation.x = AI_MATH_PI_F * als.Rotation.x / 180.0f;
-        als.Rotation.y = AI_MATH_PI_F * als.Rotation.y / 180.0f;
-        als.Rotation.z = AI_MATH_PI_F * als.Rotation.z / 180.0f;
-    } // 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.
 }
@@ -623,10 +431,8 @@ void AMFImporter::ParseNode_Object(XmlNode &node) {
     AMFNodeElementBase *ne(nullptr);
 
     // Read attributes for node <object>.
-    /*MACRO_ATTRREAD_LOOPBEG;
-    MACRO_ATTRREAD_CHECK_RET("id", id, mReader->getAttributeValue);
-    MACRO_ATTRREAD_LOOPEND;*/
     std::string id = node.attribute("id").as_string();
+
     // create and if needed - define new geometry object.
     ne = new AMFObject(mNodeElement_Cur);
 
@@ -652,35 +458,6 @@ void AMFImporter::ParseNode_Object(XmlNode &node) {
             ParseNode_Metadata(currentNode);
         }
     }
-    /*if (!mReader->isEmptyElement()) {
-        bool col_read = false;
-
-        ParseHelper_Node_Enter(ne);
-        MACRO_NODECHECK_LOOPBEGIN("object");
-        if (XML_CheckNode_NameEqual("color")) {
-            // Check if color already defined for object.
-            if (col_read) Throw_MoreThanOnceDefined("color", "Only one color can be defined for <object>.");
-            // read data and set flag about it
-            ParseNode_Color();
-            col_read = true;
-
-            continue;
-        }
-
-        if (XML_CheckNode_NameEqual("mesh")) {
-            ParseNode_Mesh();
-            continue;
-        }
-        if (XML_CheckNode_NameEqual("metadata")) {
-            ParseNode_Metadata();
-            continue;
-        }
-        MACRO_NODECHECK_LOOPEND("object");
-        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.
 }
@@ -711,12 +488,6 @@ void AMFImporter::ParseNode_Metadata(XmlNode &node) {
     value = node.value();
 
     // read attribute
-    /*MACRO_ATTRREAD_LOOPBEG;
-    MACRO_ATTRREAD_CHECK_RET("type", type, mReader->getAttributeValue);
-    MACRO_ATTRREAD_LOOPEND;*/
-    // and value of node.
-    //value = mReader->getNodeData();
-    // Create node element and assign read data.
     ne = new AMFMetadata(mNodeElement_Cur);
     ((AMFMetadata *)ne)->Type = type;
     ((AMFMetadata *)ne)->Value = value;
@@ -724,10 +495,6 @@ void AMFImporter::ParseNode_Metadata(XmlNode &node) {
     mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph.
 }
 
-/*********************************************************************************************************************************************/
-/******************************************************** Functions: BaseImporter set ********************************************************/
-/*********************************************************************************************************************************************/
-
 bool AMFImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool pCheckSig) const {
     const std::string extension = GetExtension(pFile);
 

+ 0 - 1
code/AssetLib/AMF/AMFImporter.hpp

@@ -101,7 +101,6 @@ class AMFImporter : public BaseImporter {
 private:
     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 {
         SPP_Material *Material; ///< Pointer to material - part of composition.

+ 8 - 182
code/AssetLib/AMF/AMFImporter_Geometry.cpp

@@ -81,29 +81,6 @@ void AMFImporter::ParseNode_Mesh(XmlNode &node) {
         found_volumes = true;
     }
 
-    /*if(!mReader->isEmptyElement())
-	{
-		bool vert_read = false;
-
-		ParseHelper_Node_Enter(ne);
-		MACRO_NODECHECK_LOOPBEGIN("mesh");
-			if(XML_CheckNode_NameEqual("vertices"))
-			{
-				// Check if data already defined.
-				if(vert_read) Throw_MoreThanOnceDefined("vertices", "Only one vertices set can be defined for <mesh>.");
-				// read data and set flag about it
-				ParseNode_Vertices();
-				vert_read = true;
-
-				continue;
-			}
-
-			if(XML_CheckNode_NameEqual("volume")) { ParseNode_Volume(); continue; }
-		MACRO_NODECHECK_LOOPEND("mesh");
-		ParseHelper_Node_Exit();
-	}// if(!mReader->isEmptyElement())
-	else*/
-    // Add element to child list of current element
     if (!found_verts && !found_volumes) {
         mNodeElement_Cur->Child.push_back(ne);
     } // if(!mReader->isEmptyElement()) else
@@ -130,20 +107,6 @@ void AMFImporter::ParseNode_Vertices(XmlNode &node) {
         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.
 }
 
@@ -157,6 +120,8 @@ void AMFImporter::ParseNode_Vertex(XmlNode &node) {
 
     // create new mesh object.
     ne = new AMFVertex(mNodeElement_Cur);
+
+    // Check for child nodes
     pugi::xml_node colorNode = node.child("color");
     bool col_read = false;
     bool coord_read = false;
@@ -173,42 +138,6 @@ void AMFImporter::ParseNode_Vertex(XmlNode &node) {
         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.
 }
 
@@ -238,25 +167,6 @@ void AMFImporter::ParseNode_Coordinates(XmlNode &node) {
         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.
 }
 
@@ -275,13 +185,6 @@ void AMFImporter::ParseNode_Volume(XmlNode &node) {
     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();
@@ -308,36 +211,6 @@ void AMFImporter::ParseNode_Volume(XmlNode &node) {
         }
     }
 
-    /*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.
 }
 
@@ -354,14 +227,15 @@ void AMFImporter::ParseNode_Volume(XmlNode &node) {
 void AMFImporter::ParseNode_Triangle(XmlNode &node) {
     AMFNodeElementBase *ne = new AMFTriangle(mNodeElement_Cur);
 
-    // create new color object.
-    //ne = new CAMFImporter_NodeElement_Triangle(mNodeElement_Cur);
+    // create new triangle object.
 
     AMFTriangle &als = *((AMFTriangle *)ne); // alias for convenience
 
     if (node.empty()) {
         mNodeElement_Cur->Child.push_back(ne); // Add element to child list of current element
     }
+
+    // Check for child nodes
     bool col_read = false, tex_read = false;
     bool read_flag[3] = { false, false, false };
     for (pugi::xml_node currentNode : node.children()) {
@@ -387,59 +261,11 @@ void AMFImporter::ParseNode_Triangle(XmlNode &node) {
             read_flag[2] = true;
         }
     }
-    if ((read_flag[0] && read_flag[1] && read_flag[2]) == 0) throw DeadlyImportError("Not all vertices of the triangle are defined.");
-
-
-    // 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;
-        }
+    if ((read_flag[0] && read_flag[1] && read_flag[2]) == 0) {
+        throw DeadlyImportError("Not all vertices of the triangle are defined.");
+    }
 
-        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.
 }
 

+ 0 - 2
code/AssetLib/AMF/AMFImporter_Macro.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,

+ 0 - 3
code/AssetLib/AMF/AMFImporter_Material.cpp

@@ -177,9 +177,6 @@ void AMFImporter::ParseNode_Texture(XmlNode &node) {
 
     std::string enc64_data = node.value();
 	// Check for child nodes
-    //if (!mXmlParser->isEmptyElement()) {
-    //    XML_ReadNode_GetVal_AsString(enc64_data);
-    //}
 
 	// check that all components was defined
     if (id.empty()) {

+ 37 - 43
code/AssetLib/Collada/ColladaLoader.cpp

@@ -45,24 +45,21 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include "ColladaLoader.h"
 #include "ColladaParser.h"
-
 #include <assimp/ColladaMetaData.h>
-#include <assimp/Defines.h>
-#include <assimp/anim.h>
-#include <assimp/importerdesc.h>
-#include <assimp/scene.h>
-#include <assimp/DefaultLogger.hpp>
-#include <assimp/Importer.hpp>
-
 #include <assimp/CreateAnimMesh.h>
+#include <assimp/Defines.h>
 #include <assimp/ParsingUtils.h>
 #include <assimp/SkeletonMeshBuilder.h>
 #include <assimp/ZipArchiveIOSystem.h>
+#include <assimp/anim.h>
 #include <assimp/fast_atof.h>
-
-#include "math.h"
-#include "time.h"
+#include <assimp/importerdesc.h>
+#include <assimp/scene.h>
+#include <math.h>
+#include <time.h>
 #include <algorithm>
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/Importer.hpp>
 #include <memory>
 #include <numeric>
 
@@ -125,20 +122,17 @@ ColladaLoader::~ColladaLoader() {
 bool ColladaLoader::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
     // check file extension
     const std::string extension = GetExtension(pFile);
-
-    bool readSig = checkSig && (pIOHandler != nullptr);
-
+    const bool readSig = checkSig && (pIOHandler != nullptr);
     if (!readSig) {
         if (extension == "dae" || extension == "zae") {
             return true;
         }
-    }
-
-    if (readSig) {
+    } else {
         // Look for a DAE file inside, but don't extract it
         ZipArchiveIOSystem zip_archive(pIOHandler, pFile);
-        if (zip_archive.isOpen())
+        if (zip_archive.isOpen()) {
             return !ColladaParser::ReadZaeManifest(zip_archive).empty();
+        }
     }
 
     // XML - too generic, we need to open the file and search for typical keywords
@@ -585,10 +579,10 @@ void ColladaLoader::BuildMeshesForNode(const ColladaParser &pParser, const Colla
 // ------------------------------------------------------------------------------------------------
 // Find mesh from either meshes or morph target meshes
 aiMesh *ColladaLoader::findMesh(const std::string &meshid) {
-    if ( meshid.empty()) {
+    if (meshid.empty()) {
         return nullptr;
     }
-    
+
     for (unsigned int i = 0; i < mMeshes.size(); ++i) {
         if (std::string(mMeshes[i]->mName.data) == meshid) {
             return mMeshes[i];
@@ -1377,9 +1371,9 @@ void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParse
                 double time = double(mat.d4); // remember? time is stored in mat.d4
                 mat.d4 = 1.0f;
 
-                dstAnim->mPositionKeys[a].mTime = time * kMillisecondsFromSeconds ;
-                dstAnim->mRotationKeys[a].mTime = time * kMillisecondsFromSeconds ;
-                dstAnim->mScalingKeys[a].mTime = time * kMillisecondsFromSeconds ;
+                dstAnim->mPositionKeys[a].mTime = time * kMillisecondsFromSeconds;
+                dstAnim->mRotationKeys[a].mTime = time * kMillisecondsFromSeconds;
+                dstAnim->mScalingKeys[a].mTime = time * kMillisecondsFromSeconds;
                 mat.Decompose(dstAnim->mScalingKeys[a].mValue, dstAnim->mRotationKeys[a].mValue, dstAnim->mPositionKeys[a].mValue);
             }
 
@@ -1400,7 +1394,7 @@ void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParse
                 if (e.mTargetId.find("morph-weights") != std::string::npos)
                     morphChannels.push_back(e);
             }
-            if (!morphChannels.empty() ) {
+            if (!morphChannels.empty()) {
                 // either 1) morph weight animation count should contain morph target count channels
                 // or     2) one channel with morph target count arrays
                 // assume first
@@ -1434,8 +1428,8 @@ void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParse
                     morphAnim->mKeys[key].mValues = new unsigned int[morphChannels.size()];
                     morphAnim->mKeys[key].mWeights = new double[morphChannels.size()];
 
-                    morphAnim->mKeys[key].mTime = morphTimeValues[key].mTime * kMillisecondsFromSeconds ;
-                    for (unsigned int valueIndex = 0; valueIndex < morphChannels.size(); ++valueIndex ) {
+                    morphAnim->mKeys[key].mTime = morphTimeValues[key].mTime * kMillisecondsFromSeconds;
+                    for (unsigned int valueIndex = 0; valueIndex < morphChannels.size(); ++valueIndex) {
                         morphAnim->mKeys[key].mValues[valueIndex] = valueIndex;
                         morphAnim->mKeys[key].mWeights[valueIndex] = getWeightAtKey(morphTimeValues, key, valueIndex);
                     }
@@ -1552,23 +1546,23 @@ void ColladaLoader::FillMaterials(const ColladaParser &pParser, aiScene * /*pSce
             shadeMode = aiShadingMode_Flat;
         } else {
             switch (effect.mShadeType) {
-                case Collada::Shade_Constant:
-                    shadeMode = aiShadingMode_NoShading;
-                    break;
-                case Collada::Shade_Lambert:
-                    shadeMode = aiShadingMode_Gouraud;
-                    break;
-                case Collada::Shade_Blinn:
-                    shadeMode = aiShadingMode_Blinn;
-                    break;
-                case Collada::Shade_Phong:
-                    shadeMode = aiShadingMode_Phong;
-                    break;
+            case Collada::Shade_Constant:
+                shadeMode = aiShadingMode_NoShading;
+                break;
+            case Collada::Shade_Lambert:
+                shadeMode = aiShadingMode_Gouraud;
+                break;
+            case Collada::Shade_Blinn:
+                shadeMode = aiShadingMode_Blinn;
+                break;
+            case Collada::Shade_Phong:
+                shadeMode = aiShadingMode_Phong;
+                break;
 
-                default:
-                    ASSIMP_LOG_WARN("Collada: Unrecognized shading mode, using gouraud shading");
-                    shadeMode = aiShadingMode_Gouraud;
-                    break;
+            default:
+                ASSIMP_LOG_WARN("Collada: Unrecognized shading mode, using gouraud shading");
+                shadeMode = aiShadingMode_Gouraud;
+                break;
             }
         }
         mat.AddProperty<int>(&shadeMode, 1, AI_MATKEY_SHADING_MODEL);
@@ -1734,7 +1728,7 @@ aiString ColladaLoader::FindFilenameForEffectTexture(const ColladaParser &pParse
         // and add this texture to the list
         mTextures.push_back(tex);
         return result;
-    } 
+    }
 
     if (imIt->second.mFileName.empty()) {
         throw DeadlyImportError("Collada: Invalid texture, no data or file reference given");

+ 471 - 190
code/AssetLib/Collada/ColladaParser.cpp

@@ -160,11 +160,26 @@ std::string ColladaParser::ReadZaeManifest(ZipArchiveIOSystem &zip_archive) {
 
         return file_list.front();
     }
+    XmlParser manifestParser;
+    XmlNode *root = manifestParser.parse(manifestfile.get());
+    if (nullptr == root) {
+        return std::string();
+    }
+    const std::string name = root->name();
+    if (name != "dae_root") {
+        root = manifestParser.findNode("dae_root");
+        if (nullptr == root) {
+            return std::string();
+        }
+        const char *filepath = root->value();
+        aiString ai_str(filepath);
+        UriDecodePath(ai_str);
+        return std::string(ai_str.C_Str());
+    }
+    /*std::unique_ptr<CIrrXML_IOStreamReader> mIOWrapper(new CIrrXML_IOStreamReader(manifestfile.get()));
+    std::unique_ptr<irr::io::IrrXMLReader> manifest_reader(irr::io::createIrrXMLReader(mIOWrapper.get()));*/
 
-    std::unique_ptr<CIrrXML_IOStreamReader> mIOWrapper(new CIrrXML_IOStreamReader(manifestfile.get()));
-    std::unique_ptr<irr::io::IrrXMLReader> manifest_reader(irr::io::createIrrXMLReader(mIOWrapper.get()));
-
-    while (manifest_reader->read()) {
+    /*while (manifest_reader->read()) {
         // find the manifest "dae_root" element
         if (manifest_reader->getNodeType() == irr::io::EXN_ELEMENT) {
             if (::strcmp(manifest_reader->getNodeName(), "dae_root") == 0) {
@@ -183,7 +198,7 @@ std::string ColladaParser::ReadZaeManifest(ZipArchiveIOSystem &zip_archive) {
                 return std::string(ai_str.C_Str());
             }
         }
-    }
+    }*/
     return std::string();
 }
 
@@ -314,7 +329,6 @@ void ColladaParser::ReadContents(XmlNode &node) {
 
 // ------------------------------------------------------------------------------------------------
 // Reads the structure of the file
-<<<<<<< HEAD
 void ColladaParser::ReadStructure(XmlNode &node) {
     for (pugi::xml_node curNode : node.children()) {
         const std::string name = std::string(curNode.name());
@@ -341,7 +355,7 @@ void ColladaParser::ReadStructure(XmlNode &node) {
         else if (name == "library_cameras")
             ReadCameraLibrary(curNode);
         else if (name == "library_nodes")
-            ReadSceneNode(NULL); /* some hacking to reuse this piece of code */
+            ReadSceneNode(curNode, nullptr); /* some hacking to reuse this piece of code */
         else if (name == "scene")
             ReadScene(curNode);
         //else
@@ -381,44 +395,6 @@ void ColladaParser::ReadStructure(XmlNode &node) {
             } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
                 break;
             }*/
-=======
-void ColladaParser::ReadStructure() {
-    while (mReader->read()) {
-        // beginning of elements
-        if (mReader->getNodeType() == irr::io::EXN_ELEMENT) {
-            if (IsElement("asset"))
-                ReadAssetInfo();
-            else if (IsElement("library_animations"))
-                ReadAnimationLibrary();
-            else if (IsElement("library_animation_clips"))
-                ReadAnimationClipLibrary();
-            else if (IsElement("library_controllers"))
-                ReadControllerLibrary();
-            else if (IsElement("library_images"))
-                ReadImageLibrary();
-            else if (IsElement("library_materials"))
-                ReadMaterialLibrary();
-            else if (IsElement("library_effects"))
-                ReadEffectLibrary();
-            else if (IsElement("library_geometries"))
-                ReadGeometryLibrary();
-            else if (IsElement("library_visual_scenes"))
-                ReadSceneLibrary();
-            else if (IsElement("library_lights"))
-                ReadLightLibrary();
-            else if (IsElement("library_cameras"))
-                ReadCameraLibrary();
-            else if (IsElement("library_nodes"))
-                ReadSceneNode(nullptr); /* some hacking to reuse this piece of code */
-            else if (IsElement("scene"))
-                ReadScene();
-            else
-                SkipElement();
-        } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
-            break;
-        }
-    }
->>>>>>> master
 
     PostProcessRootAnimations();
     PostProcessControllers();
@@ -436,7 +412,7 @@ void ColladaParser::ReadAssetInfo(XmlNode &node) {
             pugi::xml_attribute attr = curNode.attribute("meter");
             mUnitSize = 1.f;
             if (attr) {
-                mUnitSize = attr.as_double();
+                mUnitSize = static_cast<ai_real>(attr.as_double());
             }
         } else if (name == "up_axis") {
             const char *content = curNode.value();
@@ -602,7 +578,7 @@ void ColladaParser::ReadAnimationClipLibrary(XmlNode &node) {
                 if (urlName[0] != '#') {
                     ThrowException("Unknown reference format");
                 }
-                clip.second.push_back(url);
+                clip.second.push_back(url.as_string());
             }
         }
 
@@ -919,8 +895,27 @@ void ColladaParser::ReadAnimationSampler(XmlNode &node, Collada::AnimationChanne
     for (pugi::xml_node &curNode : node.children()) {
         const std::string currentName = curNode.name();
         if (currentName == "input") {
-            pugi::xml_attribute semantic = curNode.attribute("semantic");
-            if (semantic) {
+            pugi::xml_attribute semanticAttr = curNode.attribute("semantic");
+            if (!semanticAttr.empty()) {
+                const char *semantic = semanticAttr.as_string();
+                pugi::xml_attribute sourceAttr = curNode.attribute("source");
+                if (!sourceAttr.empty()) {
+                    const char *source = sourceAttr.as_string();
+                    if (source[0] != '#')
+                        ThrowException("Unsupported URL format");
+                    source++;
+
+                    if (strcmp(semantic, "INPUT") == 0)
+                        pChannel.mSourceTimes = source;
+                    else if (strcmp(semantic, "OUTPUT") == 0)
+                        pChannel.mSourceValues = source;
+                    else if (strcmp(semantic, "IN_TANGENT") == 0)
+                        pChannel.mInTanValues = source;
+                    else if (strcmp(semantic, "OUT_TANGENT") == 0)
+                        pChannel.mOutTanValues = source;
+                    else if (strcmp(semantic, "INTERPOLATION") == 0)
+                        pChannel.mInterpolationValues = source;
+                }
             }
         }
     }
@@ -970,7 +965,23 @@ void ColladaParser::ReadControllerLibrary(XmlNode &node) {
     /*if (mReader->isEmptyElement())
         return;*/
 
-    while (mReader->read()) {
+    const std::string name = node.name();
+    if (name != "controller") {
+        return;
+    }
+    int attrId = node.attribute("id").as_int();
+    std::string id = node.value();
+    mControllerLibrary[id] = Controller();
+    for (XmlNode currentNode : node.children()) {
+        const std::string currentName = currentNode.name();
+        if (currentName == "controller") {
+            int attrID = currentNode.attribute("id").as_int();
+            std::string controllerId = currentNode.attribute(itoa(attrID, NULL, 10)).value();
+            ReadController(node, mControllerLibrary[controllerId]);
+        }
+    }
+
+    /*while (mReader->read()) {
         if (mReader->getNodeType() == irr::io::EXN_ELEMENT) {
             if (IsElement("controller")) {
                 // read ID. Ask the spec if it's necessary or optional... you might be surprised.
@@ -992,7 +1003,7 @@ void ColladaParser::ReadControllerLibrary(XmlNode &node) {
 
             break;
         }
-    }
+    }*/
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -1001,7 +1012,54 @@ void ColladaParser::ReadController(XmlNode &node, Collada::Controller &pControll
     // initial values
     pController.mType = Skin;
     pController.mMethod = Normalized;
-    while (mReader->read()) {
+    for (XmlNode currentNode : node.children()) {
+        const std::string currentName = currentNode.name();
+        if (currentName == "morph") {
+            pController.mType = Morph;
+            int baseIndex = currentNode.attribute("source").as_int();
+            pController.mMeshId = currentNode.attribute.begin() + baseIndex + 1;
+            int methodIndex = currentNode.attribute("method").as_int();
+            if (methodIndex > 0) {
+                const char *method = currentNode.attribute("method").value();
+                if (strcmp(method, "RELATIVE") == 0) {
+                    pController.mMethod = Relative;
+                }
+            }
+        } else if (currentName == "skin") {
+            int sourceIndex = currentNode.attribute("source").as_int();
+            pController.mMeshId = currentNode.attribute.begin() + sourceIndex + 1;
+        } else if (currentName == "bind_shape_matrix") {
+            const char *content = currentNode.value();
+            for (unsigned int a = 0; a < 16; a++) {
+                // read a number
+                content = fast_atoreal_move<ai_real>(content, pController.mBindShapeMatrix[a]);
+                // skip whitespace after it
+                SkipSpacesAndLineEnd(&content);
+            }
+        } else if (currentName == "source") {
+            ReadSource(currentNode);
+        } else if (IsElement("joints")) {
+            ReadControllerJoints(currentNode, pController);
+        } else if (IsElement("vertex_weights")) {
+            ReadControllerWeights(currentNode, pController);
+        } else if (IsElement("targets")) {
+            for (XmlNode currendChildNode : currentNode.children()) {
+                const std::string currentChildName = currendChildNode.name();
+                if (currentChildName == "input") {
+                    int semanticsIndex = currendChildNode.attribute("semantic").as_int();
+                    int sourceIndex = currendChildNode.attribute("source").as_int();
+                    const char *semantics = currendChildNode.attributes.begin() + semanticsIndex;
+                    const char *source = currendChildNode.attributes.begin() + sourceIndex;
+                    if (strcmp(semantics, "MORPH_TARGET") == 0) {
+                        pController.mMorphTarget = source + 1;
+                    } else if (strcmp(semantics, "MORPH_WEIGHT") == 0) {
+                        pController.mMorphWeight = source + 1;
+                    }
+                }
+            }
+        }
+    }
+    /*while (mReader->read()) {
         if (mReader->getNodeType() == irr::io::EXN_ELEMENT) {
             // two types of controllers: "skin" and "morph". Only the first one is relevant, we skip the other
             if (IsElement("morph")) {
@@ -1071,59 +1129,141 @@ void ColladaParser::ReadController(XmlNode &node, Collada::Controller &pControll
             else if (strcmp(mReader->getNodeName(), "skin") != 0 && strcmp(mReader->getNodeName(), "morph") != 0)
                 ThrowException("Expected end of <controller> element.");
         }
-    }
+    }*/
 }
 
 // ------------------------------------------------------------------------------------------------
 // Reads the joint definitions for the given controller
 void ColladaParser::ReadControllerJoints(XmlNode &node, Collada::Controller &pController) {
-    while (mReader->read()) {
-        if (mReader->getNodeType() == irr::io::EXN_ELEMENT) {
-            // Input channels for joint data. Two possible semantics: "JOINT" and "INV_BIND_MATRIX"
-            if (IsElement("input")) {
-                int indexSemantic = GetAttribute("semantic");
-                const char *attrSemantic = mReader->getAttributeValue(indexSemantic);
-                int indexSource = GetAttribute("source");
-                const char *attrSource = mReader->getAttributeValue(indexSource);
-
-                // local URLS always start with a '#'. We don't support global URLs
-                if (attrSource[0] != '#')
-                    ThrowException(format() << "Unsupported URL format in \"" << attrSource << "\" in source attribute of <joints> data <input> element");
-                attrSource++;
-
-                // parse source URL to corresponding source
-                if (strcmp(attrSemantic, "JOINT") == 0)
-                    pController.mJointNameSource = attrSource;
-                else if (strcmp(attrSemantic, "INV_BIND_MATRIX") == 0)
-                    pController.mJointOffsetMatrixSource = attrSource;
-                else
-                    ThrowException(format() << "Unknown semantic \"" << attrSemantic << "\" in <joints> data <input> element");
-
-                // skip inner data, if present
-                if (!mReader->isEmptyElement())
-                    SkipElement();
+    for (XmlNode currentNode : node.children()) {
+        const std::string currentName = currentNode.name();
+        if (currentName == "input") {
+            int indexSemantic = currentNode.attribute("semantic").as_int();
+            const char *attrSemantic = currentNode.attributes.begin() + indexSemantic;
+            int indexSource = currentNode.attribute("source").as_int();
+            const char *attrSource = currentNode.attributes.begin() + indexSource;
+            if (attrSource[0] != '#') {
+                ThrowException(format() << "Unsupported URL format in \"" << attrSource << "\" in source attribute of <joints> data <input> element");
+            }
+            attrSource++;
+            // parse source URL to corresponding source
+            if (strcmp(attrSemantic, "JOINT") == 0) {
+                pController.mJointNameSource = attrSource;
+            } else if (strcmp(attrSemantic, "INV_BIND_MATRIX") == 0) {
+                pController.mJointOffsetMatrixSource = attrSource;
             } else {
-                // ignore the rest
-                SkipElement();
+                ThrowException(format() << "Unknown semantic \"" << attrSemantic << "\" in <joints> data <input> element");
             }
-        } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
-            if (strcmp(mReader->getNodeName(), "joints") != 0)
-                ThrowException("Expected end of <joints> element.");
-
-            break;
         }
     }
+    /*while (mReader->read()) {
+            if (mReader->getNodeType() == irr::io::EXN_ELEMENT) {
+                // Input channels for joint data. Two possible semantics: "JOINT" and "INV_BIND_MATRIX"
+                if (IsElement("input")) {
+                    int indexSemantic = GetAttribute("semantic");
+                    const char *attrSemantic = mReader->getAttributeValue(indexSemantic);
+                    int indexSource = GetAttribute("source");
+                    const char *attrSource = mReader->getAttributeValue(indexSource);
+
+                    // local URLS always start with a '#'. We don't support global URLs
+                    if (attrSource[0] != '#')
+                        ThrowException(format() << "Unsupported URL format in \"" << attrSource << "\" in source attribute of <joints> data <input> element");
+                    attrSource++;
+
+                    // parse source URL to corresponding source
+                    if (strcmp(attrSemantic, "JOINT") == 0)
+                        pController.mJointNameSource = attrSource;
+                    else if (strcmp(attrSemantic, "INV_BIND_MATRIX") == 0)
+                        pController.mJointOffsetMatrixSource = attrSource;
+                    else
+                        ThrowException(format() << "Unknown semantic \"" << attrSemantic << "\" in <joints> data <input> element");
+
+                    // skip inner data, if present
+                    if (!mReader->isEmptyElement())
+                        SkipElement();
+                } else {
+                    // ignore the rest
+                    SkipElement();
+                }
+            } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
+                if (strcmp(mReader->getNodeName(), "joints") != 0)
+                    ThrowException("Expected end of <joints> element.");
+
+                break;
+            }
+        }*/
 }
 
 // ------------------------------------------------------------------------------------------------
 // Reads the joint weights for the given controller
 void ColladaParser::ReadControllerWeights(XmlNode &node, Collada::Controller &pController) {
-    // read vertex count from attributes and resize the array accordingly
+    // Read vertex count from attributes and resize the array accordingly
+    int indexCount = node.attribute("count").as_int();
+    size_t vertexCount = node.attributes.begin() + indexCount;
+    pController.mWeightCounts.resize(vertexCount);
+
+    /*// read vertex count from attributes and resize the array accordingly
     int indexCount = GetAttribute("count");
     size_t vertexCount = (size_t)mReader->getAttributeValueAsInt(indexCount);
-    pController.mWeightCounts.resize(vertexCount);
+    pController.mWeightCounts.resize(vertexCount);*/
 
-    while (mReader->read()) {
+    for (XmlNode currentNode : node.children()) {
+        std::string currentName = currentNode.name();
+        if (currentName == "input") {
+            InputChannel channel;
+
+            int indexSemantic = currentNode.attribute("semantic").as_int();
+            const char *attrSemantic = currentNode.attributes.begin() + indexSemantic;
+            int indexSource = currentNode.attribute("source").as_int();
+            const char *attrSource = currentNode.attributes.begin() + indexSource;
+            int indexOffset = currentNode.attribute("offset").as_int();
+            if (indexOffset >= 0)
+                channel.mOffset = currentNode.attributes.begin + indexOffset;
+
+            // local URLS always start with a '#'. We don't support global URLs
+            if (attrSource[0] != '#')
+                ThrowException(format() << "Unsupported URL format in \"" << attrSource << "\" in source attribute of <vertex_weights> data <input> element");
+            channel.mAccessor = attrSource + 1;
+
+            // parse source URL to corresponding source
+            if (strcmp(attrSemantic, "JOINT") == 0) {
+                pController.mWeightInputJoints = channel;
+            } else if (strcmp(attrSemantic, "WEIGHT") == 0) {
+                pController.mWeightInputWeights = channel;
+            } else {
+                ThrowException(format() << "Unknown semantic \"" << attrSemantic << "\" in <vertex_weights> data <input> element");
+            }
+        } else if (currentName == "vcount" && vertexCount > 0) {
+            const char *text = currentNode.value();
+            size_t numWeights = 0;
+            for (std::vector<size_t>::iterator it = pController.mWeightCounts.begin(); it != pController.mWeightCounts.end(); ++it) {
+                if (*text == 0) {
+                    ThrowException("Out of data while reading <vcount>");
+                }
+
+                *it = strtoul10(text, &text);
+                numWeights += *it;
+                SkipSpacesAndLineEnd(&text);
+            }
+            // reserve weight count
+            pController.mWeights.resize(numWeights);
+        } else if (currentName == "v" && vertexCount > 0) {
+            // read JointIndex - WeightIndex pairs
+            const char *text = currentNode.value();
+            for (std::vector<std::pair<size_t, size_t>>::iterator it = pController.mWeights.begin(); it != pController.mWeights.end(); ++it) {
+                if (*text == 0) {
+                    ThrowException("Out of data while reading <vertex_weights>");
+                }
+                it->first = strtoul10(text, &text);
+                SkipSpacesAndLineEnd(&text);
+                if (*text == 0)
+                    ThrowException("Out of data while reading <vertex_weights>");
+                it->second = strtoul10(text, &text);
+                SkipSpacesAndLineEnd(&text);
+            }
+        }
+    }
+    /*while (mReader->read()) {
         if (mReader->getNodeType() == irr::io::EXN_ELEMENT) {
             // Input channels for weight data. Two possible semantics: "JOINT" and "WEIGHT"
             if (IsElement("input") && vertexCount > 0) {
@@ -1196,7 +1336,7 @@ void ColladaParser::ReadControllerWeights(XmlNode &node, Collada::Controller &pC
 
             break;
         }
-    }
+    }*/
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -1208,75 +1348,54 @@ void ColladaParser::ReadImageLibrary(XmlNode &node) {
     /*if (mReader->isEmptyElement())
         return;*/
 
-    while (mReader->read()) {
-        if (mReader->getNodeType() == irr::io::EXN_ELEMENT) {
-            if (IsElement("image")) {
-                // read ID. Another entry which is "optional" by design but obligatory in reality
-                int attrID = GetAttribute("id");
-                std::string id = mReader->getAttributeValue(attrID);
-
-                // create an entry and store it in the library under its ID
-                mImageLibrary[id] = Image();
-
-                // read on from there
-                ReadImage(mImageLibrary[id]);
-            } else {
-                // ignore the rest
-                SkipElement();
-            }
-        } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
-            if (strcmp(mReader->getNodeName(), "library_images") != 0)
-                ThrowException("Expected end of <library_images> element.");
+    for (XmlNode currentNode : node.children()) {
+        const std::string name = currentNode.name();
+        if (name == "image") {
+            int attrID = currentNode.attribute("id").as_int();
+            std::string id = currentNode.attributes.begin() + attrID;
+            mImageLibrary[id] = Image();
 
-            break;
+            // read on from there
+            ReadImage(currentNode, mImageLibrary[id]);
         }
     }
+    /*while (mReader->read()) {
+            if (mReader->getNodeType() == irr::io::EXN_ELEMENT) {
+                if (IsElement("image")) {
+                    // read ID. Another entry which is "optional" by design but obligatory in reality
+                    int attrID = GetAttribute("id");
+                    std::string id = mReader->getAttributeValue(attrID);
+
+                    // create an entry and store it in the library under its ID
+                    mImageLibrary[id] = Image();
+
+                    // read on from there
+                    ReadImage(mImageLibrary[id]);
+                } else {
+                    // ignore the rest
+                    SkipElement();
+                }
+            } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
+                if (strcmp(mReader->getNodeName(), "library_images") != 0)
+                    ThrowException("Expected end of <library_images> element.");
+
+                break;
+            }
+        }*/
 }
 
 // ------------------------------------------------------------------------------------------------
 // Reads an image entry into the given image
 void ColladaParser::ReadImage(XmlNode &node, Collada::Image &pImage) {
-    while (mReader->read()) {
-        if (mReader->getNodeType() == irr::io::EXN_ELEMENT) {
-            // Need to run different code paths here, depending on the Collada XSD version
-            if (IsElement("image")) {
-                SkipElement();
-            } else if (IsElement("init_from")) {
-                if (mFormat == FV_1_4_n) {
-                    // FIX: C4D exporter writes empty <init_from/> tags
-                    if (!mReader->isEmptyElement()) {
-                        // element content is filename - hopefully
-                        const char *sz = TestTextContent();
-                        if (sz) {
-                            aiString filepath(sz);
-                            UriDecodePath(filepath);
-                            pImage.mFileName = filepath.C_Str();
-                        }
-                        TestClosing("init_from");
-                    }
-                    if (!pImage.mFileName.length()) {
-                        pImage.mFileName = "unknown_texture";
-                    }
-                } else if (mFormat == FV_1_5_n) {
-                    // make sure we skip over mip and array initializations, which
-                    // we don't support, but which could confuse the loader if
-                    // they're not skipped.
-                    int attrib = TestAttribute("array_index");
-                    if (attrib != -1 && mReader->getAttributeValueAsInt(attrib) > 0) {
-                        ASSIMP_LOG_WARN("Collada: Ignoring texture array index");
-                        continue;
-                    }
-
-                    attrib = TestAttribute("mip_index");
-                    if (attrib != -1 && mReader->getAttributeValueAsInt(attrib) > 0) {
-                        ASSIMP_LOG_WARN("Collada: Ignoring MIP map layer");
-                        continue;
-                    }
-
-                    // TODO: correctly jump over cube and volume maps?
-                }
-            } else if (mFormat == FV_1_5_n) {
-                if (IsElement("ref")) {
+    for (XmlNode currentNode : node.children()) {
+        const std::string currentName = currentNode.name();
+        if (currentName == "image") {
+            // Ignore
+            continue;
+        } else if (currentName == "init_from") {
+            if (mFormat == FV_1_4_n) {
+                // FIX: C4D exporter writes empty <init_from/> tags
+                if (!currentNode.empty()) {
                     // element content is filename - hopefully
                     const char *sz = TestTextContent();
                     if (sz) {
@@ -1284,39 +1403,150 @@ void ColladaParser::ReadImage(XmlNode &node, Collada::Image &pImage) {
                         UriDecodePath(filepath);
                         pImage.mFileName = filepath.C_Str();
                     }
-                    TestClosing("ref");
-                } else if (IsElement("hex") && !pImage.mFileName.length()) {
-                    // embedded image. get format
-                    const int attrib = TestAttribute("format");
-                    if (-1 == attrib)
-                        ASSIMP_LOG_WARN("Collada: Unknown image file format");
-                    else
-                        pImage.mEmbeddedFormat = mReader->getAttributeValue(attrib);
+                    TestClosing("init_from");
+                }
+                if (!pImage.mFileName.length()) {
+                    pImage.mFileName = "unknown_texture";
+                }
+            } else if (mFormat == FV_1_5_n) {
+                // make sure we skip over mip and array initializations, which
+                // we don't support, but which could confuse the loader if
+                // they're not skipped.
+                int attrib = currentNode.attribute("ref").as_int();
+                int v = currentNode.attributes.begin + attrib;
+                if (attrib != -1 && v > 0) {
+                    ASSIMP_LOG_WARN("Collada: Ignoring texture array index");
+                    continue;
+                }
 
-                    const char *data = GetTextContent();
+                attrib = currentNode.attribute("mip_index").as_int();
+                v = currentNode.attributes.begin + attrib;
+                if (attrib != -1 && v > 0) {
+                    ASSIMP_LOG_WARN("Collada: Ignoring MIP map layer");
+                    continue;
+                }
 
-                    // hexadecimal-encoded binary octets. First of all, find the
-                    // required buffer size to reserve enough storage.
-                    const char *cur = data;
-                    while (!IsSpaceOrNewLine(*cur))
-                        cur++;
+                // TODO: correctly jump over cube and volume maps?
+            }
+        } else if (mFormat == FV_1_5_n) {
+            XmlNode refChild = currentNode.child("ref");
+            XmlNode hexChild = currentNode.child("hex");
+            if (refChild) {
+                // element content is filename - hopefully
+                const char *sz = refChild.value();
+                if (sz) {
+                    aiString filepath(sz);
+                    UriDecodePath(filepath);
+                    pImage.mFileName = filepath.C_Str();
+                }
+            } else if (hexChild && !pImage.mFileName.length()) {
+                // embedded image. get format
+                const int attrib = hexChild.attribute("format").as_int();
+                if (-1 == attrib) {
+                    ASSIMP_LOG_WARN("Collada: Unknown image file format");
+                } else {
+                    pImage.mEmbeddedFormat = hexChild.attributes.begin() + attrib;
+                }
 
-                    const unsigned int size = (unsigned int)(cur - data) * 2;
-                    pImage.mImageData.resize(size);
-                    for (unsigned int i = 0; i < size; ++i)
-                        pImage.mImageData[i] = HexOctetToDecimal(data + (i << 1));
+                const char *data = hexChild.value();
 
-                    TestClosing("hex");
+                // hexadecimal-encoded binary octets. First of all, find the
+                // required buffer size to reserve enough storage.
+                const char *cur = data;
+                while (!IsSpaceOrNewLine(*cur)) {
+                    ++cur;
+                }
+
+                const unsigned int size = (unsigned int)(cur - data) * 2;
+                pImage.mImageData.resize(size);
+                for (unsigned int i = 0; i < size; ++i) {
+                    pImage.mImageData[i] = HexOctetToDecimal(data + (i << 1));
                 }
-            } else {
-                // ignore the rest
-                SkipElement();
             }
-        } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
-            if (strcmp(mReader->getNodeName(), "image") == 0)
-                break;
-        }
+        } 
     }
+        
+        /*while (mReader->read()) {
+            if (mReader->getNodeType() == irr::io::EXN_ELEMENT) {
+                // Need to run different code paths here, depending on the Collada XSD version
+                if (IsElement("image")) {
+                    SkipElement();
+                } else if (IsElement("init_from")) {
+                    if (mFormat == FV_1_4_n) {
+                        // FIX: C4D exporter writes empty <init_from/> tags
+                        if (!mReader->isEmptyElement()) {
+                            // element content is filename - hopefully
+                            const char *sz = TestTextContent();
+                            if (sz) {
+                                aiString filepath(sz);
+                                UriDecodePath(filepath);
+                                pImage.mFileName = filepath.C_Str();
+                            }
+                            TestClosing("init_from");
+                        }
+                        if (!pImage.mFileName.length()) {
+                            pImage.mFileName = "unknown_texture";
+                        }
+                    } else if (mFormat == FV_1_5_n) {
+                        // make sure we skip over mip and array initializations, which
+                        // we don't support, but which could confuse the loader if
+                        // they're not skipped.
+                        int attrib = TestAttribute("array_index");
+                        if (attrib != -1 && mReader->getAttributeValueAsInt(attrib) > 0) {
+                            ASSIMP_LOG_WARN("Collada: Ignoring texture array index");
+                            continue;
+                        }
+
+                        attrib = TestAttribute("mip_index");
+                        if (attrib != -1 && mReader->getAttributeValueAsInt(attrib) > 0) {
+                            ASSIMP_LOG_WARN("Collada: Ignoring MIP map layer");
+                            continue;
+                        }
+
+                        // TODO: correctly jump over cube and volume maps?
+                    }
+                } else if (mFormat == FV_1_5_n) {
+                    if (IsElement("ref")) {
+                        // element content is filename - hopefully
+                        const char *sz = TestTextContent();
+                        if (sz) {
+                            aiString filepath(sz);
+                            UriDecodePath(filepath);
+                            pImage.mFileName = filepath.C_Str();
+                        }
+                        TestClosing("ref");
+                    } else if (IsElement("hex") && !pImage.mFileName.length()) {
+                        // embedded image. get format
+                        const int attrib = TestAttribute("format");
+                        if (-1 == attrib)
+                            ASSIMP_LOG_WARN("Collada: Unknown image file format");
+                        else
+                            pImage.mEmbeddedFormat = mReader->getAttributeValue(attrib);
+
+                        const char *data = GetTextContent();
+
+                        // hexadecimal-encoded binary octets. First of all, find the
+                        // required buffer size to reserve enough storage.
+                        const char *cur = data;
+                        while (!IsSpaceOrNewLine(*cur))
+                            cur++;
+
+                        const unsigned int size = (unsigned int)(cur - data) * 2;
+                        pImage.mImageData.resize(size);
+                        for (unsigned int i = 0; i < size; ++i)
+                            pImage.mImageData[i] = HexOctetToDecimal(data + (i << 1));
+
+                        TestClosing("hex");
+                    }
+                } else {
+                    // ignore the rest
+                    SkipElement();
+                }
+            } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
+                if (strcmp(mReader->getNodeName(), "image") == 0)
+                    break;
+            }
+        }*/
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -1329,7 +1559,36 @@ void ColladaParser::ReadMaterialLibrary(XmlNode &node) {
         return;*/
 
     std::map<std::string, int> names;
-    while (mReader->read()) {
+
+    for (XmlNode currentNode : node.children()) {
+        const std::string currentName = currentNode.name();
+        int attrID = currentNode.attribute("id").as_int();
+        std::string id = currentNode.attributes.begin() + attrID;
+        std::string name;
+        int attrName = currentNode.attribute("name").as_int();
+        if (attrName >= 0) {
+            name = currentNode.attributes.begin() + attrName;
+        }
+        mMaterialLibrary[id] = Material();
+
+        if (!name.empty()) {
+            std::map<std::string, int>::iterator it = names.find(name);
+            if (it != names.end()) {
+                std::ostringstream strStream;
+                strStream << ++it->second;
+                name.append(" " + strStream.str());
+            } else {
+                names[name] = 0;
+            }
+
+            mMaterialLibrary[id].mName = name;
+        }
+
+        ReadMaterial(currentNode, mMaterialLibrary[id]);
+        
+    }
+
+    /*while (mReader->read()) {
         if (mReader->getNodeType() == irr::io::EXN_ELEMENT) {
             if (IsElement("material")) {
                 // read ID. By now you probably know my opinion about this "specification"
@@ -1368,7 +1627,7 @@ void ColladaParser::ReadMaterialLibrary(XmlNode &node) {
 
             break;
         }
-    }
+    }*/
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -2778,7 +3037,7 @@ void ColladaParser::ReadSceneNode(XmlNode &node, Node *pNode) {
         return;
     }
 
-/*    if (mReader->isEmptyElement())
+    /*    if (mReader->isEmptyElement())
         return;*/
 
     while (mReader->read()) {
@@ -2796,7 +3055,6 @@ void ColladaParser::ReadSceneNode(XmlNode &node, Node *pNode) {
                 if (attrName > -1)
                     child->mName = mReader->getAttributeValue(attrName);
 
-
                 if (pNode) {
                     pNode->mChildren.push_back(child);
                     child->mParent = pNode;
@@ -3034,7 +3292,30 @@ void ColladaParser::ReadScene(XmlNode &node) {
     /*if (mReader->isEmptyElement())
         return;*/
 
-    while (mReader->read()) {
+    for (XmlNode currentNode : node.children()) {
+        const std::string currentName = currentNode.name();
+        if (currentName == "instance_visual_scene") {
+            // should be the first and only occurrence
+            if (mRootNode)
+                ThrowException("Invalid scene containing multiple root nodes in <instance_visual_scene> element");
+
+            // read the url of the scene to instance. Should be of format "#some_name"
+            int urlIndex = currentNode.attribute("url").as_int();
+            const char *url = currentNode.attributes.begin() + urlIndex;
+            if (url[0] != '#') {
+                ThrowException("Unknown reference format in <instance_visual_scene> element");
+            }
+
+            // find the referred scene, skip the leading #
+            NodeLibrary::const_iterator sit = mNodeLibrary.find(url + 1);
+            if (sit == mNodeLibrary.end()) {
+                ThrowException("Unable to resolve visual_scene reference \"" + std::string(url) + "\" in <instance_visual_scene> element.");
+            }
+            mRootNode = sit->second;
+        }
+    }
+
+    /*while (mReader->read()) {
         if (mReader->getNodeType() == irr::io::EXN_ELEMENT) {
             if (IsElement("instance_visual_scene")) {
                 // should be the first and only occurrence
@@ -3058,7 +3339,7 @@ void ColladaParser::ReadScene(XmlNode &node) {
         } else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
             break;
         }
-    }
+    }*/
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -3159,7 +3440,7 @@ void ColladaParser::ReportWarning(const char *msg, ...) {
 
 // ------------------------------------------------------------------------------------------------
 // Returns the index of the named attribute or -1 if not found. Does not throw, therefore useful for optional attributes
-int ColladaParser::GetAttribute(const char *pAttr) const {
+/*int ColladaParser::GetAttribute(const char *pAttr) const {
     int index = TestAttribute(pAttr);
     if (index == -1) {
         ThrowException(format() << "Expected attribute \"" << pAttr << "\" for element <" << mReader->getNodeName() << ">.");
@@ -3167,31 +3448,31 @@ int ColladaParser::GetAttribute(const char *pAttr) const {
 
     // attribute not found -> throw an exception
     return index;
-}
+}*/
 
 // ------------------------------------------------------------------------------------------------
 // Tests the present element for the presence of one attribute, returns its index or throws an exception if not found
-int ColladaParser::TestAttribute(const char *pAttr) const {
+/*int ColladaParser::TestAttribute(const char *pAttr) const {
     for (int a = 0; a < mReader->getAttributeCount(); a++)
         if (strcmp(mReader->getAttributeName(a), pAttr) == 0)
             return a;
 
     return -1;
-}
+}*/
 
 // ------------------------------------------------------------------------------------------------
 // Reads the text contents of an element, throws an exception if not given. Skips leading whitespace.
-const char *ColladaParser::GetTextContent() {
+/*const char *ColladaParser::GetTextContent() {
     const char *sz = TestTextContent();
     if (!sz) {
         ThrowException("Invalid contents in element \"n\".");
     }
     return sz;
-}
+}*/
 
 // ------------------------------------------------------------------------------------------------
 // Reads the text contents of an element, returns nullptr if not given. Skips leading whitespace.
-const char *ColladaParser::TestTextContent() {
+/*const char *ColladaParser::TestTextContent() {
     // present node should be the beginning of an element
     if (mReader->getNodeType() != irr::io::EXN_ELEMENT || mReader->isEmptyElement())
         return nullptr;
@@ -3209,7 +3490,7 @@ const char *ColladaParser::TestTextContent() {
     SkipSpacesAndLineEnd(&text);
 
     return text;
-}
+}*/
 
 // ------------------------------------------------------------------------------------------------
 // Calculates the resulting transformation from all the given transform steps

+ 331 - 107
code/AssetLib/Ogre/OgreXmlSerializer.cpp

@@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
 
 Copyright (c) 2006-2020, assimp team
 
-
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -43,7 +42,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "OgreXmlSerializer.h"
 #include "OgreBinarySerializer.h"
 #include "OgreParsingUtils.h"
-
 #include <assimp/TinyFormatter.h>
 #include <assimp/DefaultLogger.hpp>
 #include <memory>
@@ -56,85 +54,86 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 namespace Assimp {
 namespace Ogre {
 
-AI_WONT_RETURN void ThrowAttibuteError(const XmlReader *reader, const std::string &name, const std::string &error = "") AI_WONT_RETURN_SUFFIX;
-AI_WONT_RETURN void ThrowAttibuteError(const XmlReader *reader, const std::string &name, const std::string &error) {
+AI_WONT_RETURN void ThrowAttibuteError(const XmlParser *reader, const std::string &name, const std::string &error = "") AI_WONT_RETURN_SUFFIX;
+
+AI_WONT_RETURN void ThrowAttibuteError(const std::string &nodeName, const std::string &name, const std::string &error) {
     if (!error.empty()) {
-        throw DeadlyImportError(error + " in node '" + std::string(reader->getNodeName()) + "' and attribute '" + name + "'");
+        throw DeadlyImportError(error + " in node '" + nodeName + "' and attribute '" + name + "'");
     } else {
-        throw DeadlyImportError("Attribute '" + name + "' does not exist in node '" + std::string(reader->getNodeName()) + "'");
+        throw DeadlyImportError("Attribute '" + name + "' does not exist in node '" + nodeName + "'");
     }
 }
+static inline bool hasAttribute( XmlNode &xmlNode, const char *name ) {
+    pugi::xml_attribute attr = xmlNode.attribute(name);
+    return !attr.empty();
+}
 
 template <>
-int32_t OgreXmlSerializer::ReadAttribute<int32_t>(const char *name) const {
-    if (!HasAttribute(name)) {
-        ThrowAttibuteError(m_reader, name);
+int32_t OgreXmlSerializer::ReadAttribute<int32_t>(XmlNode &xmlNode, const char *name) const {
+    if (!hasAttribute(xmlNode, name )) {
+        ThrowAttibuteError(mParser, name);
     }
-
-    return static_cast<int32_t>(m_reader->getAttributeValueAsInt(name));
+    pugi::xml_attribute attr = xmlNode.attribute(name);
+    return static_cast<int32_t>(attr.as_int());
 }
 
 template <>
-uint32_t OgreXmlSerializer::ReadAttribute<uint32_t>(const char *name) const {
-    if (!HasAttribute(name)) {
-        ThrowAttibuteError(m_reader, name);
+uint32_t OgreXmlSerializer::ReadAttribute<uint32_t>(XmlNode &xmlNode, const char *name) const {
+    if (!hasAttribute(xmlNode, name)) {
+        ThrowAttibuteError(mParser, name);
     }
+
     // @note This is hackish. But we are never expecting unsigned values that go outside the
     //       int32_t range. Just monitor for negative numbers and kill the import.
-    int32_t temp = ReadAttribute<int32_t>(name);
+    int32_t temp = ReadAttribute<int32_t>(xmlNode, name);
     if (temp < 0) {
-        ThrowAttibuteError(m_reader, name, "Found a negative number value where expecting a uint32_t value");
+        ThrowAttibuteError(mParser, name, "Found a negative number value where expecting a uint32_t value");
     }
 
     return static_cast<uint32_t>(temp);
 }
 
 template <>
-uint16_t OgreXmlSerializer::ReadAttribute<uint16_t>(const char *name) const {
-    if (!HasAttribute(name)) {
-        ThrowAttibuteError(m_reader, name);
+uint16_t OgreXmlSerializer::ReadAttribute<uint16_t>(XmlNode &xmlNode, const char *name) const {
+    if (!hasAttribute(xmlNode, name)) {
+        ThrowAttibuteError(mParser, name);
     }
 
-    return static_cast<uint16_t>(ReadAttribute<uint32_t>(name));
+    return static_cast<uint16_t>(xmlNode.attribute(name).as_int());
 }
 
 template <>
-float OgreXmlSerializer::ReadAttribute<float>(const char *name) const {
-    if (!HasAttribute(name)) {
-        ThrowAttibuteError(m_reader, name);
+float OgreXmlSerializer::ReadAttribute<float>(XmlNode &xmlNode, const char *name) const {
+    if (!hasAttribute(xmlNode, name)) {
+        ThrowAttibuteError(mParser, name);
     }
-
-    return m_reader->getAttributeValueAsFloat(name);
+    
+    return xmlNode.attribute(name).as_float();
 }
 
 template <>
-std::string OgreXmlSerializer::ReadAttribute<std::string>(const char *name) const {
-    const char *value = m_reader->getAttributeValue(name);
-    if (nullptr == value) {
-        ThrowAttibuteError(m_reader, name);
+std::string OgreXmlSerializer::ReadAttribute<std::string>(XmlNode &xmlNode, const char *name) const {
+    if (!hasAttribute(xmlNode, name)) {
+        ThrowAttibuteError(mParser, name);
     }
 
-    return std::string(value);
+    return xmlNode.attribute(name).as_string();
 }
 
 template <>
-bool OgreXmlSerializer::ReadAttribute<bool>(const char *name) const {
-    std::string value = Ogre::ToLower(ReadAttribute<std::string>(name));
+bool OgreXmlSerializer::ReadAttribute<bool>(XmlNode &xmlNode, const char *name) const {
+    std::string value = Ogre::ToLower(ReadAttribute<std::string>(xmlNode, name));
     if (ASSIMP_stricmp(value, "true") == 0) {
         return true;
     } else if (ASSIMP_stricmp(value, "false") == 0) {
         return false;
-    } else {
-        ThrowAttibuteError(m_reader, name, "Boolean value is expected to be 'true' or 'false', encountered '" + value + "'");
-        return false;
-    }
-}
+    } 
 
-bool OgreXmlSerializer::HasAttribute(const char *name) const {
-    return (m_reader->getAttributeValue(name) != 0);
+    ThrowAttibuteError(mParser, name, "Boolean value is expected to be 'true' or 'false', encountered '" + value + "'");
+    return false;
 }
 
-std::string &OgreXmlSerializer::NextNode() {
+/*std::string &OgreXmlSerializer::NextNode() {
     do {
         if (!m_reader->read()) {
             m_currentNodeName = "";
@@ -178,7 +177,7 @@ std::string &OgreXmlSerializer::SkipCurrentNode() {
 
     return NextNode();
 }
-
+*/
 // Mesh XML constants
 
 // <mesh>
@@ -247,15 +246,14 @@ static const char *nnTranslate = "translate";
 static const char *nnRotate = "rotate";
 
 // Common XML constants
-
 static const char *anX = "x";
 static const char *anY = "y";
 static const char *anZ = "z";
 
 // Mesh
 
-MeshXml *OgreXmlSerializer::ImportMesh(XmlReader *reader) {
-    OgreXmlSerializer serializer(reader);
+MeshXml *OgreXmlSerializer::ImportMesh(XmlParser *xmlParser) {
+    OgreXmlSerializer serializer(xmlParser);
 
     MeshXml *mesh = new MeshXml();
     serializer.ReadMesh(mesh);
@@ -264,16 +262,32 @@ MeshXml *OgreXmlSerializer::ImportMesh(XmlReader *reader) {
 }
 
 void OgreXmlSerializer::ReadMesh(MeshXml *mesh) {
-    if (NextNode() != nnMesh) {
+    const XmlNode *root = mParser->getRootNode();
+    if (nullptr == root || std::string(nnMesh)!=root->name()) {
         throw DeadlyImportError("Root node is <" + m_currentNodeName + "> expecting <mesh>");
     }
 
+    for (XmlNode currentNode : root->children()) {
+        const std::string currentName = currentNode.name();
+        if (currentName == nnSharedGeometry) {
+            mesh->sharedVertexData = new VertexDataXml();
+            ReadGeometry(currentNode, mesh->sharedVertexData);
+        } else if (currentName == nnSubMesh) {
+            ReadSubMesh(currentNode, mesh);
+        } else if (currentName == nnBoneAssignments) {
+            ReadBoneAssignments(currentNode, mesh->sharedVertexData);
+        } else if (currentName == nnSkeletonLink) {
+        }
+    }
+    /*if (NextNode() != nnMesh) {
+    }*/
+
     ASSIMP_LOG_VERBOSE_DEBUG("Reading Mesh");
 
-    NextNode();
+    //NextNode();
 
     // Root level nodes
-    while (m_currentNodeName == nnSharedGeometry ||
+    /*while (m_currentNodeName == nnSharedGeometry ||
             m_currentNodeName == nnSubMeshes ||
             m_currentNodeName == nnSkeletonLink ||
             m_currentNodeName == nnBoneAssignments ||
@@ -298,26 +312,33 @@ void OgreXmlSerializer::ReadMesh(MeshXml *mesh) {
             NextNode();
         }
         // Assimp incompatible/ignored nodes
-        else
+        else {
             SkipCurrentNode();
-    }
+        }
+    }*/
 }
 
-void OgreXmlSerializer::ReadGeometry(VertexDataXml *dest) {
-    dest->count = ReadAttribute<uint32_t>("vertexcount");
+void OgreXmlSerializer::ReadGeometry(XmlNode &node, VertexDataXml *dest) {
+    dest->count = ReadAttribute<uint32_t>(node, "vertexcount");
     ASSIMP_LOG_VERBOSE_DEBUG_F("  - Reading geometry of ", dest->count, " vertices");
 
-    NextNode();
-    while (m_currentNodeName == nnVertexBuffer) {
-        ReadGeometryVertexBuffer(dest);
+    for (XmlNode currentNode : node.children()) {
+        const std::string &currentName = currentNode.name();
+        if (currentName == nnVertexBuffer) {
+            ReadGeometryVertexBuffer(currentNode, dest);
+        }
     }
+    //NextNode();
+    /*while (m_currentNodeName == nnVertexBuffer) {
+        ReadGeometryVertexBuffer(dest);
+    }*/
 }
 
-void OgreXmlSerializer::ReadGeometryVertexBuffer(VertexDataXml *dest) {
-    bool positions = (HasAttribute("positions") && ReadAttribute<bool>("positions"));
-    bool normals = (HasAttribute("normals") && ReadAttribute<bool>("normals"));
-    bool tangents = (HasAttribute("tangents") && ReadAttribute<bool>("tangents"));
-    uint32_t uvs = (HasAttribute("texture_coords") ? ReadAttribute<uint32_t>("texture_coords") : 0);
+void OgreXmlSerializer::ReadGeometryVertexBuffer(XmlNode &node, VertexDataXml *dest) {
+    bool positions = (hasAttribute(node, "positions") && ReadAttribute<bool>(node, "positions"));
+    bool normals = (hasAttribute(node, "normals") && ReadAttribute<bool>(node, "normals"));
+    bool tangents = (hasAttribute(node, "tangents") && ReadAttribute<bool>(node, "tangents"));
+    uint32_t uvs = (hasAttribute(node, "texture_coords") ? ReadAttribute<uint32_t>(node, "texture_coords") : 0);
 
     // Not having positions is a error only if a previous vertex buffer did not have them.
     if (!positions && !dest->HasPositions()) {
@@ -348,9 +369,38 @@ void OgreXmlSerializer::ReadGeometryVertexBuffer(VertexDataXml *dest) {
     bool warnColorDiffuse = true;
     bool warnColorSpecular = true;
 
-    NextNode();
+    //NextNode();
+    for (XmlNode currentNode : node.children()) {
+        const std::string &currentName = currentNode.name();
+        if (positions && currentName == nnPosition) {
+            aiVector3D pos;
+            pos.x = ReadAttribute<float>(currentNode, anX);
+            pos.y = ReadAttribute<float>(currentNode, anY);
+            pos.z = ReadAttribute<float>(currentNode, anZ);
+            dest->positions.push_back(pos);
+        } else if (normals && currentName == nnNormal) {
+            aiVector3D normal;
+            normal.x = ReadAttribute<float>(currentNode, anX);
+            normal.y = ReadAttribute<float>(currentNode, anY);
+            normal.z = ReadAttribute<float>(currentNode, anZ);
+            dest->normals.push_back(normal);
+        } else if (tangents && currentName == nnTangent) {
+            aiVector3D tangent;
+            tangent.x = ReadAttribute<float>(currentNode, anX);
+            tangent.y = ReadAttribute<float>(currentNode, anY);
+            tangent.z = ReadAttribute<float>(currentNode, anZ);
+            dest->tangents.push_back(tangent);
+        } else if (uvs > 0 && currentName == nnTexCoord) {
+            for (auto &curUvs : dest->uvs) {
+                aiVector3D uv;
+                uv.x = ReadAttribute<float>(currentNode, "u");
+                uv.y = (ReadAttribute<float>(currentNode, "v") * -1) + 1; // Flip UV from Ogre to Assimp form
+                curUvs.push_back(uv);
+            }
+        }
+    }
 
-    while (m_currentNodeName == nnVertex ||
+    /*while (m_currentNodeName == nnVertex ||
             m_currentNodeName == nnPosition ||
             m_currentNodeName == nnNormal ||
             m_currentNodeName == nnTangent ||
@@ -422,11 +472,11 @@ void OgreXmlSerializer::ReadGeometryVertexBuffer(VertexDataXml *dest) {
             if (warn) {
                 ASSIMP_LOG_WARN_F("Vertex buffer attribute read not implemented for element: ", m_currentNodeName);
             }
-        }
+        }*/
 
         // Advance
-        NextNode();
-    }
+        //NextNode();
+    //}
 
     // Sanity checks
     if (dest->positions.size() != dest->count) {
@@ -446,7 +496,7 @@ void OgreXmlSerializer::ReadGeometryVertexBuffer(VertexDataXml *dest) {
     }
 }
 
-void OgreXmlSerializer::ReadSubMesh(MeshXml *mesh) {
+void OgreXmlSerializer::ReadSubMesh(XmlNode &node, MeshXml *mesh) {
     static const char *anMaterial = "material";
     static const char *anUseSharedVertices = "usesharedvertices";
     static const char *anCount = "count";
@@ -457,10 +507,10 @@ void OgreXmlSerializer::ReadSubMesh(MeshXml *mesh) {
 
     SubMeshXml *submesh = new SubMeshXml();
 
-    if (HasAttribute(anMaterial)) {
-        submesh->materialRef = ReadAttribute<std::string>(anMaterial);
+    if (hasAttribute(node, anMaterial)) {
+        submesh->materialRef = ReadAttribute<std::string>(node, anMaterial);
     }
-    if (HasAttribute(anUseSharedVertices)) {
+    if (hasAttribute(node, anUseSharedVertices)) {
         submesh->usesSharedVertexData = ReadAttribute<bool>(anUseSharedVertices);
     }
 
@@ -474,7 +524,46 @@ void OgreXmlSerializer::ReadSubMesh(MeshXml *mesh) {
 
     bool quadWarned = false;
 
-    NextNode();
+    for (XmlNode &currentNode : node.children()) {
+        const std::string &currentName = currentNode.name();
+        if (currentName == nnFaces) {
+            submesh->indexData->faceCount = ReadAttribute<uint32_t>(currentNode, anCount);
+            submesh->indexData->faces.reserve(submesh->indexData->faceCount);
+            for (XmlNode currentChildNode : currentNode.children()) {
+                const std::string &currentChildName = currentNode.name();
+                if (currentChildName == nnFace) {
+                    aiFace face;
+                    face.mNumIndices = 3;
+                    face.mIndices = new unsigned int[3];
+                    face.mIndices[0] = ReadAttribute<uint32_t>(currentChildNode, anV1);
+                    face.mIndices[1] = ReadAttribute<uint32_t>(currentChildNode, anV2);
+                    face.mIndices[2] = ReadAttribute<uint32_t>(currentChildNode, anV3);
+                    /// @todo Support quads if Ogre even supports them in XML (I'm not sure but I doubt it)
+                    if (!quadWarned && hasAttribute(currentChildNode, anV4)) {
+                        ASSIMP_LOG_WARN("Submesh <face> has quads with <v4>, only triangles are supported at the moment!");
+                        quadWarned = true;
+                    }
+                }
+            }
+            if (submesh->indexData->faces.size() == submesh->indexData->faceCount) {
+                ASSIMP_LOG_VERBOSE_DEBUG_F("  - Faces ", submesh->indexData->faceCount);
+            } else {
+                throw DeadlyImportError(Formatter::format() << "Read only " << submesh->indexData->faces.size() << " faces when should have read " << submesh->indexData->faceCount);
+            }
+
+        } else if (currentName == nnGeometry) {
+            if (submesh->usesSharedVertexData) {
+                throw DeadlyImportError("Found <geometry> in <submesh> when use shared geometry is true. Invalid mesh file.");
+            }
+
+            submesh->vertexData = new VertexDataXml();
+            ReadGeometry(currentNode, submesh->vertexData);
+        } else if (m_currentNodeName == nnBoneAssignments) {
+            ReadBoneAssignments(currentNode, submesh->vertexData);
+        }
+    }
+
+    /*NextNode();
     while (m_currentNodeName == nnFaces ||
             m_currentNodeName == nnGeometry ||
             m_currentNodeName == nnTextures ||
@@ -523,13 +612,13 @@ void OgreXmlSerializer::ReadSubMesh(MeshXml *mesh) {
         else {
             SkipCurrentNode();
         }
-    }
+    }*/
 
     submesh->index = static_cast<unsigned int>(mesh->subMeshes.size());
     mesh->subMeshes.push_back(submesh);
 }
 
-void OgreXmlSerializer::ReadBoneAssignments(VertexDataXml *dest) {
+void OgreXmlSerializer::ReadBoneAssignments(XmlNode &node, VertexDataXml *dest) {
     if (!dest) {
         throw DeadlyImportError("Cannot read bone assignments, vertex data is null.");
     }
@@ -539,8 +628,20 @@ void OgreXmlSerializer::ReadBoneAssignments(VertexDataXml *dest) {
     static const char *anWeight = "weight";
 
     std::set<uint32_t> influencedVertices;
+    for (XmlNode &currentNode : node.children()) {
+        const std::string &currentName = currentNode.name();
+        if (currentName == nnVertexBoneAssignment) {
+            VertexBoneAssignment ba;
+            ba.vertexIndex = ReadAttribute<uint32_t>(currentNode, anVertexIndex);
+            ba.boneIndex = ReadAttribute<uint16_t>(currentNode, anBoneIndex);
+            ba.weight = ReadAttribute<float>(currentNode, anWeight);
+
+            dest->boneAssignments.push_back(ba);
+            influencedVertices.insert(ba.vertexIndex);
+        }
+    }
 
-    NextNode();
+    /*NextNode();
     while (m_currentNodeName == nnVertexBoneAssignment) {
         VertexBoneAssignment ba;
         ba.vertexIndex = ReadAttribute<uint32_t>(anVertexIndex);
@@ -551,7 +652,7 @@ void OgreXmlSerializer::ReadBoneAssignments(VertexDataXml *dest) {
         influencedVertices.insert(ba.vertexIndex);
 
         NextNode();
-    }
+    }*/
 
     /** Normalize bone weights.
         Some exporters won't care if the sum of all bone weights
@@ -593,41 +694,43 @@ bool OgreXmlSerializer::ImportSkeleton(Assimp::IOSystem *pIOHandler, MeshXml *me
         mesh->skeletonRef = mesh->skeletonRef + ".xml";
     }
 
-    XmlReaderPtr reader = OpenReader(pIOHandler, mesh->skeletonRef);
-    if (!reader.get())
+    XmlParserPtr xmlParser = OpenXmlParser(pIOHandler, mesh->skeletonRef);
+    if (!xmlParser.get())
         return false;
 
     Skeleton *skeleton = new Skeleton();
-    OgreXmlSerializer serializer(reader.get());
+    OgreXmlSerializer serializer(xmlParser.get());
     serializer.ReadSkeleton(skeleton);
     mesh->skeleton = skeleton;
     return true;
 }
 
 bool OgreXmlSerializer::ImportSkeleton(Assimp::IOSystem *pIOHandler, Mesh *mesh) {
-    if (!mesh || mesh->skeletonRef.empty())
+    if (!mesh || mesh->skeletonRef.empty()) {
         return false;
+    }
 
-    XmlReaderPtr reader = OpenReader(pIOHandler, mesh->skeletonRef);
-    if (!reader.get())
+    XmlParserPtr xmlParser = OpenXmlParser(pIOHandler, mesh->skeletonRef);
+    if (!xmlParser.get()) {
         return false;
+    }
 
     Skeleton *skeleton = new Skeleton();
-    OgreXmlSerializer serializer(reader.get());
+    OgreXmlSerializer serializer(xmlParser.get());
     serializer.ReadSkeleton(skeleton);
     mesh->skeleton = skeleton;
     return true;
 }
 
-XmlReaderPtr OgreXmlSerializer::OpenReader(Assimp::IOSystem *pIOHandler, const std::string &filename) {
+XmlParserPtr OgreXmlSerializer::OpenXmlParser(Assimp::IOSystem *pIOHandler, const std::string &filename) {
     if (!EndsWith(filename, ".skeleton.xml", false)) {
         ASSIMP_LOG_ERROR_F("Imported Mesh is referencing to unsupported '", filename, "' skeleton file.");
-        return XmlReaderPtr();
+        return XmlParserPtr();
     }
 
     if (!pIOHandler->Exists(filename)) {
         ASSIMP_LOG_ERROR_F("Failed to find skeleton file '", filename, "' that is referenced by imported Mesh.");
-        return XmlReaderPtr();
+        return XmlParserPtr();
     }
 
     std::unique_ptr<IOStream> file(pIOHandler->Open(filename));
@@ -635,27 +738,36 @@ XmlReaderPtr OgreXmlSerializer::OpenReader(Assimp::IOSystem *pIOHandler, const s
         throw DeadlyImportError("Failed to open skeleton file " + filename);
     }
 
-    std::unique_ptr<CIrrXML_IOStreamReader> stream(new CIrrXML_IOStreamReader(file.get()));
-    XmlReaderPtr reader = XmlReaderPtr(irr::io::createIrrXMLReader(stream.get()));
-    if (!reader.get()) {
+    XmlParserPtr xmlParser = XmlParserPtr(new XmlParser);
+    if (!xmlParser->parse(file.get())) {
         throw DeadlyImportError("Failed to create XML reader for skeleton file " + filename);
     }
-    return reader;
+    return xmlParser;
 }
 
-void OgreXmlSerializer::ReadSkeleton(Skeleton *skeleton) {
-    if (NextNode() != nnSkeleton) {
-        throw DeadlyImportError("Root node is <" + m_currentNodeName + "> expecting <skeleton>");
+void OgreXmlSerializer::ReadSkeleton(XmlNode &node, Skeleton *skeleton) {
+    if (node.name() != nnSkeleton) {
+        throw DeadlyImportError("Root node is <" + node.name() + "> expecting <skeleton>");
     }
 
     ASSIMP_LOG_VERBOSE_DEBUG("Reading Skeleton");
 
     // Optional blend mode from root node
-    if (HasAttribute("blendmode")) {
-        skeleton->blendMode = (ToLower(ReadAttribute<std::string>("blendmode")) == "cumulative" ? Skeleton::ANIMBLEND_CUMULATIVE : Skeleton::ANIMBLEND_AVERAGE);
+    if (hasAttribute(node, "blendmode")) {
+        skeleton->blendMode = (ToLower(ReadAttribute<std::string>(node, "blendmode")) == "cumulative" ? Skeleton::ANIMBLEND_CUMULATIVE : Skeleton::ANIMBLEND_AVERAGE);
     }
 
-    NextNode();
+    for (XmlNode &currentNode : node.children()) {
+        const std::string currentName = currentNode.name();
+        if (currentName == nnBones) {
+            ReadBones(currentNode, skeleton);
+        } else if (currentName == nnBoneHierarchy) {
+            ReadBoneHierarchy(currentNode, skeleton);
+        } else if (currentName == nnAnimations) {
+            ReadAnimations(currentNode, skeleton);
+        }
+    }
+    /*NextNode();
 
     // Root level nodes
     while (m_currentNodeName == nnBones ||
@@ -670,17 +782,35 @@ void OgreXmlSerializer::ReadSkeleton(Skeleton *skeleton) {
             ReadAnimations(skeleton);
         else
             SkipCurrentNode();
-    }
+    }*/
 }
 
-void OgreXmlSerializer::ReadAnimations(Skeleton *skeleton) {
+void OgreXmlSerializer::ReadAnimations(XmlNode &node, Skeleton *skeleton) {
     if (skeleton->bones.empty()) {
         throw DeadlyImportError("Cannot read <animations> for a Skeleton without bones");
     }
 
     ASSIMP_LOG_VERBOSE_DEBUG("  - Animations");
 
-    NextNode();
+    for (XmlNode &currentNode : node.children()) {
+        const std::string currentName = currentNode.name();
+        if (currentName == nnAnimation) {
+            Animation *anim = new Animation(skeleton);
+            anim->name = ReadAttribute<std::string>(currentNode, "name");
+            anim->length = ReadAttribute<float>(currentNode , "length");
+            for (XmlNode &currentChildNode : currentNode.children()) {
+                const std::string currentChildName = currentNode.name();
+                if (currentChildName == nnTracks) {
+                    ReadAnimationTracks(currentChildNode, anim);
+                    skeleton->animations.push_back(anim);
+                } else {
+                    throw DeadlyImportError(Formatter::format() << "No <tracks> found in <animation> " << anim->name);
+                }
+            }
+        }
+    }
+
+/*    NextNode();
     while (m_currentNodeName == nnAnimation) {
         Animation *anim = new Animation(skeleton);
         anim->name = ReadAttribute<std::string>("name");
@@ -694,11 +824,29 @@ void OgreXmlSerializer::ReadAnimations(Skeleton *skeleton) {
         skeleton->animations.push_back(anim);
 
         ASSIMP_LOG_VERBOSE_DEBUG_F("    ", anim->name, " (", anim->length, " sec, ", anim->tracks.size(), " tracks)");
-    }
+    }*/
 }
 
-void OgreXmlSerializer::ReadAnimationTracks(Animation *dest) {
-    NextNode();
+void OgreXmlSerializer::ReadAnimationTracks(XmlNode &node, Animation *dest) {
+    for (XmlNode &currentNode : node.children()) {
+        const std::string currentName = currentNode.name();
+        if (currentName == nnTrack) {
+            VertexAnimationTrack track;
+            track.type = VertexAnimationTrack::VAT_TRANSFORM;
+            track.boneName = ReadAttribute<std::string>(currentNode, "bone");
+            for (XmlNode &currentChildNode : currentNode.children()) {
+                const std::string currentChildName = currentNode.name();
+                if (currentChildName == nnKeyFrames) {
+                    ReadAnimationKeyFrames(currentChildNode, dest, &track);
+                    dest->tracks.push_back(track);
+                } else {
+                    throw DeadlyImportError(Formatter::format() << "No <keyframes> found in <track> " << dest->name);
+                }
+            }
+
+        }
+    }
+    /*NextNode();
     while (m_currentNodeName == nnTrack) {
         VertexAnimationTrack track;
         track.type = VertexAnimationTrack::VAT_TRANSFORM;
@@ -711,13 +859,52 @@ void OgreXmlSerializer::ReadAnimationTracks(Animation *dest) {
         ReadAnimationKeyFrames(dest, &track);
 
         dest->tracks.push_back(track);
-    }
+    }*/
 }
 
-void OgreXmlSerializer::ReadAnimationKeyFrames(Animation *anim, VertexAnimationTrack *dest) {
+void OgreXmlSerializer::ReadAnimationKeyFrames(XmlNode &node, Animation *anim, VertexAnimationTrack *dest) {
     const aiVector3D zeroVec(0.f, 0.f, 0.f);
+    for (XmlNode &currentNode : node.children()) {
+        const std::string currentName = currentNode.name();
+        if (currentName == nnKeyFrame) {
+            TransformKeyFrame keyframe;
+            keyframe.timePos = ReadAttribute<float>(currentNode, "time");
+            for (XmlNode &currentChildNode : currentNode.children()) {
+                const std::string currentChildName = currentNode.name();
+                if (currentChildName == nnTranslate) {
+                    keyframe.position.x = ReadAttribute<float>(currentChildNode, anX);
+                    keyframe.position.y = ReadAttribute<float>(currentChildNode, anY);
+                    keyframe.position.z = ReadAttribute<float>(currentChildNode, anZ);
+                } else if (currentChildName == nnRotate) {
+                    float angle = ReadAttribute<float>(currentChildNode, "angle");
+                    for (XmlNode &currentChildChildNode : currentNode.children()) {
+                        const std::string currentChildChildName = currentNode.name();
+                        if (currentChildChildName == nnAxis) {
+                            aiVector3D axis;
+                            axis.x = ReadAttribute<float>(currentChildChildNode, anX);
+                            axis.y = ReadAttribute<float>(currentChildChildNode, anY);
+                            axis.z = ReadAttribute<float>(currentChildChildNode, anZ);
+                            if (axis.Equal(zeroVec)) {
+                                axis.x = 1.0f;
+                                if (angle != 0) {
+                                    ASSIMP_LOG_WARN_F("Found invalid a key frame with a zero rotation axis in animation: ", anim->name);
+                                }
+                            }
+                            keyframe.rotation = aiQuaternion(axis, angle);
+                        }
+                    }
+                } else if (currentChildName == nnScale) {
+                    keyframe.scale.x = ReadAttribute<float>(currentChildNode, anX);
+                    keyframe.scale.y = ReadAttribute<float>(currentChildNode, anY);
+                    keyframe.scale.z = ReadAttribute<float>(currentChildNode, anZ);
 
-    NextNode();
+                } 
+
+            }
+        }
+        dest->transformKeyFrames.push_back(keyframe);
+    }
+    /*NextNode();
     while (m_currentNodeName == nnKeyFrame) {
         TransformKeyFrame keyframe;
         keyframe.timePos = ReadAttribute<float>("time");
@@ -756,15 +943,33 @@ void OgreXmlSerializer::ReadAnimationKeyFrames(Animation *anim, VertexAnimationT
         }
 
         dest->transformKeyFrames.push_back(keyframe);
-    }
+    }*/
 }
 
-void OgreXmlSerializer::ReadBoneHierarchy(Skeleton *skeleton) {
+void OgreXmlSerializer::ReadBoneHierarchy(XmlNode &node, Skeleton *skeleton) {
     if (skeleton->bones.empty()) {
         throw DeadlyImportError("Cannot read <bonehierarchy> for a Skeleton without bones");
     }
 
-    while (NextNode() == nnBoneParent) {
+    for (XmlNode &currentNode : node.children()) {
+        const std::string currentName = currentNode.name();
+        if (currentName == nnBoneParent) {
+            const std::string name = ReadAttribute<std::string>(currentNode, "bone");
+            const std::string parentName = ReadAttribute<std::string>(currentNode, "parent");
+
+            Bone *bone = skeleton->BoneByName(name);
+            Bone *parent = skeleton->BoneByName(parentName);
+
+            if (bone && parent) {
+                parent->AddChild(bone);
+            } else {
+                throw DeadlyImportError("Failed to find bones for parenting: Child " + name + " for parent " + parentName);
+            }
+        }
+    }
+
+
+    /*while (NextNode() == nnBoneParent) {
         const std::string name = ReadAttribute<std::string>("bone");
         const std::string parentName = ReadAttribute<std::string>("parent");
 
@@ -775,7 +980,7 @@ void OgreXmlSerializer::ReadBoneHierarchy(Skeleton *skeleton) {
             parent->AddChild(bone);
         else
             throw DeadlyImportError("Failed to find bones for parenting: Child " + name + " for parent " + parentName);
-    }
+    }*/
 
     // Calculate bone matrices for root bones. Recursively calculates their children.
     for (size_t i = 0, len = skeleton->bones.size(); i < len; ++i) {
@@ -792,9 +997,28 @@ static bool BoneCompare(Bone *a, Bone *b) {
     return (a->id < b->id);
 }
 
-void OgreXmlSerializer::ReadBones(Skeleton *skeleton) {
+void OgreXmlSerializer::ReadBones(XmlNode &node, Skeleton *skeleton) {
     ASSIMP_LOG_VERBOSE_DEBUG("  - Bones");
 
+    for (XmlNode &currentNode : node.children()) {
+        const std::string currentName = currentNode.name();
+        if (currentName == nnBone) {
+            Bone *bone = new Bone();
+            bone->id = ReadAttribute<uint16_t>(currentNode, "id");
+            bone->name = ReadAttribute<std::string>(currentNode, "name");
+            for (XmlNode &currentChildNode : currentNode.children()) {
+                const std::string currentChildName = currentNode.name();
+                if (currentChildName == nnPosition) {
+                    bone->position.x = ReadAttribute<float>(currentChildNode, anX);
+                    bone->position.y = ReadAttribute<float>(currentChildNode, anY);
+                    bone->position.z = ReadAttribute<float>(currentChildNode, anZ);
+                } else if (currentChildName == nnScale) {
+                } else if (currentChildName == nnScale) {
+                }
+            }
+        }
+    }
+
     NextNode();
     while (m_currentNodeName == nnBone) {
         Bone *bone = new Bone();

+ 35 - 36
code/AssetLib/Ogre/OgreXmlSerializer.h

@@ -48,71 +48,70 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "OgreStructs.h"
 #include <assimp/XmlParser.h>
 
-namespace Assimp
-{
-namespace Ogre
-{
+namespace Assimp {
+namespace Ogre {
 
-typedef irr::io::IrrXMLReader XmlReader;
-typedef std::shared_ptr<XmlReader> XmlReaderPtr;
+//typedef irr::io::IrrXMLReader XmlReader;
+using XmlParserPtr = std::shared_ptr<XmlParser> ;
 
-class OgreXmlSerializer
-{
+class OgreXmlSerializer {
 public:
     /// Imports mesh and returns the result.
     /** @note Fatal unrecoverable errors will throw a DeadlyImportError. */
-    static MeshXml *ImportMesh(XmlReader *reader);
+    static MeshXml *ImportMesh(XmlParser *parser);
 
     /// Imports skeleton to @c mesh.
     /** If mesh does not have a skeleton reference or the skeleton file
         cannot be found it is not a fatal DeadlyImportError.
         @return If skeleton import was successful. */
-    static bool ImportSkeleton(Assimp::IOSystem *pIOHandler, MeshXml *mesh);
-    static bool ImportSkeleton(Assimp::IOSystem *pIOHandler, Mesh *mesh);
+    static bool ImportSkeleton(IOSystem *pIOHandler, MeshXml *mesh);
+    static bool ImportSkeleton(IOSystem *pIOHandler, Mesh *mesh);
 
 private:
-    explicit OgreXmlSerializer(XmlReader *reader) :
-        m_reader(reader)
-    {
-    }
+    explicit OgreXmlSerializer(XmlParser *xmlParser);
 
-    static XmlReaderPtr OpenReader(Assimp::IOSystem *pIOHandler, const std::string &filename);
+    static XmlParserPtr OpenXmlParser(Assimp::IOSystem *pIOHandler, const std::string &filename);
 
     // Mesh
     void ReadMesh(MeshXml *mesh);
-    void ReadSubMesh(MeshXml *mesh);
+    void ReadSubMesh(XmlNode &node, MeshXml *mesh);
 
-    void ReadGeometry(VertexDataXml *dest);
-    void ReadGeometryVertexBuffer(VertexDataXml *dest);
+    void ReadGeometry(XmlNode &node, VertexDataXml *dest);
+    void ReadGeometryVertexBuffer(XmlNode &node, VertexDataXml *dest);
 
-    void ReadBoneAssignments(VertexDataXml *dest);
+    void ReadBoneAssignments(XmlNode &node, VertexDataXml *dest);
 
     // Skeleton
-    void ReadSkeleton(Skeleton *skeleton);
+    void ReadSkeleton(XmlNode &node, Skeleton *skeleton);
 
-    void ReadBones(Skeleton *skeleton);
-    void ReadBoneHierarchy(Skeleton *skeleton);
+    void ReadBones(XmlNode &node, Skeleton *skeleton);
+    void ReadBoneHierarchy(XmlNode &node, Skeleton *skeleton);
 
-    void ReadAnimations(Skeleton *skeleton);
-    void ReadAnimationTracks(Animation *dest);
-    void ReadAnimationKeyFrames(Animation *anim, VertexAnimationTrack *dest);
+    void ReadAnimations(XmlNode &node, Skeleton *skeleton);
+    void ReadAnimationTracks(XmlNode &node, Animation *dest);
+    void ReadAnimationKeyFrames(XmlNode &node, Animation *anim, VertexAnimationTrack *dest);
 
-    template<typename T>
-    T ReadAttribute(const char *name) const;
-    bool HasAttribute(const char *name) const;
+    template <typename T>
+    T ReadAttribute(XmlNode &xmlNode, const char *name) const;
+    //bool HasAttribute(const char *name) const;
 
-    std::string &NextNode();
-    std::string &SkipCurrentNode();
+    //std::string &NextNode();
+    //std::string &SkipCurrentNode();
 
-    bool CurrentNodeNameEquals(const std::string &name) const;
-    std::string CurrentNodeName(bool forceRead = false);
+    //bool CurrentNodeNameEquals(const std::string &name) const;
+    //std::string CurrentNodeName(bool forceRead = false);
 
-    XmlReader *m_reader;
+    XmlParser *mParser;
     std::string m_currentNodeName;
 };
 
-} // Ogre
-} // Assimp
+inline OgreXmlSerializer::OgreXmlSerializer(XmlParser *xmlParser) :
+        mParser(xmlParser) {
+    // empty
+}
+
+} // namespace Ogre
+} // namespace Assimp
 
 #endif // ASSIMP_BUILD_NO_OGRE_IMPORTER
 #endif // AI_OGREXMLSERIALIZER_H_INC