AMF: fix adding for child-nodes.

pull/2966/head
Kim Kulling 2020-09-10 00:05:53 +02:00
parent 0618db1f99
commit d854f3b842
4 changed files with 190 additions and 126 deletions

View File

@ -266,7 +266,7 @@ void AMFImporter::ParseFile(const std::string &pFile, IOSystem *pIOHandler) {
} }
mXmlParser = new XmlParser(); mXmlParser = new XmlParser();
if (!mXmlParser->parse( file.get() )) { if (!mXmlParser->parse(file.get())) {
delete mXmlParser; delete mXmlParser;
throw DeadlyImportError("Failed to create XML reader for file" + pFile + "."); 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(); ParseNode_Root();
} // namespace Assimp } // 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 // <amf
// unit="" - The units to be used. May be "inch", "millimeter", "meter", "feet", or "micron". // unit="" - The units to be used. May be "inch", "millimeter", "meter", "feet", or "micron".
// version="" - Version of file format. // version="" - Version of file format.
@ -352,15 +361,18 @@ void AMFImporter::ParseNode_Constellation(XmlNode &node) {
} }
// Check for child nodes // Check for child nodes
for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) { if (!node.empty()) {
std::string name = currentNode.name(); ParseHelper_Node_Enter(ne);
if (name == "instance") { for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
ParseNode_Instance(currentNode); std::string name = currentNode.name();
} else if (name == "metadata") { if (name == "instance") {
ParseNode_Metadata(currentNode); ParseNode_Instance(currentNode);
} else if (name == "metadata") {
ParseNode_Metadata(currentNode);
}
} }
} ParseHelper_Node_Exit();
if (node.empty()) { } else {
mNodeElement_Cur->Child.push_back(ne); mNodeElement_Cur->Child.push_back(ne);
} }
mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph. 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); AMFInstance &als = *((AMFInstance *)ne);
als.ObjectID = objectid; als.ObjectID = objectid;
if (node.empty()) { if (!node.empty()) {
mNodeElement_Cur->Child.push_back(ne); ParseHelper_Node_Enter(ne);
} for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) { bool read_flag[6] = { false, false, false, false, false, false };
bool read_flag[6] = { false, false, false, false, false, false }; std::string currentName = currentNode.name();
std::string currentName = currentNode.name(); if (currentName == "deltax") {
if (currentName == "deltax") { read_flag[0] = true;
read_flag[0] = true; als.Delta.x = (ai_real)std::atof(currentNode.value());
als.Delta.x = (ai_real) std::atof(currentNode.value()); } else if (currentName == "deltay") {
} else if (currentName == "deltay") { read_flag[1] = true;
read_flag[1] = true; als.Delta.y = (ai_real)std::atof(currentNode.value());
als.Delta.y = (ai_real)std::atof(currentNode.value()); } else if (currentName == "deltaz") {
} else if (currentName == "deltaz") { read_flag[2] = true;
read_flag[2] = true; als.Delta.z = (ai_real)std::atof(currentNode.value());
als.Delta.z = (ai_real)std::atof(currentNode.value()); } else if (currentName == "rx") {
} else if (currentName == "rx") { read_flag[3] = true;
read_flag[3] = true; als.Delta.x = (ai_real)std::atof(currentNode.value());
als.Delta.x = (ai_real)std::atof(currentNode.value()); } else if (currentName == "ry") {
} else if (currentName == "ry") { read_flag[4] = true;
read_flag[4] = true; als.Delta.y = (ai_real)std::atof(currentNode.value());
als.Delta.y = (ai_real)std::atof(currentNode.value()); } else if (currentName == "rz") {
} else if (currentName == "rz") { read_flag[5] = true;
read_flag[5] = true; als.Delta.z = (ai_real)std::atof(currentNode.value());
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. 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. // Multi elements - Yes.
// Parent element - <amf>. // Parent element - <amf>.
void AMFImporter::ParseNode_Object(XmlNode &node) { void AMFImporter::ParseNode_Object(XmlNode &node) {
AMFNodeElementBase *ne(nullptr); AMFNodeElementBase *ne(nullptr);
// Read attributes for node <object>. // Read attributes for node <object>.
@ -443,19 +458,22 @@ void AMFImporter::ParseNode_Object(XmlNode &node) {
// Check for child nodes // Check for child nodes
bool col_read = false; bool col_read = false;
if (node.empty()) { if (!node.empty()) {
mNodeElement_Cur->Child.push_back(ne); // Add element to child list of current element ParseHelper_Node_Enter(ne);
} for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) { const std::string currentName = currentNode.name();
const std::string currentName = currentNode.name(); if (currentName == "color") {
if (currentName == "color") { ParseNode_Color(currentNode);
ParseNode_Color(currentNode); col_read = true;
col_read = true; } else if (currentName == "mesh") {
} else if (currentName == "mesh") { ParseNode_Mesh(currentNode);
ParseNode_Mesh(currentNode); } else if (currentName == "metadata") {
} else if (currentName == "metadata") { ParseNode_Metadata(currentNode);
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. mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph.

View File

@ -274,7 +274,8 @@ public:
/// \param [in] pFile - name of file to be parsed. /// \param [in] pFile - name of file to be parsed.
/// \param [in] pIOHandler - pointer to IO helper object. /// \param [in] pIOHandler - pointer to IO helper object.
void ParseFile(const std::string &pFile, IOSystem *pIOHandler); 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; bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool pCheckSig) const;
void GetExtensionList(std::set<std::string> &pExtensionList); void GetExtensionList(std::set<std::string> &pExtensionList);
void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler); void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler);

View File

@ -67,19 +67,22 @@ void AMFImporter::ParseNode_Mesh(XmlNode &node) {
if (0 != ASSIMP_stricmp(node.name(), "mesh")) { if (0 != ASSIMP_stricmp(node.name(), "mesh")) {
return; return;
} }
bool found_verts = false, found_volumes = false; bool found_verts = false, found_volumes = false;
pugi::xml_node vertNode = node.child("vertices"); if (!node.empty()) {
if (!vertNode.empty()) { ParseHelper_Node_Enter(ne);
ParseNode_Vertices(vertNode); pugi::xml_node vertNode = node.child("vertices");
found_verts = true; if (!vertNode.empty()) {
} ParseNode_Vertices(vertNode);
found_verts = true;
}
pugi::xml_node volumeNode = node.child("volume"); pugi::xml_node volumeNode = node.child("volume");
if (!volumeNode.empty()) { if (!volumeNode.empty()) {
ParseNode_Volume(volumeNode); ParseNode_Volume(volumeNode);
found_volumes = true; found_volumes = true;
} }
ParseHelper_Node_Exit();
}
if (!found_verts && !found_volumes) { if (!found_verts && !found_volumes) {
mNodeElement_Cur->Child.push_back(ne); mNodeElement_Cur->Child.push_back(ne);
@ -102,7 +105,12 @@ void AMFImporter::ParseNode_Vertices(XmlNode &node) {
// Check for child nodes // Check for child nodes
pugi::xml_node vertexNode = node.child("vertex"); pugi::xml_node vertexNode = node.child("vertex");
if (!vertexNode.empty()) { if (!vertexNode.empty()) {
ParseHelper_Node_Enter(ne);
ParseNode_Vertex(vertexNode); ParseNode_Vertex(vertexNode);
ParseHelper_Node_Exit();
} else { } else {
mNodeElement_Cur->Child.push_back(ne); // Add element to child list of current element mNodeElement_Cur->Child.push_back(ne); // Add element to child list of current element
} // if(!mReader->isEmptyElement()) else } // if(!mReader->isEmptyElement()) else
@ -125,15 +133,20 @@ void AMFImporter::ParseNode_Vertex(XmlNode &node) {
pugi::xml_node colorNode = node.child("color"); pugi::xml_node colorNode = node.child("color");
bool col_read = false; bool col_read = false;
bool coord_read = false; bool coord_read = false;
if (!colorNode.empty()) { if (!node.empty()) {
ParseNode_Color(colorNode); ParseHelper_Node_Enter(ne);
col_read = true; if (!colorNode.empty()) {
} ParseNode_Color(colorNode);
pugi::xml_node coordNode = node.child("coordinates"); col_read = true;
if (!coordNode.empty()) { }
ParseNode_Coordinates(coordNode); pugi::xml_node coordNode = node.child("coordinates");
coord_read = true; if (!coordNode.empty()) {
ParseNode_Coordinates(coordNode);
coord_read = true;
}
ParseHelper_Node_Exit();
} }
if (!coord_read && !col_read) { if (!coord_read && !col_read) {
mNodeElement_Cur->Child.push_back(ne); // Add element to child list of current element 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); ne = new AMFCoordinates(mNodeElement_Cur);
AMFCoordinates &als = *((AMFCoordinates *)ne); // alias for convenience 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(); ParseHelper_Node_Exit();
als.Coordinate.y = (ai_real)node.attribute("y").as_float(); } else {
als.Coordinate.z = (ai_real)node.attribute("z").as_float(); mNodeElement_Cur->Child.push_back(ne);
mNodeElement_Cur->Child.push_back(ne); }
mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph. 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; ((AMFVolume *)ne)->Type = type;
// Check for child nodes // 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; bool col_read = false;
for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) { if (!node.empty()) {
const std::string currentName = currentNode.name(); ParseHelper_Node_Enter(ne);
if (currentName == "color") { for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
if (col_read) Throw_MoreThanOnceDefined(currentName ,"color", "Only one color can be defined for <volume>."); const std::string currentName = currentNode.name();
ParseNode_Color(currentNode); if (currentName == "color") {
col_read = true; if (col_read) Throw_MoreThanOnceDefined(currentName, "color", "Only one color can be defined for <volume>.");
} else if (currentName == "triangle") { ParseNode_Color(currentNode);
ParseNode_Triangle(currentNode); col_read = true;
} else if (currentName == "metadata") { } else if (currentName == "triangle") {
ParseNode_Metadata(currentNode); ParseNode_Triangle(currentNode);
} else if (currentName == "volume") { } else if (currentName == "metadata") {
ParseNode_Metadata(currentNode); 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. 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 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 <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 mNodeElement_Cur->Child.push_back(ne); // Add element to child list of current element
} }
// Check for child nodes // 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 ((read_flag[0] && read_flag[1] && read_flag[2]) == 0) { if ((read_flag[0] && read_flag[1] && read_flag[2]) == 0) {
throw DeadlyImportError("Not all vertices of the triangle are defined."); throw DeadlyImportError("Not all vertices of the triangle are defined.");
} }

View File

@ -49,7 +49,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_AMF_IMPORTER #ifndef ASSIMP_BUILD_NO_AMF_IMPORTER
#include "AMFImporter.hpp" #include "AMFImporter.hpp"
//#include "AMFImporter_Macro.hpp"
namespace Assimp { namespace Assimp {
@ -76,22 +75,24 @@ void AMFImporter::ParseNode_Color(XmlNode &node) {
als.Profile = profile; als.Profile = profile;
if (!node.empty()) { if (!node.empty()) {
ParseHelper_Node_Enter(ne);
bool read_flag[4] = { false, false, false, false }; bool read_flag[4] = { false, false, false, false };
for (pugi::xml_node &child : node.children()) { for (pugi::xml_node &child : node.children()) {
std::string name = child.name(); std::string name = child.name();
if ( name == "r") { if ( name == "r") {
read_flag[0] = true; read_flag[0] = true;
als.Color.r = (ai_real)::atof(child.value()); XmlParser::getValueAsFloat(child, als.Color.r);
} else if (name == "g") { } else if (name == "g") {
read_flag[1] = true; read_flag[1] = true;
als.Color.g = (ai_real)::atof(child.value()); XmlParser::getValueAsFloat(child, als.Color.g);
} else if (name == "b") { } else if (name == "b") {
read_flag[2] = true; read_flag[2] = true;
als.Color.b = (ai_real)::atof(child.value()); XmlParser::getValueAsFloat(child, als.Color.b);
} else if (name == "g") { } else if (name == "a") {
read_flag[3] = true; 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 // check that all components was defined
if (!(read_flag[0] && read_flag[1] && read_flag[2])) { if (!(read_flag[0] && read_flag[1] && read_flag[2])) {
@ -126,6 +127,7 @@ void AMFImporter::ParseNode_Material(XmlNode &node) {
// Check for child nodes // Check for child nodes
if (!node.empty()) { if (!node.empty()) {
bool col_read = false; bool col_read = false;
ParseHelper_Node_Enter(ne);
for (pugi::xml_node &child : node.children()) { for (pugi::xml_node &child : node.children()) {
const std::string name = child.name(); const std::string name = child.name();
if (name == "color") { if (name == "color") {
@ -135,6 +137,7 @@ void AMFImporter::ParseNode_Material(XmlNode &node) {
ParseNode_Metadata(child); ParseNode_Metadata(child);
} }
} }
ParseHelper_Node_Exit();
} else { } else {
mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element 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. // Texture coordinates for every vertex of triangle.
void AMFImporter::ParseNode_TexMap(XmlNode &node, const bool pUseOldName) { void AMFImporter::ParseNode_TexMap(XmlNode &node, const bool pUseOldName) {
// Read attributes for node <color>. // Read attributes for node <color>.
std::string rtexid = node.attribute("rtexid").as_string(); AMFNodeElementBase *ne = new AMFTexMap(mNodeElement_Cur);
std::string gtexid = node.attribute("gtexid").as_string(); AMFTexMap &als = *((AMFTexMap *)ne); //
std::string btexid = node.attribute("btexid").as_string(); std::string rtexid, gtexid, btexid, atexid;
std::string atexid = node.attribute("atexid").as_string(); 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 // create new texture coordinates object, alias for convenience
AMFNodeElementBase *ne = new AMFTexMap(mNodeElement_Cur);
AMFTexMap& als = *((AMFTexMap*)ne);//
// check data // check data
if (rtexid.empty() && gtexid.empty() && btexid.empty()) { if (rtexid.empty() && gtexid.empty() && btexid.empty()) {
throw DeadlyImportError("ParseNode_TexMap. At least one texture ID must be defined."); throw DeadlyImportError("ParseNode_TexMap. At least one texture ID must be defined.");