Sfoglia il codice sorgente

AMF: fix adding for child-nodes.

Kim Kulling 5 anni fa
parent
commit
d854f3b842

+ 64 - 46
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;
+}
+
 // <amf
 // unit="" - The units to be used. May be "inch", "millimeter", "meter", "feet", or "micron".
 // version="" - Version of file format.
@@ -352,15 +361,18 @@ void AMFImporter::ParseNode_Constellation(XmlNode &node) {
     }
 
     // Check for child nodes
-    for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
-        std::string name = currentNode.name();
-        if (name == "instance") {
-            ParseNode_Instance(currentNode);
-        } else if (name == "metadata") {
-            ParseNode_Metadata(currentNode);
+    if (!node.empty()) {
+        ParseHelper_Node_Enter(ne);
+        for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
+            std::string name = currentNode.name();
+            if (name == "instance") {
+                ParseNode_Instance(currentNode);
+            } else if (name == "metadata") {
+                ParseNode_Metadata(currentNode);
+            }
         }
-    }
-    if (node.empty()) {
+        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.
@@ -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 - <amf>.
 void AMFImporter::ParseNode_Object(XmlNode &node) {
-    
+
     AMFNodeElementBase *ne(nullptr);
 
     // Read attributes for node <object>.
@@ -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.

+ 2 - 1
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<std::string> &pExtensionList);
     void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler);

+ 95 - 65
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 &currentNode : node.children()) {
+            const std::string &currentName = 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 <volume>.");
-            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 <volume>.");
+                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()) {
-        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 <triangle>.");
-            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 (!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 <triangle>.");
+                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
     if ((read_flag[0] && read_flag[1] && read_flag[2]) == 0) {
         throw DeadlyImportError("Not all vertices of the triangle are defined.");
     }

+ 29 - 14
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 <color>.
-	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 &currentNode : node.children()) {
+            const std::string &currentName = 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.");