Browse Source

xml-migration: migration of XGLImporter.

Kim Kulling 5 years ago
parent
commit
979153522c

+ 45 - 43
code/AMF/AMFImporter.cpp

@@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
 
 Copyright (c) 2006-2020, assimp team
 
-
-
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -90,9 +88,9 @@ void AMFImporter::Clear() {
 }
 
 AMFImporter::~AMFImporter() {
-	if (mReader != nullptr) {
-		delete mReader;
-		mReader = nullptr;
+	if (mXmlParser != nullptr) {
+		delete mXmlParser;
+		mXmlParser = nullptr;
 	}
 
 	// Clear() is accounting if data already is deleted. So, just check again if all data is deleted.
@@ -106,7 +104,9 @@ AMFImporter::~AMFImporter() {
 bool AMFImporter::Find_NodeElement(const std::string &pID, const CAMFImporter_NodeElement::EType pType, CAMFImporter_NodeElement **pNodeElement) const {
 	for (CAMFImporter_NodeElement *ne : mNodeElement_List) {
 		if ((ne->ID == pID) && (ne->Type == pType)) {
-			if (pNodeElement != nullptr) *pNodeElement = ne;
+			if (pNodeElement != nullptr) {
+				*pNodeElement = ne;
+			}
 
 			return true;
 		}
@@ -173,10 +173,9 @@ void AMFImporter::Throw_ID_NotFound(const std::string &pID) const {
 /************************************************************* Functions: XML set ************************************************************/
 /*********************************************************************************************************************************************/
 
-void AMFImporter::XML_CheckNode_MustHaveChildren( XmlNode *node ) {
-	//if (mReader->isEmptyElement()) throw DeadlyImportError(std::string("Node <") + mReader->getNodeName() + "> must have children.");
-	if (node->getNode()->children().begin() == node->getNode()->children().end()) {
-		throw DeadlyImportError(std::string("Node <") + std::string(node->getNode()->name()) + "> must have children.");
+void AMFImporter::XML_CheckNode_MustHaveChildren( XmlNode &node ) {
+	if (node.children().begin() == node.children().end()) {
+		throw DeadlyImportError(std::string("Node <") + std::string(node.name()) + "> must have children.");
     }
 }
 
@@ -221,20 +220,23 @@ casu_cres:
 	}
 }
 */
-bool AMFImporter::XML_SearchNode(const std::string &pNodeName) {
-	
-    mReader->while (mReader->read()) {
-		//if((mReader->getNodeType() == irr::io::EXN_ELEMENT) && XML_CheckNode_NameEqual(pNodeName)) return true;
-		if ((mReader->getNodeType() == pugi::node_element) && XML_CheckNode_NameEqual(pNodeName)) {
-			return true;
-		}
-	}
+bool AMFImporter::XML_SearchNode(const std::string &nodeName) {
+	XmlNode *root = mXmlParser->getRootNode();
+	if (nullptr == root) {
+		return false;
+    }
 
-	return false;
+    find_node_by_name_predicate predicate(nodeName);
+	XmlNode node = root->find_node(predicate);
+	if (node.empty()) {
+		return false;
+    }
+
+	return true;
 }
 
-bool AMFImporter::XML_ReadNode_GetAttrVal_AsBool(const int pAttrIdx) {
-	std::string val(mReader->getAttributeValue(pAttrIdx));
+bool AMFImporter::XML_ReadNode_GetAttrVal_AsBool (const int pAttrIdx) {
+	std::string val(mXmlParser->getAttributeValue(pAttrIdx));
 
 	if ((val == "false") || (val == "0"))
 		return false;
@@ -248,42 +250,42 @@ float AMFImporter::XML_ReadNode_GetAttrVal_AsFloat(const int pAttrIdx) {
 	std::string val;
 	float tvalf;
 
-	ParseHelper_FixTruncatedFloatString(mReader->getAttributeValue(pAttrIdx), val);
+	ParseHelper_FixTruncatedFloatString(mXmlParser->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));
+	return strtoul10(mXmlParser->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.");
+	if (!mXmlParser->read()) throw DeadlyImportError("XML_ReadNode_GetVal_AsFloat. No data, seems file is corrupt.");
+	if (mXmlParser->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);
+	ParseHelper_FixTruncatedFloatString(mXmlParser->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.");
+	if (!mXmlParser->read()) throw DeadlyImportError("XML_ReadNode_GetVal_AsU32. No data, seems file is corrupt.");
+	if (mXmlParser->getNodeType() != irr::io::EXN_TEXT) throw DeadlyImportError("XML_ReadNode_GetVal_AsU32. Invalid type of XML element, seems file is corrupt.");
 
-	return strtoul10(mReader->getNodeData());
+	return strtoul10(mXmlParser->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)
+	if (!mXmlParser->read()) throw DeadlyImportError("XML_ReadNode_GetVal_AsString. No data, seems file is corrupt.");
+	if (mXmlParser->getNodeType() != irr::io::EXN_TEXT)
 		throw DeadlyImportError("XML_ReadNode_GetVal_AsString. Invalid type of XML element, seems file is corrupt.");
 
-	pValue = mReader->getNodeData();
+	pValue = mXmlParser->getNodeData();
 }
 
 /*********************************************************************************************************************************************/
@@ -383,8 +385,8 @@ void AMFImporter::ParseFile(const std::string &pFile, IOSystem *pIOHandler) {
 		throw DeadlyImportError("Failed to open AMF file " + pFile + ".");
 	}
 
-	mReader = new XmlParser;
-	XmlNode *root = mReader->parse(file.get());
+	mXmlParser = new XmlParser;
+	XmlNode *root = mXmlParser->parse(file.get());
 	if (nullptr == root) {
 		throw DeadlyImportError("Failed to create XML reader for file" + pFile + ".");
 	}
@@ -398,8 +400,8 @@ void AMFImporter::ParseFile(const std::string &pFile, IOSystem *pIOHandler) {
 
 	ParseNode_Root(root);
 
-	delete mReader;
-	mReader = nullptr;
+	delete mXmlParser;
+	mXmlParser = nullptr;
 }
 
 // <amf
@@ -502,7 +504,7 @@ void AMFImporter::ParseNode_Constellation() {
 
 	// Read attributes for node <constellation>.
 	MACRO_ATTRREAD_LOOPBEG;
-	MACRO_ATTRREAD_CHECK_RET("id", id, mReader->getAttributeValue);
+	MACRO_ATTRREAD_CHECK_RET("id", id, mXmlParser->getAttributeValue);
 	MACRO_ATTRREAD_LOOPEND;
 
 	// create and if needed - define new grouping object.
@@ -512,7 +514,7 @@ void AMFImporter::ParseNode_Constellation() {
 
 	if (!id.empty()) als.ID = id;
 	// Check for child nodes
-	if (!mReader->isEmptyElement()) {
+	if (!mXmlParser->isEmptyElement()) {
 		ParseHelper_Node_Enter(ne);
 		MACRO_NODECHECK_LOOPBEGIN("constellation");
 		if (XML_CheckNode_NameEqual("instance")) {
@@ -546,7 +548,7 @@ void AMFImporter::ParseNode_Instance() {
 
 	// Read attributes for node <constellation>.
 	MACRO_ATTRREAD_LOOPBEG;
-	MACRO_ATTRREAD_CHECK_RET("objectid", objectid, mReader->getAttributeValue);
+	MACRO_ATTRREAD_CHECK_RET("objectid", objectid, mXmlParser->getAttributeValue);
 	MACRO_ATTRREAD_LOOPEND;
 
 	// used object id must be defined, check that.
@@ -558,7 +560,7 @@ void AMFImporter::ParseNode_Instance() {
 
 	als.ObjectID = objectid;
 	// Check for child nodes
-	if (!mReader->isEmptyElement()) {
+	if (!mXmlParser->isEmptyElement()) {
 		bool read_flag[6] = { false, false, false, false, false, false };
 
 		als.Delta.Set(0, 0, 0);
@@ -625,7 +627,7 @@ void AMFImporter::ParseNode_Object(XmlNode *nodeInst) {
 			ParseNode_Metadata(*it);
         }
 	}
-	if (!mReader->isEmptyElement()) {
+	if (!mXmlParser->isEmptyElement()) {
 		bool col_read = false;
 
 		ParseHelper_Node_Enter(ne);
@@ -682,10 +684,10 @@ void AMFImporter::ParseNode_Metadata() {
 
 	// read attribute
 	MACRO_ATTRREAD_LOOPBEG;
-	MACRO_ATTRREAD_CHECK_RET("type", type, mReader->getAttributeValue);
+	MACRO_ATTRREAD_CHECK_RET("type", type, mXmlParser->getAttributeValue);
 	MACRO_ATTRREAD_LOOPEND;
 	// and value of node.
-	value = mReader->getNodeData();
+	value = mXmlParser->getNodeData();
 	// Create node element and assign read data.
 	ne = new CAMFImporter_NodeElement_Metadata(mNodeElement_Cur);
 	((CAMFImporter_NodeElement_Metadata *)ne)->Type = type;

+ 18 - 20
code/AMF/AMFImporter.hpp

@@ -63,8 +63,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 namespace Assimp {
 
-class XmlNode;
-
 /// \class AMFImporter
 /// Class that holding scene graph which include: geometry, metadata, materials etc.
 ///
@@ -280,7 +278,7 @@ private:
 	void Throw_ID_NotFound(const std::string& pID) const;
 
 	/// Check if current node have children: <node>...</node>. If not then exception will thrown.
-	void XML_CheckNode_MustHaveChildren(XmlNode *node);
+	void XML_CheckNode_MustHaveChildren( XmlNode &node);
 
 	/// Check if current node name is equal to pNodeName.
 	/// \param [in] pNodeName - name for checking.
@@ -345,49 +343,49 @@ private:
 	void ParseHelper_Decode_Base64(const std::string& pInputBase64, std::vector<uint8_t>& pOutputData) const;
 
 	/// Parse <AMF> node of the file.
-	void ParseNode_Root(XmlNode *root);
+	void ParseNode_Root(XmlNode &root);
 
 	/// Parse <constellation> node of the file.
-	void ParseNode_Constellation(XmlNode *node);
+	void ParseNode_Constellation(XmlNode &node);
 
 	/// Parse <instance> node of the file.
-	void ParseNode_Instance(XmlNode *node);
+	void ParseNode_Instance(XmlNode &node);
 
 	/// Parse <material> node of the file.
-	void ParseNode_Material(XmlNode *node);
+	void ParseNode_Material(XmlNode &node);
 
 	/// Parse <metadata> node.
-	void ParseNode_Metadata(XmlNode *node);
+	void ParseNode_Metadata(XmlNode &node);
 
 	/// Parse <object> node of the file.
-	void ParseNode_Object(XmlNode *node);
+	void ParseNode_Object(XmlNode &node);
 
 	/// Parse <texture> node of the file.
-	void ParseNode_Texture(XmlNode *node);
+	void ParseNode_Texture(XmlNode &node);
 
 	/// Parse <coordinates> node of the file.
-	void ParseNode_Coordinates(XmlNode *node);
+	void ParseNode_Coordinates(XmlNode &node);
 
 	/// Parse <edge> node of the file.
-	void ParseNode_Edge(XmlNode *node);
+	void ParseNode_Edge(XmlNode &node);
 
 	/// Parse <mesh> node of the file.
-	void ParseNode_Mesh(XmlNode *node);
+	void ParseNode_Mesh(XmlNode &node);
 
 	/// Parse <triangle> node of the file.
-	void ParseNode_Triangle(XmlNode *node);
+	void ParseNode_Triangle(XmlNode &node);
 
 	/// Parse <vertex> node of the file.
-	void ParseNode_Vertex(XmlNode *node);
+	void ParseNode_Vertex(XmlNode &node);
 
 	/// Parse <vertices> node of the file.
-	void ParseNode_Vertices(XmlNode *node);
+	void ParseNode_Vertices(XmlNode &node);
 
 	/// Parse <volume> node of the file.
-	void ParseNode_Volume(XmlNode *node);
+	void ParseNode_Volume(XmlNode &node);
 
 	/// Parse <color> node of the file.
-	void ParseNode_Color(XmlNode *node);
+	void ParseNode_Color(XmlNode &node);
 
 	/// Parse <texmap> of <map> node of the file.
 	/// \param [in] pUseOldName - if true then use old name of node(and children) - <map>, instead of new name - <texmap>.
@@ -397,7 +395,7 @@ public:
 	/// Default constructor.
 	AMFImporter() AI_NO_EXCEPT
     : mNodeElement_Cur(nullptr)
-    , mReader(nullptr) {
+    , mXmlParser(nullptr) {
         // empty
     }
 
@@ -423,7 +421,7 @@ private:
 
     CAMFImporter_NodeElement* mNodeElement_Cur;///< Current element.
     std::list<CAMFImporter_NodeElement*> mNodeElement_List;///< All elements of scene graph.
-	XmlParser *mReader;
+	XmlParser *mXmlParser;
     //irr::io::IrrXMLReader* mReader;///< Pointer to XML-reader object
     std::string mUnit;
     std::list<SPP_Material> mMaterial_Converted;///< List of converted materials for postprocessing step.

+ 8 - 8
code/AMF/AMFImporter_Geometry.cpp

@@ -66,7 +66,7 @@ void AMFImporter::ParseNode_Mesh()
 	// create new mesh object.
 	ne = new CAMFImporter_NodeElement_Mesh(mNodeElement_Cur);
 	// Check for child nodes
-	if(!mReader->isEmptyElement())
+	if(!mXmlParser->isEmptyElement())
 	{
 		bool vert_read = false;
 
@@ -107,7 +107,7 @@ CAMFImporter_NodeElement* ne;
 	// create new mesh object.
 	ne = new CAMFImporter_NodeElement_Vertices(mNodeElement_Cur);
 	// Check for child nodes
-	if(!mReader->isEmptyElement())
+	if(!mXmlParser->isEmptyElement())
 	{
 		ParseHelper_Node_Enter(ne);
 		MACRO_NODECHECK_LOOPBEGIN("vertices");
@@ -135,7 +135,7 @@ CAMFImporter_NodeElement* ne;
 	// create new mesh object.
 	ne = new CAMFImporter_NodeElement_Vertex(mNodeElement_Cur);
 	// Check for child nodes
-	if(!mReader->isEmptyElement())
+	if(!mXmlParser->isEmptyElement())
 	{
 		bool col_read = false;
 		bool coord_read = false;
@@ -196,7 +196,7 @@ CAMFImporter_NodeElement* ne;
 	CAMFImporter_NodeElement_Coordinates& als = *((CAMFImporter_NodeElement_Coordinates*)ne);// alias for convenience
 
 	// Check for child nodes
-	if(!mReader->isEmptyElement())
+	if(!mXmlParser->isEmptyElement())
 	{
 		bool read_flag[3] = { false, false, false };
 
@@ -236,8 +236,8 @@ CAMFImporter_NodeElement* ne;
 
 	// Read attributes for node <color>.
 	MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECK_RET("materialid", materialid, mReader->getAttributeValue);
-		MACRO_ATTRREAD_CHECK_RET("type", type, mReader->getAttributeValue);
+		MACRO_ATTRREAD_CHECK_RET("materialid", materialid, mXmlParser->getAttributeValue);
+		MACRO_ATTRREAD_CHECK_RET("type", type, mXmlParser->getAttributeValue);
 	MACRO_ATTRREAD_LOOPEND;
 
 	// create new object.
@@ -246,7 +246,7 @@ CAMFImporter_NodeElement* ne;
 	((CAMFImporter_NodeElement_Volume*)ne)->MaterialID = materialid;
 	((CAMFImporter_NodeElement_Volume*)ne)->Type = type;
 	// Check for child nodes
-	if(!mReader->isEmptyElement())
+	if(!mXmlParser->isEmptyElement())
 	{
 		bool col_read = false;
 
@@ -296,7 +296,7 @@ CAMFImporter_NodeElement* ne;
 	CAMFImporter_NodeElement_Triangle& als = *((CAMFImporter_NodeElement_Triangle*)ne);// alias for convenience
 
 	// Check for child nodes
-	if(!mReader->isEmptyElement())
+	if(!mXmlParser->isEmptyElement())
 	{
 		bool col_read = false, tex_read = false;
 		bool read_flag[3] = { false, false, false };

+ 16 - 28
code/AMF/AMFImporter_Material.cpp

@@ -74,7 +74,7 @@ void AMFImporter::ParseNode_Color() {
 
 	// Read attributes for node <color>.
 	MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECK_RET("profile", profile, mReader->getAttributeValue);
+		MACRO_ATTRREAD_CHECK_RET("profile", profile, mXmlParser->getAttributeValue);
 	MACRO_ATTRREAD_LOOPEND;
 
 	// create new color object.
@@ -84,7 +84,7 @@ void AMFImporter::ParseNode_Color() {
 
 	als.Profile = profile;
 	// Check for child nodes
-	if(!mReader->isEmptyElement())
+	if(!mXmlParser->isEmptyElement())
 	{
 		bool read_flag[4] = { false, false, false, false };
 
@@ -128,7 +128,7 @@ void AMFImporter::ParseNode_Material() {
 
 	// Read attributes for node <color>.
 	MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECK_RET("id", id, mReader->getAttributeValue);
+		MACRO_ATTRREAD_CHECK_RET("id", id, mXmlParser->getAttributeValue);
 	MACRO_ATTRREAD_LOOPEND;
 
 	// create new object.
@@ -138,7 +138,7 @@ void AMFImporter::ParseNode_Material() {
 	((CAMFImporter_NodeElement_Material*)ne)->ID = id;
 
     // Check for child nodes
-	if(!mReader->isEmptyElement())
+	if(!mXmlParser->isEmptyElement())
 	{
 		bool col_read = false;
 
@@ -183,25 +183,13 @@ void AMFImporter::ParseNode_Material() {
 // then layer by layer.
 // Multi elements - Yes.
 // Parent element - <amf>.
-void AMFImporter::ParseNode_Texture()
-{
-    std::string id;
-    uint32_t width = 0;
-    uint32_t height = 0;
-    uint32_t depth = 1;
-    std::string type;
-    bool tiled = false;
-    std::string enc64_data;
-
-	// Read attributes for node <color>.
-	MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECK_RET("id", id, mReader->getAttributeValue);
-		MACRO_ATTRREAD_CHECK_RET("width", width, XML_ReadNode_GetAttrVal_AsU32);
-		MACRO_ATTRREAD_CHECK_RET("height", height, XML_ReadNode_GetAttrVal_AsU32);
-		MACRO_ATTRREAD_CHECK_RET("depth", depth, XML_ReadNode_GetAttrVal_AsU32);
-		MACRO_ATTRREAD_CHECK_RET("type", type, mReader->getAttributeValue);
-		MACRO_ATTRREAD_CHECK_RET("tiled", tiled, XML_ReadNode_GetAttrVal_AsBool);
-	MACRO_ATTRREAD_LOOPEND;
+void AMFImporter::ParseNode_Texture(XmlNode &node) {
+    std::string id = node.attribute("id").as_string();
+	uint32_t width = node.attribute("width").as_uint();
+	uint32_t height = node.attribute("height").as_uint();
+	uint32_t depth = node.attribute("depth").as_uint();
+	std::string type = node.attribute("type").as_string();
+	bool tiled = node.attribute("tiled").as_bool();
 
 	// create new texture object.
     CAMFImporter_NodeElement *ne = new CAMFImporter_NodeElement_Texture(mNodeElement_Cur);
@@ -209,7 +197,7 @@ void AMFImporter::ParseNode_Texture()
 	CAMFImporter_NodeElement_Texture& als = *((CAMFImporter_NodeElement_Texture*)ne);// alias for convenience
 
 	// Check for child nodes
-    if (!mReader->isEmptyElement()) {
+    if (!mXmlParser->isEmptyElement()) {
         XML_ReadNode_GetVal_AsString(enc64_data);
     }
 
@@ -268,10 +256,10 @@ void AMFImporter::ParseNode_TexMap(const bool pUseOldName) {
 
 	// Read attributes for node <color>.
 	MACRO_ATTRREAD_LOOPBEG;
-		MACRO_ATTRREAD_CHECK_RET("rtexid", rtexid, mReader->getAttributeValue);
-		MACRO_ATTRREAD_CHECK_RET("gtexid", gtexid, mReader->getAttributeValue);
-		MACRO_ATTRREAD_CHECK_RET("btexid", btexid, mReader->getAttributeValue);
-		MACRO_ATTRREAD_CHECK_RET("atexid", atexid, mReader->getAttributeValue);
+		MACRO_ATTRREAD_CHECK_RET("rtexid", rtexid, mXmlParser->getAttributeValue);
+		MACRO_ATTRREAD_CHECK_RET("gtexid", gtexid, mXmlParser->getAttributeValue);
+		MACRO_ATTRREAD_CHECK_RET("btexid", btexid, mXmlParser->getAttributeValue);
+		MACRO_ATTRREAD_CHECK_RET("atexid", atexid, mXmlParser->getAttributeValue);
 	MACRO_ATTRREAD_LOOPEND;
 
 	// create new texture coordinates object.

+ 11 - 16
code/Collada/ColladaParser.cpp

@@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
 
 Copyright (c) 2006-2020, assimp team
 
-
-
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -68,11 +66,8 @@ using namespace Assimp::Formatter;
 
 // ------------------------------------------------------------------------------------------------
 // Constructor to be privately used by Importer
-ColladaParser::ColladaParser(IOSystem* pIOHandler, const std::string& pFile)
-    : mFileName(pFile)
-    , mReader(nullptr)
-    , mDataLibrary()
-    , mAccessorLibrary()
+ColladaParser::ColladaParser(IOSystem* pIOHandler, const std::string& pFile) :
+		mFileName(pFile), mXmlParser(nullptr), mDataLibrary(), mAccessorLibrary()
     , mMeshLibrary()
     , mNodeLibrary()
     , mImageLibrary()
@@ -1532,7 +1527,7 @@ void ColladaParser::ReadLight(Collada::Light& pLight)
 
 // ------------------------------------------------------------------------------------------------
 // Reads a camera entry into the given light
-void ColladaParser::ReadCamera(Collada::Camera& pCamera)
+void ColladaParser::ReadCamera(Collada::Camera& camera)
 {
     while (mReader->read())
     {
@@ -1541,26 +1536,26 @@ void ColladaParser::ReadCamera(Collada::Camera& pCamera)
                 SkipElement();
             }
             else if (IsElement("orthographic")) {
-                pCamera.mOrtho = true;
+                camera.mOrtho = true;
             }
             else if (IsElement("xfov") || IsElement("xmag")) {
-                pCamera.mHorFov = ReadFloatFromTextContent();
-                TestClosing((pCamera.mOrtho ? "xmag" : "xfov"));
+                camera.mHorFov = ReadFloatFromTextContent();
+                TestClosing((camera.mOrtho ? "xmag" : "xfov"));
             }
             else if (IsElement("yfov") || IsElement("ymag")) {
-                pCamera.mVerFov = ReadFloatFromTextContent();
-                TestClosing((pCamera.mOrtho ? "ymag" : "yfov"));
+                camera.mVerFov = ReadFloatFromTextContent();
+                TestClosing((camera.mOrtho ? "ymag" : "yfov"));
             }
             else if (IsElement("aspect_ratio")) {
-                pCamera.mAspect = ReadFloatFromTextContent();
+                camera.mAspect = ReadFloatFromTextContent();
                 TestClosing("aspect_ratio");
             }
             else if (IsElement("znear")) {
-                pCamera.mZNear = ReadFloatFromTextContent();
+                camera.mZNear = ReadFloatFromTextContent();
                 TestClosing("znear");
             }
             else if (IsElement("zfar")) {
-                pCamera.mZFar = ReadFloatFromTextContent();
+                camera.mZFar = ReadFloatFromTextContent();
                 TestClosing("zfar");
             }
         }

+ 24 - 18
code/Collada/ColladaParser.h

@@ -4,7 +4,6 @@
 
  Copyright (c) 2006-2020, assimp team
 
-
  All rights reserved.
 
  Redistribution and use of this software in source and binary forms,
@@ -55,6 +54,7 @@
 namespace Assimp
 {
     class ZipArchiveIOSystem;
+    class XmlParser;
 
     // ------------------------------------------------------------------------------------------
     /** Parser helper class for the Collada loader.
@@ -112,7 +112,7 @@ namespace Assimp
         /** Reads an animation into the given parent structure */
         void ReadAnimation( Collada::Animation* pParent);
 
-        /** Reads an animation sampler into the given anim channel */
+        /** Reads an animation sampler into the given animation channel */
         void ReadAnimationSampler( Collada::AnimationChannel& pChannel);
 
         /** Reads the skeleton controller library */
@@ -157,16 +157,16 @@ namespace Assimp
         /** Reads an effect entry into the given effect*/
         void ReadEffect( Collada::Effect& pEffect);
 
-        /** Reads an COMMON effect profile */
+        /// Reads an COMMON effect profile
         void ReadEffectProfileCommon( Collada::Effect& pEffect);
 
-        /** Read sampler properties */
+        /// Read sampler properties
         void ReadSamplerProperties( Collada::Sampler& pSampler);
 
-        /** Reads an effect entry containing a color or a texture defining that color */
+        /// Reads an effect entry containing a color or a texture defining that color
         void ReadEffectColor( aiColor4D& pColor, Collada::Sampler& pSampler);
 
-        /** Reads an effect entry containing a float */
+        /// Reads an effect entry containing a float
         void ReadEffectFloat( ai_real& pFloat);
 
         /** Reads an effect parameter specification of any kind */
@@ -182,7 +182,7 @@ namespace Assimp
         void ReadMesh( Collada::Mesh* pMesh);
 
         /** Reads a source element - a combination of raw data and an accessor defining
-         * things that should not be redefinable. Yes, that's another rant.
+         * things that should not be re-definable. Yes, that's another rant.
          */
         void ReadSource();
 
@@ -214,7 +214,7 @@ namespace Assimp
                         Collada::Mesh* pMesh, std::vector<Collada::InputChannel>& pPerIndexChannels,
                         size_t currentPrimitive, const std::vector<size_t>& indices);
 
-        /** Reads one triangle of a tristrip into the mesh */
+        /** Reads one triangle of a triangle-strip into the mesh */
         void ReadPrimTriStrips(size_t numOffsets, size_t perVertexOffset, Collada::Mesh* pMesh,
                                std::vector<Collada::InputChannel>& pPerIndexChannels, size_t currentPrimitive, const std::vector<size_t>& indices);
 
@@ -298,7 +298,8 @@ namespace Assimp
         std::string mFileName;
 
         /** XML reader, member for everyday use */
-        irr::io::IrrXMLReader* mReader;
+        //irr::io::IrrXMLReader* mReader;
+		XmlParser *mXmlParser;
 
         /** All data arrays found in the file by ID. Might be referred to by actually
          everyone. Collada, you are a steaming pile of indirection. */
@@ -359,19 +360,24 @@ namespace Assimp
         /** Size unit: how large compared to a meter */
         ai_real mUnitSize;
 
-        /** Which is the up vector */
-        enum { UP_X, UP_Y, UP_Z } mUpDirection;
+        /// Which is the up vector.
+        enum {
+            UP_X,
+            UP_Y,
+            UP_Z
+        } mUpDirection;
 
-        /** Asset metadata (global for scene) */
+        /// Asset metadata (global for scene)
         StringMetaData mAssetMetaData;
 
-        /** Collada file format version */
+        /// Collada file format version
         Collada::FormatVersion mFormat;
     };
 
     // ------------------------------------------------------------------------------------------------
     // Check for element match
-    inline bool ColladaParser::IsElement( const char* pName) const
+    inline
+    bool ColladaParser::IsElement( const char* pName) const
     {
         ai_assert( mReader->getNodeType() == irr::io::EXN_ELEMENT);
         return ::strcmp( mReader->getNodeName(), pName) == 0;
@@ -380,11 +386,11 @@ namespace Assimp
     // ------------------------------------------------------------------------------------------------
     // Finds the item in the given library by its reference, throws if not found
     template <typename Type>
-    const Type& ColladaParser::ResolveLibraryReference( const std::map<std::string, Type>& pLibrary, const std::string& pURL) const
+    const Type& ColladaParser::ResolveLibraryReference( const std::map<std::string, Type>& library, const std::string& url) const
     {
-        typename std::map<std::string, Type>::const_iterator it = pLibrary.find( pURL);
-        if( it == pLibrary.end())
-            ThrowException( Formatter::format() << "Unable to resolve library reference \"" << pURL << "\"." );
+        typename std::map<std::string, Type>::const_iterator it = library.find( url);
+        if( it == library.end())
+            ThrowException( Formatter::format() << "Unable to resolve library reference \"" << url << "\"." );
         return it->second;
     }
 

+ 11 - 22
code/Irr/IRRLoader.h

@@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
 
 Copyright (c) 2006-2020, assimp team
 
-
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -40,7 +39,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ----------------------------------------------------------------------
 */
 
-
 /** @file IRRLoader.h
  *  @brief Declaration of the .irrMesh (Irrlight Engine Mesh Format)
  *  importer class.
@@ -83,7 +81,7 @@ protected:
 
 private:
 
-    /** Data structure for a scenegraph node animator
+    /** Data structure for a scene-graph node animator
      */
     struct Animator {
         // Type of the animator
@@ -129,7 +127,7 @@ private:
         int timeForWay;
     };
 
-    /** Data structure for a scenegraph node in an IRR file
+    /** Data structure for a scene-graph node in an IRR file
      */
     struct Node
     {
@@ -227,8 +225,7 @@ private:
 
 
     // -------------------------------------------------------------------
-    /** Fill the scenegraph recursively
-     */
+    /// Fill the scene-graph recursively
     void GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene,
         BatchLoader& batch,
         std::vector<aiMesh*>& meshes,
@@ -237,27 +234,22 @@ private:
         std::vector<aiMaterial*>& materials,
         unsigned int& defaultMatIdx);
 
-
     // -------------------------------------------------------------------
-    /** Generate a mesh that consists of just a single quad
-     */
+    /// Generate a mesh that consists of just a single quad
     aiMesh* BuildSingleQuadMesh(const SkyboxVertex& v1,
         const SkyboxVertex& v2,
         const SkyboxVertex& v3,
         const SkyboxVertex& v4);
 
-
     // -------------------------------------------------------------------
-    /** Build a skybox
-     *
-     *  @param meshes Receives 6 output meshes
-     *  @param materials The last 6 materials are assigned to the newly
-     *    created meshes. The names of the materials are adjusted.
-     */
+    /// Build a sky-box
+    ///
+    /// @param meshes Receives 6 output meshes
+    /// @param materials The last 6 materials are assigned to the newly
+    ///                  created meshes. The names of the materials are adjusted.
     void BuildSkybox(std::vector<aiMesh*>& meshes,
         std::vector<aiMaterial*> materials);
 
-
     // -------------------------------------------------------------------
     /** Copy a material for a mesh to the output material list
      *
@@ -271,7 +263,6 @@ private:
         unsigned int& defMatIdx,
         aiMesh* mesh);
 
-
     // -------------------------------------------------------------------
     /** Compute animations for a specific node
      *
@@ -281,13 +272,11 @@ private:
     void ComputeAnimations(Node* root, aiNode* real,
         std::vector<aiNodeAnim*>& anims);
 
-
 private:
-
-    /** Configuration option: desired output FPS */
+    /// Configuration option: desired output FPS 
     double fps;
 
-    /** Configuration option: speed flag was set? */
+    /// Configuration option: speed flag was set?
     bool configSpeedFlag;
 };
 

+ 38 - 45
code/X3D/X3DExporter.cpp

@@ -14,23 +14,14 @@
 #include <assimp/Exporter.hpp>
 #include <assimp/IOSystem.hpp>
 
-using namespace std;
+namespace Assimp {
 
-namespace Assimp
-{
-
-void ExportSceneX3D(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
-{
+void ExportSceneX3D(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties) {
 	X3DExporter exporter(pFile, pIOSystem, pScene, pProperties);
 }
 
-}// namespace Assimp
 
-namespace Assimp
-{
-
-void X3DExporter::IndentationStringSet(const size_t pNewLevel)
-{
+void X3DExporter::IndentationStringSet(const size_t pNewLevel) {
 	if(pNewLevel > mIndentationString.size())
 	{
 		if(pNewLevel > mIndentationString.capacity()) mIndentationString.reserve(pNewLevel + 1);
@@ -43,31 +34,33 @@ void X3DExporter::IndentationStringSet(const size_t pNewLevel)
 	}
 }
 
-void X3DExporter::XML_Write(const string& pData)
-{
-	if(pData.size() == 0) return;
-	if(mOutFile->Write((void*)pData.data(), pData.length(), 1) != 1) throw DeadlyExportError("Failed to write scene data!");
+void X3DExporter::XML_Write(const std::string& pData) {
+	if (pData.empty() ) {
+		return;
+	}
+
+	if (mOutFile->Write((void *)pData.data(), pData.length(), 1) != 1) {
+		throw DeadlyExportError("Failed to write scene data!");
+	}
 }
 
-aiMatrix4x4 X3DExporter::Matrix_GlobalToCurrent(const aiNode& pNode) const
-{
-aiNode* cur_node;
-std::list<aiMatrix4x4> matr;
-aiMatrix4x4 out_matr;
+aiMatrix4x4 X3DExporter::Matrix_GlobalToCurrent(const aiNode& pNode) const {
+	aiNode *cur_node;
+	std::list<aiMatrix4x4> matr;
+	aiMatrix4x4 out_matr;
 
 	// starting walk from current element to root
 	matr.push_back(pNode.mTransformation);
 	cur_node = pNode.mParent;
 	if(cur_node != nullptr)
 	{
-		do
-		{
+		do {
 			matr.push_back(cur_node->mTransformation);
 			cur_node = cur_node->mParent;
 		} while(cur_node != nullptr);
 	}
 
-	// multiplicate all matrices in reverse order
+	// Multiplication of all matrices in reverse order
 	for(std::list<aiMatrix4x4>::reverse_iterator rit = matr.rbegin(); rit != matr.rend(); ++rit) out_matr = out_matr * (*rit);
 
 	return out_matr;
@@ -142,7 +135,7 @@ void X3DExporter::AttrHelper_Col3DArrToString(const aiColor3D* pArray, const siz
 
 void X3DExporter::AttrHelper_Color3ToAttrList(std::list<SAttribute>& pList, const std::string& pName, const aiColor3D& pValue, const aiColor3D& pDefaultValue)
 {
-string tstr;
+    string tstr;
 
 	if(pValue == pDefaultValue) return;
 
@@ -152,7 +145,7 @@ string tstr;
 
 void X3DExporter::AttrHelper_FloatToAttrList(std::list<SAttribute>& pList, const string& pName, const float pValue, const float pDefaultValue)
 {
-string tstr;
+        string tstr;
 
 	if(pValue == pDefaultValue) return;
 
@@ -183,7 +176,7 @@ void X3DExporter::NodeHelper_OpenNode(const string& pNodeName, const size_t pTab
 
 void X3DExporter::NodeHelper_OpenNode(const string& pNodeName, const size_t pTabLevel, const bool pEmptyElement)
 {
-const list<SAttribute> attr_list;
+    const list<SAttribute> attr_list;
 
 	NodeHelper_OpenNode(pNodeName, pTabLevel, pEmptyElement, attr_list);
 }
@@ -199,8 +192,8 @@ void X3DExporter::NodeHelper_CloseNode(const string& pNodeName, const size_t pTa
 
 void X3DExporter::Export_Node(const aiNode *pNode, const size_t pTabLevel)
 {
-bool transform = false;
-list<SAttribute> attr_list;
+    bool transform = false;
+    list<SAttribute> attr_list;
 
 	// In Assimp lights is stored in next way: light source store in mScene->mLights and in node tree must present aiNode with name same as
 	// light source has. Considering it we must compare every aiNode name with light sources names. Why not to look where ligths is present
@@ -303,11 +296,11 @@ list<SAttribute> attr_list;
 
 void X3DExporter::Export_Mesh(const size_t pIdxMesh, const size_t pTabLevel)
 {
-const char* NodeName_IFS = "IndexedFaceSet";
-const char* NodeName_Shape = "Shape";
+    const char* NodeName_IFS = "IndexedFaceSet";
+    const char* NodeName_Shape = "Shape";
 
-list<SAttribute> attr_list;
-aiMesh& mesh = *mScene->mMeshes[pIdxMesh];// create alias for conveniance.
+    list<SAttribute> attr_list;
+    aiMesh& mesh = *mScene->mMeshes[pIdxMesh];// create alias for conveniance.
 
 	// Check if mesh already defined early.
 	if(mDEF_Map_Mesh.find(pIdxMesh) != mDEF_Map_Mesh.end())
@@ -407,10 +400,10 @@ aiMesh& mesh = *mScene->mMeshes[pIdxMesh];// create alias for conveniance.
 
 void X3DExporter::Export_Material(const size_t pIdxMaterial, const size_t pTabLevel)
 {
-const char* NodeName_A = "Appearance";
+    const char* NodeName_A = "Appearance";
 
-list<SAttribute> attr_list;
-aiMaterial& material = *mScene->mMaterials[pIdxMaterial];// create alias for conveniance.
+    list<SAttribute> attr_list;
+    aiMaterial& material = *mScene->mMaterials[pIdxMaterial];// create alias for conveniance.
 
 	// Check if material already defined early.
 	if(mDEF_Map_Material.find(pIdxMaterial) != mDEF_Map_Material.end())
@@ -564,7 +557,7 @@ aiMaterial& material = *mScene->mMaterials[pIdxMaterial];// create alias for con
 
 void X3DExporter::Export_MetadataBoolean(const aiString& pKey, const bool pValue, const size_t pTabLevel)
 {
-list<SAttribute> attr_list;
+    list<SAttribute> attr_list;
 
 	attr_list.push_back({"name", pKey.C_Str()});
 	attr_list.push_back({"value", pValue ? "true" : "false"});
@@ -573,7 +566,7 @@ list<SAttribute> attr_list;
 
 void X3DExporter::Export_MetadataDouble(const aiString& pKey, const double pValue, const size_t pTabLevel)
 {
-list<SAttribute> attr_list;
+    list<SAttribute> attr_list;
 
 	attr_list.push_back({"name", pKey.C_Str()});
 	attr_list.push_back({"value", to_string(pValue)});
@@ -582,7 +575,7 @@ list<SAttribute> attr_list;
 
 void X3DExporter::Export_MetadataFloat(const aiString& pKey, const float pValue, const size_t pTabLevel)
 {
-list<SAttribute> attr_list;
+    list<SAttribute> attr_list;
 
 	attr_list.push_back({"name", pKey.C_Str()});
 	attr_list.push_back({"value", to_string(pValue)});
@@ -591,7 +584,7 @@ list<SAttribute> attr_list;
 
 void X3DExporter::Export_MetadataInteger(const aiString& pKey, const int32_t pValue, const size_t pTabLevel)
 {
-list<SAttribute> attr_list;
+    list<SAttribute> attr_list;
 
 	attr_list.push_back({"name", pKey.C_Str()});
 	attr_list.push_back({"value", to_string(pValue)});
@@ -600,7 +593,7 @@ list<SAttribute> attr_list;
 
 void X3DExporter::Export_MetadataString(const aiString& pKey, const aiString& pValue, const size_t pTabLevel)
 {
-list<SAttribute> attr_list;
+    list<SAttribute> attr_list;
 
 	attr_list.push_back({"name", pKey.C_Str()});
 	attr_list.push_back({"value", pValue.C_Str()});
@@ -609,7 +602,7 @@ list<SAttribute> attr_list;
 
 bool X3DExporter::CheckAndExport_Light(const aiNode& pNode, const size_t pTabLevel)
 {
-list<SAttribute> attr_list;
+    list<SAttribute> attr_list;
 
 auto Vec3ToAttrList = [&](const string& pAttrName, const aiVector3D& pAttrValue, const aiVector3D& pAttrDefaultValue)
 {
@@ -622,8 +615,8 @@ auto Vec3ToAttrList = [&](const string& pAttrName, const aiVector3D& pAttrValue,
 	}
 };
 
-size_t idx_light;
-bool found = false;
+    size_t idx_light;
+    bool found = false;
 
 	// Name of the light source can not be empty.
 	if(pNode.mName.length == 0) return false;
@@ -699,7 +692,7 @@ bool found = false;
 X3DExporter::X3DExporter(const char* pFileName, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/)
 	: mScene(pScene)
 {
-list<SAttribute> attr_list;
+    list<SAttribute> attr_list;
 
 	mOutFile = pIOSystem->Open(pFileName, "wt");
 	if(mOutFile == nullptr) throw DeadlyExportError("Could not open output .x3d file: " + string(pFileName));

+ 2 - 0
code/X3D/X3DExporter.hpp

@@ -47,6 +47,8 @@ namespace Assimp
 ///
 class X3DExporter
 {
+    using AttrubuteList = std::list<SAttribute>;
+
 	/***********************************************/
 	/******************** Types ********************/
 	/***********************************************/

+ 633 - 750
code/XGL/XGLLoader.cpp

@@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
 
 Copyright (c) 2006-2020, assimp team
 
-
-
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -43,453 +41,387 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 /** @file Implementation of the XGL/ZGL importer class */
 
-
 #ifndef ASSIMP_BUILD_NO_XGL_IMPORTER
 
 #include "XGLLoader.h"
 #include <assimp/ParsingUtils.h>
 #include <assimp/fast_atof.h>
 
-#include <assimp/StreamReader.h>
 #include <assimp/MemoryIOWrapper.h>
+#include <assimp/StreamReader.h>
+#include <assimp/importerdesc.h>
 #include <assimp/mesh.h>
 #include <assimp/scene.h>
-#include <assimp/importerdesc.h>
 #include <cctype>
 #include <memory>
 
 using namespace Assimp;
-using namespace irr;
-using namespace irr::io;
+//using namespace irr;
+//using namespace irr::io;
 
 // zlib is needed for compressed XGL files
 #ifndef ASSIMP_BUILD_NO_COMPRESSED_XGL
-#   ifdef ASSIMP_BUILD_NO_OWN_ZLIB
-#       include <zlib.h>
-#   else
-#       include <contrib/zlib/zlib.h>
-#   endif
+#ifdef ASSIMP_BUILD_NO_OWN_ZLIB
+#include <zlib.h>
+#else
+#include <contrib/zlib/zlib.h>
+#endif
 #endif
-
 
 namespace Assimp { // this has to be in here because LogFunctions is in ::Assimp
-    template<> const char* LogFunctions<XGLImporter>::Prefix()
-    {
-        static auto prefix = "XGL: ";
-        return prefix;
-    }
+template <>
+const char *LogFunctions<XGLImporter>::Prefix() {
+	static auto prefix = "XGL: ";
+	return prefix;
 }
+} // namespace Assimp
 
 static const aiImporterDesc desc = {
-    "XGL Importer",
-    "",
-    "",
-    "",
-    aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportCompressedFlavour,
-    0,
-    0,
-    0,
-    0,
-    "xgl zgl"
+	"XGL Importer",
+	"",
+	"",
+	"",
+	aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportCompressedFlavour,
+	0,
+	0,
+	0,
+	0,
+	"xgl zgl"
 };
 
-
 // ------------------------------------------------------------------------------------------------
 // Constructor to be privately used by Importer
-XGLImporter::XGLImporter()
-: m_reader( nullptr )
-, m_scene( nullptr ) {
-    // empty
+XGLImporter::XGLImporter() :
+		m_xmlParser(nullptr), m_scene(nullptr) {
+	// empty
 }
 
 // ------------------------------------------------------------------------------------------------
 // Destructor, private as well
 XGLImporter::~XGLImporter() {
-    // empty
+	// empty
 }
 
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
-bool XGLImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
-{
-    /* NOTE: A simple check for the file extension is not enough
+bool XGLImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
+	/* NOTE: A simple check for the file extension is not enough
      * here. XGL and ZGL are ok, but xml is too generic
      * and might be collada as well. So open the file and
      * look for typical signal tokens.
      */
-    const std::string extension = GetExtension(pFile);
+	const std::string extension = GetExtension(pFile);
 
-    if (extension == "xgl" || extension == "zgl") {
-        return true;
-    }
-    else if (extension == "xml" || checkSig) {
-        ai_assert(pIOHandler != NULL);
+	if (extension == "xgl" || extension == "zgl") {
+		return true;
+	} else if (extension == "xml" || checkSig) {
+		ai_assert(pIOHandler != NULL);
 
-        const char* tokens[] = {"<world>","<World>","<WORLD>"};
-        return SearchFileHeaderForToken(pIOHandler,pFile,tokens,3);
-    }
-    return false;
+		const char *tokens[] = { "<world>", "<World>", "<WORLD>" };
+		return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 3);
+	}
+	return false;
 }
 
 // ------------------------------------------------------------------------------------------------
 // Get a list of all file extensions which are handled by this class
-const aiImporterDesc* XGLImporter::GetInfo () const
-{
-    return &desc;
+const aiImporterDesc *XGLImporter::GetInfo() const {
+	return &desc;
 }
 
 // ------------------------------------------------------------------------------------------------
 // Imports the given file into the given scene structure.
-void XGLImporter::InternReadFile( const std::string& pFile,
-    aiScene* pScene, IOSystem* pIOHandler)
-{
+void XGLImporter::InternReadFile(const std::string &pFile,
+		aiScene *pScene, IOSystem *pIOHandler) {
 #ifndef ASSIMP_BUILD_NO_COMPRESSED_XGL
-    std::vector<Bytef> uncompressed;
+	std::vector<Bytef> uncompressed;
 #endif
 
-    m_scene = pScene;
-    std::shared_ptr<IOStream> stream( pIOHandler->Open( pFile, "rb"));
+	m_scene = pScene;
+	std::shared_ptr<IOStream> stream(pIOHandler->Open(pFile, "rb"));
 
-    // check whether we can read from the file
-    if( stream.get() == NULL) {
-        throw DeadlyImportError( "Failed to open XGL/ZGL file " + pFile + "");
-    }
+	// check whether we can read from the file
+	if (stream.get() == NULL) {
+		throw DeadlyImportError("Failed to open XGL/ZGL file " + pFile + "");
+	}
 
-    // see if its compressed, if so uncompress it
-    if (GetExtension(pFile) == "zgl") {
+	// see if its compressed, if so uncompress it
+	if (GetExtension(pFile) == "zgl") {
 #ifdef ASSIMP_BUILD_NO_COMPRESSED_XGL
-        ThrowException("Cannot read ZGL file since Assimp was built without compression support");
+		ThrowException("Cannot read ZGL file since Assimp was built without compression support");
 #else
-        std::unique_ptr<StreamReaderLE> raw_reader(new StreamReaderLE(stream));
-
-        // build a zlib stream
-        z_stream zstream;
-        zstream.opaque = Z_NULL;
-        zstream.zalloc = Z_NULL;
-        zstream.zfree  = Z_NULL;
-        zstream.data_type = Z_BINARY;
-
-        // raw decompression without a zlib or gzip header
-        inflateInit2(&zstream, -MAX_WBITS);
-
-        // skip two extra bytes, zgl files do carry a crc16 upfront (I think)
-        raw_reader->IncPtr(2);
-
-        zstream.next_in   = reinterpret_cast<Bytef*>( raw_reader->GetPtr() );
-        zstream.avail_in  = raw_reader->GetRemainingSize();
-
-        size_t total = 0l;
-
-        // TODO: be smarter about this, decompress directly into heap buffer
-        // and decompress the data .... do 1k chunks in the hope that we won't kill the stack
-    #define MYBLOCK 1024
-        Bytef block[MYBLOCK];
-        int ret;
-        do {
-            zstream.avail_out = MYBLOCK;
-            zstream.next_out = block;
-            ret = inflate(&zstream, Z_NO_FLUSH);
-
-            if (ret != Z_STREAM_END && ret != Z_OK) {
-                ThrowException("Failure decompressing this file using gzip, seemingly it is NOT a compressed .XGL file");
-            }
-            const size_t have = MYBLOCK - zstream.avail_out;
-            total += have;
-            uncompressed.resize(total);
-            memcpy(uncompressed.data() + total - have,block,have);
-        }
-        while (ret != Z_STREAM_END);
-
-        // terminate zlib
-        inflateEnd(&zstream);
-
-        // replace the input stream with a memory stream
-        stream.reset(new MemoryIOStream(reinterpret_cast<uint8_t*>(uncompressed.data()),total));
+		std::unique_ptr<StreamReaderLE> raw_reader(new StreamReaderLE(stream));
+
+		// build a zlib stream
+		z_stream zstream;
+		zstream.opaque = Z_NULL;
+		zstream.zalloc = Z_NULL;
+		zstream.zfree = Z_NULL;
+		zstream.data_type = Z_BINARY;
+
+		// raw decompression without a zlib or gzip header
+		inflateInit2(&zstream, -MAX_WBITS);
+
+		// skip two extra bytes, zgl files do carry a crc16 upfront (I think)
+		raw_reader->IncPtr(2);
+
+		zstream.next_in = reinterpret_cast<Bytef *>(raw_reader->GetPtr());
+		zstream.avail_in = raw_reader->GetRemainingSize();
+
+		size_t total = 0l;
+
+		// TODO: be smarter about this, decompress directly into heap buffer
+		// and decompress the data .... do 1k chunks in the hope that we won't kill the stack
+#define MYBLOCK 1024
+		Bytef block[MYBLOCK];
+		int ret;
+		do {
+			zstream.avail_out = MYBLOCK;
+			zstream.next_out = block;
+			ret = inflate(&zstream, Z_NO_FLUSH);
+
+			if (ret != Z_STREAM_END && ret != Z_OK) {
+				ThrowException("Failure decompressing this file using gzip, seemingly it is NOT a compressed .XGL file");
+			}
+			const size_t have = MYBLOCK - zstream.avail_out;
+			total += have;
+			uncompressed.resize(total);
+			memcpy(uncompressed.data() + total - have, block, have);
+		} while (ret != Z_STREAM_END);
+
+		// terminate zlib
+		inflateEnd(&zstream);
+
+		// replace the input stream with a memory stream
+		stream.reset(new MemoryIOStream(reinterpret_cast<uint8_t *>(uncompressed.data()), total));
 #endif
-    }
-
-    // construct the irrXML parser
-    CIrrXML_IOStreamReader st(stream.get());
-    m_reader.reset( createIrrXMLReader( ( IFileReadCallBack* ) &st ) );
-
-    // parse the XML file
-    TempScope scope;
-
-    while (ReadElement())   {
+	}
+
+	// construct the irrXML parser
+	/*CIrrXML_IOStreamReader st(stream.get());
+    m_reader.reset( createIrrXMLReader( ( IFileReadCallBack* ) &st ) );*/
+	m_xmlParser = new XmlParser;
+	XmlNode *root = m_xmlParser->parse(stream.get());
+	if (nullptr == root) {
+		return;
+	}
+
+	// parse the XML file
+	TempScope scope;
+	if (!ASSIMP_stricmp(root->name(), "world")) {
+		ReadWorld(scope);
+	}
+
+	/*    while (ReadElement())   {
         if (!ASSIMP_stricmp(m_reader->getNodeName(),"world")) {
             ReadWorld(scope);
         }
-    }
-
-
-    std::vector<aiMesh*>& meshes = scope.meshes_linear;
-    std::vector<aiMaterial*>& materials = scope.materials_linear;
-    if(!meshes.size() || !materials.size()) {
-        ThrowException("failed to extract data from XGL file, no meshes loaded");
-    }
+    }*/
 
-    // copy meshes
-    m_scene->mNumMeshes = static_cast<unsigned int>(meshes.size());
-    m_scene->mMeshes = new aiMesh*[m_scene->mNumMeshes]();
-    std::copy(meshes.begin(),meshes.end(),m_scene->mMeshes);
+	std::vector<aiMesh *> &meshes = scope.meshes_linear;
+	std::vector<aiMaterial *> &materials = scope.materials_linear;
+	if (!meshes.size() || !materials.size()) {
+		ThrowException("failed to extract data from XGL file, no meshes loaded");
+	}
 
-    // copy materials
-    m_scene->mNumMaterials = static_cast<unsigned int>(materials.size());
-    m_scene->mMaterials = new aiMaterial*[m_scene->mNumMaterials]();
-    std::copy(materials.begin(),materials.end(),m_scene->mMaterials);
+	// copy meshes
+	m_scene->mNumMeshes = static_cast<unsigned int>(meshes.size());
+	m_scene->mMeshes = new aiMesh *[m_scene->mNumMeshes]();
+	std::copy(meshes.begin(), meshes.end(), m_scene->mMeshes);
 
-    if (scope.light) {
-        m_scene->mNumLights = 1;
-        m_scene->mLights = new aiLight*[1];
-        m_scene->mLights[0] = scope.light;
+	// copy materials
+	m_scene->mNumMaterials = static_cast<unsigned int>(materials.size());
+	m_scene->mMaterials = new aiMaterial *[m_scene->mNumMaterials]();
+	std::copy(materials.begin(), materials.end(), m_scene->mMaterials);
 
-        scope.light->mName = m_scene->mRootNode->mName;
-    }
+	if (scope.light) {
+		m_scene->mNumLights = 1;
+		m_scene->mLights = new aiLight *[1];
+		m_scene->mLights[0] = scope.light;
 
-    scope.dismiss();
-}
-
-// ------------------------------------------------------------------------------------------------
-bool XGLImporter::ReadElement()
-{
-    while(m_reader->read()) {
-        if (m_reader->getNodeType() == EXN_ELEMENT) {
-            return true;
-        }
-    }
-    return false;
-}
-
-// ------------------------------------------------------------------------------------------------
-bool XGLImporter::ReadElementUpToClosing(const char* closetag)
-{
-    while(m_reader->read()) {
-        if (m_reader->getNodeType() == EXN_ELEMENT) {
-            return true;
-        }
-        else if (m_reader->getNodeType() == EXN_ELEMENT_END && !ASSIMP_stricmp(m_reader->getNodeName(),closetag)) {
-            return false;
-        }
-    }
-    LogError("unexpected EOF, expected closing <" + std::string(closetag) + "> tag");
-    return false;
-}
+		scope.light->mName = m_scene->mRootNode->mName;
+	}
 
-// ------------------------------------------------------------------------------------------------
-bool XGLImporter::SkipToText()
-{
-    while(m_reader->read()) {
-        if (m_reader->getNodeType() == EXN_TEXT) {
-            return true;
-        }
-        else if (m_reader->getNodeType() == EXN_ELEMENT || m_reader->getNodeType() == EXN_ELEMENT_END) {
-            ThrowException("expected text contents but found another element (or element end)");
-        }
-    }
-    return false;
+	scope.dismiss();
 }
 
 // ------------------------------------------------------------------------------------------------
-std::string XGLImporter::GetElementName()
-{
-    const char* s  = m_reader->getNodeName();
-    size_t len = strlen(s);
-
-    std::string ret;
-    ret.resize(len);
-
-    std::transform(s,s+len,ret.begin(),::tolower);
-    return ret;
+void XGLImporter::ReadWorld(TempScope &scope) {
+	XmlNode *root = m_xmlParser->getRootNode();
+	for (XmlNode &node : root->children()) {
+		const std::string &s = node.name();
+		// XXX right now we'd skip <lighting> if it comes after
+		// <object> or <mesh>
+		if (s == "lighting") {
+			ReadLighting(node, scope);
+		} else if (s == "object" || s == "mesh" || s == "mat") {
+			break;
+		}
+	}
+
+	aiNode *const nd = ReadObject(*root, scope, true, "world");
+	if (!nd) {
+		ThrowException("failure reading <world>");
+	}
+	if (!nd->mName.length) {
+		nd->mName.Set("WORLD");
+	}
+
+	m_scene->mRootNode = nd;
 }
 
 // ------------------------------------------------------------------------------------------------
-void XGLImporter::ReadWorld(TempScope& scope)
-{
-    while (ReadElementUpToClosing("world")) {
-        const std::string& s = GetElementName();
-        // XXX right now we'd skip <lighting> if it comes after
-        // <object> or <mesh>
-        if (s == "lighting") {
-            ReadLighting(scope);
-        }
-        else if (s == "object" || s == "mesh" || s == "mat") {
-            break;
-        }
-    }
-
-
-    aiNode* const nd = ReadObject(scope,true,"world");
-    if(!nd) {
-        ThrowException("failure reading <world>");
-    }
-    if(!nd->mName.length) {
-        nd->mName.Set("WORLD");
-    }
-
-    m_scene->mRootNode = nd;
+void XGLImporter::ReadLighting(XmlNode &node, TempScope &scope) {
+	const std::string &s = node.name();
+	if (s == "directionallight") {
+		scope.light = ReadDirectionalLight(node);
+	} else if (s == "ambient") {
+		LogWarn("ignoring <ambient> tag");
+	} else if (s == "spheremap") {
+		LogWarn("ignoring <spheremap> tag");
+	}
 }
 
 // ------------------------------------------------------------------------------------------------
-void XGLImporter::ReadLighting(TempScope& scope)
-{
-    while (ReadElementUpToClosing("lighting"))  {
-        const std::string& s = GetElementName();
-        if (s == "directionallight") {
-            scope.light = ReadDirectionalLight();
-        }
-        else if (s == "ambient") {
-            LogWarn("ignoring <ambient> tag");
-        }
-        else if (s == "spheremap") {
-            LogWarn("ignoring <spheremap> tag");
-        }
-    }
+aiLight *XGLImporter::ReadDirectionalLight(XmlNode &node) {
+	std::unique_ptr<aiLight> l(new aiLight());
+	l->mType = aiLightSource_DIRECTIONAL;
+	find_node_by_name_predicate predicate("directionallight");
+	XmlNode child = node.find_child(predicate);
+	if (child.empty()) {
+		return nullptr;
+	}
+
+	const std::string &s = child.name();
+	if (s == "direction") {
+		l->mDirection = ReadVec3(child);
+	} else if (s == "diffuse") {
+		l->mColorDiffuse = ReadCol3(child);
+	} else if (s == "specular") {
+		l->mColorSpecular = ReadCol3(child);
+	}
+
+	return l.release();
 }
 
 // ------------------------------------------------------------------------------------------------
-aiLight* XGLImporter::ReadDirectionalLight()
-{
-    std::unique_ptr<aiLight> l(new aiLight());
-    l->mType = aiLightSource_DIRECTIONAL;
-
-    while (ReadElementUpToClosing("directionallight"))  {
-        const std::string& s = GetElementName();
-        if (s == "direction") {
-            l->mDirection = ReadVec3();
-        }
-        else if (s == "diffuse") {
-            l->mColorDiffuse = ReadCol3();
-        }
-        else if (s == "specular") {
-            l->mColorSpecular = ReadCol3();
-        }
-    }
-    return l.release();
+aiNode *XGLImporter::ReadObject(XmlNode &node, TempScope &scope, bool skipFirst, const char *closetag) {
+	aiNode *nd = new aiNode;
+	std::vector<aiNode *> children;
+	std::vector<unsigned int> meshes;
+
+	try {
+		for (XmlNode &child : node.children()) {
+
+			skipFirst = false;
+
+			const std::string &s = child.name();
+			if (s == "mesh") {
+				const size_t prev = scope.meshes_linear.size();
+				if (ReadMesh(child, scope)) {
+					const size_t newc = scope.meshes_linear.size();
+					for (size_t i = 0; i < newc - prev; ++i) {
+						meshes.push_back(static_cast<unsigned int>(i + prev));
+					}
+				}
+			} else if (s == "mat") {
+				ReadMaterial(child, scope);
+			} else if (s == "object") {
+				children.push_back(ReadObject(child, scope));
+			} else if (s == "objectref") {
+				// XXX
+			} else if (s == "meshref") {
+				const unsigned int id = static_cast<unsigned int>(ReadIndexFromText(child));
+
+				std::multimap<unsigned int, aiMesh *>::iterator it = scope.meshes.find(id), end = scope.meshes.end();
+				if (it == end) {
+					ThrowException("<meshref> index out of range");
+				}
+
+				for (; it != end && (*it).first == id; ++it) {
+					// ok, this is n^2 and should get optimized one day
+					aiMesh *const m = it->second;
+					unsigned int i = 0, mcount = static_cast<unsigned int>(scope.meshes_linear.size());
+					for (; i < mcount; ++i) {
+						if (scope.meshes_linear[i] == m) {
+							meshes.push_back(i);
+							break;
+						}
+					}
+
+					ai_assert(i < mcount);
+				}
+			} else if (s == "transform") {
+				nd->mTransformation = ReadTrafo(child);
+			}
+		}
+	} catch (...) {
+		for (aiNode *ch : children) {
+			delete ch;
+		}
+		throw;
+	}
+
+	// FIX: since we used std::multimap<> to keep meshes by id, mesh order now depends on the behaviour
+	// of the multimap implementation with respect to the ordering of entries with same values.
+	// C++11 gives the guarantee that it uses insertion order, before it is implementation-specific.
+	// Sort by material id to always guarantee a deterministic result.
+	std::sort(meshes.begin(), meshes.end(), SortMeshByMaterialId(scope));
+
+	// link meshes to node
+	nd->mNumMeshes = static_cast<unsigned int>(meshes.size());
+	if (0 != nd->mNumMeshes) {
+		nd->mMeshes = new unsigned int[nd->mNumMeshes]();
+		for (unsigned int i = 0; i < nd->mNumMeshes; ++i) {
+			nd->mMeshes[i] = meshes[i];
+		}
+	}
+
+	// link children to parent
+	nd->mNumChildren = static_cast<unsigned int>(children.size());
+	if (nd->mNumChildren) {
+		nd->mChildren = new aiNode *[nd->mNumChildren]();
+		for (unsigned int i = 0; i < nd->mNumChildren; ++i) {
+			nd->mChildren[i] = children[i];
+			children[i]->mParent = nd;
+		}
+	}
+
+	return nd;
 }
 
 // ------------------------------------------------------------------------------------------------
-aiNode* XGLImporter::ReadObject(TempScope& scope, bool skipFirst, const char* closetag)
-{
-    aiNode *nd = new aiNode;
-    std::vector<aiNode*> children;
-    std::vector<unsigned int> meshes;
-
-    try {
-        while (skipFirst || ReadElementUpToClosing(closetag))   {
-            skipFirst = false;
-
-            const std::string& s = GetElementName();
-            if (s == "mesh") {
-                const size_t prev = scope.meshes_linear.size();
-                if(ReadMesh(scope)) {
-                    const size_t newc = scope.meshes_linear.size();
-                    for(size_t i = 0; i < newc-prev; ++i) {
-                        meshes.push_back(static_cast<unsigned int>(i+prev));
-                    }
-                }
-            }
-            else if (s == "mat") {
-                ReadMaterial(scope);
-            }
-            else if (s == "object") {
-                children.push_back(ReadObject(scope));
-            }
-            else if (s == "objectref") {
-                // XXX
-            }
-            else if (s == "meshref") {
-                const unsigned int id = static_cast<unsigned int>( ReadIndexFromText() );
-
-                std::multimap<unsigned int, aiMesh*>::iterator it = scope.meshes.find(id), end = scope.meshes.end();
-                if (it == end) {
-                    ThrowException("<meshref> index out of range");
-                }
-
-                for(; it != end && (*it).first == id; ++it) {
-                    // ok, this is n^2 and should get optimized one day
-                    aiMesh* const m = (*it).second;
-
-                    unsigned int i = 0, mcount = static_cast<unsigned int>(scope.meshes_linear.size());
-                    for(; i < mcount; ++i) {
-                        if (scope.meshes_linear[i] == m) {
-                            meshes.push_back(i);
-                            break;
-                        }
-                    }
-
-                    ai_assert(i < mcount);
-                }
-            }
-            else if (s == "transform") {
-                nd->mTransformation = ReadTrafo();
-            }
-        }
-
-    } catch(...) {
-        for(aiNode* ch : children) {
-            delete ch;
-        }
-        throw;
-    }
-
-    // FIX: since we used std::multimap<> to keep meshes by id, mesh order now depends on the behaviour
-    // of the multimap implementation with respect to the ordering of entries with same values.
-    // C++11 gives the guarantee that it uses insertion order, before it is implementation-specific.
-    // Sort by material id to always guarantee a deterministic result.
-    std::sort(meshes.begin(), meshes.end(), SortMeshByMaterialId(scope));
-
-    // link meshes to node
-    nd->mNumMeshes = static_cast<unsigned int>(meshes.size());
-    if (nd->mNumMeshes) {
-        nd->mMeshes = new unsigned int[nd->mNumMeshes]();
-        for(unsigned int i = 0; i < nd->mNumMeshes; ++i) {
-            nd->mMeshes[i] = meshes[i];
-        }
-    }
-
-    // link children to parent
-    nd->mNumChildren = static_cast<unsigned int>(children.size());
-    if (nd->mNumChildren) {
-        nd->mChildren = new aiNode*[nd->mNumChildren]();
-        for(unsigned int i = 0; i < nd->mNumChildren; ++i) {
-            nd->mChildren[i] = children[i];
-            children[i]->mParent = nd;
-        }
-    }
-
-    return nd;
-}
-
-// ------------------------------------------------------------------------------------------------
-aiMatrix4x4 XGLImporter::ReadTrafo()
-{
-    aiVector3D forward, up, right, position;
-    float scale = 1.0f;
-
-    while (ReadElementUpToClosing("transform")) {
-        const std::string& s = GetElementName();
-        if (s == "forward") {
-            forward = ReadVec3();
-        }
-        else if (s == "up") {
-            up = ReadVec3();
-        }
-        else if (s == "position") {
-            position = ReadVec3();
-        }
-        if (s == "scale") {
-            scale = ReadFloat();
-            if(scale < 0.f) {
-                // this is wrong, but we can leave the value and pass it to the caller
-                LogError("found negative scaling in <transform>, ignoring");
-            }
-        }
-    }
-
-    aiMatrix4x4 m;
-    if(forward.SquareLength() < 1e-4 || up.SquareLength() < 1e-4) {
-        LogError("A direction vector in <transform> is zero, ignoring trafo");
-        return m;
+aiMatrix4x4 XGLImporter::ReadTrafo(XmlNode &node) {
+	aiVector3D forward, up, right, position;
+	float scale = 1.0f;
+
+	aiMatrix4x4 m;
+	XmlNode child = node.child("transform");
+	if (child.empty()) {
+		return m;
+	}
+
+	for (XmlNode &sub_child : child.children()) {
+		const std::string &s = sub_child.name();
+		if (s == "forward") {
+			forward = ReadVec3(sub_child);
+		} else if (s == "up") {
+			up = ReadVec3(sub_child);
+		} else if (s == "position") {
+			position = ReadVec3(sub_child);
+		}
+		if (s == "scale") {
+			scale = ReadFloat(sub_child);
+			if (scale < 0.f) {
+				// this is wrong, but we can leave the value and pass it to the caller
+				LogError("found negative scaling in <transform>, ignoring");
+			}
+		}
+	}
+
+    if (forward.SquareLength() < 1e-4 || up.SquareLength() < 1e-4) {
+	    LogError("A direction vector in <transform> is zero, ignoring trafo");
+	    return m;
     }
 
     forward.Normalize();
@@ -497,10 +429,10 @@ aiMatrix4x4 XGLImporter::ReadTrafo()
 
     right = forward ^ up;
     if (std::fabs(up * forward) > 1e-4) {
-        // this is definitely wrong - a degenerate coordinate space ruins everything
-        // so substitute identity transform.
-        LogError("<forward> and <up> vectors in <transform> are skewing, ignoring trafo");
-        return m;
+	    // this is definitely wrong - a degenerate coordinate space ruins everything
+	    // so substitute identity transform.
+	    LogError("<forward> and <up> vectors in <transform> are skewing, ignoring trafo");
+	    return m;
     }
 
     right *= scale;
@@ -523,434 +455,385 @@ aiMatrix4x4 XGLImporter::ReadTrafo()
     m.b4 = position.y;
     m.c4 = position.z;
 
-    return m;
+	return m;
 }
 
 // ------------------------------------------------------------------------------------------------
-aiMesh* XGLImporter::ToOutputMesh(const TempMaterialMesh& m)
-{
-    std::unique_ptr<aiMesh> mesh(new aiMesh());
+aiMesh *XGLImporter::ToOutputMesh(const TempMaterialMesh &m) {
+	std::unique_ptr<aiMesh> mesh(new aiMesh());
 
-    mesh->mNumVertices = static_cast<unsigned int>(m.positions.size());
-    mesh->mVertices = new aiVector3D[mesh->mNumVertices];
-    std::copy(m.positions.begin(),m.positions.end(),mesh->mVertices);
+	mesh->mNumVertices = static_cast<unsigned int>(m.positions.size());
+	mesh->mVertices = new aiVector3D[mesh->mNumVertices];
+	std::copy(m.positions.begin(), m.positions.end(), mesh->mVertices);
 
-    if(m.normals.size()) {
-        mesh->mNormals = new aiVector3D[mesh->mNumVertices];
-        std::copy(m.normals.begin(),m.normals.end(),mesh->mNormals);
-    }
+	if (m.normals.size()) {
+		mesh->mNormals = new aiVector3D[mesh->mNumVertices];
+		std::copy(m.normals.begin(), m.normals.end(), mesh->mNormals);
+	}
 
-    if(m.uvs.size()) {
-        mesh->mNumUVComponents[0] = 2;
-        mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices];
+	if (m.uvs.size()) {
+		mesh->mNumUVComponents[0] = 2;
+		mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices];
 
-        for(unsigned int i = 0; i < mesh->mNumVertices; ++i) {
-            mesh->mTextureCoords[0][i] = aiVector3D(m.uvs[i].x,m.uvs[i].y,0.f);
-        }
-    }
+		for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
+			mesh->mTextureCoords[0][i] = aiVector3D(m.uvs[i].x, m.uvs[i].y, 0.f);
+		}
+	}
 
-    mesh->mNumFaces =  static_cast<unsigned int>(m.vcounts.size());
-    mesh->mFaces = new aiFace[m.vcounts.size()];
+	mesh->mNumFaces = static_cast<unsigned int>(m.vcounts.size());
+	mesh->mFaces = new aiFace[m.vcounts.size()];
 
-    unsigned int idx = 0;
-    for(unsigned int i = 0; i < mesh->mNumFaces; ++i) {
-        aiFace& f = mesh->mFaces[i];
-        f.mNumIndices = m.vcounts[i];
-        f.mIndices = new unsigned int[f.mNumIndices];
-        for(unsigned int c = 0; c < f.mNumIndices; ++c) {
-            f.mIndices[c] = idx++;
-        }
-    }
+	unsigned int idx = 0;
+	for (unsigned int i = 0; i < mesh->mNumFaces; ++i) {
+		aiFace &f = mesh->mFaces[i];
+		f.mNumIndices = m.vcounts[i];
+		f.mIndices = new unsigned int[f.mNumIndices];
+		for (unsigned int c = 0; c < f.mNumIndices; ++c) {
+			f.mIndices[c] = idx++;
+		}
+	}
 
-    ai_assert(idx == mesh->mNumVertices);
+	ai_assert(idx == mesh->mNumVertices);
+
+	mesh->mPrimitiveTypes = m.pflags;
+	mesh->mMaterialIndex = m.matid;
 
-    mesh->mPrimitiveTypes = m.pflags;
-    mesh->mMaterialIndex = m.matid;
     return mesh.release();
 }
 
 // ------------------------------------------------------------------------------------------------
-bool XGLImporter::ReadMesh(TempScope& scope)
-{
-    TempMesh t;
-
-    std::map<unsigned int, TempMaterialMesh> bymat;
-    const unsigned int mesh_id = ReadIDAttr();
-
-    while (ReadElementUpToClosing("mesh"))  {
-        const std::string& s = GetElementName();
-
-        if (s == "mat") {
-            ReadMaterial(scope);
-        }
-        else if (s == "p") {
-            if (!m_reader->getAttributeValue("ID")) {
-                LogWarn("no ID attribute on <p>, ignoring");
-            }
-            else {
-                int id = m_reader->getAttributeValueAsInt("ID");
-                t.points[id] = ReadVec3();
-            }
-        }
-        else if (s == "n") {
-            if (!m_reader->getAttributeValue("ID")) {
-                LogWarn("no ID attribute on <n>, ignoring");
-            }
-            else {
-                int id = m_reader->getAttributeValueAsInt("ID");
-                t.normals[id] = ReadVec3();
-            }
-        }
-        else if (s == "tc") {
-            if (!m_reader->getAttributeValue("ID")) {
-                LogWarn("no ID attribute on <tc>, ignoring");
-            }
-            else {
-                int id = m_reader->getAttributeValueAsInt("ID");
-                t.uvs[id] = ReadVec2();
-            }
-        }
-        else if (s == "f" || s == "l" || s == "p") {
-            const unsigned int vcount = s == "f" ? 3 : (s == "l" ? 2 : 1);
-
-            unsigned int mid = ~0u;
-            TempFace tf[3];
-            bool has[3] = {0};
-
-            while (ReadElementUpToClosing(s.c_str()))   {
-                const std::string& s = GetElementName();
-                if (s == "fv1" || s == "lv1" || s == "pv1") {
-                    ReadFaceVertex(t,tf[0]);
-                    has[0] = true;
-                }
-                else if (s == "fv2" || s == "lv2") {
-                    ReadFaceVertex(t,tf[1]);
-                    has[1] = true;
-                }
-                else if (s == "fv3") {
-                    ReadFaceVertex(t,tf[2]);
-                    has[2] = true;
-                }
-                else if (s == "mat") {
-                    if (mid != ~0u) {
-                        LogWarn("only one material tag allowed per <f>");
-                    }
-                    mid = ResolveMaterialRef(scope);
-                }
-                else if (s == "matref") {
-                    if (mid != ~0u) {
-                        LogWarn("only one material tag allowed per <f>");
-                    }
-                    mid = ResolveMaterialRef(scope);
-                }
-            }
-
-            if (mid == ~0u) {
-                ThrowException("missing material index");
-            }
-
-            bool nor = false;
-            bool uv = false;
-            for(unsigned int i = 0; i < vcount; ++i) {
-                if (!has[i]) {
-                    ThrowException("missing face vertex data");
-                }
-
-                nor = nor || tf[i].has_normal;
-                uv = uv || tf[i].has_uv;
-            }
-
-            if (mid >= (1<<30)) {
-                LogWarn("material indices exhausted, this may cause errors in the output");
-            }
-            unsigned int meshId = mid | ((nor?1:0)<<31) | ((uv?1:0)<<30);
-
-            TempMaterialMesh& mesh = bymat[meshId];
-            mesh.matid = mid;
-
-            for(unsigned int i = 0; i < vcount; ++i) {
-                mesh.positions.push_back(tf[i].pos);
-                if(nor) {
-                    mesh.normals.push_back(tf[i].normal);
-                }
-                if(uv) {
-                    mesh.uvs.push_back(tf[i].uv);
-                }
-
-                mesh.pflags |= 1 << (vcount-1);
-            }
-
-            mesh.vcounts.push_back(vcount);
-        }
-    }
-
-    // finally extract output meshes and add them to the scope
-    typedef std::pair<unsigned int, TempMaterialMesh> pairt;
-    for(const pairt& p : bymat) {
-        aiMesh* const m  = ToOutputMesh(p.second);
-        scope.meshes_linear.push_back(m);
-
-        // if this is a definition, keep it on the stack
-        if(mesh_id != ~0u) {
-            scope.meshes.insert(std::pair<unsigned int, aiMesh*>(mesh_id,m));
-        }
-    }
-
-    // no id == not a reference, insert this mesh right *here*
-    return mesh_id == ~0u;
+bool XGLImporter::ReadMesh(XmlNode &node, TempScope &scope) {
+	TempMesh t;
+
+	std::map<unsigned int, TempMaterialMesh> bymat;
+	const unsigned int mesh_id = ReadIDAttr(node);
+
+	for (XmlNode &child : node.children()) {
+		const std::string &s = child.name();
+
+		if (s == "mat") {
+			ReadMaterial(child, scope);
+		} else if (s == "p") {
+			pugi::xml_attribute attr = child.attribute("ID");
+			if (attr.empty()) {
+				LogWarn("no ID attribute on <p>, ignoring");
+			} else {
+				int id = attr.as_int();
+				t.points[id] = ReadVec3(child);
+			}
+		} else if (s == "n") {
+			pugi::xml_attribute attr = child.attribute("ID");
+			if (attr.empty()) {
+				LogWarn("no ID attribute on <n>, ignoring");
+			} else {
+				int id = attr.as_int();
+				t.normals[id] = ReadVec3(child);
+			}
+		} else if (s == "tc") {
+			pugi::xml_attribute attr = child.attribute("ID");
+			if (attr.empty()) {
+				LogWarn("no ID attribute on <tc>, ignoring");
+			} else {
+				int id = attr.as_int();
+				t.uvs[id] = ReadVec2(child);
+			}
+		} else if (s == "f" || s == "l" || s == "p") {
+			const unsigned int vcount = s == "f" ? 3 : (s == "l" ? 2 : 1);
+
+			unsigned int mid = ~0u;
+			TempFace tf[3];
+			bool has[3] = { false };
+			for (XmlNode &sub_child : child.children()) {
+				const std::string &s = sub_child.name();
+				if (s == "fv1" || s == "lv1" || s == "pv1") {
+					ReadFaceVertex(sub_child, t, tf[0]);
+					has[0] = true;
+				} else if (s == "fv2" || s == "lv2") {
+					ReadFaceVertex(sub_child, t, tf[1]);
+					has[1] = true;
+				} else if (s == "fv3") {
+					ReadFaceVertex(sub_child, t, tf[2]);
+					has[2] = true;
+				} else if (s == "mat") {
+					if (mid != ~0u) {
+						LogWarn("only one material tag allowed per <f>");
+					}
+					mid = ResolveMaterialRef(sub_child, scope);
+				} else if (s == "matref") {
+					if (mid != ~0u) {
+						LogWarn("only one material tag allowed per <f>");
+					}
+					mid = ResolveMaterialRef(sub_child, scope);
+				}
+			}
+
+			if (mid == ~0u) {
+				ThrowException("missing material index");
+			}
+
+			bool nor = false;
+			bool uv = false;
+			for (unsigned int i = 0; i < vcount; ++i) {
+				if (!has[i]) {
+					ThrowException("missing face vertex data");
+				}
+
+				nor = nor || tf[i].has_normal;
+				uv = uv || tf[i].has_uv;
+			}
+
+			if (mid >= (1 << 30)) {
+				LogWarn("material indices exhausted, this may cause errors in the output");
+			}
+			unsigned int meshId = mid | ((nor ? 1 : 0) << 31) | ((uv ? 1 : 0) << 30);
+
+			TempMaterialMesh &mesh = bymat[meshId];
+			mesh.matid = mid;
+
+			for (unsigned int i = 0; i < vcount; ++i) {
+				mesh.positions.push_back(tf[i].pos);
+				if (nor) {
+					mesh.normals.push_back(tf[i].normal);
+				}
+				if (uv) {
+					mesh.uvs.push_back(tf[i].uv);
+				}
+
+				mesh.pflags |= 1 << (vcount - 1);
+			}
+
+			mesh.vcounts.push_back(vcount);
+		}
+	}
+
+	// finally extract output meshes and add them to the scope
+	typedef std::pair<unsigned int, TempMaterialMesh> pairt;
+	for (const pairt &p : bymat) {
+		aiMesh *const m = ToOutputMesh(p.second);
+		scope.meshes_linear.push_back(m);
+
+		// if this is a definition, keep it on the stack
+		if (mesh_id != ~0u) {
+			scope.meshes.insert(std::pair<unsigned int, aiMesh *>(mesh_id, m));
+		}
+	}
+
+	// no id == not a reference, insert this mesh right *here*
+	return mesh_id == ~0u;
 }
 
 // ----------------------------------------------------------------------------------------------
-unsigned int XGLImporter::ResolveMaterialRef(TempScope& scope)
-{
-    const std::string& s = GetElementName();
-    if (s == "mat") {
-        ReadMaterial(scope);
-        return static_cast<unsigned int>(scope.materials_linear.size()-1);
-    }
+unsigned int XGLImporter::ResolveMaterialRef(XmlNode &node, TempScope &scope) {
+	const std::string &s = node.name();
+	if (s == "mat") {
+		ReadMaterial(node, scope);
+		return static_cast<unsigned int>(scope.materials_linear.size() - 1);
+	}
 
-    const int id = ReadIndexFromText();
+	const int id = ReadIndexFromText(node);
 
-    std::map<unsigned int, aiMaterial*>::iterator it = scope.materials.find(id), end = scope.materials.end();
-    if (it == end) {
-        ThrowException("<matref> index out of range");
-    }
+	std::map<unsigned int, aiMaterial *>::iterator it = scope.materials.find(id), end = scope.materials.end();
+	if (it == end) {
+		ThrowException("<matref> index out of range");
+	}
 
-    // ok, this is n^2 and should get optimized one day
-    aiMaterial* const m = (*it).second;
+	// ok, this is n^2 and should get optimized one day
+	aiMaterial *const m = (*it).second;
 
-    unsigned int i = 0, mcount = static_cast<unsigned int>(scope.materials_linear.size());
-    for(; i < mcount; ++i) {
-        if (scope.materials_linear[i] == m) {
-            return i;
-        }
-    }
+	unsigned int i = 0, mcount = static_cast<unsigned int>(scope.materials_linear.size());
+	for (; i < mcount; ++i) {
+		if (scope.materials_linear[i] == m) {
+			return i;
+		}
+	}
+
+	ai_assert(false);
 
-    ai_assert(false);
-    return 0;
+	return 0;
 }
 
 // ------------------------------------------------------------------------------------------------
-void XGLImporter::ReadMaterial(TempScope& scope) {
-    const unsigned int mat_id = ReadIDAttr();
-
-    aiMaterial *mat(new aiMaterial );
-    while (ReadElementUpToClosing("mat"))  {
-        const std::string& s = GetElementName();
-        if (s == "amb") {
-            const aiColor3D c = ReadCol3();
-            mat->AddProperty(&c,1,AI_MATKEY_COLOR_AMBIENT);
-        }
-        else if (s == "diff") {
-            const aiColor3D c = ReadCol3();
-            mat->AddProperty(&c,1,AI_MATKEY_COLOR_DIFFUSE);
-        }
-        else if (s == "spec") {
-            const aiColor3D c = ReadCol3();
-            mat->AddProperty(&c,1,AI_MATKEY_COLOR_SPECULAR);
-        }
-        else if (s == "emiss") {
-            const aiColor3D c = ReadCol3();
-            mat->AddProperty(&c,1,AI_MATKEY_COLOR_EMISSIVE);
-        }
-        else if (s == "alpha") {
-            const float f = ReadFloat();
-            mat->AddProperty(&f,1,AI_MATKEY_OPACITY);
-        }
-        else if (s == "shine") {
-            const float f = ReadFloat();
-            mat->AddProperty(&f,1,AI_MATKEY_SHININESS);
-        }
-    }
-
-    scope.materials[mat_id] = mat;
-    scope.materials_linear.push_back(mat);
+void XGLImporter::ReadMaterial(XmlNode &node, TempScope &scope) {
+	const unsigned int mat_id = ReadIDAttr(node);
+
+	aiMaterial *mat(new aiMaterial);
+	for (XmlNode &child : node.children()) {
+		const std::string &s = child.name();
+		if (s == "amb") {
+			const aiColor3D c = ReadCol3(child);
+			mat->AddProperty(&c, 1, AI_MATKEY_COLOR_AMBIENT);
+		} else if (s == "diff") {
+			const aiColor3D c = ReadCol3(child);
+			mat->AddProperty(&c, 1, AI_MATKEY_COLOR_DIFFUSE);
+		} else if (s == "spec") {
+			const aiColor3D c = ReadCol3(child);
+			mat->AddProperty(&c, 1, AI_MATKEY_COLOR_SPECULAR);
+		} else if (s == "emiss") {
+			const aiColor3D c = ReadCol3(child);
+			mat->AddProperty(&c, 1, AI_MATKEY_COLOR_EMISSIVE);
+		} else if (s == "alpha") {
+			const float f = ReadFloat(child);
+			mat->AddProperty(&f, 1, AI_MATKEY_OPACITY);
+		} else if (s == "shine") {
+			const float f = ReadFloat(child);
+			mat->AddProperty(&f, 1, AI_MATKEY_SHININESS);
+		}
+	}
+
+	scope.materials[mat_id] = mat;
+	scope.materials_linear.push_back(mat);
 }
 
 // ----------------------------------------------------------------------------------------------
-void XGLImporter::ReadFaceVertex(const TempMesh& t, TempFace& out)
-{
-    const std::string& end = GetElementName();
-
-    bool havep = false;
-    while (ReadElementUpToClosing(end.c_str()))  {
-        const std::string& s = GetElementName();
-        if (s == "pref") {
-            const unsigned int id = ReadIndexFromText();
-            std::map<unsigned int, aiVector3D>::const_iterator it = t.points.find(id);
-            if (it == t.points.end()) {
-                ThrowException("point index out of range");
-            }
-
-            out.pos = (*it).second;
-            havep = true;
-        }
-        else if (s == "nref") {
-            const unsigned int id = ReadIndexFromText();
-            std::map<unsigned int, aiVector3D>::const_iterator it = t.normals.find(id);
-            if (it == t.normals.end()) {
-                ThrowException("normal index out of range");
-            }
-
-            out.normal = (*it).second;
-            out.has_normal = true;
-        }
-        else if (s == "tcref") {
-            const unsigned int id = ReadIndexFromText();
-            std::map<unsigned int, aiVector2D>::const_iterator it = t.uvs.find(id);
-            if (it == t.uvs.end()) {
-                ThrowException("uv index out of range");
-            }
-
-            out.uv = (*it).second;
-            out.has_uv = true;
-        }
-        else if (s == "p") {
-            out.pos = ReadVec3();
-        }
-        else if (s == "n") {
-            out.normal = ReadVec3();
-        }
-        else if (s == "tc") {
-            out.uv = ReadVec2();
-        }
-    }
-
-    if (!havep) {
-        ThrowException("missing <pref> in <fvN> element");
-    }
+void XGLImporter::ReadFaceVertex(XmlNode &node, const TempMesh &t, TempFace &out) {
+	const std::string &end = node.name();
+
+	bool havep = false;
+	//while (ReadElementUpToClosing(end.c_str()))  {
+	for (XmlNode &child : node.children()) {
+		const std::string &s = child.name();
+		if (s == "pref") {
+			const unsigned int id = ReadIndexFromText(child);
+			std::map<unsigned int, aiVector3D>::const_iterator it = t.points.find(id);
+			if (it == t.points.end()) {
+				ThrowException("point index out of range");
+			}
+
+			out.pos = (*it).second;
+			havep = true;
+		} else if (s == "nref") {
+			const unsigned int id = ReadIndexFromText(child);
+			std::map<unsigned int, aiVector3D>::const_iterator it = t.normals.find(id);
+			if (it == t.normals.end()) {
+				ThrowException("normal index out of range");
+			}
+
+			out.normal = (*it).second;
+			out.has_normal = true;
+		} else if (s == "tcref") {
+			const unsigned int id = ReadIndexFromText(child);
+			std::map<unsigned int, aiVector2D>::const_iterator it = t.uvs.find(id);
+			if (it == t.uvs.end()) {
+				ThrowException("uv index out of range");
+			}
+
+			out.uv = (*it).second;
+			out.has_uv = true;
+		} else if (s == "p") {
+			out.pos = ReadVec3(child);
+		} else if (s == "n") {
+			out.normal = ReadVec3(child);
+		} else if (s == "tc") {
+			out.uv = ReadVec2(child);
+		}
+	}
+
+	if (!havep) {
+		ThrowException("missing <pref> in <fvN> element");
+	}
 }
 
 // ------------------------------------------------------------------------------------------------
-unsigned int XGLImporter::ReadIDAttr()
-{
-    for(int i = 0, e = m_reader->getAttributeCount(); i < e; ++i) {
-
-        if(!ASSIMP_stricmp(m_reader->getAttributeName(i),"id")) {
-            return m_reader->getAttributeValueAsInt(i);
-        }
-    }
-    return ~0u;
+unsigned int XGLImporter::ReadIDAttr(XmlNode &node) {
+	for (pugi::xml_attribute attr : node.attributes()) {
+		if (!ASSIMP_stricmp(attr.name(), "id")) {
+			return attr.as_int();
+		}
+	}
+
+	return ~0u;
 }
 
 // ------------------------------------------------------------------------------------------------
-float XGLImporter::ReadFloat()
-{
-    if(!SkipToText()) {
-        LogError("unexpected EOF reading float element contents");
-        return 0.f;
-    }
-    const char* s = m_reader->getNodeData(), *se;
-
-    if(!SkipSpaces(&s)) {
-        LogError("unexpected EOL, failed to parse float");
-        return 0.f;
-    }
-
-    float t;
-    se = fast_atoreal_move(s,t);
-
-    if (se == s) {
-        LogError("failed to read float text");
-        return 0.f;
-    }
-
-    return t;
+float XGLImporter::ReadFloat(XmlNode &node) {
+	const char *s = node.value(), *se;
+	if (!SkipSpaces(&s)) {
+		LogError("unexpected EOL, failed to parse index element");
+		return 0.f;
+	}
+	float t;
+	se = fast_atoreal_move(s, t);
+	if (se == s) {
+		LogError("failed to read float text");
+		return 0.f;
+	}
+
+	return t;
 }
 
 // ------------------------------------------------------------------------------------------------
-unsigned int XGLImporter::ReadIndexFromText()
-{
-    if(!SkipToText()) {
-        LogError("unexpected EOF reading index element contents");
-        return ~0u;
-    }
-    const char* s = m_reader->getNodeData(), *se;
-    if(!SkipSpaces(&s)) {
-        LogError("unexpected EOL, failed to parse index element");
-        return ~0u;
-    }
-
-    const unsigned int t = strtoul10(s,&se);
-
-    if (se == s) {
-        LogError("failed to read index");
-        return ~0u;
-    }
-
-    return t;
+unsigned int XGLImporter::ReadIndexFromText(XmlNode &node) {
+	const char *s = node.value();
+	if (!SkipSpaces(&s)) {
+		LogError("unexpected EOL, failed to parse index element");
+		return ~0u;
+	}
+	const char *se;
+	const unsigned int t = strtoul10(s, &se);
+
+	if (se == s) {
+		LogError("failed to read index");
+		return ~0u;
+	}
+
+	return t;
 }
 
 // ------------------------------------------------------------------------------------------------
-aiVector2D XGLImporter::ReadVec2()
-{
-    aiVector2D vec;
-
-    if(!SkipToText()) {
-        LogError("unexpected EOF reading vec2 contents");
-        return vec;
-    }
-    const char* s = m_reader->getNodeData();
-
-    ai_real v[2];
-	for(int i = 0; i < 2; ++i) {
-        if(!SkipSpaces(&s)) {
-            LogError("unexpected EOL, failed to parse vec2");
-            return vec;
-        }
-		
-        v[i] = fast_atof(&s);
-
-        SkipSpaces(&s);
-        if (i != 1 && *s != ',') {
-            LogError("expected comma, failed to parse vec2");
-            return vec;
-        }
-        ++s;
-    }
+aiVector2D XGLImporter::ReadVec2(XmlNode &node) {
+	aiVector2D vec;
+	const char *s = node.value();
+	ai_real v[2];
+	for (int i = 0; i < 2; ++i) {
+		if (!SkipSpaces(&s)) {
+			LogError("unexpected EOL, failed to parse vec2");
+			return vec;
+		}
+
+		v[i] = fast_atof(&s);
+
+		SkipSpaces(&s);
+		if (i != 1 && *s != ',') {
+			LogError("expected comma, failed to parse vec2");
+			return vec;
+		}
+		++s;
+	}
 	vec.x = v[0];
 	vec.y = v[1];
 
-    return vec;
+	return vec;
 }
 
 // ------------------------------------------------------------------------------------------------
-aiVector3D XGLImporter::ReadVec3()
-{
-    aiVector3D vec;
-
-    if(!SkipToText()) {
-        LogError("unexpected EOF reading vec3 contents");
-        return vec;
-    }
-    const char* s = m_reader->getNodeData();
-
-    for(int i = 0; i < 3; ++i) {
-        if(!SkipSpaces(&s)) {
-            LogError("unexpected EOL, failed to parse vec3");
-            return vec;
-        }
-        vec[i] = fast_atof(&s);
-
-        SkipSpaces(&s);
-        if (i != 2 && *s != ',') {
-            LogError("expected comma, failed to parse vec3");
-            return vec;
-        }
-        ++s;
-    }
-
-    return vec;
+aiVector3D XGLImporter::ReadVec3(XmlNode &node) {
+	aiVector3D vec;
+	const char *s = node.value();
+	for (int i = 0; i < 3; ++i) {
+		if (!SkipSpaces(&s)) {
+			LogError("unexpected EOL, failed to parse vec3");
+			return vec;
+		}
+		vec[i] = fast_atof(&s);
+
+		SkipSpaces(&s);
+		if (i != 2 && *s != ',') {
+			LogError("expected comma, failed to parse vec3");
+			return vec;
+		}
+		++s;
+	}
+
+	return vec;
 }
 
 // ------------------------------------------------------------------------------------------------
-aiColor3D XGLImporter::ReadCol3()
-{
-    const aiVector3D& v = ReadVec3();
-    if (v.x < 0.f || v.x > 1.0f || v.y < 0.f || v.y > 1.0f || v.z < 0.f || v.z > 1.0f) {
-        LogWarn("color values out of range, ignoring");
-    }
-    return aiColor3D(v.x,v.y,v.z);
+aiColor3D XGLImporter::ReadCol3(XmlNode &node) {
+	const aiVector3D &v = ReadVec3(node);
+	if (v.x < 0.f || v.x > 1.0f || v.y < 0.f || v.y > 1.0f || v.z < 0.f || v.z > 1.0f) {
+		LogWarn("color values out of range, ignoring");
+	}
+	return aiColor3D(v.x, v.y, v.z);
 }
 
 #endif

+ 18 - 28
code/XGL/XGLLoader.h

@@ -53,6 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/Importer.hpp>
 #include <assimp/mesh.h>
 #include <assimp/light.h>
+
 #include <memory>
 #include <map>
 
@@ -65,16 +66,11 @@ namespace Assimp    {
  *
  * Spec: http://vizstream.aveva.com/release/vsplatform/XGLSpec.htm
  */
-class XGLImporter : public BaseImporter, public LogFunctions<XGLImporter>
-{
+class XGLImporter : public BaseImporter, public LogFunctions<XGLImporter> {
 public:
-
     XGLImporter();
     ~XGLImporter();
 
-
-public:
-
     // -------------------------------------------------------------------
     /** Returns whether the class can handle the format of the given file.
      *  See BaseImporter::CanRead() for details.    */
@@ -95,8 +91,6 @@ protected:
         IOSystem* pIOHandler);
 
 private:
-
-
     struct TempScope
     {
         TempScope()
@@ -180,34 +174,30 @@ private:
     };
 
 private:
-
     void Cleanup();
 
-    std::string GetElementName();
-    bool ReadElement();
-    bool ReadElementUpToClosing(const char* closetag);
-    bool SkipToText();
-    unsigned int ReadIDAttr();
+	unsigned int ReadIDAttr(XmlNode &node);
 
     void ReadWorld(TempScope& scope);
-    void ReadLighting(TempScope& scope);
-    aiLight* ReadDirectionalLight();
-    aiNode* ReadObject(TempScope& scope,bool skipFirst = false,const char* closetag = "object");
-    bool ReadMesh(TempScope& scope);
-    void ReadMaterial(TempScope& scope);
-    aiVector2D ReadVec2();
-    aiVector3D ReadVec3();
-    aiColor3D ReadCol3();
-    aiMatrix4x4 ReadTrafo();
-    unsigned int ReadIndexFromText();
-    float ReadFloat();
+	void ReadLighting(XmlNode &node, TempScope &scope);
+	aiLight *ReadDirectionalLight(XmlNode &node);
+	aiNode *ReadObject(XmlNode &node, TempScope &scope, bool skipFirst = false, const char *closetag = "object");
+	bool ReadMesh(XmlNode &node, TempScope &scope);
+	void ReadMaterial(XmlNode &node, TempScope &scope);
+	aiVector2D ReadVec2(XmlNode &node );
+	aiVector3D ReadVec3(XmlNode &node );
+	aiColor3D ReadCol3(XmlNode &node );
+	aiMatrix4x4 ReadTrafo(XmlNode &node );
+	unsigned int ReadIndexFromText(XmlNode &node);
+	float ReadFloat(XmlNode &node );
 
     aiMesh* ToOutputMesh(const TempMaterialMesh& m);
-    void ReadFaceVertex(const TempMesh& t, TempFace& out);
-    unsigned int ResolveMaterialRef(TempScope& scope);
+	void ReadFaceVertex(XmlNode &node, const TempMesh &t, TempFace &out);
+	unsigned int ResolveMaterialRef(XmlNode &node, TempScope &scope);
 
 private:
-    std::shared_ptr<irr::io::IrrXMLReader> m_reader;
+    //std::shared_ptr<irr::io::IrrXMLReader> m_reader;
+	XmlParser *m_xmlParser;
     aiScene* m_scene;
 };
 

+ 11 - 90
include/assimp/XmlParser.h

@@ -51,96 +51,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 namespace Assimp {
 
-// ---------------------------------------------------------------------------------
-/** @brief Utility class to make IrrXML work together with our custom IO system
- *  See the IrrXML docs for more details.
- *
- *  Construct IrrXML-Reader in BaseImporter::InternReadFile():
- *  @code
- * // open the file
- * std::unique_ptr<IOStream> file( pIOHandler->Open( pFile));
- * if( file.get() == NULL) {
- *    throw DeadlyImportError( "Failed to open file " + pFile + ".");
- * }
- *
- * // generate a XML reader for it
- * std::unique_ptr<CIrrXML_IOStreamReader> mIOWrapper( new CIrrXML_IOStreamReader( file.get()));
- * mReader = irr::io::createIrrXMLReader( mIOWrapper.get());
- * if( !mReader) {
- *    ThrowException( "xxxx: Unable to open file.");
- * }
- * @endcode
- **/
-/*class CIrrXML_IOStreamReader : public irr::io::IFileReadCallBack {
-public:
-
-    // ----------------------------------------------------------------------------------
-    //! Construction from an existing IOStream
-    explicit CIrrXML_IOStreamReader(IOStream* _stream)
-        : stream (_stream)
-        , t (0)
-    {
-
-        // Map the buffer into memory and convert it to UTF8. IrrXML provides its
-        // own conversion, which is merely a cast from uintNN_t to uint8_t. Thus,
-        // it is not suitable for our purposes and we have to do it BEFORE IrrXML
-        // gets the buffer. Sadly, this forces us to map the whole file into
-        // memory.
-
-        data.resize(stream->FileSize());
-        stream->Read(&data[0],data.size(),1);
-
-        // Remove null characters from the input sequence otherwise the parsing will utterly fail
-        // std::find is usually much faster than manually iterating
-        // It is very unlikely that there will be any null characters
-        auto null_char_iter = std::find(data.begin(), data.end(), '\0');
-
-        while (null_char_iter != data.end())
-        {
-            null_char_iter = data.erase(null_char_iter);
-            null_char_iter = std::find(null_char_iter, data.end(), '\0');
-        }
-
-        BaseImporter::ConvertToUTF8(data);
-    }
-
-    // ----------------------------------------------------------------------------------
-    //! Virtual destructor
-    virtual ~CIrrXML_IOStreamReader() {}*/
-
-// ----------------------------------------------------------------------------------
-//!   Reads an amount of bytes from the file.
-/**  @param buffer:       Pointer to output buffer.
-     *   @param sizeToRead:   Amount of bytes to read
-     *   @return              Returns how much bytes were read.  */
-/*virtual int read(void* buffer, int sizeToRead)  {
-        if(sizeToRead<0) {
-            return 0;
-        }
-        if(t+sizeToRead>data.size()) {
-            sizeToRead = static_cast<int>(data.size()-t);
-        }
-
-        memcpy(buffer,&data.front()+t,sizeToRead);
-
-        t += sizeToRead;
-        return sizeToRead;
-    }
-
-    // ----------------------------------------------------------------------------------
-    //! Returns size of file in bytes
-    virtual int getSize()   {
-        return (int)data.size();
-    }
-
-private:
-    IOStream* stream;
-    std::vector<char> data;
-    size_t t;
-
-}; // ! class CIrrXML_IOStreamReader
-*/
-
 struct find_node_by_name_predicate {
 	std::string mName;
 	find_node_by_name_predicate(const std::string &name) :
@@ -153,6 +63,14 @@ struct find_node_by_name_predicate {
 	}
 };
 
+template<class TNodeType>
+struct NodeConverter {
+public:
+    static int to_int(TNodeType &node, const char *attribName ) {
+		ai_assert(nullptr != attribName);
+        return node.attribute(attribName).to_int();
+    }
+};
 
 template<class TNodeType>
 class TXmlParser {
@@ -177,6 +95,7 @@ public:
 		if (name.empty()) {
 			return nullptr;
 		}
+
 		if (nullptr == mDoc) {
 			return nullptr;
         }
@@ -187,6 +106,7 @@ public:
 			return nullptr;
         }
 
+        return &node;
     }
 
     TNodeType *parse(IOStream *stream) {
@@ -220,6 +140,7 @@ private:
 };
 
 using XmlParser = TXmlParser<pugi::xml_node>;
+using XmlNode   = pugi::xml_node;
 
 } // namespace Assimp