From d854f3b84245b22ac150f3cc6e0e48b145c75eb2 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Thu, 10 Sep 2020 00:05:53 +0200 Subject: [PATCH] AMF: fix adding for child-nodes. --- code/AssetLib/AMF/AMFImporter.cpp | 110 ++++++++------ code/AssetLib/AMF/AMFImporter.hpp | 3 +- code/AssetLib/AMF/AMFImporter_Geometry.cpp | 160 ++++++++++++--------- code/AssetLib/AMF/AMFImporter_Material.cpp | 43 ++++-- 4 files changed, 190 insertions(+), 126 deletions(-) diff --git a/code/AssetLib/AMF/AMFImporter.cpp b/code/AssetLib/AMF/AMFImporter.cpp index 78d9ffe25..f2b1216b5 100644 --- a/code/AssetLib/AMF/AMFImporter.cpp +++ b/code/AssetLib/AMF/AMFImporter.cpp @@ -266,7 +266,7 @@ void AMFImporter::ParseFile(const std::string &pFile, IOSystem *pIOHandler) { } mXmlParser = new XmlParser(); - if (!mXmlParser->parse( file.get() )) { + if (!mXmlParser->parse(file.get())) { delete mXmlParser; throw DeadlyImportError("Failed to create XML reader for file" + pFile + "."); } @@ -278,6 +278,15 @@ void AMFImporter::ParseFile(const std::string &pFile, IOSystem *pIOHandler) { ParseNode_Root(); } // namespace Assimp +void AMFImporter::ParseHelper_Node_Enter(AMFNodeElementBase *node) { + mNodeElement_Cur->Child.push_back(node); // add new element to current element child list. + mNodeElement_Cur = node; +} + +void AMFImporter::ParseHelper_Node_Exit() { + if (mNodeElement_Cur != nullptr) mNodeElement_Cur = mNodeElement_Cur->Parent; +} + // Child.push_back(ne); } mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph. @@ -388,31 +400,34 @@ void AMFImporter::ParseNode_Instance(XmlNode &node) { AMFInstance &als = *((AMFInstance *)ne); als.ObjectID = objectid; - if (node.empty()) { - mNodeElement_Cur->Child.push_back(ne); - } - for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) { - bool read_flag[6] = { false, false, false, false, false, false }; - std::string currentName = currentNode.name(); - if (currentName == "deltax") { - read_flag[0] = true; - als.Delta.x = (ai_real) std::atof(currentNode.value()); - } else if (currentName == "deltay") { - read_flag[1] = true; - als.Delta.y = (ai_real)std::atof(currentNode.value()); - } else if (currentName == "deltaz") { - read_flag[2] = true; - als.Delta.z = (ai_real)std::atof(currentNode.value()); - } else if (currentName == "rx") { - read_flag[3] = true; - als.Delta.x = (ai_real)std::atof(currentNode.value()); - } else if (currentName == "ry") { - read_flag[4] = true; - als.Delta.y = (ai_real)std::atof(currentNode.value()); - } else if (currentName == "rz") { - read_flag[5] = true; - als.Delta.z = (ai_real)std::atof(currentNode.value()); + if (!node.empty()) { + ParseHelper_Node_Enter(ne); + for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) { + bool read_flag[6] = { false, false, false, false, false, false }; + std::string currentName = currentNode.name(); + if (currentName == "deltax") { + read_flag[0] = true; + als.Delta.x = (ai_real)std::atof(currentNode.value()); + } else if (currentName == "deltay") { + read_flag[1] = true; + als.Delta.y = (ai_real)std::atof(currentNode.value()); + } else if (currentName == "deltaz") { + read_flag[2] = true; + als.Delta.z = (ai_real)std::atof(currentNode.value()); + } else if (currentName == "rx") { + read_flag[3] = true; + als.Delta.x = (ai_real)std::atof(currentNode.value()); + } else if (currentName == "ry") { + read_flag[4] = true; + als.Delta.y = (ai_real)std::atof(currentNode.value()); + } else if (currentName == "rz") { + read_flag[5] = true; + als.Delta.z = (ai_real)std::atof(currentNode.value()); + } } + ParseHelper_Node_Exit(); + } else { + mNodeElement_Cur->Child.push_back(ne); } mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph. @@ -426,7 +441,7 @@ void AMFImporter::ParseNode_Instance(XmlNode &node) { // Multi elements - Yes. // Parent element - . void AMFImporter::ParseNode_Object(XmlNode &node) { - + AMFNodeElementBase *ne(nullptr); // Read attributes for node . @@ -443,19 +458,22 @@ void AMFImporter::ParseNode_Object(XmlNode &node) { // Check for child nodes bool col_read = false; - if (node.empty()) { - mNodeElement_Cur->Child.push_back(ne); // Add element to child list of current element - } - for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) { - const std::string currentName = currentNode.name(); - if (currentName == "color") { - ParseNode_Color(currentNode); - col_read = true; - } else if (currentName == "mesh") { - ParseNode_Mesh(currentNode); - } else if (currentName == "metadata") { - ParseNode_Metadata(currentNode); + if (!node.empty()) { + ParseHelper_Node_Enter(ne); + for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) { + const std::string currentName = currentNode.name(); + if (currentName == "color") { + ParseNode_Color(currentNode); + col_read = true; + } else if (currentName == "mesh") { + ParseNode_Mesh(currentNode); + } else if (currentName == "metadata") { + ParseNode_Metadata(currentNode); + } } + ParseHelper_Node_Exit(); + } else { + mNodeElement_Cur->Child.push_back(ne); // Add element to child list of current element } mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph. diff --git a/code/AssetLib/AMF/AMFImporter.hpp b/code/AssetLib/AMF/AMFImporter.hpp index ae7b39fb7..5493a9597 100644 --- a/code/AssetLib/AMF/AMFImporter.hpp +++ b/code/AssetLib/AMF/AMFImporter.hpp @@ -274,7 +274,8 @@ public: /// \param [in] pFile - name of file to be parsed. /// \param [in] pIOHandler - pointer to IO helper object. void ParseFile(const std::string &pFile, IOSystem *pIOHandler); - + void ParseHelper_Node_Enter(AMFNodeElementBase *child); + void ParseHelper_Node_Exit(); bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool pCheckSig) const; void GetExtensionList(std::set &pExtensionList); void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler); diff --git a/code/AssetLib/AMF/AMFImporter_Geometry.cpp b/code/AssetLib/AMF/AMFImporter_Geometry.cpp index 7a64c64fd..49324842f 100644 --- a/code/AssetLib/AMF/AMFImporter_Geometry.cpp +++ b/code/AssetLib/AMF/AMFImporter_Geometry.cpp @@ -67,19 +67,22 @@ void AMFImporter::ParseNode_Mesh(XmlNode &node) { if (0 != ASSIMP_stricmp(node.name(), "mesh")) { return; } - bool found_verts = false, found_volumes = false; - pugi::xml_node vertNode = node.child("vertices"); - if (!vertNode.empty()) { - ParseNode_Vertices(vertNode); - found_verts = true; - } + if (!node.empty()) { + ParseHelper_Node_Enter(ne); + pugi::xml_node vertNode = node.child("vertices"); + if (!vertNode.empty()) { + ParseNode_Vertices(vertNode); + found_verts = true; + } - pugi::xml_node volumeNode = node.child("volume"); - if (!volumeNode.empty()) { - ParseNode_Volume(volumeNode); - found_volumes = true; - } + pugi::xml_node volumeNode = node.child("volume"); + if (!volumeNode.empty()) { + ParseNode_Volume(volumeNode); + found_volumes = true; + } + ParseHelper_Node_Exit(); + } if (!found_verts && !found_volumes) { mNodeElement_Cur->Child.push_back(ne); @@ -102,7 +105,12 @@ void AMFImporter::ParseNode_Vertices(XmlNode &node) { // Check for child nodes pugi::xml_node vertexNode = node.child("vertex"); if (!vertexNode.empty()) { + ParseHelper_Node_Enter(ne); + ParseNode_Vertex(vertexNode); + + ParseHelper_Node_Exit(); + } else { mNodeElement_Cur->Child.push_back(ne); // Add element to child list of current element } // if(!mReader->isEmptyElement()) else @@ -125,15 +133,20 @@ void AMFImporter::ParseNode_Vertex(XmlNode &node) { pugi::xml_node colorNode = node.child("color"); bool col_read = false; bool coord_read = false; - if (!colorNode.empty()) { - ParseNode_Color(colorNode); - col_read = true; - } - pugi::xml_node coordNode = node.child("coordinates"); - if (!coordNode.empty()) { - ParseNode_Coordinates(coordNode); - coord_read = true; + if (!node.empty()) { + ParseHelper_Node_Enter(ne); + if (!colorNode.empty()) { + ParseNode_Color(colorNode); + col_read = true; + } + pugi::xml_node coordNode = node.child("coordinates"); + if (!coordNode.empty()) { + ParseNode_Coordinates(coordNode); + coord_read = true; + } + ParseHelper_Node_Exit(); } + if (!coord_read && !col_read) { mNodeElement_Cur->Child.push_back(ne); // Add element to child list of current element } @@ -158,11 +171,23 @@ void AMFImporter::ParseNode_Coordinates(XmlNode &node) { ne = new AMFCoordinates(mNodeElement_Cur); AMFCoordinates &als = *((AMFCoordinates *)ne); // alias for convenience + if (!node.empty()) { + ParseHelper_Node_Enter(ne); + for (XmlNode ¤tNode : node.children()) { + const std::string ¤tName = currentNode.name(); + if (currentName == "X") { + XmlParser::getValueAsFloat(currentNode, als.Coordinate.x); + } else if (currentName == "Y") { + XmlParser::getValueAsFloat(currentNode, als.Coordinate.y); + } else if (currentName == "Z") { + XmlParser::getValueAsFloat(currentNode, als.Coordinate.z); + } + } - als.Coordinate.x = (ai_real)node.attribute("x").as_float(); - als.Coordinate.y = (ai_real)node.attribute("y").as_float(); - als.Coordinate.z = (ai_real)node.attribute("z").as_float(); - mNodeElement_Cur->Child.push_back(ne); + ParseHelper_Node_Exit(); + } else { + mNodeElement_Cur->Child.push_back(ne); + } mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph. } @@ -188,24 +213,26 @@ void AMFImporter::ParseNode_Volume(XmlNode &node) { ((AMFVolume *)ne)->Type = type; // Check for child nodes - if (node.empty()) { - mNodeElement_Cur->Child.push_back(ne); // Add element to child list of current element - } - bool col_read = false; - for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) { - const std::string currentName = currentNode.name(); - if (currentName == "color") { - if (col_read) Throw_MoreThanOnceDefined(currentName ,"color", "Only one color can be defined for ."); - ParseNode_Color(currentNode); - col_read = true; - } else if (currentName == "triangle") { - ParseNode_Triangle(currentNode); - } else if (currentName == "metadata") { - ParseNode_Metadata(currentNode); - } else if (currentName == "volume") { - ParseNode_Metadata(currentNode); + if (!node.empty()) { + ParseHelper_Node_Enter(ne); + for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) { + const std::string currentName = currentNode.name(); + if (currentName == "color") { + if (col_read) Throw_MoreThanOnceDefined(currentName, "color", "Only one color can be defined for ."); + ParseNode_Color(currentNode); + col_read = true; + } else if (currentName == "triangle") { + ParseNode_Triangle(currentNode); + } else if (currentName == "metadata") { + ParseNode_Metadata(currentNode); + } else if (currentName == "volume") { + ParseNode_Metadata(currentNode); + } } + ParseHelper_Node_Exit(); + } else { + mNodeElement_Cur->Child.push_back(ne); // Add element to child list of current element } mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph. @@ -228,36 +255,39 @@ void AMFImporter::ParseNode_Triangle(XmlNode &node) { AMFTriangle &als = *((AMFTriangle *)ne); // alias for convenience - if (node.empty()) { + bool col_read = false, tex_read = false; + bool read_flag[3] = { false, false, false }; + if (!node.empty()) { + ParseHelper_Node_Enter(ne); + for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) { + const std::string currentName = currentNode.name(); + if (currentName == "color") { + if (col_read) Throw_MoreThanOnceDefined(currentName, "color", "Only one color can be defined for ."); + ParseNode_Color(currentNode); + col_read = true; + } else if (currentName == "texmap") { + ParseNode_TexMap(currentNode); + tex_read = true; + } else if (currentName == "map") { + ParseNode_TexMap(currentNode, true); + tex_read = true; + } else if (currentName == "v1") { + als.V[0] = std::atoi(currentNode.value()); + read_flag[0] = true; + } else if (currentName == "v2") { + als.V[1] = std::atoi(currentNode.value()); + read_flag[1] = true; + } else if (currentName == "v3") { + als.V[2] = std::atoi(currentNode.value()); + read_flag[2] = true; + } + } + ParseHelper_Node_Exit(); + } else { 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 (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) { - const std::string currentName = currentNode.name(); - if (currentName == "color") { - if (col_read) Throw_MoreThanOnceDefined(currentName , "color", "Only one color can be defined for ."); - ParseNode_Color(currentNode); - col_read = true; - } else if (currentName == "texmap") { - ParseNode_TexMap(currentNode); - tex_read = true; - } else if (currentName == "map") { - ParseNode_TexMap(currentNode, true); - tex_read = true; - } else if (currentName == "v1") { - als.V[0] = std::atoi(currentNode.value()); - read_flag[0] = true; - } else if (currentName == "v2") { - als.V[1] = std::atoi(currentNode.value()); - read_flag[1] = true; - } else if (currentName == "v3") { - als.V[2] = std::atoi(currentNode.value()); - 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."); } diff --git a/code/AssetLib/AMF/AMFImporter_Material.cpp b/code/AssetLib/AMF/AMFImporter_Material.cpp index 0dde37d35..515b5dab1 100644 --- a/code/AssetLib/AMF/AMFImporter_Material.cpp +++ b/code/AssetLib/AMF/AMFImporter_Material.cpp @@ -49,7 +49,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_AMF_IMPORTER #include "AMFImporter.hpp" -//#include "AMFImporter_Macro.hpp" namespace Assimp { @@ -76,22 +75,24 @@ void AMFImporter::ParseNode_Color(XmlNode &node) { als.Profile = profile; if (!node.empty()) { + ParseHelper_Node_Enter(ne); bool read_flag[4] = { false, false, false, false }; for (pugi::xml_node &child : node.children()) { std::string name = child.name(); if ( name == "r") { read_flag[0] = true; - als.Color.r = (ai_real)::atof(child.value()); + XmlParser::getValueAsFloat(child, als.Color.r); } else if (name == "g") { read_flag[1] = true; - als.Color.g = (ai_real)::atof(child.value()); + XmlParser::getValueAsFloat(child, als.Color.g); } else if (name == "b") { read_flag[2] = true; - als.Color.b = (ai_real)::atof(child.value()); - } else if (name == "g") { + XmlParser::getValueAsFloat(child, als.Color.b); + } else if (name == "a") { read_flag[3] = true; - als.Color.a = (ai_real) ::atof(child.value()); - } + XmlParser::getValueAsFloat(child, als.Color.a); + } + ParseHelper_Node_Exit(); } // check that all components was defined if (!(read_flag[0] && read_flag[1] && read_flag[2])) { @@ -126,6 +127,7 @@ void AMFImporter::ParseNode_Material(XmlNode &node) { // Check for child nodes if (!node.empty()) { bool col_read = false; + ParseHelper_Node_Enter(ne); for (pugi::xml_node &child : node.children()) { const std::string name = child.name(); if (name == "color") { @@ -135,6 +137,7 @@ void AMFImporter::ParseNode_Material(XmlNode &node) { ParseNode_Metadata(child); } } + ParseHelper_Node_Exit(); } else { mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element } @@ -230,15 +233,27 @@ void AMFImporter::ParseNode_Texture(XmlNode &node) { // Texture coordinates for every vertex of triangle. void AMFImporter::ParseNode_TexMap(XmlNode &node, const bool pUseOldName) { // Read attributes for node . - std::string rtexid = node.attribute("rtexid").as_string(); - std::string gtexid = node.attribute("gtexid").as_string(); - std::string btexid = node.attribute("btexid").as_string(); - std::string atexid = node.attribute("atexid").as_string(); - + AMFNodeElementBase *ne = new AMFTexMap(mNodeElement_Cur); + AMFTexMap &als = *((AMFTexMap *)ne); // + std::string rtexid, gtexid, btexid, atexid; + if (!node.empty()) { + ParseHelper_Node_Enter(ne); + for (XmlNode ¤tNode : node.children()) { + const std::string ¤tName = currentNode.name(); + if (currentName == "rtexid") { + XmlParser::getValueAsString(node, rtexid); + } else if (currentName == "gtexid") { + XmlParser::getValueAsString(node, gtexid); + } else if (currentName == "btexid") { + XmlParser::getValueAsString(node, btexid); + } else if (currentName == "atexid") { + XmlParser::getValueAsString(node, atexid); + } + } + ParseHelper_Node_Exit(); + } // create new texture coordinates object, alias for convenience - AMFNodeElementBase *ne = new AMFTexMap(mNodeElement_Cur); - AMFTexMap& als = *((AMFTexMap*)ne);// // check data if (rtexid.empty() && gtexid.empty() && btexid.empty()) { throw DeadlyImportError("ParseNode_TexMap. At least one texture ID must be defined.");