Kaynağa Gözat

IrrXml: replaced irrXml by pugixml.

Kim Kulling 6 yıl önce
ebeveyn
işleme
a905303764

+ 43 - 38
code/AMF/AMFImporter.cpp

@@ -58,8 +58,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 // Header files, stdlib.
 #include <memory>
 
-namespace Assimp
-{
+namespace Assimp {
 
 /// \var aiImporterDesc AMFImporter::Description
 /// Conastant which hold importer description
@@ -76,24 +75,26 @@ const aiImporterDesc AMFImporter::Description = {
 	"amf"
 };
 
-void AMFImporter::Clear()
-{
+void AMFImporter::Clear() {
 	mNodeElement_Cur = nullptr;
 	mUnit.clear();
 	mMaterial_Converted.clear();
 	mTexture_Converted.clear();
 	// Delete all elements
-	if(!mNodeElement_List.empty())
-	{
-		for(CAMFImporter_NodeElement* ne: mNodeElement_List) { delete ne; }
+	if(!mNodeElement_List.empty()) {
+		for(CAMFImporter_NodeElement* ne: mNodeElement_List) {
+            delete ne;
+        }
 
 		mNodeElement_List.clear();
 	}
 }
 
-AMFImporter::~AMFImporter()
-{
-	if(mReader != nullptr) delete mReader;
+AMFImporter::~AMFImporter() {
+	if (mReader != nullptr) {
+		delete mReader;
+	}
+
 	// Clear() is accounting if data already is deleted. So, just check again if all data is deleted.
 	Clear();
 }
@@ -117,15 +118,14 @@ bool AMFImporter::Find_NodeElement(const std::string& pID, const CAMFImporter_No
 	return false;
 }
 
-bool AMFImporter::Find_ConvertedNode(const std::string& pID, std::list<aiNode*>& pNodeList, aiNode** pNode) const
-{
-aiString node_name(pID.c_str());
+bool AMFImporter::Find_ConvertedNode(const std::string& id, std::list<aiNode*>& nodeList, aiNode** pNode) const {
+    aiString node_name(id.c_str());
 
-	for(aiNode* node: pNodeList)
-	{
-		if(node->mName == node_name)
-		{
-			if(pNode != nullptr) *pNode = node;
+	for(aiNode* node: nodeList) {
+		if(node->mName == node_name) {
+			if (pNode != nullptr) {
+				*pNode = node;
+			}
 
 			return true;
 		}
@@ -134,13 +134,12 @@ aiString node_name(pID.c_str());
 	return false;
 }
 
-bool AMFImporter::Find_ConvertedMaterial(const std::string& pID, const SPP_Material** pConvertedMaterial) const
-{
-	for(const SPP_Material& mat: mMaterial_Converted)
-	{
-		if(mat.ID == pID)
-		{
-			if(pConvertedMaterial != nullptr) *pConvertedMaterial = &mat;
+bool AMFImporter::Find_ConvertedMaterial(const std::string& id, const SPP_Material** pConvertedMaterial) const {
+	for(const SPP_Material& mat: mMaterial_Converted) {
+		if(mat.ID == id) {
+			if (pConvertedMaterial != nullptr) {
+				*pConvertedMaterial = &mat;
+			}
 
 			return true;
 		}
@@ -153,13 +152,11 @@ bool AMFImporter::Find_ConvertedMaterial(const std::string& pID, const SPP_Mater
 /************************************************************ Functions: throw set ***********************************************************/
 /*********************************************************************************************************************************************/
 
-void AMFImporter::Throw_CloseNotFound(const std::string& pNode)
-{
+void AMFImporter::Throw_CloseNotFound(const std::string& pNode) {
 	throw DeadlyImportError("Close tag for node <" + pNode + "> not found. Seems file is corrupt.");
 }
 
-void AMFImporter::Throw_IncorrectAttr(const std::string& pAttrName)
-{
+void AMFImporter::Throw_IncorrectAttr(const std::string& pAttrName) {
 	throw DeadlyImportError("Node <" + std::string(mReader->getNodeName()) + "> has incorrect attribute \"" + pAttrName + "\".");
 }
 
@@ -234,11 +231,13 @@ casu_cres:
 	}
 }
 
-bool AMFImporter::XML_SearchNode(const std::string& pNodeName)
-{
-	while(mReader->read())
-	{
-		if((mReader->getNodeType() == irr::io::EXN_ELEMENT) && XML_CheckNode_NameEqual(pNodeName)) return true;
+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;
+		}
 	}
 
 	return false;
@@ -403,16 +402,22 @@ void AMFImporter::ParseHelper_Decode_Base64(const std::string& pInputBase64, std
 
 void AMFImporter::ParseFile(const std::string& pFile, IOSystem* pIOHandler)
 {
-    irr::io::IrrXMLReader* OldReader = mReader;// store current XMLreader.
+ //   irr::io::IrrXMLReader* OldReader = mReader;// store current XMLreader.
     std::unique_ptr<IOStream> file(pIOHandler->Open(pFile, "rb"));
 
 	// Check whether we can read from the file
 	if(file.get() == NULL) throw DeadlyImportError("Failed to open AMF file " + pFile + ".");
 
+    mReader = new XmlParser;
+	if (!mReader->parse(file.get())) {
+		throw DeadlyImportError("Failed to create XML reader for 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) throw DeadlyImportError("Failed to create XML reader for file" + pFile + ".");
+	//std::unique_ptr<CIrrXML_IOStreamReader> mIOWrapper(new CIrrXML_IOStreamReader(file.get()));
+	//mReader = irr::io::createIrrXMLReader(mIOWrapper.get());
+	//if(!mReader) throw DeadlyImportError("Failed to create XML reader for file" + pFile + ".");
+
 	//
 	// start reading
 	// search for root tag <amf>

+ 7 - 3
code/AMF/AMFImporter.hpp

@@ -58,7 +58,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/importerdesc.h>
 #include "assimp/types.h"
 #include <assimp/BaseImporter.h>
-#include <assimp/irrXMLWrapper.h>
+#include <assimp/XmlParser.h>
 
 // Header files, stdlib.
 #include <set>
@@ -285,7 +285,10 @@ private:
 	/// Check if current node name is equal to pNodeName.
 	/// \param [in] pNodeName - name for checking.
 	/// return true if current node name is equal to pNodeName, else - false.
-	bool XML_CheckNode_NameEqual(const std::string& pNodeName) { return mReader->getNodeName() == pNodeName; }
+	bool XML_CheckNode_NameEqual(const std::string& pNodeName){
+//        return mReader->getNodeName() == pNodeName;
+        mReader->mDoc.
+    }
 
 	/// Skip unsupported node and report about that. Depend on node name can be skipped begin tag of node all whole node.
 	/// \param [in] pParentNodeName - parent node name. Used for reporting.
@@ -420,7 +423,8 @@ private:
 
     CAMFImporter_NodeElement* mNodeElement_Cur;///< Current element.
     std::list<CAMFImporter_NodeElement*> mNodeElement_List;///< All elements of scene graph.
-    irr::io::IrrXMLReader* mReader;///< Pointer to XML-reader object
+	XmlParser *mReader;
+    //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.
     std::list<SPP_Texture> mTexture_Converted;///< List of converted textures for postprocessing step.

+ 1 - 1
code/AMF/AMFImporter_Geometry.cpp

@@ -61,7 +61,7 @@ namespace Assimp
 // Parent element - <object>.
 void AMFImporter::ParseNode_Mesh()
 {
-CAMFImporter_NodeElement* ne;
+    CAMFImporter_NodeElement* ne;
 
 	// create new mesh object.
 	ne = new CAMFImporter_NodeElement_Mesh(mNodeElement_Cur);

+ 4 - 4
code/CMakeLists.txt

@@ -135,7 +135,7 @@ SET( PUBLIC_HEADERS
   ${HEADER_PATH}/XMLTools.h
   ${HEADER_PATH}/IOStreamBuffer.h
   ${HEADER_PATH}/CreateAnimMesh.h
-  ${HEADER_PATH}/irrXMLWrapper.h
+  ${HEADER_PATH}/XmlParser.h
   ${HEADER_PATH}/BlobIOSystem.h
   ${HEADER_PATH}/MathFunctions.h
   ${HEADER_PATH}/Exceptional.h
@@ -703,8 +703,8 @@ SET( PostProcessing_SRCS
 )
 SOURCE_GROUP( PostProcessing FILES ${PostProcessing_SRCS})
 
-SET( IrrXML_SRCS ${HEADER_PATH}/irrXMLWrapper.h )
-SOURCE_GROUP( IrrXML FILES ${IrrXML_SRCS})
+#SET( IrrXML_SRCS ${HEADER_PATH}/irrXMLWrapper.h )
+#SOURCE_GROUP( IrrXML FILES ${IrrXML_SRCS})
 
 ADD_ASSIMP_IMPORTER( Q3D
   Q3D/Q3DLoader.cpp
@@ -1105,7 +1105,7 @@ SET( assimp_src
   ${ASSIMP_EXPORTER_SRCS}
 
   # Third-party libraries
-  ${IrrXML_SRCS}
+  #${IrrXML_SRCS}
   ${unzip_compile_SRCS}
   ${Poly2Tri_SRCS}
   ${Clipper_SRCS}

+ 1 - 1
code/Collada/ColladaParser.h

@@ -47,7 +47,7 @@
 #ifndef AI_COLLADAPARSER_H_INC
 #define AI_COLLADAPARSER_H_INC
 
-#include <assimp/irrXMLWrapper.h>
+#include <assimp/XmlParser.h>
 #include "ColladaHelper.h"
 #include <assimp/ai_assert.h>
 #include <assimp/TinyFormatter.h>

+ 1191 - 1298
code/Irr/IRRLoader.cpp

@@ -45,231 +45,220 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *  @brief Implementation of the Irr importer class
  */
 
-
-
 #ifndef ASSIMP_BUILD_NO_IRR_IMPORTER
 
 #include "Irr/IRRLoader.h"
 #include "Common/Importer.h"
 
-#include <assimp/ParsingUtils.h>
-#include <assimp/fast_atof.h>
 #include <assimp/GenericProperty.h>
+#include <assimp/MathFunctions.h>
+#include <assimp/ParsingUtils.h>
 #include <assimp/SceneCombiner.h>
 #include <assimp/StandardShapes.h>
-#include <assimp/MathFunctions.h>
-#include <assimp/DefaultLogger.hpp>
-#include <assimp/mesh.h>
+#include <assimp/fast_atof.h>
+#include <assimp/importerdesc.h>
 #include <assimp/material.h>
+#include <assimp/mesh.h>
+#include <assimp/postprocess.h>
 #include <assimp/scene.h>
+#include <assimp/DefaultLogger.hpp>
 #include <assimp/IOSystem.hpp>
-#include <assimp/postprocess.h>
-#include <assimp/importerdesc.h>
 
 #include <memory>
 
 using namespace Assimp;
-using namespace irr;
-using namespace irr::io;
 
 static const aiImporterDesc desc = {
-    "Irrlicht Scene Reader",
-    "",
-    "",
-    "http://irrlicht.sourceforge.net/",
-    aiImporterFlags_SupportTextFlavour,
-    0,
-    0,
-    0,
-    0,
-    "irr xml"
+	"Irrlicht Scene Reader",
+	"",
+	"",
+	"http://irrlicht.sourceforge.net/",
+	aiImporterFlags_SupportTextFlavour,
+	0,
+	0,
+	0,
+	0,
+	"irr xml"
 };
 
 // ------------------------------------------------------------------------------------------------
 // Constructor to be privately used by Importer
-IRRImporter::IRRImporter()
-: fps()
-, configSpeedFlag(){
-    // empty
+IRRImporter::IRRImporter() :
+		fps(), configSpeedFlag() {
+	// empty
 }
 
 // ------------------------------------------------------------------------------------------------
 // Destructor, private as well
 IRRImporter::~IRRImporter() {
-    // empty
+	// empty
 }
 
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
-bool IRRImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const {
-    const std::string extension = GetExtension(pFile);
-    if ( extension == "irr" ) {
-        return true;
-    } else if (extension == "xml" || checkSig) {
-        /*  If CanRead() is called in order to check whether we
+bool IRRImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
+	const std::string extension = GetExtension(pFile);
+	if (extension == "irr") {
+		return true;
+	} else if (extension == "xml" || checkSig) {
+		/*  If CanRead() is called in order to check whether we
          *  support a specific file extension in general pIOHandler
          *  might be nullptr and it's our duty to return true here.
          */
-        if (nullptr == pIOHandler ) {
-            return true;
-        }
-        const char* tokens[] = {"irr_scene"};
-        return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
-    }
-
-    return false;
+		if (nullptr == pIOHandler) {
+			return true;
+		}
+		const char *tokens[] = { "irr_scene" };
+		return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
+	}
+
+	return false;
 }
 
 // ------------------------------------------------------------------------------------------------
-const aiImporterDesc* IRRImporter::GetInfo () const
-{
-    return &desc;
+const aiImporterDesc *IRRImporter::GetInfo() const {
+	return &desc;
 }
 
 // ------------------------------------------------------------------------------------------------
-void IRRImporter::SetupProperties(const Importer* pImp)
-{
-    // read the output frame rate of all node animation channels
-    fps = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_IRR_ANIM_FPS,100);
-    if (fps < 10.)  {
-        ASSIMP_LOG_ERROR("IRR: Invalid FPS configuration");
-        fps = 100;
-    }
-
-    // AI_CONFIG_FAVOUR_SPEED
-    configSpeedFlag = (0 != pImp->GetPropertyInteger(AI_CONFIG_FAVOUR_SPEED,0));
+void IRRImporter::SetupProperties(const Importer *pImp) {
+	// read the output frame rate of all node animation channels
+	fps = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_IRR_ANIM_FPS, 100);
+	if (fps < 10.) {
+		ASSIMP_LOG_ERROR("IRR: Invalid FPS configuration");
+		fps = 100;
+	}
+
+	// AI_CONFIG_FAVOUR_SPEED
+	configSpeedFlag = (0 != pImp->GetPropertyInteger(AI_CONFIG_FAVOUR_SPEED, 0));
 }
 
 // ------------------------------------------------------------------------------------------------
 // Build a mesh tha consists of a single squad (a side of a skybox)
-aiMesh* IRRImporter::BuildSingleQuadMesh(const SkyboxVertex& v1,
-    const SkyboxVertex& v2,
-    const SkyboxVertex& v3,
-    const SkyboxVertex& v4)
-{
-    // allocate and prepare the mesh
-    aiMesh* out = new aiMesh();
-
-    out->mPrimitiveTypes = aiPrimitiveType_POLYGON;
-    out->mNumFaces = 1;
-
-    // build the face
-    out->mFaces    = new aiFace[1];
-    aiFace& face   = out->mFaces[0];
-
-    face.mNumIndices = 4;
-    face.mIndices    = new unsigned int[4];
-    for (unsigned int i = 0; i < 4;++i)
-        face.mIndices[i] = i;
-
-    out->mNumVertices = 4;
-
-    // copy vertex positions
-    aiVector3D* vec = out->mVertices = new aiVector3D[4];
-    *vec++ = v1.position;
-    *vec++ = v2.position;
-    *vec++ = v3.position;
-    *vec   = v4.position;
-
-    // copy vertex normals
-    vec = out->mNormals = new aiVector3D[4];
-    *vec++ = v1.normal;
-    *vec++ = v2.normal;
-    *vec++ = v3.normal;
-    *vec   = v4.normal;
-
-    // copy texture coordinates
-    vec = out->mTextureCoords[0] = new aiVector3D[4];
-    *vec++ = v1.uv;
-    *vec++ = v2.uv;
-    *vec++ = v3.uv;
-    *vec   = v4.uv;
-    return out;
+aiMesh *IRRImporter::BuildSingleQuadMesh(const SkyboxVertex &v1,
+		const SkyboxVertex &v2,
+		const SkyboxVertex &v3,
+		const SkyboxVertex &v4) {
+	// allocate and prepare the mesh
+	aiMesh *out = new aiMesh();
+
+	out->mPrimitiveTypes = aiPrimitiveType_POLYGON;
+	out->mNumFaces = 1;
+
+	// build the face
+	out->mFaces = new aiFace[1];
+	aiFace &face = out->mFaces[0];
+
+	face.mNumIndices = 4;
+	face.mIndices = new unsigned int[4];
+	for (unsigned int i = 0; i < 4; ++i)
+		face.mIndices[i] = i;
+
+	out->mNumVertices = 4;
+
+	// copy vertex positions
+	aiVector3D *vec = out->mVertices = new aiVector3D[4];
+	*vec++ = v1.position;
+	*vec++ = v2.position;
+	*vec++ = v3.position;
+	*vec = v4.position;
+
+	// copy vertex normals
+	vec = out->mNormals = new aiVector3D[4];
+	*vec++ = v1.normal;
+	*vec++ = v2.normal;
+	*vec++ = v3.normal;
+	*vec = v4.normal;
+
+	// copy texture coordinates
+	vec = out->mTextureCoords[0] = new aiVector3D[4];
+	*vec++ = v1.uv;
+	*vec++ = v2.uv;
+	*vec++ = v3.uv;
+	*vec = v4.uv;
+	return out;
 }
 
 // ------------------------------------------------------------------------------------------------
-void IRRImporter::BuildSkybox(std::vector<aiMesh*>& meshes, std::vector<aiMaterial*> materials)
-{
-    // Update the material of the skybox - replace the name and disable shading for skyboxes.
-    for (unsigned int i = 0; i < 6;++i) {
-        aiMaterial* out = ( aiMaterial* ) (*(materials.end()-(6-i)));
-
-        aiString s;
-        s.length = ::ai_snprintf( s.data, MAXLEN, "SkyboxSide_%u",i );
-        out->AddProperty(&s,AI_MATKEY_NAME);
-
-        int shading = aiShadingMode_NoShading;
-        out->AddProperty(&shading,1,AI_MATKEY_SHADING_MODEL);
-    }
-
-    // Skyboxes are much more difficult. They are represented
-    // by six single planes with different textures, so we'll
-    // need to build six meshes.
-
-    const ai_real l = 10.0; // the size used by Irrlicht
-
-    // FRONT SIDE
-    meshes.push_back( BuildSingleQuadMesh(
-        SkyboxVertex(-l,-l,-l,  0, 0, 1,   1.0,1.0),
-        SkyboxVertex( l,-l,-l,  0, 0, 1,   0.0,1.0),
-        SkyboxVertex( l, l,-l,  0, 0, 1,   0.0,0.0),
-        SkyboxVertex(-l, l,-l,  0, 0, 1,   1.0,0.0)) );
-    meshes.back()->mMaterialIndex = static_cast<unsigned int>(materials.size()-6u);
-
-    // LEFT SIDE
-    meshes.push_back( BuildSingleQuadMesh(
-        SkyboxVertex( l,-l,-l,  -1, 0, 0,   1.0,1.0),
-        SkyboxVertex( l,-l, l,  -1, 0, 0,   0.0,1.0),
-        SkyboxVertex( l, l, l,  -1, 0, 0,   0.0,0.0),
-        SkyboxVertex( l, l,-l,  -1, 0, 0,   1.0,0.0)) );
-    meshes.back()->mMaterialIndex = static_cast<unsigned int>(materials.size()-5u);
-
-    // BACK SIDE
-    meshes.push_back( BuildSingleQuadMesh(
-        SkyboxVertex( l,-l, l,  0, 0, -1,   1.0,1.0),
-        SkyboxVertex(-l,-l, l,  0, 0, -1,   0.0,1.0),
-        SkyboxVertex(-l, l, l,  0, 0, -1,   0.0,0.0),
-        SkyboxVertex( l, l, l,  0, 0, -1,   1.0,0.0)) );
-    meshes.back()->mMaterialIndex = static_cast<unsigned int>(materials.size()-4u);
-
-    // RIGHT SIDE
-    meshes.push_back( BuildSingleQuadMesh(
-        SkyboxVertex(-l,-l, l,  1, 0, 0,   1.0,1.0),
-        SkyboxVertex(-l,-l,-l,  1, 0, 0,   0.0,1.0),
-        SkyboxVertex(-l, l,-l,  1, 0, 0,   0.0,0.0),
-        SkyboxVertex(-l, l, l,  1, 0, 0,   1.0,0.0)) );
-    meshes.back()->mMaterialIndex = static_cast<unsigned int>(materials.size()-3u);
-
-    // TOP SIDE
-    meshes.push_back( BuildSingleQuadMesh(
-        SkyboxVertex( l, l,-l,  0, -1, 0,   1.0,1.0),
-        SkyboxVertex( l, l, l,  0, -1, 0,   0.0,1.0),
-        SkyboxVertex(-l, l, l,  0, -1, 0,   0.0,0.0),
-        SkyboxVertex(-l, l,-l,  0, -1, 0,   1.0,0.0)) );
-    meshes.back()->mMaterialIndex = static_cast<unsigned int>(materials.size()-2u);
-
-    // BOTTOM SIDE
-    meshes.push_back( BuildSingleQuadMesh(
-        SkyboxVertex( l,-l, l,  0,  1, 0,   0.0,0.0),
-        SkyboxVertex( l,-l,-l,  0,  1, 0,   1.0,0.0),
-        SkyboxVertex(-l,-l,-l,  0,  1, 0,   1.0,1.0),
-        SkyboxVertex(-l,-l, l,  0,  1, 0,   0.0,1.0)) );
-    meshes.back()->mMaterialIndex = static_cast<unsigned int>(materials.size()-1u);
+void IRRImporter::BuildSkybox(std::vector<aiMesh *> &meshes, std::vector<aiMaterial *> materials) {
+	// Update the material of the skybox - replace the name and disable shading for skyboxes.
+	for (unsigned int i = 0; i < 6; ++i) {
+		aiMaterial *out = (aiMaterial *)(*(materials.end() - (6 - i)));
+
+		aiString s;
+		s.length = ::ai_snprintf(s.data, MAXLEN, "SkyboxSide_%u", i);
+		out->AddProperty(&s, AI_MATKEY_NAME);
+
+		int shading = aiShadingMode_NoShading;
+		out->AddProperty(&shading, 1, AI_MATKEY_SHADING_MODEL);
+	}
+
+	// Skyboxes are much more difficult. They are represented
+	// by six single planes with different textures, so we'll
+	// need to build six meshes.
+
+	const ai_real l = 10.0; // the size used by Irrlicht
+
+	// FRONT SIDE
+	meshes.push_back(BuildSingleQuadMesh(
+			SkyboxVertex(-l, -l, -l, 0, 0, 1, 1.0, 1.0),
+			SkyboxVertex(l, -l, -l, 0, 0, 1, 0.0, 1.0),
+			SkyboxVertex(l, l, -l, 0, 0, 1, 0.0, 0.0),
+			SkyboxVertex(-l, l, -l, 0, 0, 1, 1.0, 0.0)));
+	meshes.back()->mMaterialIndex = static_cast<unsigned int>(materials.size() - 6u);
+
+	// LEFT SIDE
+	meshes.push_back(BuildSingleQuadMesh(
+			SkyboxVertex(l, -l, -l, -1, 0, 0, 1.0, 1.0),
+			SkyboxVertex(l, -l, l, -1, 0, 0, 0.0, 1.0),
+			SkyboxVertex(l, l, l, -1, 0, 0, 0.0, 0.0),
+			SkyboxVertex(l, l, -l, -1, 0, 0, 1.0, 0.0)));
+	meshes.back()->mMaterialIndex = static_cast<unsigned int>(materials.size() - 5u);
+
+	// BACK SIDE
+	meshes.push_back(BuildSingleQuadMesh(
+			SkyboxVertex(l, -l, l, 0, 0, -1, 1.0, 1.0),
+			SkyboxVertex(-l, -l, l, 0, 0, -1, 0.0, 1.0),
+			SkyboxVertex(-l, l, l, 0, 0, -1, 0.0, 0.0),
+			SkyboxVertex(l, l, l, 0, 0, -1, 1.0, 0.0)));
+	meshes.back()->mMaterialIndex = static_cast<unsigned int>(materials.size() - 4u);
+
+	// RIGHT SIDE
+	meshes.push_back(BuildSingleQuadMesh(
+			SkyboxVertex(-l, -l, l, 1, 0, 0, 1.0, 1.0),
+			SkyboxVertex(-l, -l, -l, 1, 0, 0, 0.0, 1.0),
+			SkyboxVertex(-l, l, -l, 1, 0, 0, 0.0, 0.0),
+			SkyboxVertex(-l, l, l, 1, 0, 0, 1.0, 0.0)));
+	meshes.back()->mMaterialIndex = static_cast<unsigned int>(materials.size() - 3u);
+
+	// TOP SIDE
+	meshes.push_back(BuildSingleQuadMesh(
+			SkyboxVertex(l, l, -l, 0, -1, 0, 1.0, 1.0),
+			SkyboxVertex(l, l, l, 0, -1, 0, 0.0, 1.0),
+			SkyboxVertex(-l, l, l, 0, -1, 0, 0.0, 0.0),
+			SkyboxVertex(-l, l, -l, 0, -1, 0, 1.0, 0.0)));
+	meshes.back()->mMaterialIndex = static_cast<unsigned int>(materials.size() - 2u);
+
+	// BOTTOM SIDE
+	meshes.push_back(BuildSingleQuadMesh(
+			SkyboxVertex(l, -l, l, 0, 1, 0, 0.0, 0.0),
+			SkyboxVertex(l, -l, -l, 0, 1, 0, 1.0, 0.0),
+			SkyboxVertex(-l, -l, -l, 0, 1, 0, 1.0, 1.0),
+			SkyboxVertex(-l, -l, l, 0, 1, 0, 0.0, 1.0)));
+	meshes.back()->mMaterialIndex = static_cast<unsigned int>(materials.size() - 1u);
 }
 
 // ------------------------------------------------------------------------------------------------
-void IRRImporter::CopyMaterial(std::vector<aiMaterial*>& materials,
-    std::vector< std::pair<aiMaterial*, unsigned int> >& inmaterials,
-    unsigned int& defMatIdx,
-    aiMesh* mesh)
-{
-    if (inmaterials.empty())    {
-        // Do we have a default material? If not we need to create one
-        if (UINT_MAX == defMatIdx)
-        {
-            defMatIdx = (unsigned int)materials.size();
-            //TODO: add this materials to someone?
-            /*aiMaterial* mat = new aiMaterial();
+void IRRImporter::CopyMaterial(std::vector<aiMaterial *> &materials,
+		std::vector<std::pair<aiMaterial *, unsigned int>> &inmaterials,
+		unsigned int &defMatIdx,
+		aiMesh *mesh) {
+	if (inmaterials.empty()) {
+		// Do we have a default material? If not we need to create one
+		if (UINT_MAX == defMatIdx) {
+			defMatIdx = (unsigned int)materials.size();
+			//TODO: add this materials to someone?
+			/*aiMaterial* mat = new aiMaterial();
 
             aiString s;
             s.Set(AI_DEFAULT_MATERIAL_NAME);
@@ -277,141 +266,137 @@ void IRRImporter::CopyMaterial(std::vector<aiMaterial*>& materials,
 
             aiColor3D c(0.6f,0.6f,0.6f);
             mat->AddProperty(&c,1,AI_MATKEY_COLOR_DIFFUSE);*/
-        }
-        mesh->mMaterialIndex = defMatIdx;
-        return;
-    }
-    else if (inmaterials.size() > 1)    {
-        ASSIMP_LOG_INFO("IRR: Skipping additional materials");
-    }
-
-    mesh->mMaterialIndex = (unsigned int)materials.size();
-    materials.push_back(inmaterials[0].first);
+		}
+		mesh->mMaterialIndex = defMatIdx;
+		return;
+	} else if (inmaterials.size() > 1) {
+		ASSIMP_LOG_INFO("IRR: Skipping additional materials");
+	}
+
+	mesh->mMaterialIndex = (unsigned int)materials.size();
+	materials.push_back(inmaterials[0].first);
 }
 
-
 // ------------------------------------------------------------------------------------------------
-inline
-int ClampSpline(int idx, int size) {
-    return ( idx<0 ? size+idx : ( idx>=size ? idx-size : idx ) );
+inline int ClampSpline(int idx, int size) {
+	return (idx < 0 ? size + idx : (idx >= size ? idx - size : idx));
 }
 
 // ------------------------------------------------------------------------------------------------
-inline void FindSuitableMultiple(int& angle)
-{
-    if (angle < 3) angle = 3;
-    else if (angle < 10) angle = 10;
-    else if (angle < 20) angle = 20;
-    else if (angle < 30) angle = 30;
+inline void FindSuitableMultiple(int &angle) {
+	if (angle < 3)
+		angle = 3;
+	else if (angle < 10)
+		angle = 10;
+	else if (angle < 20)
+		angle = 20;
+	else if (angle < 30)
+		angle = 30;
 }
 
 // ------------------------------------------------------------------------------------------------
-void IRRImporter::ComputeAnimations(Node* root, aiNode* real, std::vector<aiNodeAnim*>& anims)
-{
-    ai_assert(nullptr != root && nullptr != real);
-
-    // XXX totally WIP - doesn't produce proper results, need to evaluate
-    // whether there's any use for Irrlicht's proprietary scene format
-    // outside Irrlicht ...
-    // This also applies to the above function of FindSuitableMultiple and ClampSpline which are
-    // solely used in this function
-
-    if (root->animators.empty()) {
-        return;
-    }
-    unsigned int total( 0 );
-    for (std::list<Animator>::iterator it = root->animators.begin();it != root->animators.end(); ++it)  {
-        if ((*it).type == Animator::UNKNOWN || (*it).type == Animator::OTHER)   {
-            ASSIMP_LOG_WARN("IRR: Skipping unknown or unsupported animator");
-            continue;
-        }
-        ++total;
-    }
-    if (!total) {
-        return;
-    } else if (1 == total)    {
-        ASSIMP_LOG_WARN("IRR: Adding dummy nodes to simulate multiple animators");
-    }
-
-    // NOTE: 1 tick == i millisecond
-
-    unsigned int cur = 0;
-    for (std::list<Animator>::iterator it = root->animators.begin();
-        it != root->animators.end(); ++it)
-    {
-        if ((*it).type == Animator::UNKNOWN || (*it).type == Animator::OTHER)continue;
-
-        Animator& in = *it ;
-        aiNodeAnim* anim = new aiNodeAnim();
-
-        if (cur != total-1) {
-            // Build a new name - a prefix instead of a suffix because it is
-            // easier to check against
-            anim->mNodeName.length = ::ai_snprintf(anim->mNodeName.data, MAXLEN,
-                "$INST_DUMMY_%i_%s",total-1,
-                (root->name.length() ? root->name.c_str() : ""));
-
-            // we'll also need to insert a dummy in the node hierarchy.
-            aiNode* dummy = new aiNode();
-
-            for (unsigned int i = 0; i < real->mParent->mNumChildren;++i)
-                if (real->mParent->mChildren[i] == real)
-                    real->mParent->mChildren[i] = dummy;
-
-            dummy->mParent = real->mParent;
-            dummy->mName = anim->mNodeName;
-
-            dummy->mNumChildren = 1;
-            dummy->mChildren = new aiNode*[dummy->mNumChildren];
-            dummy->mChildren[0] = real;
-
-            // the transformation matrix of the dummy node is the identity
-
-            real->mParent = dummy;
-        }
-        else anim->mNodeName.Set(root->name);
-        ++cur;
-
-        switch (in.type)    {
-        case Animator::ROTATION:
-            {
-                // -----------------------------------------------------
-                // find out how long a full rotation will take
-                // This is the least common multiple of 360.f and all
-                // three euler angles. Although we'll surely find a
-                // possible multiple (haha) it could be somewhat large
-                // for our purposes. So we need to modify the angles
-                // here in order to get good results.
-                // -----------------------------------------------------
-                int angles[3];
-                angles[0] = (int)(in.direction.x*100);
-                angles[1] = (int)(in.direction.y*100);
-                angles[2] = (int)(in.direction.z*100);
-
-                angles[0] %= 360;
-                angles[1] %= 360;
-                angles[2] %= 360;
-
-                if ( (angles[0]*angles[1]) != 0 && (angles[1]*angles[2]) != 0 )
-                {
-                    FindSuitableMultiple(angles[0]);
-                    FindSuitableMultiple(angles[1]);
-                    FindSuitableMultiple(angles[2]);
-                }
-
-                int lcm = 360;
-
-                if (angles[0])
-                    lcm  = Math::lcm(lcm,angles[0]);
-
-                if (angles[1])
-                    lcm  = Math::lcm(lcm,angles[1]);
-
-                if (angles[2])
-                    lcm  = Math::lcm(lcm,angles[2]);
-
-                if (360 == lcm)
-                    break;
+void IRRImporter::ComputeAnimations(Node *root, aiNode *real, std::vector<aiNodeAnim *> &anims) {
+	ai_assert(nullptr != root && nullptr != real);
+
+	// XXX totally WIP - doesn't produce proper results, need to evaluate
+	// whether there's any use for Irrlicht's proprietary scene format
+	// outside Irrlicht ...
+	// This also applies to the above function of FindSuitableMultiple and ClampSpline which are
+	// solely used in this function
+
+	if (root->animators.empty()) {
+		return;
+	}
+	unsigned int total(0);
+	for (std::list<Animator>::iterator it = root->animators.begin(); it != root->animators.end(); ++it) {
+		if ((*it).type == Animator::UNKNOWN || (*it).type == Animator::OTHER) {
+			ASSIMP_LOG_WARN("IRR: Skipping unknown or unsupported animator");
+			continue;
+		}
+		++total;
+	}
+	if (!total) {
+		return;
+	} else if (1 == total) {
+		ASSIMP_LOG_WARN("IRR: Adding dummy nodes to simulate multiple animators");
+	}
+
+	// NOTE: 1 tick == i millisecond
+
+	unsigned int cur = 0;
+	for (std::list<Animator>::iterator it = root->animators.begin();
+			it != root->animators.end(); ++it) {
+		if ((*it).type == Animator::UNKNOWN || (*it).type == Animator::OTHER) continue;
+
+		Animator &in = *it;
+		aiNodeAnim *anim = new aiNodeAnim();
+
+		if (cur != total - 1) {
+			// Build a new name - a prefix instead of a suffix because it is
+			// easier to check against
+			anim->mNodeName.length = ::ai_snprintf(anim->mNodeName.data, MAXLEN,
+					"$INST_DUMMY_%i_%s", total - 1,
+					(root->name.length() ? root->name.c_str() : ""));
+
+			// we'll also need to insert a dummy in the node hierarchy.
+			aiNode *dummy = new aiNode();
+
+			for (unsigned int i = 0; i < real->mParent->mNumChildren; ++i)
+				if (real->mParent->mChildren[i] == real)
+					real->mParent->mChildren[i] = dummy;
+
+			dummy->mParent = real->mParent;
+			dummy->mName = anim->mNodeName;
+
+			dummy->mNumChildren = 1;
+			dummy->mChildren = new aiNode *[dummy->mNumChildren];
+			dummy->mChildren[0] = real;
+
+			// the transformation matrix of the dummy node is the identity
+
+			real->mParent = dummy;
+		} else
+			anim->mNodeName.Set(root->name);
+		++cur;
+
+		switch (in.type) {
+			case Animator::ROTATION: {
+				// -----------------------------------------------------
+				// find out how long a full rotation will take
+				// This is the least common multiple of 360.f and all
+				// three euler angles. Although we'll surely find a
+				// possible multiple (haha) it could be somewhat large
+				// for our purposes. So we need to modify the angles
+				// here in order to get good results.
+				// -----------------------------------------------------
+				int angles[3];
+				angles[0] = (int)(in.direction.x * 100);
+				angles[1] = (int)(in.direction.y * 100);
+				angles[2] = (int)(in.direction.z * 100);
+
+				angles[0] %= 360;
+				angles[1] %= 360;
+				angles[2] %= 360;
+
+				if ((angles[0] * angles[1]) != 0 && (angles[1] * angles[2]) != 0) {
+					FindSuitableMultiple(angles[0]);
+					FindSuitableMultiple(angles[1]);
+					FindSuitableMultiple(angles[2]);
+				}
+
+				int lcm = 360;
+
+				if (angles[0])
+					lcm = Math::lcm(lcm, angles[0]);
+
+				if (angles[1])
+					lcm = Math::lcm(lcm, angles[1]);
+
+				if (angles[2])
+					lcm = Math::lcm(lcm, angles[2]);
+
+				if (360 == lcm)
+					break;
 
 #if 0
                 // This can be a division through zero, but we don't care
@@ -420,1068 +405,976 @@ void IRRImporter::ComputeAnimations(Node* root, aiNode* real, std::vector<aiNode
                 float f3 = (float)lcm / angles[2];
 #endif
 
-                // find out how many time units we'll need for the finest
-                // track (in seconds) - this defines the number of output
-                // keys (fps * seconds)
-                float max  = 0.f;
-                if (angles[0])
-                    max = (float)lcm / angles[0];
-                if (angles[1])
-                    max = std::max(max, (float)lcm / angles[1]);
-                if (angles[2])
-                    max = std::max(max, (float)lcm / angles[2]);
-
-                anim->mNumRotationKeys = (unsigned int)(max*fps);
-                anim->mRotationKeys = new aiQuatKey[anim->mNumRotationKeys];
-
-                // begin with a zero angle
-                aiVector3D angle;
-                for (unsigned int i = 0; i < anim->mNumRotationKeys;++i)
-                {
-                    // build the quaternion for the given euler angles
-                    aiQuatKey& q = anim->mRotationKeys[i];
-
-                    q.mValue = aiQuaternion(angle.x, angle.y, angle.z);
-                    q.mTime = (double)i;
-
-                    // increase the angle
-                    angle += in.direction;
-                }
-
-                // This animation is repeated and repeated ...
-                anim->mPostState = anim->mPreState = aiAnimBehaviour_REPEAT;
-            }
-            break;
-
-        case Animator::FLY_CIRCLE:
-            {
-                // -----------------------------------------------------
-                // Find out how much time we'll need to perform a
-                // full circle.
-                // -----------------------------------------------------
-                const double seconds = (1. / in.speed) / 1000.;
-                const double tdelta = 1000. / fps;
-
-                anim->mNumPositionKeys = (unsigned int) (fps * seconds);
-                anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys];
-
-                // from Irrlicht, what else should we do than copying it?
-                aiVector3D vecU,vecV;
-                if (in.direction.y) {
-                    vecV = aiVector3D(50,0,0) ^ in.direction;
-                }
-                else vecV = aiVector3D(0,50,00) ^ in.direction;
-                vecV.Normalize();
-                vecU = (vecV ^ in.direction).Normalize();
-
-                // build the output keys
-                for (unsigned int i = 0; i < anim->mNumPositionKeys;++i)    {
-                    aiVectorKey& key = anim->mPositionKeys[i];
-                    key.mTime = i * tdelta;
-
-                    const ai_real t = (ai_real) ( in.speed * key.mTime );
-                    key.mValue = in.circleCenter  + in.circleRadius * ((vecU * std::cos(t)) + (vecV * std::sin(t)));
-                }
-
-                // This animation is repeated and repeated ...
-                anim->mPostState = anim->mPreState = aiAnimBehaviour_REPEAT;
-            }
-            break;
-
-        case Animator::FLY_STRAIGHT:
-            {
-                anim->mPostState = anim->mPreState = (in.loop ? aiAnimBehaviour_REPEAT : aiAnimBehaviour_CONSTANT);
-                const double seconds = in.timeForWay / 1000.;
-                const double tdelta = 1000. / fps;
-
-                anim->mNumPositionKeys = (unsigned int) (fps * seconds);
-                anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys];
-
-                aiVector3D diff = in.direction - in.circleCenter;
-                const ai_real lengthOfWay = diff.Length();
-                diff.Normalize();
-
-                const double timeFactor = lengthOfWay / in.timeForWay;
-
-                // build the output keys
-                for (unsigned int i = 0; i < anim->mNumPositionKeys;++i)    {
-                    aiVectorKey& key = anim->mPositionKeys[i];
-                    key.mTime = i * tdelta;
-                    key.mValue = in.circleCenter + diff * ai_real(timeFactor * key.mTime);
-                }
-            }
-            break;
-
-        case Animator::FOLLOW_SPLINE:
-            {
-                // repeat outside the defined time range
-                anim->mPostState = anim->mPreState = aiAnimBehaviour_REPEAT;
-                const int size = (int)in.splineKeys.size();
-                if (!size)  {
-                    // We have no point in the spline. That's bad. Really bad.
-                    ASSIMP_LOG_WARN("IRR: Spline animators with no points defined");
-
-                    delete anim;
-                    anim = nullptr;
-                    break;
-                }
-                else if (size == 1) {
-                    // We have just one point in the spline so we don't need the full calculation
-                    anim->mNumPositionKeys = 1;
-                    anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys];
-
-                    anim->mPositionKeys[0].mValue = in.splineKeys[0].mValue;
-                    anim->mPositionKeys[0].mTime  = 0.f;
-                    break;
-                }
-
-                unsigned int ticksPerFull = 15;
-                anim->mNumPositionKeys = (unsigned int) ( ticksPerFull * fps );
-                anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys];
-
-                for (unsigned int i = 0; i < anim->mNumPositionKeys;++i)
-                {
-                    aiVectorKey& key = anim->mPositionKeys[i];
-
-                    const ai_real dt = (i * in.speed * ai_real( 0.001 ) );
-                    const ai_real u = dt - std::floor(dt);
-                    const int idx = (int)std::floor(dt) % size;
-
-                    // get the 4 current points to evaluate the spline
-                    const aiVector3D& p0 = in.splineKeys[ ClampSpline( idx - 1, size ) ].mValue;
-                    const aiVector3D& p1 = in.splineKeys[ ClampSpline( idx + 0, size ) ].mValue;
-                    const aiVector3D& p2 = in.splineKeys[ ClampSpline( idx + 1, size ) ].mValue;
-                    const aiVector3D& p3 = in.splineKeys[ ClampSpline( idx + 2, size ) ].mValue;
-
-                    // compute polynomials
-                    const ai_real u2 = u*u;
-                    const ai_real u3 = u2*2;
-
-                    const ai_real h1 = ai_real( 2.0 ) * u3 - ai_real( 3.0 ) * u2 + ai_real( 1.0 );
-                    const ai_real h2 = ai_real( -2.0 ) * u3 + ai_real( 3.0 ) * u3;
-                    const ai_real h3 = u3 - ai_real( 2.0 ) * u3;
-                    const ai_real h4 = u3 - u2;
-
-                    // compute the spline tangents
-                    const aiVector3D t1 = ( p2 - p0 ) * in.tightness;
-                    aiVector3D t2 = ( p3 - p1 ) * in.tightness;
-
-                    // and use them to get the interpolated point
-                    t2 = (h1 * p1 + p2 * h2 + t1 * h3 + h4 * t2);
-
-                    // build a simple translation matrix from it
-                    key.mValue = t2;
-                    key.mTime  = (double) i;
-                }
-            }
-            break;
-        default:
-            // UNKNOWN , OTHER
-            break;
-        };
-        if (anim)   {
-            anims.push_back(anim);
-            ++total;
-        }
-    }
+				// find out how many time units we'll need for the finest
+				// track (in seconds) - this defines the number of output
+				// keys (fps * seconds)
+				float max = 0.f;
+				if (angles[0])
+					max = (float)lcm / angles[0];
+				if (angles[1])
+					max = std::max(max, (float)lcm / angles[1]);
+				if (angles[2])
+					max = std::max(max, (float)lcm / angles[2]);
+
+				anim->mNumRotationKeys = (unsigned int)(max * fps);
+				anim->mRotationKeys = new aiQuatKey[anim->mNumRotationKeys];
+
+				// begin with a zero angle
+				aiVector3D angle;
+				for (unsigned int i = 0; i < anim->mNumRotationKeys; ++i) {
+					// build the quaternion for the given euler angles
+					aiQuatKey &q = anim->mRotationKeys[i];
+
+					q.mValue = aiQuaternion(angle.x, angle.y, angle.z);
+					q.mTime = (double)i;
+
+					// increase the angle
+					angle += in.direction;
+				}
+
+				// This animation is repeated and repeated ...
+				anim->mPostState = anim->mPreState = aiAnimBehaviour_REPEAT;
+			} break;
+
+			case Animator::FLY_CIRCLE: {
+				// -----------------------------------------------------
+				// Find out how much time we'll need to perform a
+				// full circle.
+				// -----------------------------------------------------
+				const double seconds = (1. / in.speed) / 1000.;
+				const double tdelta = 1000. / fps;
+
+				anim->mNumPositionKeys = (unsigned int)(fps * seconds);
+				anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys];
+
+				// from Irrlicht, what else should we do than copying it?
+				aiVector3D vecU, vecV;
+				if (in.direction.y) {
+					vecV = aiVector3D(50, 0, 0) ^ in.direction;
+				} else
+					vecV = aiVector3D(0, 50, 00) ^ in.direction;
+				vecV.Normalize();
+				vecU = (vecV ^ in.direction).Normalize();
+
+				// build the output keys
+				for (unsigned int i = 0; i < anim->mNumPositionKeys; ++i) {
+					aiVectorKey &key = anim->mPositionKeys[i];
+					key.mTime = i * tdelta;
+
+					const ai_real t = (ai_real)(in.speed * key.mTime);
+					key.mValue = in.circleCenter + in.circleRadius * ((vecU * std::cos(t)) + (vecV * std::sin(t)));
+				}
+
+				// This animation is repeated and repeated ...
+				anim->mPostState = anim->mPreState = aiAnimBehaviour_REPEAT;
+			} break;
+
+			case Animator::FLY_STRAIGHT: {
+				anim->mPostState = anim->mPreState = (in.loop ? aiAnimBehaviour_REPEAT : aiAnimBehaviour_CONSTANT);
+				const double seconds = in.timeForWay / 1000.;
+				const double tdelta = 1000. / fps;
+
+				anim->mNumPositionKeys = (unsigned int)(fps * seconds);
+				anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys];
+
+				aiVector3D diff = in.direction - in.circleCenter;
+				const ai_real lengthOfWay = diff.Length();
+				diff.Normalize();
+
+				const double timeFactor = lengthOfWay / in.timeForWay;
+
+				// build the output keys
+				for (unsigned int i = 0; i < anim->mNumPositionKeys; ++i) {
+					aiVectorKey &key = anim->mPositionKeys[i];
+					key.mTime = i * tdelta;
+					key.mValue = in.circleCenter + diff * ai_real(timeFactor * key.mTime);
+				}
+			} break;
+
+			case Animator::FOLLOW_SPLINE: {
+				// repeat outside the defined time range
+				anim->mPostState = anim->mPreState = aiAnimBehaviour_REPEAT;
+				const int size = (int)in.splineKeys.size();
+				if (!size) {
+					// We have no point in the spline. That's bad. Really bad.
+					ASSIMP_LOG_WARN("IRR: Spline animators with no points defined");
+
+					delete anim;
+					anim = nullptr;
+					break;
+				} else if (size == 1) {
+					// We have just one point in the spline so we don't need the full calculation
+					anim->mNumPositionKeys = 1;
+					anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys];
+
+					anim->mPositionKeys[0].mValue = in.splineKeys[0].mValue;
+					anim->mPositionKeys[0].mTime = 0.f;
+					break;
+				}
+
+				unsigned int ticksPerFull = 15;
+				anim->mNumPositionKeys = (unsigned int)(ticksPerFull * fps);
+				anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys];
+
+				for (unsigned int i = 0; i < anim->mNumPositionKeys; ++i) {
+					aiVectorKey &key = anim->mPositionKeys[i];
+
+					const ai_real dt = (i * in.speed * ai_real(0.001));
+					const ai_real u = dt - std::floor(dt);
+					const int idx = (int)std::floor(dt) % size;
+
+					// get the 4 current points to evaluate the spline
+					const aiVector3D &p0 = in.splineKeys[ClampSpline(idx - 1, size)].mValue;
+					const aiVector3D &p1 = in.splineKeys[ClampSpline(idx + 0, size)].mValue;
+					const aiVector3D &p2 = in.splineKeys[ClampSpline(idx + 1, size)].mValue;
+					const aiVector3D &p3 = in.splineKeys[ClampSpline(idx + 2, size)].mValue;
+
+					// compute polynomials
+					const ai_real u2 = u * u;
+					const ai_real u3 = u2 * 2;
+
+					const ai_real h1 = ai_real(2.0) * u3 - ai_real(3.0) * u2 + ai_real(1.0);
+					const ai_real h2 = ai_real(-2.0) * u3 + ai_real(3.0) * u3;
+					const ai_real h3 = u3 - ai_real(2.0) * u3;
+					const ai_real h4 = u3 - u2;
+
+					// compute the spline tangents
+					const aiVector3D t1 = (p2 - p0) * in.tightness;
+					aiVector3D t2 = (p3 - p1) * in.tightness;
+
+					// and use them to get the interpolated point
+					t2 = (h1 * p1 + p2 * h2 + t1 * h3 + h4 * t2);
+
+					// build a simple translation matrix from it
+					key.mValue = t2;
+					key.mTime = (double)i;
+				}
+			} break;
+			default:
+				// UNKNOWN , OTHER
+				break;
+		};
+		if (anim) {
+			anims.push_back(anim);
+			++total;
+		}
+	}
 }
 
 // ------------------------------------------------------------------------------------------------
 // This function is maybe more generic than we'd need it here
-void SetupMapping (aiMaterial* mat, aiTextureMapping mode, const aiVector3D& axis = aiVector3D(0.f,0.f,-1.f))
-{
-    // Check whether there are texture properties defined - setup
-    // the desired texture mapping mode for all of them and ignore
-    // all UV settings we might encounter. WE HAVE NO UVS!
-
-    std::vector<aiMaterialProperty*> p;
-    p.reserve(mat->mNumProperties+1);
-
-    for (unsigned int i = 0; i < mat->mNumProperties;++i)
-    {
-        aiMaterialProperty* prop = mat->mProperties[i];
-        if (!::strcmp( prop->mKey.data, "$tex.file"))   {
-            // Setup the mapping key
-            aiMaterialProperty* m = new aiMaterialProperty();
-            m->mKey.Set("$tex.mapping");
-            m->mIndex    = prop->mIndex;
-            m->mSemantic = prop->mSemantic;
-            m->mType     = aiPTI_Integer;
-
-            m->mDataLength = 4;
-            m->mData = new char[4];
-            *((int*)m->mData) = mode;
-
-            p.push_back(prop);
-            p.push_back(m);
-
-            // Setup the mapping axis
-            if (mode == aiTextureMapping_CYLINDER || mode == aiTextureMapping_PLANE || mode == aiTextureMapping_SPHERE) {
-                m = new aiMaterialProperty();
-                m->mKey.Set("$tex.mapaxis");
-                m->mIndex    = prop->mIndex;
-                m->mSemantic = prop->mSemantic;
-                m->mType     = aiPTI_Float;
-
-                m->mDataLength = 12;
-                m->mData = new char[12];
-                *((aiVector3D*)m->mData) = axis;
-                p.push_back(m);
-            }
-        }
-        else if (! ::strcmp( prop->mKey.data, "$tex.uvwsrc"))   {
-            delete mat->mProperties[i];
-        }
-        else p.push_back(prop);
-    }
-
-    if (p.empty())return;
-
-    // rebuild the output array
-    if (p.size() > mat->mNumAllocated)  {
-        delete[] mat->mProperties;
-        mat->mProperties = new aiMaterialProperty*[p.size()*2];
-
-        mat->mNumAllocated = static_cast<unsigned int>(p.size()*2);
-    }
-    mat->mNumProperties = (unsigned int)p.size();
-    ::memcpy(mat->mProperties,&p[0],sizeof(void*)*mat->mNumProperties);
+void SetupMapping(aiMaterial *mat, aiTextureMapping mode, const aiVector3D &axis = aiVector3D(0.f, 0.f, -1.f)) {
+	// Check whether there are texture properties defined - setup
+	// the desired texture mapping mode for all of them and ignore
+	// all UV settings we might encounter. WE HAVE NO UVS!
+
+	std::vector<aiMaterialProperty *> p;
+	p.reserve(mat->mNumProperties + 1);
+
+	for (unsigned int i = 0; i < mat->mNumProperties; ++i) {
+		aiMaterialProperty *prop = mat->mProperties[i];
+		if (!::strcmp(prop->mKey.data, "$tex.file")) {
+			// Setup the mapping key
+			aiMaterialProperty *m = new aiMaterialProperty();
+			m->mKey.Set("$tex.mapping");
+			m->mIndex = prop->mIndex;
+			m->mSemantic = prop->mSemantic;
+			m->mType = aiPTI_Integer;
+
+			m->mDataLength = 4;
+			m->mData = new char[4];
+			*((int *)m->mData) = mode;
+
+			p.push_back(prop);
+			p.push_back(m);
+
+			// Setup the mapping axis
+			if (mode == aiTextureMapping_CYLINDER || mode == aiTextureMapping_PLANE || mode == aiTextureMapping_SPHERE) {
+				m = new aiMaterialProperty();
+				m->mKey.Set("$tex.mapaxis");
+				m->mIndex = prop->mIndex;
+				m->mSemantic = prop->mSemantic;
+				m->mType = aiPTI_Float;
+
+				m->mDataLength = 12;
+				m->mData = new char[12];
+				*((aiVector3D *)m->mData) = axis;
+				p.push_back(m);
+			}
+		} else if (!::strcmp(prop->mKey.data, "$tex.uvwsrc")) {
+			delete mat->mProperties[i];
+		} else
+			p.push_back(prop);
+	}
+
+	if (p.empty()) return;
+
+	// rebuild the output array
+	if (p.size() > mat->mNumAllocated) {
+		delete[] mat->mProperties;
+		mat->mProperties = new aiMaterialProperty *[p.size() * 2];
+
+		mat->mNumAllocated = static_cast<unsigned int>(p.size() * 2);
+	}
+	mat->mNumProperties = (unsigned int)p.size();
+	::memcpy(mat->mProperties, &p[0], sizeof(void *) * mat->mNumProperties);
 }
 
 // ------------------------------------------------------------------------------------------------
-void IRRImporter::GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene,
-    BatchLoader& batch,
-    std::vector<aiMesh*>&        meshes,
-    std::vector<aiNodeAnim*>&    anims,
-    std::vector<AttachmentInfo>& attach,
-    std::vector<aiMaterial*>&    materials,
-    unsigned int&                defMatIdx)
-{
-    unsigned int oldMeshSize = (unsigned int)meshes.size();
-    //unsigned int meshTrafoAssign = 0;
-
-    // Now determine the type of the node
-    switch (root->type)
-    {
-    case Node::ANIMMESH:
-    case Node::MESH:
-        {
-            if (!root->meshPath.length())
-                break;
-
-            // Get the loaded mesh from the scene and add it to
-            // the list of all scenes to be attached to the
-            // graph we're currently building
-            aiScene* localScene = batch.GetImport(root->id);
-            if (!localScene) {
-                ASSIMP_LOG_ERROR("IRR: Unable to load external file: " + root->meshPath);
-                break;
-            }
-            attach.push_back(AttachmentInfo(localScene,rootOut));
-
-            // Now combine the material we've loaded for this mesh
-            // with the real materials we got from the file. As we
-            // don't execute any pp-steps on the file, the numbers
-            // should be equal. If they are not, we can impossibly
-            // do this  ...
-            if (root->materials.size() != (unsigned int)localScene->mNumMaterials)   {
-                ASSIMP_LOG_WARN("IRR: Failed to match imported materials "
-                    "with the materials found in the IRR scene file");
-
-                break;
-            }
-            for (unsigned int i = 0; i < localScene->mNumMaterials;++i)  {
-                // Delete the old material, we don't need it anymore
-                delete localScene->mMaterials[i];
-
-                std::pair<aiMaterial*, unsigned int>& src = root->materials[i];
-                localScene->mMaterials[i] = src.first;
-            }
-
-            // NOTE: Each mesh should have exactly one material assigned,
-            // but we do it in a separate loop if this behaviour changes
-            // in future.
-            for (unsigned int i = 0; i < localScene->mNumMeshes;++i) {
-                // Process material flags
-                aiMesh* mesh = localScene->mMeshes[i];
-
-
-                // If "trans_vertex_alpha" mode is enabled, search all vertex colors
-                // and check whether they have a common alpha value. This is quite
-                // often the case so we can simply extract it to a shared oacity
-                // value.
-                std::pair<aiMaterial*, unsigned int>& src = root->materials[mesh->mMaterialIndex];
-                aiMaterial* mat = (aiMaterial*)src.first;
-
-                if (mesh->HasVertexColors(0) && src.second & AI_IRRMESH_MAT_trans_vertex_alpha)
-                {
-                    bool bdo = true;
-                    for (unsigned int a = 1; a < mesh->mNumVertices;++a)    {
-
-                        if (mesh->mColors[0][a].a != mesh->mColors[0][a-1].a)   {
-                            bdo = false;
-                            break;
-                        }
-                    }
-                    if (bdo)    {
-                        ASSIMP_LOG_INFO("IRR: Replacing mesh vertex alpha with common opacity");
-
-                        for (unsigned int a = 0; a < mesh->mNumVertices;++a)
-                            mesh->mColors[0][a].a = 1.f;
-
-                        mat->AddProperty(& mesh->mColors[0][0].a, 1, AI_MATKEY_OPACITY);
-                    }
-                }
-
-                // If we have a second texture coordinate set and a second texture
-                // (either lightmap, normalmap, 2layered material) we need to
-                // setup the correct UV index for it. The texture can either
-                // be diffuse (lightmap & 2layer) or a normal map (normal & parallax)
-                if (mesh->HasTextureCoords(1))  {
-
-                    int idx = 1;
-                    if (src.second & (AI_IRRMESH_MAT_solid_2layer | AI_IRRMESH_MAT_lightmap))   {
-                        mat->AddProperty(&idx,1,AI_MATKEY_UVWSRC_DIFFUSE(0));
-                    }
-                    else if (src.second & AI_IRRMESH_MAT_normalmap_solid)   {
-                        mat->AddProperty(&idx,1,AI_MATKEY_UVWSRC_NORMALS(0));
-                    }
-                }
-            }
-        }
-        break;
-
-    case Node::LIGHT:
-    case Node::CAMERA:
-
-        // We're already finished with lights and cameras
-        break;
-
-
-    case Node::SPHERE:
-        {
-            // Generate the sphere model. Our input parameter to
-            // the sphere generation algorithm is the number of
-            // subdivisions of each triangle - but here we have
-            // the number of poylgons on a specific axis. Just
-            // use some hardcoded limits to approximate this ...
-            unsigned int mul = root->spherePolyCountX*root->spherePolyCountY;
-            if      (mul < 100)mul = 2;
-            else if (mul < 300)mul = 3;
-            else               mul = 4;
-
-            meshes.push_back(StandardShapes::MakeMesh(mul,
-                &StandardShapes::MakeSphere));
-
-            // Adjust scaling
-            root->scaling *= root->sphereRadius/2;
-
-            // Copy one output material
-            CopyMaterial(materials, root->materials, defMatIdx, meshes.back());
-
-            // Now adjust this output material - if there is a first texture
-            // set, setup spherical UV mapping around the Y axis.
-            SetupMapping ( (aiMaterial*) materials.back(), aiTextureMapping_SPHERE);
-        }
-        break;
-
-    case Node::CUBE:
-        {
-            // Generate an unit cube first
-            meshes.push_back(StandardShapes::MakeMesh(
-                &StandardShapes::MakeHexahedron));
-
-            // Adjust scaling
-            root->scaling *= root->sphereRadius;
-
-            // Copy one output material
-            CopyMaterial(materials, root->materials, defMatIdx, meshes.back());
-
-            // Now adjust this output material - if there is a first texture
-            // set, setup cubic UV mapping
-            SetupMapping ( (aiMaterial*) materials.back(), aiTextureMapping_BOX );
-        }
-        break;
-
-
-    case Node::SKYBOX:
-        {
-            // A skybox is defined by six materials
-            if (root->materials.size() < 6) {
-                ASSIMP_LOG_ERROR("IRR: There should be six materials for a skybox");
-                break;
-            }
-
-            // copy those materials and generate 6 meshes for our new skybox
-            materials.reserve(materials.size() + 6);
-            for (unsigned int i = 0; i < 6;++i)
-                materials.insert(materials.end(),root->materials[i].first);
-
-            BuildSkybox(meshes,materials);
-
-            // *************************************************************
-            // Skyboxes will require a different code path for rendering,
-            // so there must be a way for the user to add special support
-            // for IRR skyboxes. We add a 'IRR.SkyBox_' prefix to the node.
-            // *************************************************************
-            root->name = "IRR.SkyBox_" + root->name;
-            ASSIMP_LOG_INFO("IRR: Loading skybox, this will "
-                "require special handling to be displayed correctly");
-        }
-        break;
-
-    case Node::TERRAIN:
-        {
-            // to support terrains, we'd need to have a texture decoder
-            ASSIMP_LOG_ERROR("IRR: Unsupported node - TERRAIN");
-        }
-        break;
-    default:
-        // DUMMY
-        break;
-    };
-
-    // Check whether we added a mesh (or more than one ...). In this case
-    // we'll also need to attach it to the node
-    if (oldMeshSize != (unsigned int) meshes.size())    {
-
-        rootOut->mNumMeshes = (unsigned int)meshes.size() - oldMeshSize;
-        rootOut->mMeshes    = new unsigned int[rootOut->mNumMeshes];
-
-        for (unsigned int a = 0; a  < rootOut->mNumMeshes;++a)  {
-            rootOut->mMeshes[a] = oldMeshSize+a;
-        }
-    }
-
-    // Setup the name of this node
-    rootOut->mName.Set(root->name);
-
-    // Now compute the final local transformation matrix of the
-    // node from the given translation, rotation and scaling values.
-    // (the rotation is given in Euler angles, XYZ order)
-    //std::swap((float&)root->rotation.z,(float&)root->rotation.y);
-    rootOut->mTransformation.FromEulerAnglesXYZ(AI_DEG_TO_RAD(root->rotation) );
-
-    // apply scaling
-    aiMatrix4x4& mat = rootOut->mTransformation;
-    mat.a1 *= root->scaling.x;
-    mat.b1 *= root->scaling.x;
-    mat.c1 *= root->scaling.x;
-    mat.a2 *= root->scaling.y;
-    mat.b2 *= root->scaling.y;
-    mat.c2 *= root->scaling.y;
-    mat.a3 *= root->scaling.z;
-    mat.b3 *= root->scaling.z;
-    mat.c3 *= root->scaling.z;
-
-    // apply translation
-    mat.a4 += root->position.x;
-    mat.b4 += root->position.y;
-    mat.c4 += root->position.z;
-
-    // now compute animations for the node
-    ComputeAnimations(root,rootOut, anims);
-
-    // Add all children recursively. First allocate enough storage
-    // for them, then call us again
-    rootOut->mNumChildren = (unsigned int)root->children.size();
-    if (rootOut->mNumChildren)  {
-
-        rootOut->mChildren = new aiNode*[rootOut->mNumChildren];
-        for (unsigned int i = 0; i < rootOut->mNumChildren;++i) {
-
-            aiNode* node = rootOut->mChildren[i] =  new aiNode();
-            node->mParent = rootOut;
-            GenerateGraph(root->children[i],node,scene,batch,meshes,
-                anims,attach,materials,defMatIdx);
-        }
-    }
+void IRRImporter::GenerateGraph(Node *root, aiNode *rootOut, aiScene *scene,
+		BatchLoader &batch,
+		std::vector<aiMesh *> &meshes,
+		std::vector<aiNodeAnim *> &anims,
+		std::vector<AttachmentInfo> &attach,
+		std::vector<aiMaterial *> &materials,
+		unsigned int &defMatIdx) {
+	unsigned int oldMeshSize = (unsigned int)meshes.size();
+	//unsigned int meshTrafoAssign = 0;
+
+	// Now determine the type of the node
+	switch (root->type) {
+		case Node::ANIMMESH:
+		case Node::MESH: {
+			if (!root->meshPath.length())
+				break;
+
+			// Get the loaded mesh from the scene and add it to
+			// the list of all scenes to be attached to the
+			// graph we're currently building
+			aiScene *localScene = batch.GetImport(root->id);
+			if (!localScene) {
+				ASSIMP_LOG_ERROR("IRR: Unable to load external file: " + root->meshPath);
+				break;
+			}
+			attach.push_back(AttachmentInfo(localScene, rootOut));
+
+			// Now combine the material we've loaded for this mesh
+			// with the real materials we got from the file. As we
+			// don't execute any pp-steps on the file, the numbers
+			// should be equal. If they are not, we can impossibly
+			// do this  ...
+			if (root->materials.size() != (unsigned int)localScene->mNumMaterials) {
+				ASSIMP_LOG_WARN("IRR: Failed to match imported materials "
+								"with the materials found in the IRR scene file");
+
+				break;
+			}
+			for (unsigned int i = 0; i < localScene->mNumMaterials; ++i) {
+				// Delete the old material, we don't need it anymore
+				delete localScene->mMaterials[i];
+
+				std::pair<aiMaterial *, unsigned int> &src = root->materials[i];
+				localScene->mMaterials[i] = src.first;
+			}
+
+			// NOTE: Each mesh should have exactly one material assigned,
+			// but we do it in a separate loop if this behaviour changes
+			// in future.
+			for (unsigned int i = 0; i < localScene->mNumMeshes; ++i) {
+				// Process material flags
+				aiMesh *mesh = localScene->mMeshes[i];
+
+				// If "trans_vertex_alpha" mode is enabled, search all vertex colors
+				// and check whether they have a common alpha value. This is quite
+				// often the case so we can simply extract it to a shared oacity
+				// value.
+				std::pair<aiMaterial *, unsigned int> &src = root->materials[mesh->mMaterialIndex];
+				aiMaterial *mat = (aiMaterial *)src.first;
+
+				if (mesh->HasVertexColors(0) && src.second & AI_IRRMESH_MAT_trans_vertex_alpha) {
+					bool bdo = true;
+					for (unsigned int a = 1; a < mesh->mNumVertices; ++a) {
+
+						if (mesh->mColors[0][a].a != mesh->mColors[0][a - 1].a) {
+							bdo = false;
+							break;
+						}
+					}
+					if (bdo) {
+						ASSIMP_LOG_INFO("IRR: Replacing mesh vertex alpha with common opacity");
+
+						for (unsigned int a = 0; a < mesh->mNumVertices; ++a)
+							mesh->mColors[0][a].a = 1.f;
+
+						mat->AddProperty(&mesh->mColors[0][0].a, 1, AI_MATKEY_OPACITY);
+					}
+				}
+
+				// If we have a second texture coordinate set and a second texture
+				// (either lightmap, normalmap, 2layered material) we need to
+				// setup the correct UV index for it. The texture can either
+				// be diffuse (lightmap & 2layer) or a normal map (normal & parallax)
+				if (mesh->HasTextureCoords(1)) {
+
+					int idx = 1;
+					if (src.second & (AI_IRRMESH_MAT_solid_2layer | AI_IRRMESH_MAT_lightmap)) {
+						mat->AddProperty(&idx, 1, AI_MATKEY_UVWSRC_DIFFUSE(0));
+					} else if (src.second & AI_IRRMESH_MAT_normalmap_solid) {
+						mat->AddProperty(&idx, 1, AI_MATKEY_UVWSRC_NORMALS(0));
+					}
+				}
+			}
+		} break;
+
+		case Node::LIGHT:
+		case Node::CAMERA:
+
+			// We're already finished with lights and cameras
+			break;
+
+		case Node::SPHERE: {
+			// Generate the sphere model. Our input parameter to
+			// the sphere generation algorithm is the number of
+			// subdivisions of each triangle - but here we have
+			// the number of poylgons on a specific axis. Just
+			// use some hardcoded limits to approximate this ...
+			unsigned int mul = root->spherePolyCountX * root->spherePolyCountY;
+			if (mul < 100)
+				mul = 2;
+			else if (mul < 300)
+				mul = 3;
+			else
+				mul = 4;
+
+			meshes.push_back(StandardShapes::MakeMesh(mul,
+					&StandardShapes::MakeSphere));
+
+			// Adjust scaling
+			root->scaling *= root->sphereRadius / 2;
+
+			// Copy one output material
+			CopyMaterial(materials, root->materials, defMatIdx, meshes.back());
+
+			// Now adjust this output material - if there is a first texture
+			// set, setup spherical UV mapping around the Y axis.
+			SetupMapping((aiMaterial *)materials.back(), aiTextureMapping_SPHERE);
+		} break;
+
+		case Node::CUBE: {
+			// Generate an unit cube first
+			meshes.push_back(StandardShapes::MakeMesh(
+					&StandardShapes::MakeHexahedron));
+
+			// Adjust scaling
+			root->scaling *= root->sphereRadius;
+
+			// Copy one output material
+			CopyMaterial(materials, root->materials, defMatIdx, meshes.back());
+
+			// Now adjust this output material - if there is a first texture
+			// set, setup cubic UV mapping
+			SetupMapping((aiMaterial *)materials.back(), aiTextureMapping_BOX);
+		} break;
+
+		case Node::SKYBOX: {
+			// A skybox is defined by six materials
+			if (root->materials.size() < 6) {
+				ASSIMP_LOG_ERROR("IRR: There should be six materials for a skybox");
+				break;
+			}
+
+			// copy those materials and generate 6 meshes for our new skybox
+			materials.reserve(materials.size() + 6);
+			for (unsigned int i = 0; i < 6; ++i)
+				materials.insert(materials.end(), root->materials[i].first);
+
+			BuildSkybox(meshes, materials);
+
+			// *************************************************************
+			// Skyboxes will require a different code path for rendering,
+			// so there must be a way for the user to add special support
+			// for IRR skyboxes. We add a 'IRR.SkyBox_' prefix to the node.
+			// *************************************************************
+			root->name = "IRR.SkyBox_" + root->name;
+			ASSIMP_LOG_INFO("IRR: Loading skybox, this will "
+							"require special handling to be displayed correctly");
+		} break;
+
+		case Node::TERRAIN: {
+			// to support terrains, we'd need to have a texture decoder
+			ASSIMP_LOG_ERROR("IRR: Unsupported node - TERRAIN");
+		} break;
+		default:
+			// DUMMY
+			break;
+	};
+
+	// Check whether we added a mesh (or more than one ...). In this case
+	// we'll also need to attach it to the node
+	if (oldMeshSize != (unsigned int)meshes.size()) {
+
+		rootOut->mNumMeshes = (unsigned int)meshes.size() - oldMeshSize;
+		rootOut->mMeshes = new unsigned int[rootOut->mNumMeshes];
+
+		for (unsigned int a = 0; a < rootOut->mNumMeshes; ++a) {
+			rootOut->mMeshes[a] = oldMeshSize + a;
+		}
+	}
+
+	// Setup the name of this node
+	rootOut->mName.Set(root->name);
+
+	// Now compute the final local transformation matrix of the
+	// node from the given translation, rotation and scaling values.
+	// (the rotation is given in Euler angles, XYZ order)
+	//std::swap((float&)root->rotation.z,(float&)root->rotation.y);
+	rootOut->mTransformation.FromEulerAnglesXYZ(AI_DEG_TO_RAD(root->rotation));
+
+	// apply scaling
+	aiMatrix4x4 &mat = rootOut->mTransformation;
+	mat.a1 *= root->scaling.x;
+	mat.b1 *= root->scaling.x;
+	mat.c1 *= root->scaling.x;
+	mat.a2 *= root->scaling.y;
+	mat.b2 *= root->scaling.y;
+	mat.c2 *= root->scaling.y;
+	mat.a3 *= root->scaling.z;
+	mat.b3 *= root->scaling.z;
+	mat.c3 *= root->scaling.z;
+
+	// apply translation
+	mat.a4 += root->position.x;
+	mat.b4 += root->position.y;
+	mat.c4 += root->position.z;
+
+	// now compute animations for the node
+	ComputeAnimations(root, rootOut, anims);
+
+	// Add all children recursively. First allocate enough storage
+	// for them, then call us again
+	rootOut->mNumChildren = (unsigned int)root->children.size();
+	if (rootOut->mNumChildren) {
+
+		rootOut->mChildren = new aiNode *[rootOut->mNumChildren];
+		for (unsigned int i = 0; i < rootOut->mNumChildren; ++i) {
+
+			aiNode *node = rootOut->mChildren[i] = new aiNode();
+			node->mParent = rootOut;
+			GenerateGraph(root->children[i], node, scene, batch, meshes,
+					anims, attach, materials, defMatIdx);
+		}
+	}
 }
 
 // ------------------------------------------------------------------------------------------------
 // Imports the given file into the given scene structure.
-void IRRImporter::InternReadFile( const std::string& pFile,
-    aiScene* pScene, IOSystem* pIOHandler)
-{
-    std::unique_ptr<IOStream> file( pIOHandler->Open( pFile));
-
-    // Check whether we can read from the file
-    if (file.get() == nullptr) {
-        throw DeadlyImportError("Failed to open IRR file " + pFile + "");
-    }
-
-    // Construct the irrXML parser
-    CIrrXML_IOStreamReader st(file.get());
-    reader = createIrrXMLReader((IFileReadCallBack*) &st);
-
-    // The root node of the scene
-    Node* root = new Node(Node::DUMMY);
-    root->parent = nullptr;
-    root->name = "<IRRSceneRoot>";
-
-    // Current node parent
-    Node* curParent = root;
-
-    // Scenegraph node we're currently working on
-    Node* curNode = nullptr;
-
-    // List of output cameras
-    std::vector<aiCamera*> cameras;
-
-    // List of output lights
-    std::vector<aiLight*> lights;
-
-    // Batch loader used to load external models
-    BatchLoader batch(pIOHandler);
-//  batch.SetBasePath(pFile);
-
-    cameras.reserve(5);
-    lights.reserve(5);
-
-    bool inMaterials = false, inAnimator = false;
-    unsigned int guessedAnimCnt = 0, guessedMeshCnt = 0, guessedMatCnt = 0;
-
-    // Parse the XML file
-    while (reader->read())  {
-        switch (reader->getNodeType())  {
-        case EXN_ELEMENT:
-
-            if (!ASSIMP_stricmp(reader->getNodeName(),"node"))  {
-                // ***********************************************************************
-                /*  What we're going to do with the node depends
-                 *  on its type:
-                 *
-                 *  "mesh" - Load a mesh from an external file
-                 *  "cube" - Generate a cube
-                 *  "skybox" - Generate a skybox
-                 *  "light" - A light source
-                 *  "sphere" - Generate a sphere mesh
-                 *  "animatedMesh" - Load an animated mesh from an external file
-                 *    and join its animation channels with ours.
-                 *  "empty" - A dummy node
-                 *  "camera" - A camera
-                 *  "terrain" - a terrain node (data comes from a heightmap)
-                 *  "billboard", ""
-                 *
-                 *  Each of these nodes can be animated and all can have multiple
-                 *  materials assigned (except lights, cameras and dummies, of course).
-                 */
-                // ***********************************************************************
-                const char* sz = reader->getAttributeValueSafe("type");
-                Node* nd;
-                if (!ASSIMP_stricmp(sz,"mesh") || !ASSIMP_stricmp(sz,"octTree"))    {
-                    // OctTree's and meshes are treated equally
-                    nd = new Node(Node::MESH);
-                }
-                else if (!ASSIMP_stricmp(sz,"cube"))    {
-                    nd = new Node(Node::CUBE);
-                    ++guessedMeshCnt;
-                    // meshes.push_back(StandardShapes::MakeMesh(&StandardShapes::MakeHexahedron));
-                }
-                else if (!ASSIMP_stricmp(sz,"skybox"))  {
-                    nd = new Node(Node::SKYBOX);
-                    guessedMeshCnt += 6;
-                }
-                else if (!ASSIMP_stricmp(sz,"camera"))  {
-                    nd = new Node(Node::CAMERA);
-
-                    // Setup a temporary name for the camera
-                    aiCamera* cam = new aiCamera();
-                    cam->mName.Set( nd->name );
-                    cameras.push_back(cam);
-                }
-                else if (!ASSIMP_stricmp(sz,"light"))   {
-                    nd = new Node(Node::LIGHT);
-
-                    // Setup a temporary name for the light
-                    aiLight* cam = new aiLight();
-                    cam->mName.Set( nd->name );
-                    lights.push_back(cam);
-                }
-                else if (!ASSIMP_stricmp(sz,"sphere"))  {
-                    nd = new Node(Node::SPHERE);
-                    ++guessedMeshCnt;
-                }
-                else if (!ASSIMP_stricmp(sz,"animatedMesh"))    {
-                    nd = new Node(Node::ANIMMESH);
-                }
-                else if (!ASSIMP_stricmp(sz,"empty"))   {
-                    nd = new Node(Node::DUMMY);
-                }
-                else if (!ASSIMP_stricmp(sz,"terrain")) {
-                    nd = new Node(Node::TERRAIN);
-                }
-                else if (!ASSIMP_stricmp(sz,"billBoard"))   {
-                    // We don't support billboards, so ignore them
-                    ASSIMP_LOG_ERROR("IRR: Billboards are not supported by Assimp");
-                    nd = new Node(Node::DUMMY);
-                }
-                else    {
-                    ASSIMP_LOG_WARN("IRR: Found unknown node: " + std::string(sz));
-
-                    /*  We skip the contents of nodes we don't know.
-                     *  We parse the transformation and all animators
-                     *  and skip the rest.
+void IRRImporter::InternReadFile(const std::string &pFile,
+		aiScene *pScene, IOSystem *pIOHandler) {
+	std::unique_ptr<IOStream> file(pIOHandler->Open(pFile));
+
+	// Check whether we can read from the file
+	if (file.get() == nullptr) {
+		throw DeadlyImportError("Failed to open IRR file " + pFile + "");
+	}
+
+	// Construct the irrXML parser
+	XmlParser st;
+	pugi::xml_node *rootElement = st.parse(file.get());
+	//    reader = createIrrXMLReader((IFileReadCallBack*) &st);
+
+	// The root node of the scene
+	Node *root = new Node(Node::DUMMY);
+	root->parent = nullptr;
+	root->name = "<IRRSceneRoot>";
+
+	// Current node parent
+	Node *curParent = root;
+
+	// Scenegraph node we're currently working on
+	Node *curNode = nullptr;
+
+	// List of output cameras
+	std::vector<aiCamera *> cameras;
+
+	// List of output lights
+	std::vector<aiLight *> lights;
+
+	// Batch loader used to load external models
+	BatchLoader batch(pIOHandler);
+	//  batch.SetBasePath(pFile);
+
+	cameras.reserve(5);
+	lights.reserve(5);
+
+	bool inMaterials = false, inAnimator = false;
+	unsigned int guessedAnimCnt = 0, guessedMeshCnt = 0, guessedMatCnt = 0;
+
+	// Parse the XML file
+
+	//while (reader->read())  {
+	for (pugi::xml_node child : rootElement->children())
+		switch (child.type()) {
+			case pugi::node_element:
+                if (!ASSIMP_stricmp(child.name(), "node")) {
+					// ***********************************************************************
+					/*  What we're going to do with the node depends
+                     *  on its type:
+                     *
+                     *  "mesh" - Load a mesh from an external file
+                     *  "cube" - Generate a cube
+                     *  "skybox" - Generate a skybox
+                     *  "light" - A light source
+                     *  "sphere" - Generate a sphere mesh
+                     *  "animatedMesh" - Load an animated mesh from an external file
+                     *    and join its animation channels with ours.
+                     *  "empty" - A dummy node
+                     *  "camera" - A camera
+                     *  "terrain" - a terrain node (data comes from a heightmap)
+                     *  "billboard", ""
+                     *
+                     *  Each of these nodes can be animated and all can have multiple
+                     *  materials assigned (except lights, cameras and dummies, of course).
                      */
-                    nd = new Node(Node::DUMMY);
-                }
-
-                /* Attach the newly created node to the scenegraph
-                 */
-                curNode = nd;
-                nd->parent = curParent;
-                curParent->children.push_back(nd);
-            }
-            else if (!ASSIMP_stricmp(reader->getNodeName(),"materials"))    {
-                inMaterials = true;
-            }
-            else if (!ASSIMP_stricmp(reader->getNodeName(),"animators"))    {
-                inAnimator = true;
-            }
-            else if (!ASSIMP_stricmp(reader->getNodeName(),"attributes"))   {
-                /*  We should have a valid node here
-                 *  FIX: no ... the scene root node is also contained in an attributes block
-                 */
-                if (!curNode)   {
+					// ***********************************************************************
+					//const char *sz = reader->getAttributeValueSafe("type");
+					pugi::xml_attribute attrib = child.attribute("type");
+					Node *nd;
+					if (!ASSIMP_stricmp(attrib.name(), "mesh") || !ASSIMP_stricmp(attrib.name(), "octTree")) {
+						// OctTree's and meshes are treated equally
+						nd = new Node(Node::MESH);
+					} else if (!ASSIMP_stricmp(attrib.name(), "cube")) {
+						nd = new Node(Node::CUBE);
+						++guessedMeshCnt;
+					} else if (!ASSIMP_stricmp(attrib.name(), "skybox")) {
+						nd = new Node(Node::SKYBOX);
+						guessedMeshCnt += 6;
+					} else if (!ASSIMP_stricmp(attrib.name(), "camera")) {
+						nd = new Node(Node::CAMERA);
+
+						// Setup a temporary name for the camera
+						aiCamera *cam = new aiCamera();
+						cam->mName.Set(nd->name);
+						cameras.push_back(cam);
+					} else if (!ASSIMP_stricmp(attrib.name(), "light")) {
+						nd = new Node(Node::LIGHT);
+
+						// Setup a temporary name for the light
+						aiLight *cam = new aiLight();
+						cam->mName.Set(nd->name);
+						lights.push_back(cam);
+					} else if (!ASSIMP_stricmp(attrib.name(), "sphere")) {
+						nd = new Node(Node::SPHERE);
+						++guessedMeshCnt;
+					} else if (!ASSIMP_stricmp(attrib.name(), "animatedMesh")) {
+						nd = new Node(Node::ANIMMESH);
+					} else if (!ASSIMP_stricmp(attrib.name(), "empty")) {
+						nd = new Node(Node::DUMMY);
+					} else if (!ASSIMP_stricmp(attrib.name(), "terrain")) {
+						nd = new Node(Node::TERRAIN);
+					} else if (!ASSIMP_stricmp(attrib.name(), "billBoard")) {
+						// We don't support billboards, so ignore them
+						ASSIMP_LOG_ERROR("IRR: Billboards are not supported by Assimp");
+						nd = new Node(Node::DUMMY);
+					} else {
+						ASSIMP_LOG_WARN("IRR: Found unknown node: " + std::string(attrib.name()));
+
+						/*  We skip the contents of nodes we don't know.
+                         *  We parse the transformation and all animators
+                         *  and skip the rest.
+                         */
+						nd = new Node(Node::DUMMY);
+					}
+
+					/* Attach the newly created node to the scene-graph
+                     */
+					curNode = nd;
+					nd->parent = curParent;
+					curParent->children.push_back(nd);
+				} else if (!ASSIMP_stricmp(child.name(), "materials")) {
+					inMaterials = true;
+				} else if (!ASSIMP_stricmp(child.name(), "animators")) {
+					inAnimator = true;
+				} else if (!ASSIMP_stricmp(child.name(), "attributes")) {
+					//  We should have a valid node here
+                    //  FIX: no ... the scene root node is also contained in an attributes block
+					if (!curNode) {
 #if 0
-                    ASSIMP_LOG_ERROR("IRR: Encountered <attributes> element, but "
-                        "there is no node active");
+                        ASSIMP_LOG_ERROR("IRR: Encountered <attributes> element, but "
+                            "there is no node active");
 #endif
-                    continue;
-                }
+						continue;
+					}
 
-                Animator* curAnim = nullptr;
+					Animator *curAnim = nullptr;
 
-                // Materials can occur for nearly any type of node
-                if (inMaterials && curNode->type != Node::DUMMY)    {
-                    /*  This is a material description - parse it!
-                     */
-                    curNode->materials.push_back(std::pair< aiMaterial*, unsigned int > () );
-                    std::pair< aiMaterial*, unsigned int >& p = curNode->materials.back();
+					// Materials can occur for nearly any type of node
+					if (inMaterials && curNode->type != Node::DUMMY) {
+						//  This is a material description - parse it!
+						curNode->materials.push_back(std::pair<aiMaterial *, unsigned int>());
+						std::pair<aiMaterial *, unsigned int> &p = curNode->materials.back();
+
+						p.first = ParseMaterial(p.second);
 
-                    p.first = ParseMaterial(p.second);
+						++guessedMatCnt;
+						continue;
+					} else if (inAnimator) {
+						//  This is an animation path - add a new animator
+                        //  to the list.
+						curNode->animators.push_back(Animator());
+						curAnim = &curNode->animators.back();
 
-                    ++guessedMatCnt;
-                    continue;
-                }
-                else if (inAnimator)    {
-                    /*  This is an animation path - add a new animator
-                     *  to the list.
+						++guessedAnimCnt;
+					}
+
+					/*  Parse all elements in the attributes block
+                     *  and process them.
                      */
-                    curNode->animators.push_back(Animator());
-                    curAnim = & curNode->animators.back();
-
-                    ++guessedAnimCnt;
-                }
-
-                /*  Parse all elements in the attributes block
-                 *  and process them.
-                 */
-                while (reader->read())  {
-                    if (reader->getNodeType() == EXN_ELEMENT)   {
-                        if (!ASSIMP_stricmp(reader->getNodeName(),"vector3d"))  {
-                            VectorProperty prop;
-                            ReadVectorProperty(prop);
-
-                            if (inAnimator) {
-                                if (curAnim->type == Animator::ROTATION && prop.name == "Rotation") {
-                                    // We store the rotation euler angles in 'direction'
-                                    curAnim->direction = prop.value;
-                                }
-                                else if (curAnim->type == Animator::FOLLOW_SPLINE)  {
-                                    // Check whether the vector follows the PointN naming scheme,
-                                    // here N is the ONE-based index of the point
-                                    if (prop.name.length() >= 6 && prop.name.substr(0,5) == "Point")    {
-                                        // Add a new key to the list
-                                        curAnim->splineKeys.push_back(aiVectorKey());
-                                        aiVectorKey& key = curAnim->splineKeys.back();
-
-                                        // and parse its properties
-                                        key.mValue = prop.value;
-                                        key.mTime  = strtoul10(&prop.name[5]);
-                                    }
-                                }
-                                else if (curAnim->type == Animator::FLY_CIRCLE) {
-                                    if (prop.name == "Center")  {
-                                        curAnim->circleCenter = prop.value;
-                                    }
-                                    else if (prop.name == "Direction")  {
-                                        curAnim->direction = prop.value;
-
-                                        // From Irrlicht's source - a workaround for backward compatibility with Irrlicht 1.1
-                                        if (curAnim->direction == aiVector3D()) {
-                                            curAnim->direction = aiVector3D(0.f,1.f,0.f);
-                                        }
-                                        else curAnim->direction.Normalize();
-                                    }
-                                }
-                                else if (curAnim->type == Animator::FLY_STRAIGHT)   {
-                                    if (prop.name == "Start")   {
-                                        // We reuse the field here
-                                        curAnim->circleCenter = prop.value;
-                                    }
-                                    else if (prop.name == "End")    {
-                                        // We reuse the field here
-                                        curAnim->direction = prop.value;
-                                    }
-                                }
-                            }
-                            else    {
-                                if (prop.name == "Position")    {
-                                    curNode->position = prop.value;
-                                }
-                                else if (prop.name == "Rotation")   {
-                                    curNode->rotation = prop.value;
-                                }
-                                else if (prop.name == "Scale")  {
-                                    curNode->scaling = prop.value;
-                                }
-                                else if (Node::CAMERA == curNode->type)
-                                {
-                                    aiCamera* cam = cameras.back();
-                                    if (prop.name == "Target")  {
-                                        cam->mLookAt = prop.value;
-                                    }
-                                    else if (prop.name == "UpVector")   {
-                                        cam->mUp = prop.value;
-                                    }
-                                }
-                            }
-                        }
-                        else if (!ASSIMP_stricmp(reader->getNodeName(),"bool")) {
-                            BoolProperty prop;
-                            ReadBoolProperty(prop);
-
-                            if (inAnimator && curAnim->type == Animator::FLY_CIRCLE && prop.name == "Loop") {
-                                curAnim->loop = prop.value;
-                            }
-                        }
-                        else if (!ASSIMP_stricmp(reader->getNodeName(),"float"))    {
-                            FloatProperty prop;
-                            ReadFloatProperty(prop);
-
-                            if (inAnimator) {
-                                // The speed property exists for several animators
-                                if (prop.name == "Speed")   {
-                                    curAnim->speed = prop.value;
-                                }
-                                else if (curAnim->type == Animator::FLY_CIRCLE && prop.name == "Radius")    {
-                                    curAnim->circleRadius = prop.value;
-                                }
-                                else if (curAnim->type == Animator::FOLLOW_SPLINE && prop.name == "Tightness")  {
-                                    curAnim->tightness = prop.value;
-                                }
-                            }
-                            else    {
-                                if (prop.name == "FramesPerSecond" && Node::ANIMMESH == curNode->type)  {
-                                    curNode->framesPerSecond = prop.value;
-                                }
-                                else if (Node::CAMERA == curNode->type) {
-                                    /*  This is the vertical, not the horizontal FOV.
+//					while (reader->read()) {
+					for (pugi::xml_node attrib : child.children()) {
+						if (attrib.type() == pugi::node_element) {
+						//if (reader->getNodeType() == EXN_ELEMENT) {
+							//if (!ASSIMP_stricmp(reader->getNodeName(), "vector3d")) {
+							if (!ASSIMP_stricmp(attrib.name(), "vector3d")) {
+								VectorProperty prop;
+								ReadVectorProperty(prop);
+
+								if (inAnimator) {
+									if (curAnim->type == Animator::ROTATION && prop.name == "Rotation") {
+										// We store the rotation euler angles in 'direction'
+										curAnim->direction = prop.value;
+									} else if (curAnim->type == Animator::FOLLOW_SPLINE) {
+										// Check whether the vector follows the PointN naming scheme,
+										// here N is the ONE-based index of the point
+										if (prop.name.length() >= 6 && prop.name.substr(0, 5) == "Point") {
+											// Add a new key to the list
+											curAnim->splineKeys.push_back(aiVectorKey());
+											aiVectorKey &key = curAnim->splineKeys.back();
+
+											// and parse its properties
+											key.mValue = prop.value;
+											key.mTime = strtoul10(&prop.name[5]);
+										}
+									} else if (curAnim->type == Animator::FLY_CIRCLE) {
+										if (prop.name == "Center") {
+											curAnim->circleCenter = prop.value;
+										} else if (prop.name == "Direction") {
+											curAnim->direction = prop.value;
+
+											// From Irrlicht's source - a workaround for backward compatibility with Irrlicht 1.1
+											if (curAnim->direction == aiVector3D()) {
+												curAnim->direction = aiVector3D(0.f, 1.f, 0.f);
+											} else
+												curAnim->direction.Normalize();
+										}
+									} else if (curAnim->type == Animator::FLY_STRAIGHT) {
+										if (prop.name == "Start") {
+											// We reuse the field here
+											curAnim->circleCenter = prop.value;
+										} else if (prop.name == "End") {
+											// We reuse the field here
+											curAnim->direction = prop.value;
+										}
+									}
+								} else {
+									if (prop.name == "Position") {
+										curNode->position = prop.value;
+									} else if (prop.name == "Rotation") {
+										curNode->rotation = prop.value;
+									} else if (prop.name == "Scale") {
+										curNode->scaling = prop.value;
+									} else if (Node::CAMERA == curNode->type) {
+										aiCamera *cam = cameras.back();
+										if (prop.name == "Target") {
+											cam->mLookAt = prop.value;
+										} else if (prop.name == "UpVector") {
+											cam->mUp = prop.value;
+										}
+									}
+								}
+							//} else if (!ASSIMP_stricmp(reader->getNodeName(), "bool")) {
+                            } else if (!ASSIMP_stricmp(attrib.name(), "bool")) {
+								BoolProperty prop;
+								ReadBoolProperty(prop);
+
+								if (inAnimator && curAnim->type == Animator::FLY_CIRCLE && prop.name == "Loop") {
+									curAnim->loop = prop.value;
+								}
+							//} else if (!ASSIMP_stricmp(reader->getNodeName(), "float")) {
+                            } else if (!ASSIMP_stricmp(attrib.name(), "float")) {
+								FloatProperty prop;
+								ReadFloatProperty(prop);
+
+								if (inAnimator) {
+									// The speed property exists for several animators
+									if (prop.name == "Speed") {
+										curAnim->speed = prop.value;
+									} else if (curAnim->type == Animator::FLY_CIRCLE && prop.name == "Radius") {
+										curAnim->circleRadius = prop.value;
+									} else if (curAnim->type == Animator::FOLLOW_SPLINE && prop.name == "Tightness") {
+										curAnim->tightness = prop.value;
+									}
+								} else {
+									if (prop.name == "FramesPerSecond" && Node::ANIMMESH == curNode->type) {
+										curNode->framesPerSecond = prop.value;
+									} else if (Node::CAMERA == curNode->type) {
+										/*  This is the vertical, not the horizontal FOV.
                                     *  We need to compute the right FOV from the
                                     *  screen aspect which we don't know yet.
                                     */
-                                    if (prop.name == "Fovy")    {
-                                        cameras.back()->mHorizontalFOV  = prop.value;
-                                    }
-                                    else if (prop.name == "Aspect") {
-                                        cameras.back()->mAspect = prop.value;
-                                    }
-                                    else if (prop.name == "ZNear")  {
-                                        cameras.back()->mClipPlaneNear = prop.value;
-                                    }
-                                    else if (prop.name == "ZFar")   {
-                                        cameras.back()->mClipPlaneFar = prop.value;
-                                    }
-                                }
-                                else if (Node::LIGHT == curNode->type)  {
-                                    /*  Additional light information
+										if (prop.name == "Fovy") {
+											cameras.back()->mHorizontalFOV = prop.value;
+										} else if (prop.name == "Aspect") {
+											cameras.back()->mAspect = prop.value;
+										} else if (prop.name == "ZNear") {
+											cameras.back()->mClipPlaneNear = prop.value;
+										} else if (prop.name == "ZFar") {
+											cameras.back()->mClipPlaneFar = prop.value;
+										}
+									} else if (Node::LIGHT == curNode->type) {
+										/*  Additional light information
                                      */
-                                    if (prop.name == "Attenuation") {
-                                        lights.back()->mAttenuationLinear  = prop.value;
-                                    }
-                                    else if (prop.name == "OuterCone")  {
-                                        lights.back()->mAngleOuterCone =  AI_DEG_TO_RAD( prop.value );
-                                    }
-                                    else if (prop.name == "InnerCone")  {
-                                        lights.back()->mAngleInnerCone =  AI_DEG_TO_RAD( prop.value );
-                                    }
-                                }
-                                // radius of the sphere to be generated -
-                                // or alternatively, size of the cube
-                                else if ((Node::SPHERE == curNode->type && prop.name == "Radius")
-                                    || (Node::CUBE == curNode->type   && prop.name == "Size" )) {
-
-                                        curNode->sphereRadius = prop.value;
-                                }
-                            }
-                        }
-                        else if (!ASSIMP_stricmp(reader->getNodeName(),"int"))  {
-                            IntProperty prop;
-                            ReadIntProperty(prop);
-
-                            if (inAnimator) {
-                                if (curAnim->type == Animator::FLY_STRAIGHT && prop.name == "TimeForWay")   {
-                                    curAnim->timeForWay = prop.value;
-                                }
-                            }
-                            else    {
-                                // sphere polgon numbers in each direction
-                                if (Node::SPHERE == curNode->type)  {
-
-                                    if (prop.name == "PolyCountX")  {
-                                        curNode->spherePolyCountX = prop.value;
-                                    }
-                                    else if (prop.name == "PolyCountY") {
-                                        curNode->spherePolyCountY = prop.value;
-                                    }
-                                }
-                            }
-                        }
-                        else if (!ASSIMP_stricmp(reader->getNodeName(),"string") ||!ASSIMP_stricmp(reader->getNodeName(),"enum"))   {
-                            StringProperty prop;
-                            ReadStringProperty(prop);
-                            if (prop.value.length())    {
-                                if (prop.name == "Name")    {
-                                    curNode->name = prop.value;
-
-                                    /*  If we're either a camera or a light source
+										if (prop.name == "Attenuation") {
+											lights.back()->mAttenuationLinear = prop.value;
+										} else if (prop.name == "OuterCone") {
+											lights.back()->mAngleOuterCone = AI_DEG_TO_RAD(prop.value);
+										} else if (prop.name == "InnerCone") {
+											lights.back()->mAngleInnerCone = AI_DEG_TO_RAD(prop.value);
+										}
+									}
+									// radius of the sphere to be generated -
+									// or alternatively, size of the cube
+									else if ((Node::SPHERE == curNode->type && prop.name == "Radius") || (Node::CUBE == curNode->type && prop.name == "Size")) {
+
+										curNode->sphereRadius = prop.value;
+									}
+								}
+							//} else if (!ASSIMP_stricmp(reader->getNodeName(), "int")) {
+                            } else if (!ASSIMP_stricmp(attrib.name(), "int")) {
+								IntProperty prop;
+								ReadIntProperty(prop);
+
+								if (inAnimator) {
+									if (curAnim->type == Animator::FLY_STRAIGHT && prop.name == "TimeForWay") {
+										curAnim->timeForWay = prop.value;
+									}
+								} else {
+									// sphere polygon numbers in each direction
+									if (Node::SPHERE == curNode->type) {
+
+										if (prop.name == "PolyCountX") {
+											curNode->spherePolyCountX = prop.value;
+										} else if (prop.name == "PolyCountY") {
+											curNode->spherePolyCountY = prop.value;
+										}
+									}
+								}
+							//} else if (!ASSIMP_stricmp(reader->getNodeName(), "string") || !ASSIMP_stricmp(reader->getNodeName(), "enum")) {
+                            } else if (!ASSIMP_stricmp(attrib.name(), "string") || !ASSIMP_stricmp(attrib.name(), "enum")) {
+								StringProperty prop;
+								ReadStringProperty(prop);
+								if (prop.value.length()) {
+									if (prop.name == "Name") {
+										curNode->name = prop.value;
+
+										/*  If we're either a camera or a light source
                                      *  we need to update the name in the aiLight/
                                      *  aiCamera structure, too.
                                      */
-                                    if (Node::CAMERA == curNode->type)  {
-                                        cameras.back()->mName.Set(prop.value);
-                                    }
-                                    else if (Node::LIGHT == curNode->type)  {
-                                        lights.back()->mName.Set(prop.value);
-                                    }
-                                }
-                                else if (Node::LIGHT == curNode->type && "LightType" == prop.name)
-                                {
-                                    if (prop.value == "Spot")
-                                        lights.back()->mType = aiLightSource_SPOT;
-                                    else if (prop.value == "Point")
-                                        lights.back()->mType = aiLightSource_POINT;
-                                    else if (prop.value == "Directional")
-                                        lights.back()->mType = aiLightSource_DIRECTIONAL;
-                                    else
-                                    {
-                                        // We won't pass the validation with aiLightSourceType_UNDEFINED,
-                                        // so we remove the light and replace it with a silly dummy node
-                                        delete lights.back();
-                                        lights.pop_back();
-                                        curNode->type = Node::DUMMY;
-
-                                        ASSIMP_LOG_ERROR("Ignoring light of unknown type: " + prop.value);
-                                    }
-                                }
-                                else if ((prop.name == "Mesh" && Node::MESH == curNode->type) ||
-                                    Node::ANIMMESH == curNode->type)
-                                {
-                                    /*  This is the file name of the mesh - either
+										if (Node::CAMERA == curNode->type) {
+											cameras.back()->mName.Set(prop.value);
+										} else if (Node::LIGHT == curNode->type) {
+											lights.back()->mName.Set(prop.value);
+										}
+									} else if (Node::LIGHT == curNode->type && "LightType" == prop.name) {
+										if (prop.value == "Spot")
+											lights.back()->mType = aiLightSource_SPOT;
+										else if (prop.value == "Point")
+											lights.back()->mType = aiLightSource_POINT;
+										else if (prop.value == "Directional")
+											lights.back()->mType = aiLightSource_DIRECTIONAL;
+										else {
+											// We won't pass the validation with aiLightSourceType_UNDEFINED,
+											// so we remove the light and replace it with a silly dummy node
+											delete lights.back();
+											lights.pop_back();
+											curNode->type = Node::DUMMY;
+
+											ASSIMP_LOG_ERROR("Ignoring light of unknown type: " + prop.value);
+										}
+									} else if ((prop.name == "Mesh" && Node::MESH == curNode->type) ||
+											   Node::ANIMMESH == curNode->type) {
+										/*  This is the file name of the mesh - either
                                      *  animated or not. We need to make sure we setup
                                      *  the correct post-processing settings here.
                                      */
-                                    unsigned int pp = 0;
-                                    BatchLoader::PropertyMap map;
+										unsigned int pp = 0;
+										BatchLoader::PropertyMap map;
 
-                                    /* If the mesh is a static one remove all animations from the impor data
+										/* If the mesh is a static one remove all animations from the impor data
                                      */
-                                    if (Node::ANIMMESH != curNode->type)    {
-                                        pp |= aiProcess_RemoveComponent;
-                                        SetGenericProperty<int>(map.ints,AI_CONFIG_PP_RVC_FLAGS,
-                                            aiComponent_ANIMATIONS | aiComponent_BONEWEIGHTS);
-                                    }
+										if (Node::ANIMMESH != curNode->type) {
+											pp |= aiProcess_RemoveComponent;
+											SetGenericProperty<int>(map.ints, AI_CONFIG_PP_RVC_FLAGS,
+													aiComponent_ANIMATIONS | aiComponent_BONEWEIGHTS);
+										}
 
-                                    /*  TODO: maybe implement the protection against recursive
+										/*  TODO: maybe implement the protection against recursive
                                     *  loading calls directly in BatchLoader? The current
                                     *  implementation is not absolutely safe. A LWS and an IRR
                                     *  file referencing each other *could* cause the system to
                                     *  recurse forever.
                                     */
 
-                                    const std::string extension = GetExtension(prop.value);
-                                    if ("irr" == extension) {
-                                        ASSIMP_LOG_ERROR("IRR: Can't load another IRR file recursively");
-                                    }
-                                    else
-                                    {
-                                        curNode->id = batch.AddLoadRequest(prop.value,pp,&map);
-                                        curNode->meshPath = prop.value;
-                                    }
-                                }
-                                else if (inAnimator && prop.name == "Type")
-                                {
-                                    // type of the animator
-                                    if (prop.value == "rotation")   {
-                                        curAnim->type = Animator::ROTATION;
-                                    }
-                                    else if (prop.value == "flyCircle") {
-                                        curAnim->type = Animator::FLY_CIRCLE;
-                                    }
-                                    else if (prop.value == "flyStraight")   {
-                                        curAnim->type = Animator::FLY_CIRCLE;
-                                    }
-                                    else if (prop.value == "followSpline")  {
-                                        curAnim->type = Animator::FOLLOW_SPLINE;
-                                    }
-                                    else    {
-                                        ASSIMP_LOG_WARN("IRR: Ignoring unknown animator: "
-                                            + prop.value);
-
-                                        curAnim->type = Animator::UNKNOWN;
-                                    }
-                                }
-                            }
-                        }
-                    }
-                    else if (reader->getNodeType() == EXN_ELEMENT_END && !ASSIMP_stricmp(reader->getNodeName(),"attributes"))   {
-                        break;
-                    }
-                }
-            }
-            break;
-
-        case EXN_ELEMENT_END:
-
-            // If we reached the end of a node, we need to continue processing its parent
-            if (!ASSIMP_stricmp(reader->getNodeName(),"node"))  {
-                if (!curNode)   {
-                    // currently is no node set. We need to go
-                    // back in the node hierarchy
-                    if (!curParent) {
-                        curParent = root;
-                        ASSIMP_LOG_ERROR("IRR: Too many closing <node> elements");
-                    }
-                    else curParent = curParent->parent;
-                }
-                else curNode = nullptr;
-            }
-            // clear all flags
-            else if (!ASSIMP_stricmp(reader->getNodeName(),"materials"))    {
-                inMaterials = false;
-            }
-            else if (!ASSIMP_stricmp(reader->getNodeName(),"animators"))    {
-                inAnimator = false;
-            }
-            break;
-
-        default:
-            // GCC complains that not all enumeration values are handled
-            break;
-        }
+										const std::string extension = GetExtension(prop.value);
+										if ("irr" == extension) {
+											ASSIMP_LOG_ERROR("IRR: Can't load another IRR file recursively");
+										} else {
+											curNode->id = batch.AddLoadRequest(prop.value, pp, &map);
+											curNode->meshPath = prop.value;
+										}
+									} else if (inAnimator && prop.name == "Type") {
+										// type of the animator
+										if (prop.value == "rotation") {
+											curAnim->type = Animator::ROTATION;
+										} else if (prop.value == "flyCircle") {
+											curAnim->type = Animator::FLY_CIRCLE;
+										} else if (prop.value == "flyStraight") {
+											curAnim->type = Animator::FLY_CIRCLE;
+										} else if (prop.value == "followSpline") {
+											curAnim->type = Animator::FOLLOW_SPLINE;
+										} else {
+											ASSIMP_LOG_WARN("IRR: Ignoring unknown animator: " + prop.value);
+
+											curAnim->type = Animator::UNKNOWN;
+										}
+									}
+								}
+							}
+						//} else if (reader->getNodeType() == EXN_ELEMENT_END && !ASSIMP_stricmp(reader->getNodeName(), "attributes")) {
+						} else if (attrib.type() == pugi::node_null && !ASSIMP_stricmp(attrib.name(), "attributes")) {
+							break;
+						}
+					}
+				}
+				break;
+
+			/*case EXN_ELEMENT_END:
+
+				// If we reached the end of a node, we need to continue processing its parent
+				if (!ASSIMP_stricmp(reader->getNodeName(), "node")) {
+					if (!curNode) {
+						// currently is no node set. We need to go
+						// back in the node hierarchy
+						if (!curParent) {
+							curParent = root;
+							ASSIMP_LOG_ERROR("IRR: Too many closing <node> elements");
+						} else
+							curParent = curParent->parent;
+					} else
+						curNode = nullptr;
+				}
+				// clear all flags
+				else if (!ASSIMP_stricmp(reader->getNodeName(), "materials")) {
+					inMaterials = false;
+				} else if (!ASSIMP_stricmp(reader->getNodeName(), "animators")) {
+					inAnimator = false;
+				}
+				break;*/
+
+			default:
+				// GCC complains that not all enumeration values are handled
+				break;
     }
+    //}
 
     //  Now iterate through all cameras and compute their final (horizontal) FOV
     for (aiCamera *cam : cameras) {
-        // screen aspect could be missing
-        if (cam->mAspect)   {
-            cam->mHorizontalFOV *= cam->mAspect;
-        } else {
-            ASSIMP_LOG_WARN("IRR: Camera aspect is not given, can't compute horizontal FOV");
-        }
+	    // screen aspect could be missing
+	    if (cam->mAspect) {
+		    cam->mHorizontalFOV *= cam->mAspect;
+	    } else {
+		    ASSIMP_LOG_WARN("IRR: Camera aspect is not given, can't compute horizontal FOV");
+	    }
     }
 
     batch.LoadAll();
 
-    /* Allocate a tempoary scene data structure
-     */
-    aiScene* tempScene = new aiScene();
+    // Allocate a temporary scene data structure
+    aiScene *tempScene = new aiScene();
     tempScene->mRootNode = new aiNode();
     tempScene->mRootNode->mName.Set("<IRRRoot>");
 
-    /* Copy the cameras to the output array
-     */
-    if (!cameras.empty())   {
-        tempScene->mNumCameras = (unsigned int)cameras.size();
-        tempScene->mCameras = new aiCamera*[tempScene->mNumCameras];
-        ::memcpy(tempScene->mCameras,&cameras[0],sizeof(void*)*tempScene->mNumCameras);
+    // Copy the cameras to the output array
+    if (!cameras.empty()) {
+	    tempScene->mNumCameras = (unsigned int)cameras.size();
+	    tempScene->mCameras = new aiCamera *[tempScene->mNumCameras];
+	    ::memcpy(tempScene->mCameras, &cameras[0], sizeof(void *) * tempScene->mNumCameras);
     }
 
-    /* Copy the light sources to the output array
-     */
-    if (!lights.empty())    {
-        tempScene->mNumLights = (unsigned int)lights.size();
-        tempScene->mLights = new aiLight*[tempScene->mNumLights];
-        ::memcpy(tempScene->mLights,&lights[0],sizeof(void*)*tempScene->mNumLights);
+    // Copy the light sources to the output array
+    if (!lights.empty()) {
+	    tempScene->mNumLights = (unsigned int)lights.size();
+	    tempScene->mLights = new aiLight *[tempScene->mNumLights];
+	    ::memcpy(tempScene->mLights, &lights[0], sizeof(void *) * tempScene->mNumLights);
     }
 
     // temporary data
-    std::vector< aiNodeAnim*>       anims;
-    std::vector< aiMaterial*>       materials;
-    std::vector< AttachmentInfo >   attach;
-    std::vector<aiMesh*>            meshes;
+    std::vector<aiNodeAnim *> anims;
+    std::vector<aiMaterial *> materials;
+    std::vector<AttachmentInfo> attach;
+    std::vector<aiMesh *> meshes;
 
     // try to guess how much storage we'll need
-    anims.reserve     (guessedAnimCnt + (guessedAnimCnt >> 2));
-    meshes.reserve    (guessedMeshCnt + (guessedMeshCnt >> 2));
-    materials.reserve (guessedMatCnt  + (guessedMatCnt >> 2));
+    anims.reserve(guessedAnimCnt + (guessedAnimCnt >> 2));
+    meshes.reserve(guessedMeshCnt + (guessedMeshCnt >> 2));
+    materials.reserve(guessedMatCnt + (guessedMatCnt >> 2));
 
-    /* Now process our scenegraph recursively: generate final
-     * meshes and generate animation channels for all nodes.
-     */
+    // Now process our scene-graph recursively: generate final
+    // meshes and generate animation channels for all nodes.
     unsigned int defMatIdx = UINT_MAX;
-    GenerateGraph(root,tempScene->mRootNode, tempScene,
-        batch, meshes, anims, attach, materials, defMatIdx);
-
-    if (!anims.empty())
-    {
-        tempScene->mNumAnimations = 1;
-        tempScene->mAnimations = new aiAnimation*[tempScene->mNumAnimations];
-        aiAnimation* an = tempScene->mAnimations[0] = new aiAnimation();
-
-        // ***********************************************************
-        // This is only the global animation channel of the scene.
-        // If there are animated models, they will have separate
-        // animation channels in the scene. To display IRR scenes
-        // correctly, users will need to combine the global anim
-        // channel with all the local animations they want to play
-        // ***********************************************************
-        an->mName.Set("Irr_GlobalAnimChannel");
-
-        // copy all node animation channels to the global channel
-        an->mNumChannels = (unsigned int)anims.size();
-        an->mChannels = new aiNodeAnim*[an->mNumChannels];
-        ::memcpy(an->mChannels, & anims [0], sizeof(void*)*an->mNumChannels);
+    GenerateGraph(root, tempScene->mRootNode, tempScene,
+		    batch, meshes, anims, attach, materials, defMatIdx);
+
+    if (!anims.empty()) {
+	    tempScene->mNumAnimations = 1;
+	    tempScene->mAnimations = new aiAnimation *[tempScene->mNumAnimations];
+	    aiAnimation *an = tempScene->mAnimations[0] = new aiAnimation();
+
+	    // ***********************************************************
+	    // This is only the global animation channel of the scene.
+	    // If there are animated models, they will have separate
+	    // animation channels in the scene. To display IRR scenes
+	    // correctly, users will need to combine the global anim
+	    // channel with all the local animations they want to play
+	    // ***********************************************************
+	    an->mName.Set("Irr_GlobalAnimChannel");
+
+	    // copy all node animation channels to the global channel
+	    an->mNumChannels = (unsigned int)anims.size();
+	    an->mChannels = new aiNodeAnim *[an->mNumChannels];
+	    ::memcpy(an->mChannels, &anims[0], sizeof(void *) * an->mNumChannels);
     }
-    if (!meshes.empty())    {
-        // copy all meshes to the temporary scene
-        tempScene->mNumMeshes = (unsigned int)meshes.size();
-        tempScene->mMeshes = new aiMesh*[tempScene->mNumMeshes];
-        ::memcpy(tempScene->mMeshes,&meshes[0],tempScene->mNumMeshes*
-            sizeof(void*));
+    if (!meshes.empty()) {
+	    // copy all meshes to the temporary scene
+	    tempScene->mNumMeshes = (unsigned int)meshes.size();
+	    tempScene->mMeshes = new aiMesh *[tempScene->mNumMeshes];
+	    ::memcpy(tempScene->mMeshes, &meshes[0], tempScene->mNumMeshes * sizeof(void *));
     }
 
-    /* Copy all materials to the output array
-     */
+    // Copy all materials to the output array
     if (!materials.empty()) {
-        tempScene->mNumMaterials = (unsigned int)materials.size();
-        tempScene->mMaterials = new aiMaterial*[tempScene->mNumMaterials];
-        ::memcpy(tempScene->mMaterials,&materials[0],sizeof(void*)*
-            tempScene->mNumMaterials);
+	    tempScene->mNumMaterials = (unsigned int)materials.size();
+	    tempScene->mMaterials = new aiMaterial *[tempScene->mNumMaterials];
+	    ::memcpy(tempScene->mMaterials, &materials[0], sizeof(void *) * tempScene->mNumMaterials);
     }
 
-    /*  Now merge all sub scenes and attach them to the correct
-     *  attachment points in the scenegraph.
-     */
-    SceneCombiner::MergeScenes(&pScene,tempScene,attach,
-        AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES | (!configSpeedFlag ? (
-        AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY | AI_INT_MERGE_SCENE_GEN_UNIQUE_MATNAMES) : 0));
-
-
-    /*  If we have no meshes | no materials now set the INCOMPLETE
-     *  scene flag. This is necessary if we failed to load all
-     *  models from external files
-     */
-    if (!pScene->mNumMeshes || !pScene->mNumMaterials)  {
-        ASSIMP_LOG_WARN("IRR: No meshes loaded, setting AI_SCENE_FLAGS_INCOMPLETE");
-        pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
+    //  Now merge all sub scenes and attach them to the correct
+    //  attachment points in the scenegraph.
+    SceneCombiner::MergeScenes(&pScene, tempScene, attach,
+		    AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES | (!configSpeedFlag ? (
+																		      AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY | AI_INT_MERGE_SCENE_GEN_UNIQUE_MATNAMES) :
+																      0));
+
+    // If we have no meshes | no materials now set the INCOMPLETE
+    // scene flag. This is necessary if we failed to load all
+    // models from external files
+    if (!pScene->mNumMeshes || !pScene->mNumMaterials) {
+	    ASSIMP_LOG_WARN("IRR: No meshes loaded, setting AI_SCENE_FLAGS_INCOMPLETE");
+	    pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
     }
 
-    /* Finished ... everything destructs automatically and all
-     * temporary scenes have already been deleted by MergeScenes()
-     */
-
+// Finished ... everything destructs automatically and all
+// temporary scenes have already been deleted by MergeScenes()
     delete root;
 }
 

+ 3 - 4
code/Irr/IRRShared.h

@@ -7,7 +7,7 @@
 #ifndef INCLUDED_AI_IRRSHARED_H
 #define INCLUDED_AI_IRRSHARED_H
 
-#include <assimp/irrXMLWrapper.h>
+#include <assimp/XmlParser.h>
 #include <assimp/BaseImporter.h>
 #include <stdint.h>
 
@@ -78,9 +78,8 @@ protected:
     typedef Property<aiVector3D>    VectorProperty;
     typedef Property<int>           IntProperty;
 
-    /** XML reader instance
-     */
-  irr::io::IrrXMLReader* reader;
+    /// XML reader instance
+	XmlParser mParser;
 
     // -------------------------------------------------------------------
     /** Parse a material description from the XML

+ 1 - 1
code/Ogre/OgreXmlSerializer.h

@@ -46,7 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
 
 #include "OgreStructs.h"
-#include <assimp/irrXMLWrapper.h>
+#include <assimp/XmlParser.h>
 
 namespace Assimp
 {

+ 1 - 1
code/X3D/FIReader.hpp

@@ -60,7 +60,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifdef ASSIMP_USE_HUNTER
 #  include <irrXML/irrXML.h>
 #else
-#  include <irrXML.h>
+#  include <assimp/XmlParser.h>
 #endif
 
 namespace Assimp {

+ 1 - 1
code/X3D/X3DImporter.hpp

@@ -56,7 +56,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/ProgressHandler.hpp>
 #include <assimp/types.h>
 #include <assimp/BaseImporter.h>
-#include <assimp/irrXMLWrapper.h>
+#include <assimp/XmlParser.h>
 #include "FIReader.hpp"
 //#include <regex>
 

+ 1 - 1
code/XGL/XGLLoader.h

@@ -47,7 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #define AI_XGLLOADER_H_INCLUDED
 
 #include <assimp/BaseImporter.h>
-#include <assimp/irrXMLWrapper.h>
+#include <assimp/XmlParser.h>
 #include <assimp/LogAux.h>
 #include <assimp/material.h>
 #include <assimp/Importer.hpp>

+ 3 - 3
contrib/CMakeLists.txt

@@ -1,6 +1,6 @@
 # Compile internal irrXML only if system is not requested
-if( NOT SYSTEM_IRRXML )
-    add_subdirectory(irrXML)
-endif( NOT SYSTEM_IRRXML )
+#if( NOT SYSTEM_IRRXML )
+#    add_subdirectory(irrXML)
+#endif( NOT SYSTEM_IRRXML )
 
 add_subdirectory( pugixml-1.9 )

+ 0 - 29
contrib/irrXML/CMakeLists.txt

@@ -1,29 +0,0 @@
-set( IrrXML_SRCS
-  CXMLReaderImpl.h
-  heapsort.h
-  irrArray.h
-  irrString.h
-  irrTypes.h
-  irrXML.cpp
-  irrXML.h
-)
-
-if ( MSVC )
-  ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS )
-  ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS )
-endif ( MSVC )
-
-IF(CMAKE_SYSTEM_NAME MATCHES "(Darwin|FreeBSD)")
-  add_library(IrrXML ${IrrXML_SRCS})
-ELSE()
-  add_library(IrrXML STATIC ${IrrXML_SRCS})
-ENDIF()
-set(IRRXML_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" CACHE INTERNAL "IrrXML_Include" )
-set(IRRXML_LIBRARY "IrrXML" CACHE INTERNAL "IrrXML" )
-
-install(TARGETS IrrXML
-  LIBRARY DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
-  ARCHIVE DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
-  RUNTIME DESTINATION ${ASSIMP_BIN_INSTALL_DIR}
-  FRAMEWORK DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
-  COMPONENT ${LIBASSIMP_COMPONENT})

+ 0 - 819
contrib/irrXML/CXMLReaderImpl.h

@@ -1,819 +0,0 @@
-// Copyright (C) 2002-2005 Nikolaus Gebhardt
-// This file is part of the "Irrlicht Engine" and the "irrXML" project.
-// For conditions of distribution and use, see copyright notice in irrlicht.h and/or irrXML.h
-
-#ifndef __ICXML_READER_IMPL_H_INCLUDED__
-#define __ICXML_READER_IMPL_H_INCLUDED__
-
-#include "irrXML.h"
-#include "irrString.h"
-#include "irrArray.h"
-
-#include <cassert>
-#include <stdlib.h>    
-#include <cctype>
-#include <cstdint>
-//using namespace Assimp;
-
-// For locale independent number conversion
-#include <sstream>
-#include <locale>
-
-#ifdef _DEBUG
-#define IRR_DEBUGPRINT(x) printf((x));
-#else // _DEBUG 
-#define IRR_DEBUGPRINT(x)
-#endif // _DEBUG
-
-
-namespace irr
-{
-namespace io
-{
-
-
-//! implementation of the IrrXMLReader
-template<class char_type, class superclass>
-class CXMLReaderImpl : public IIrrXMLReader<char_type, superclass>
-{
-public:
-
-	//! Constructor
-	CXMLReaderImpl(IFileReadCallBack* callback, bool deleteCallBack = true)
-		: TextData(0), P(0), TextBegin(0), TextSize(0), CurrentNodeType(EXN_NONE),
-		SourceFormat(ETF_ASCII), TargetFormat(ETF_ASCII)
-	{
-		if (!callback)
-			return;
-
-		storeTargetFormat();
-
-		// read whole xml file
-
-		readFile(callback);
-		
-		// clean up
-
-		if (deleteCallBack)
-			delete callback;
-
-		// create list with special characters
-
-		createSpecialCharacterList();
-
-		// set pointer to text begin
-		P = TextBegin;
-	}
-    	
-
-	//! Destructor
-	virtual ~CXMLReaderImpl()
-	{
-		delete [] TextData;
-	}
-
-
-	//! Reads forward to the next xml node. 
-	//! \return Returns false, if there was no further node. 
-	virtual bool read()
-	{
-		// if not end reached, parse the node
-		if (P && (unsigned int)(P - TextBegin) < TextSize - 1 && *P != 0)
-		{
-			parseCurrentNode();
-			return true;
-		}
-
-		_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
-		return false;
-	}
-
-
-	//! Returns the type of the current XML node.
-	virtual EXML_NODE getNodeType() const
-	{
-		return CurrentNodeType;
-	}
-
-
-	//! Returns attribute count of the current XML node.
-	virtual int getAttributeCount() const
-	{
-		return Attributes.size();
-	}
-
-
-	//! Returns name of an attribute.
-	virtual const char_type* getAttributeName(int idx) const
-	{
-		if (idx < 0 || idx >= (int)Attributes.size())
-			return 0;
-
-		return Attributes[idx].Name.c_str();
-	}
-
-
-	//! Returns the value of an attribute. 
-	virtual const char_type* getAttributeValue(int idx) const
-	{
-		if (idx < 0 || idx >= (int)Attributes.size())
-			return 0;
-
-		return Attributes[idx].Value.c_str();
-	}
-
-
-	//! Returns the value of an attribute. 
-	virtual const char_type* getAttributeValue(const char_type* name) const
-	{
-		const SAttribute* attr = getAttributeByName(name);
-		if (!attr)
-			return 0;
-
-		return attr->Value.c_str();
-	}
-
-
-	//! Returns the value of an attribute
-	virtual const char_type* getAttributeValueSafe(const char_type* name) const
-	{
-		const SAttribute* attr = getAttributeByName(name);
-		if (!attr)
-			return EmptyString.c_str();
-
-		return attr->Value.c_str();
-	}
-
-
-
-	//! Returns the value of an attribute as integer. 
-	int getAttributeValueAsInt(const char_type* name) const
-	{
-		return (int)getAttributeValueAsFloat(name);
-	}
-
-
-	//! Returns the value of an attribute as integer. 
-	int getAttributeValueAsInt(int idx) const
-	{
-		return (int)getAttributeValueAsFloat(idx);
-	}
-
-
-	//! Returns the value of an attribute as float. 
-	float getAttributeValueAsFloat(const char_type* name) const
-	{
-		const SAttribute* attr = getAttributeByName(name);
-		if (!attr)
-			return 0;
-
-		core::stringc c = attr->Value.c_str();
-        return static_cast<float>(atof(c.c_str()));
-        //return fast_atof(c.c_str());
-	}
-
-
-	//! Returns the value of an attribute as float. 
-	float getAttributeValueAsFloat(int idx) const
-	{
-		const char_type* attrvalue = getAttributeValue(idx);
-		if (!attrvalue)
-			return 0;
-
-		core::stringc c = attrvalue;
-		std::istringstream sstr(c.c_str());
-		sstr.imbue(std::locale("C")); // Locale free number convert
-		float fNum;
-		sstr >> fNum;
-		return fNum;
-	}
-
-
-	//! Returns the name of the current node.
-	virtual const char_type* getNodeName() const
-	{
-		return NodeName.c_str();
-	}
-
-
-	//! Returns data of the current node.
-	virtual const char_type* getNodeData() const
-	{
-		return NodeName.c_str();
-	}
-
-
-	//! Returns if an element is an empty element, like <foo />
-	virtual bool isEmptyElement() const
-	{
-		return IsEmptyElement;
-	}
-
-	//! Returns format of the source xml file.
-	virtual ETEXT_FORMAT getSourceFormat() const
-	{
-		return SourceFormat;
-	}
-
-	//! Returns format of the strings returned by the parser.
-	virtual ETEXT_FORMAT getParserFormat() const
-	{
-		return TargetFormat;
-	}
-
-private:
-
-	// Reads the current xml node
-	void parseCurrentNode()
-	{
-		char_type* start = P;
-
-		// move forward until '<' found
-		while(*P != L'<' && *P)
-			++P;
-
-		if (!*P)
-			return;
-
-		if (P - start > 0)
-		{
-			// we found some text, store it
-			if (setText(start, P))
-				return;
-		}
-
-		++P;
-
-		// based on current token, parse and report next element
-		switch(*P)
-		{
-		case L'/':
-			parseClosingXMLElement(); 
-			break;
-		case L'?':
-			ignoreDefinition();	
-			break;
-		case L'!':
-			if (!parseCDATA())
-				parseComment();	
-			break;
-		default:
-			parseOpeningXMLElement();
-			break;
-		}
-	}
-
-
-	//! sets the state that text was found. Returns true if set should be set
-	bool setText(char_type* start, char_type* end)
-	{
-		// check if text is more than 2 characters, and if not, check if there is 
-		// only white space, so that this text won't be reported
-		if (end - start < 3)
-		{
-			char_type* p = start;
-			for(; p != end; ++p)
-				if (!isWhiteSpace(*p))
-					break;
-
-			if (p == end)
-				return false;
-		}
-
-		// set current text to the parsed text, and replace xml special characters
-		core::string<char_type> s(start, (int)(end - start));
-		NodeName = replaceSpecialCharacters(s);
-
-		// current XML node type is text
-		CurrentNodeType = EXN_TEXT;
-
-		return true;
-	}
-
-
-
-	//! ignores an xml definition like <?xml something />
-	void ignoreDefinition()
-	{
-		CurrentNodeType = EXN_UNKNOWN;
-
-		// move until end marked with '>' reached
-		while(*P != L'>')
-			++P;
-
-		++P;
-	}
-
-
-	//! parses a comment
-	void parseComment()
-	{
-		CurrentNodeType = EXN_COMMENT;
-		P += 1;
-
-		char_type *pCommentBegin = P;
-
-		int count = 1;
-
-		// move until end of comment reached
-		while(count)
-		{
-			if (*P == L'>')
-				--count;
-			else
-			if (*P == L'<')
-				++count;
-
-			++P;
-		}
-
-		P -= 3;
-		NodeName = core::string<char_type>(pCommentBegin+2, (int)(P - pCommentBegin-2));
-		P += 3;
-	}
-
-
-	//! parses an opening xml element and reads attributes
-	void parseOpeningXMLElement()
-	{
-		CurrentNodeType = EXN_ELEMENT;
-		IsEmptyElement = false;
-		Attributes.clear();
-
-		// find name
-		const char_type* startName = P;
-
-		// find end of element
-		while(*P != L'>' && !isWhiteSpace(*P))
-			++P;
-
-		const char_type* endName = P;
-
-		// find Attributes
-		while(*P != L'>')
-		{
-			if (isWhiteSpace(*P))
-				++P;
-			else
-			{
-				if (*P != L'/')
-				{
-					// we've got an attribute
-
-					// read the attribute names
-					const char_type* attributeNameBegin = P;
-
-					while(!isWhiteSpace(*P) && *P != L'=')
-						++P;
-
-					const char_type* attributeNameEnd = P;
-					++P;
-
-					// read the attribute value
-					// check for quotes and single quotes, thx to murphy
-					while( (*P != L'\"') && (*P != L'\'') && *P) 
-						++P;
-
-					if (!*P) // malformatted xml file
-						return;
-
-					const char_type attributeQuoteChar = *P;
-
-					++P;
-					const char_type* attributeValueBegin = P;
-					
-					while(*P != attributeQuoteChar && *P)
-						++P;
-
-					if (!*P) // malformatted xml file
-						return;
-
-					const char_type* attributeValueEnd = P;
-					++P;
-
-					SAttribute attr;
-					attr.Name = core::string<char_type>(attributeNameBegin, 
-						(int)(attributeNameEnd - attributeNameBegin));
-
-					core::string<char_type> s(attributeValueBegin, 
-						(int)(attributeValueEnd - attributeValueBegin));
-
-					attr.Value = replaceSpecialCharacters(s);
-					Attributes.push_back(attr);
-				}
-				else
-				{
-					// tag is closed directly
-					++P;
-					IsEmptyElement = true;
-					break;
-				}
-			}
-		}
-
-		// check if this tag is closing directly
-		if (endName > startName && *(endName-1) == L'/')
-		{
-			// directly closing tag
-			IsEmptyElement = true;
-			endName--;
-		}
-		
-		NodeName = core::string<char_type>(startName, (int)(endName - startName));
-
-		++P;
-	}
-
-
-	//! parses an closing xml tag
-	void parseClosingXMLElement()
-	{
-		CurrentNodeType = EXN_ELEMENT_END;
-		IsEmptyElement = false;
-		Attributes.clear();
-
-		++P;
-		const char_type* pBeginClose = P;
-
-		while(*P != L'>')
-			++P;
-
-    // remove trailing whitespace, if any
-    while( std::isspace( P[-1]))
-      --P;
-
-		NodeName = core::string<char_type>(pBeginClose, (int)(P - pBeginClose));
-		++P;
-	}
-
-	//! parses a possible CDATA section, returns false if begin was not a CDATA section
-	bool parseCDATA()
-	{
-		if (*(P+1) != L'[')
-			return false;
-
-		CurrentNodeType = EXN_CDATA;
-
-		// skip '<![CDATA['
-		int count=0;
-		while( *P && count<8 )
-		{
-			++P;
-			++count;
-		}
-
-		if (!*P)
-			return true;
-
-		char_type *cDataBegin = P;
-		char_type *cDataEnd = 0;
-
-		// find end of CDATA
-		while(*P && !cDataEnd)
-		{
-			if (*P == L'>' && 
-			   (*(P-1) == L']') &&
-			   (*(P-2) == L']'))
-			{
-				cDataEnd = P - 2;
-			}
-
-			++P;
-		}
-
-		if ( cDataEnd )
-			NodeName = core::string<char_type>(cDataBegin, (int)(cDataEnd - cDataBegin));
-		else
-			NodeName = "";
-
-		return true;
-	}
-
-
-	// structure for storing attribute-name pairs
-	struct SAttribute
-	{
-		core::string<char_type> Name;
-		core::string<char_type> Value;
-	};
-
-	// finds a current attribute by name, returns 0 if not found
-	const SAttribute* getAttributeByName(const char_type* name) const
-	{
-		if (!name)
-			return 0;
-
-		core::string<char_type> n = name;
-
-		for (int i=0; i<(int)Attributes.size(); ++i)
-			if (Attributes[i].Name == n)
-				return &Attributes[i];
-
-		return 0;
-	}
-
-	// replaces xml special characters in a string and creates a new one
-	core::string<char_type> replaceSpecialCharacters(
-		core::string<char_type>& origstr)
-	{
-		int pos = origstr.findFirst(L'&');
-		int oldPos = 0;
-
-		if (pos == -1)
-			return origstr;
-
-		core::string<char_type> newstr;
-
-		while(pos != -1 && pos < origstr.size()-2)
-		{
-			// check if it is one of the special characters
-
-			int specialChar = -1;
-			for (int i=0; i<(int)SpecialCharacters.size(); ++i)
-			{
-				const char_type* p = &origstr.c_str()[pos]+1;
-
-				if (equalsn(&SpecialCharacters[i][1], p, SpecialCharacters[i].size()-1))
-				{
-					specialChar = i;
-					break;
-				}
-			}
-
-			if (specialChar != -1)
-			{
-				newstr.append(origstr.subString(oldPos, pos - oldPos));
-				newstr.append(SpecialCharacters[specialChar][0]);
-				pos += SpecialCharacters[specialChar].size();
-			}
-			else
-			{
-				newstr.append(origstr.subString(oldPos, pos - oldPos + 1));
-				pos += 1;
-			}
-
-			// find next &
-			oldPos = pos;
-			pos = origstr.findNext(L'&', pos);		
-		}
-
-		if (oldPos < origstr.size()-1)
-			newstr.append(origstr.subString(oldPos, origstr.size()-oldPos));
-
-		return newstr;
-	}
-
-
-
-	//! reads the xml file and converts it into the wanted character format.
-	bool readFile(IFileReadCallBack* callback)
-	{
-		int size = callback->getSize();		
-		size += 4; // We need two terminating 0's at the end.
-		           // For ASCII we need 1 0's, for UTF-16 2, for UTF-32 4.
-
-		char* data8 = new char[size];
-
-		if (!callback->read(data8, size-4))
-		{
-			delete [] data8;
-			return false;
-		}
-
-		// add zeros at end
-
-		data8[size-1] = 0;
-		data8[size-2] = 0;
-		data8[size-3] = 0;
-		data8[size-4] = 0;
-
-		char16* data16 = reinterpret_cast<char16*>(data8);
-		char32* data32 = reinterpret_cast<char32*>(data8);	
-
-		// now we need to convert the data to the desired target format
-		// based on the byte order mark.
-
-		const unsigned char UTF8[] = {0xEF, 0xBB, 0xBF}; // 0xEFBBBF;
-		const int UTF16_BE = 0xFFFE;
-		const int UTF16_LE = 0xFEFF;
-		const int UTF32_BE = 0xFFFE0000;
-		const int UTF32_LE = 0x0000FEFF;
-
-		// check source for all utf versions and convert to target data format
-		
-		if (size >= 4 && data32[0] == (char32)UTF32_BE)
-		{
-			// UTF-32, big endian
-			SourceFormat = ETF_UTF32_BE;
-			convertTextData(data32+1, data8, (size/4)); // data32+1 because we need to skip the header
-		}
-		else
-		if (size >= 4 && data32[0] == (char32)UTF32_LE)
-		{
-			// UTF-32, little endian
-			SourceFormat = ETF_UTF32_LE;
-			convertTextData(data32+1, data8, (size/4)); // data32+1 because we need to skip the header
-		}
-		else
-		if (size >= 2 && data16[0] == UTF16_BE)
-		{
-			// UTF-16, big endian
-			SourceFormat = ETF_UTF16_BE;
-			convertTextData(data16+1, data8, (size/2)); // data16+1 because we need to skip the header
-		}
-		else
-		if (size >= 2 && data16[0] == UTF16_LE)
-		{
-			// UTF-16, little endian
-			SourceFormat = ETF_UTF16_LE;
-			convertTextData(data16+1, data8, (size/2)); // data16+1 because we need to skip the header
-		}
-		else
-		if (size >= 3 && data8[0] == UTF8[0] && data8[1] == UTF8[1] && data8[2] == UTF8[2])
-		{
-			// UTF-8
-			SourceFormat = ETF_UTF8;
-			convertTextData(data8+3, data8, size); // data8+3 because we need to skip the header
-		}
-		else
-		{
-			// ASCII
-			SourceFormat = ETF_ASCII;
-			convertTextData(data8, data8, size);
-		}
-
-		return true;
-	}
-
-
-	//! converts the text file into the desired format.
-	//! \param source: begin of the text (without byte order mark)
-	//! \param pointerToStore: pointer to text data block which can be
-	//! stored or deleted based on the nesessary conversion.
-	//! \param sizeWithoutHeader: Text size in characters without header
-	template<class src_char_type>
-	void convertTextData(src_char_type* source, char* pointerToStore, int sizeWithoutHeader)
-	{
-		// convert little to big endian if necessary
-		if (sizeof(src_char_type) > 1 && 
-			isLittleEndian(TargetFormat) != isLittleEndian(SourceFormat))
-			convertToLittleEndian(source);
-
-		// check if conversion is necessary:
-		if (sizeof(src_char_type) == sizeof(char_type))
-		{
-			// no need to convert
-			TextBegin = (char_type*)source;
-			TextData = (char_type*)pointerToStore;
-			TextSize = sizeWithoutHeader;
-		}
-		else
-		{
-			// convert source into target data format. 
-			// TODO: implement a real conversion. This one just 
-			// copies bytes. This is a problem when there are 
-			// unicode symbols using more than one character.
-
-			TextData = new char_type[sizeWithoutHeader];
-
-			// MSVC debugger complains here about loss of data ...
-			size_t numShift = sizeof( char_type) * 8;
-			assert(numShift < 64);
-			const src_char_type cc = (src_char_type)(((uint64_t(1u) << numShift) - 1));
-			for (int i=0; i<sizeWithoutHeader; ++i)
-				TextData[i] = char_type( source[i] & cc); 
-
-			TextBegin = TextData;
-			TextSize = sizeWithoutHeader;
-
-			// delete original data because no longer needed
-			delete [] pointerToStore;
-		}
-	}
-
-	//! converts whole text buffer to little endian
-	template<class src_char_type>
-	void convertToLittleEndian(src_char_type* t)
-	{
-		if (sizeof(src_char_type) == 4) 
-		{
-			// 32 bit
-
-			while(*t)
-			{
-				*t = ((*t & 0xff000000) >> 24) |
-				     ((*t & 0x00ff0000) >> 8)  |
-				     ((*t & 0x0000ff00) << 8)  |
-				     ((*t & 0x000000ff) << 24);
-				++t;
-			}
-		}
-		else
-		{
-			// 16 bit 
-
-			while(*t)
-			{
-				*t = (*t >> 8) | (*t << 8);
-				++t;
-			}
-		}
-	}
-
-	//! returns if a format is little endian
-	inline bool isLittleEndian(ETEXT_FORMAT f)
-	{
-		return f == ETF_ASCII ||
-		       f == ETF_UTF8 ||
-		       f == ETF_UTF16_LE ||
-		       f == ETF_UTF32_LE;
-	}
-
-
-	//! returns true if a character is whitespace
-	inline bool isWhiteSpace(char_type c)
-	{
-		return (c==' ' || c=='\t' || c=='\n' || c=='\r');
-	}
-
-
-	//! generates a list with xml special characters
-	void createSpecialCharacterList()
-	{
-		// list of strings containing special symbols, 
-		// the first character is the special character,
-		// the following is the symbol string without trailing &.
-
-		SpecialCharacters.push_back("&amp;");
-		SpecialCharacters.push_back("<lt;");
-		SpecialCharacters.push_back(">gt;");
-		SpecialCharacters.push_back("\"quot;");
-		SpecialCharacters.push_back("'apos;");
-		
-	}
-
-
-	//! compares the first n characters of the strings
-	bool equalsn(const char_type* str1, const char_type* str2, int len)
-	{
-		int i;
-		for(i=0; str1[i] && str2[i] && i < len; ++i)
-			if (str1[i] != str2[i])
-				return false;
-
-		// if one (or both) of the strings was smaller then they
-		// are only equal if they have the same lenght
-		return (i == len) || (str1[i] == 0 && str2[i] == 0);
-	}
-
-
-	//! stores the target text format
-	void storeTargetFormat()
-	{
-		// get target format. We could have done this using template specialization,
-		// but VisualStudio 6 don't like it and we want to support it.
-
-		switch(sizeof(char_type))
-		{
-		case 1: 
-			TargetFormat = ETF_UTF8;
-			break;
-		case 2: 
-			TargetFormat = ETF_UTF16_LE;
-			break;
-		case 4: 
-			TargetFormat = ETF_UTF32_LE;
-			break;
-		default:
-			TargetFormat = ETF_ASCII; // should never happen.
-		}
-	}
-
-
-	// instance variables:
-
-	char_type* TextData;         // data block of the text file
-	char_type* P;                // current point in text to parse
-	char_type* TextBegin;        // start of text to parse
-	unsigned int TextSize;       // size of text to parse in characters, not bytes
-
-	EXML_NODE CurrentNodeType;   // type of the currently parsed node
-	ETEXT_FORMAT SourceFormat;   // source format of the xml file
-	ETEXT_FORMAT TargetFormat;   // output format of this parser
-
-	core::string<char_type> NodeName;    // name of the node currently in
-	core::string<char_type> EmptyString; // empty string to be returned by getSafe() methods
-
-	bool IsEmptyElement;       // is the currently parsed node empty?
-
-	core::array< core::string<char_type> > SpecialCharacters; // see createSpecialCharacterList()
-
-	core::array<SAttribute> Attributes; // attributes of current element
-	
-}; // end CXMLReaderImpl
-
-
-} // end namespace
-} // end namespace
-
-#endif

+ 0 - 73
contrib/irrXML/heapsort.h

@@ -1,73 +0,0 @@
-// Copyright (C) 2002-2005 Nikolaus Gebhardt
-// This file is part of the "Irrlicht Engine".
-// For conditions of distribution and use, see copyright notice in irrlicht.h
-
-#ifndef __IRR_HEAPSORT_H_INCLUDED__
-#define __IRR_HEAPSORT_H_INCLUDED__
-
-#include "irrTypes.h"
-
-namespace irr
-{
-namespace core
-{
-
-//! Sinks an element into the heap.
-template<class T>
-inline void heapsink(T*array, s32 element, s32 max)
-{
-	while ((element<<1) < max)	// there is a left child
-	{
-		s32 j = (element<<1);
-	
-		if (j+1 < max && array[j] < array[j+1])
-			j = j+1;							// take right child
-
-		if (array[element] < array[j])
-		{
-			T t = array[j];						// swap elements
-			array[j] = array[element];
-			array[element] = t;
-			element = j;
-		}
-		else
-			return;
-	}
-}
-
-
-//! Sorts an array with size 'size' using heapsort.
-template<class T>
-inline void heapsort(T* array_, s32 size)
-{
-	// for heapsink we pretent this is not c++, where
-	// arrays start with index 0. So we decrease the array pointer,
-	// the maximum always +2 and the element always +1
-
-	T* virtualArray = array_ - 1;
-	s32 virtualSize = size + 2;
-	s32 i;
-
-	// build heap
-
-	for (i=((size-1)/2); i>=0; --i)	
-		heapsink(virtualArray, i+1, virtualSize-1);
-
-	// sort array
-
-	for (i=size-1; i>=0; --i)	
-	{
-		T t = array_[0];
-		array_[0] = array_[i];
-		array_[i] = t;
-		heapsink(virtualArray, 1, i + 1);
-	}
-}
-
-} // end namespace core
-} // end namespace irr
-
-
-
-#endif
-

+ 0 - 443
contrib/irrXML/irrArray.h

@@ -1,443 +0,0 @@
-// Copyright (C) 2002-2005 Nikolaus Gebhardt
-// This file is part of the "Irrlicht Engine" and the "irrXML" project.
-// For conditions of distribution and use, see copyright notice in irrlicht.h and irrXML.h
-
-#ifndef __IRR_ARRAY_H_INCLUDED__
-#define __IRR_ARRAY_H_INCLUDED__
-
-#include "irrTypes.h"
-#include "heapsort.h"
-
-namespace irr
-{
-namespace core
-{
-
-//!	Self reallocating template array (like stl vector) with additional features.
-/** Some features are: Heap sorting, binary search methods, easier debugging.
-*/
-template <class T>
-class array
-{
-
-public:
-	array() 
-		: data(0), allocated(0), used(0),
-			free_when_destroyed(true), is_sorted(true)
-	{
-	}
-
-	//! Constructs a array and allocates an initial chunk of memory.
-	//! \param start_count: Amount of elements to allocate.
-	array(u32 start_count)
-		: data(0), allocated(0), used(0),
-			free_when_destroyed(true),	is_sorted(true)
-	{
-		reallocate(start_count);
-	}
-
-
-	//! Copy constructor
-	array(const array<T>& other)
-		: data(0)
-	{
-		*this = other;
-	}
-
-
-
-	//! Destructor. Frees allocated memory, if set_free_when_destroyed
-	//! was not set to false by the user before.
-	~array()
-	{
-		if (free_when_destroyed)
-			delete [] data;
-	}
-
-
-
-	//! Reallocates the array, make it bigger or smaller.
-	//! \param new_size: New size of array.
-	void reallocate(u32 new_size)
-	{
-		T* old_data = data;
-
-		data = new T[new_size];
-		allocated = new_size;
-		
-		s32 end = used < new_size ? used : new_size;
-		for (s32 i=0; i<end; ++i)
-			data[i] = old_data[i];
-
-		if (allocated < used)
-			used = allocated;
-		
-		delete [] old_data;
-	}
-
-	//! Adds an element at back of array. If the array is to small to 
-	//! add this new element, the array is made bigger.
-	//! \param element: Element to add at the back of the array.
-	void push_back(const T& element)
-	{
-		if (used + 1 > allocated)
-		{
-			// reallocate(used * 2 +1);
-			// this doesn't work if the element is in the same array. So
-			// we'll copy the element first to be sure we'll get no data
-			// corruption
-
-			T e;
-			e = element;           // copy element
-			reallocate(used * 2 +1); // increase data block
-			data[used++] = e;        // push_back
-			is_sorted = false; 
-			return;
-		}
-
-		data[used++] = element;
-		is_sorted = false;
-	}
-
-
-	//! Adds an element at the front of the array. If the array is to small to 
-	//! add this new element, the array is made bigger. Please note that this
-	//! is slow, because the whole array needs to be copied for this.
-	//! \param element: Element to add at the back of the array.
-	void push_front(const T& element)
-	{
-		if (used + 1 > allocated)
-			reallocate(used * 2 +1);
-
-		for (int i=(int)used; i>0; --i)
-			data[i] = data[i-1];
-
-		data[0] = element;
-		is_sorted = false;
-		++used;
-	}
-
-	
-	//! Insert item into array at specified position. Please use this
-	//! only if you know what you are doing (possible performance loss). 
-	//! The preferred method of adding elements should be push_back().
-	//! \param element: Element to be inserted
-	//! \param index: Where position to insert the new element.
-	void insert(const T& element, u32 index=0) 
-	{
-		_IRR_DEBUG_BREAK_IF(index>used) // access violation
-
-		if (used + 1 > allocated)
-			reallocate(used * 2 +1);
-
-		for (u32 i=used++; i>index; i--) 
-			data[i] = data[i-1];
-
-		data[index] = element;
-		is_sorted = false;
-	}
-
-
-
-
-	//! Clears the array and deletes all allocated memory.
-	void clear()
-	{
-		delete [] data;
-		data = 0;
-		used = 0;
-		allocated = 0;
-		is_sorted = true;
-	}
-
-
-
-	//! Sets pointer to new array, using this as new workspace.
-	//! \param newPointer: Pointer to new array of elements.
-	//! \param size: Size of the new array.
-	void set_pointer(T* newPointer, u32 size)
-	{
-		delete [] data;
-		data = newPointer;
-		allocated = size;
-		used = size;
-		is_sorted = false;
-	}
-
-
-
-	//! Sets if the array should delete the memory it used.
-	//! \param f: If true, the array frees the allocated memory in its
-	//! destructor, otherwise not. The default is true.
-	void set_free_when_destroyed(bool f)
-	{
-		free_when_destroyed = f;
-	}
-
-
-
-	//! Sets the size of the array.
-	//! \param usedNow: Amount of elements now used.
-	void set_used(u32 usedNow)
-	{
-		if (allocated < usedNow)
-			reallocate(usedNow);
-
-		used = usedNow;
-	}
-
-
-
-	//! Assignement operator
-	void operator=(const array<T>& other)
-	{
-		if (data)
-			delete [] data;
-
-		//if (allocated < other.allocated)
-		if (other.allocated == 0)
-			data = 0;
-		else
-			data = new T[other.allocated];
-
-		used = other.used;
-		free_when_destroyed = other.free_when_destroyed;
-		is_sorted = other.is_sorted;
-		allocated = other.allocated;
-
-		for (u32 i=0; i<other.used; ++i)
-			data[i] = other.data[i];
-	}
-
-
-	//! Direct access operator
-	T& operator [](u32 index)
-	{
-		_IRR_DEBUG_BREAK_IF(index>=used) // access violation
-
-		return data[index];
-	}
-
-
-
-	//! Direct access operator
-	const T& operator [](u32 index) const
-	{
-		_IRR_DEBUG_BREAK_IF(index>=used) // access violation
-
-		return data[index];
-	}
-
-    //! Gets last frame
-	const T& getLast() const
-	{
-		_IRR_DEBUG_BREAK_IF(!used) // access violation
-
-		return data[used-1];
-	}
-
-    //! Gets last frame
-	T& getLast()
-	{
-		_IRR_DEBUG_BREAK_IF(!used) // access violation
-
-		return data[used-1];
-	}
-    
-
-	//! Returns a pointer to the array.
-	//! \return Pointer to the array.
-	T* pointer()
-	{
-		return data;
-	}
-
-
-
-	//! Returns a const pointer to the array.
-	//! \return Pointer to the array.
-	const T* const_pointer() const
-	{
-		return data;
-	}
-
-
-
-	//! Returns size of used array.
-	//! \return Size of elements in the array.
-	u32 size() const
-	{
-		return used;
-	}
-
-
-
-	//! Returns amount memory allocated.
-	//! \return Returns amount of memory allocated. The amount of bytes
-	//! allocated would  be allocated_size() * sizeof(ElementsUsed);
-	u32 allocated_size() const
-	{
-		return allocated;
-	}
-
-
-
-	//! Returns true if array is empty
-	//! \return True if the array is empty, false if not.
-	bool empty() const
-	{
-		return used == 0;
-	}
-
-
-
-	//! Sorts the array using heapsort. There is no additional memory waste and
-	//! the algorithm performs (O) n log n in worst case.
-	void sort()
-	{
-		if (is_sorted || used<2)
-			return;
-
-		heapsort(data, used);
-		is_sorted = true;
-	}
-
-
-
-	//! Performs a binary search for an element, returns -1 if not found.
-	//! The array will be sorted before the binary search if it is not
-	//! already sorted.
-	//! \param element: Element to search for.
-	//! \return Returns position of the searched element if it was found,
-	//! otherwise -1 is returned.
-	s32 binary_search(const T& element)
-	{
-		return binary_search(element, 0, used-1);
-	}
-
-
-
-	//! Performs a binary search for an element, returns -1 if not found.
-	//! The array will be sorted before the binary search if it is not
-	//! already sorted.
-	//! \param element: Element to search for.
-	//! \param left: First left index
-	//! \param right: Last right index.
-	//! \return Returns position of the searched element if it was found,
-	//! otherwise -1 is returned.
-	s32 binary_search(const T& element, s32 left, s32 right)
-	{
-		if (!used)
-			return -1;
-
-		sort();
-
-		s32 m;
-
-		do
-		{
-			m = (left+right)>>1;
-
-			if (element < data[m])
-				right = m - 1;
-			else
-				left = m + 1;
-
-		} while((element < data[m] || data[m] < element) && left<=right);
-
-		// this last line equals to:
-		// " while((element != array[m]) && left<=right);"
-		// but we only want to use the '<' operator.
-		// the same in next line, it is "(element == array[m])"
-
-		if (!(element < data[m]) && !(data[m] < element))
-			return m;
-
-		return -1;
-	}
-
-
-	//! Finds an element in linear time, which is very slow. Use
-	//! binary_search for faster finding. Only works if =operator is implemented.
-	//! \param element: Element to search for.
-	//! \return Returns position of the searched element if it was found,
-	//! otherwise -1 is returned.
-	s32 linear_search(T& element)
-	{
-		for (u32 i=0; i<used; ++i)
-			if (!(element < data[i]) && !(data[i] < element))
-				return (s32)i;
-
-		return -1;
-	}
-
-
-	//! Finds an element in linear time, which is very slow. Use
-	//! binary_search for faster finding. Only works if =operator is implemented.
-	//! \param element: Element to search for.
-	//! \return Returns position of the searched element if it was found,
-	//! otherwise -1 is returned.
-	s32 linear_reverse_search(T& element)
-	{
-		for (s32 i=used-1; i>=0; --i)
-			if (data[i] == element)
-				return (s32)i;
-
-		return -1;
-	}
-
-
-
-	//! Erases an element from the array. May be slow, because all elements 
-	//! following after the erased element have to be copied.
-	//! \param index: Index of element to be erased.
-	void erase(u32 index)
-	{
-		_IRR_DEBUG_BREAK_IF(index>=used || index<0) // access violation
-
-		for (u32 i=index+1; i<used; ++i)
-			data[i-1] = data[i];
-
-		--used;
-	}
-
-
-	//! Erases some elements from the array. may be slow, because all elements 
-	//! following after the erased element have to be copied.
-	//! \param index: Index of the first element to be erased.
-	//! \param count: Amount of elements to be erased.
-	void erase(u32 index, s32 count)
-	{
-		_IRR_DEBUG_BREAK_IF(index>=used || index<0 || count<1 || index+count>used) // access violation
-
-		for (u32 i=index+count; i<used; ++i)
-			data[i-count] = data[i];
-
-		used-= count;
-	}
-
-
-	//! Sets if the array is sorted
-	void set_sorted(bool _is_sorted)
-	{
-		is_sorted = _is_sorted;
-	}
-
-			
-	private:
-
-		T* data;
-		u32 allocated;
-		u32 used;
-		bool free_when_destroyed;
-		bool is_sorted;
-};
-
-
-} // end namespace core
-} // end namespace irr
-
-
-
-#endif
-

+ 0 - 664
contrib/irrXML/irrString.h

@@ -1,664 +0,0 @@
-// Copyright (C) 2002-2005 Nikolaus Gebhardt
-// This file is part of the "Irrlicht Engine" and the "irrXML" project.
-// For conditions of distribution and use, see copyright notice in irrlicht.h and irrXML.h
-
-#ifndef __IRR_STRING_H_INCLUDED__
-#define __IRR_STRING_H_INCLUDED__
-
-#include "irrTypes.h"
-
-namespace irr
-{
-namespace core
-{
-
-//!	Very simple string class with some useful features.
-/**	string<c8> and string<wchar_t> work both with unicode AND ascii,
-so you can assign unicode to string<c8> and ascii to string<wchar_t> 
-(and the other way round) if your ever would want to. 
-Note that the conversation between both is not done using an encoding.
-
-Known bugs:
-Special characters like 'Ä', 'Ü' and 'Ö' are ignored in the
-methods make_upper, make_lower and equals_ignore_case.
-*/
-template <class T>
-class string
-{
-public:
-
-	//! Default constructor
-	string()
-	: array(0), allocated(1), used(1)
-	{
-		array = new T[1];
-		array[0] = 0x0;
-	}
-
-
-
-	//! Constructor
-	string(const string<T>& other)
-	: array(0), allocated(0), used(0)
-	{
-		*this = other;
-	}
-
-
-	//! Constructs a string from an int
-	string(int number)
-	: array(0), allocated(0), used(0)
-	{
-		// store if negative and make positive
-
-		bool negative = false;
-		if (number < 0)
-		{
-			number *= -1;
-			negative = true;
-		}
-
-		// temporary buffer for 16 numbers
-
-		c8 tmpbuf[16];
-		tmpbuf[15] = 0;
-		s32 idx = 15;	
-
-		// special case '0'
-
-		if (!number) 
-		{
-			tmpbuf[14] = '0';
-			*this = &tmpbuf[14];
-			return;
-		}
-
-		// add numbers
-
-		while(number && idx)
-		{
-			idx--;	
-			tmpbuf[idx] = (c8)('0' + (number % 10));
-			number = number / 10;					
-		}
-
-		// add sign
-
-		if (negative)
-		{
-			idx--;
-			tmpbuf[idx] = '-';			
-		}
-
-		*this = &tmpbuf[idx];
-	}
-
-
-
-	//! Constructor for copying a string from a pointer with a given lenght
-	template <class B>
-	string(const B* c, s32 lenght)
-	: array(0), allocated(0), used(0)
-	{
-		if (!c)
-			return;
-
-        allocated = used = lenght+1;
-		array = new T[used];
-
-		for (s32 l = 0; l<lenght; ++l)
-			array[l] = (T)c[l];
-
-		array[lenght] = 0;
-	}
-
-
-
-	//! Constructor for unicode and ascii strings
-	template <class B>
-	string(const B* c)
-	: array(0),allocated(0), used(0)
-	{
-		*this = c;
-	}
-
-
-
-	//! destructor
-	~string()
-	{
-		delete [] array;
-	}
-
-
-
-	//! Assignment operator
-	string<T>& operator=(const string<T>& other) 
-	{
-		if (this == &other)
-			return *this;
-
-		delete [] array;
-		allocated = used = other.size()+1;
-		array = new T[used];
-
-		const T* p = other.c_str();
-		for (s32 i=0; i<used; ++i, ++p)
-			array[i] = *p;
-
-		return *this;
-	}
-
-
-
-	//! Assignment operator for strings, ascii and unicode
-	template <class B>
-	string<T>& operator=(const B* c) 
-	{
-		if (!c)
-		{
-			if (!array)
-			{
-				array = new T[1];
-				allocated = 1;
-				used = 1;
-			}
-			array[0] = 0x0;
-			return *this;
-		}
-
-		if ((void*)c == (void*)array)
-			return *this;
-
-		s32 len = 0;
-		const B* p = c;
-		while(*p)
-		{
-			++len;
-			++p;
-		}
-
-		// we'll take the old string for a while, because the new string could be
-		// a part of the current string.
-		T* oldArray = array;
-
-        allocated = used = len+1;
-		array = new T[used];
-
-		for (s32 l = 0; l<len+1; ++l)
-			array[l] = (T)c[l];
-
-		delete [] oldArray;
-		return *this;
-	}
-
-	//! Add operator for other strings
-	string<T> operator+(const string<T>& other) 
-	{ 
-		string<T> str(*this); 
-		str.append(other); 
-
-		return str; 
-	} 
-
-	//! Add operator for strings, ascii and unicode 
-	template <class B> 
-	string<T> operator+(const B* c) 
-	{ 
-		string<T> str(*this); 
-		str.append(c); 
-
-		return str; 
-	}
-
-
-
-	//! Direct access operator
-	T& operator [](const s32 index)  const
-	{
-		_IRR_DEBUG_BREAK_IF(index>=used) // bad index
-
-		return array[index];
-	}
-
-
-	//! Comparison operator
-	bool operator ==(const T* str) const
-	{
-		int i;
-		for(i=0; array[i] && str[i]; ++i)
-			if (array[i] != str[i])
-				return false;
-
-		return !array[i] && !str[i];
-	}
-
-
-
-	//! Comparison operator
-	bool operator ==(const string<T>& other) const
-	{
-		for(s32 i=0; array[i] && other.array[i]; ++i)
-			if (array[i] != other.array[i])
-				return false;
-
-		return used == other.used;
-	}
-
-
-
-	//! Is smaller operator
-	bool operator <(const string<T>& other) const
-	{
-		for(s32 i=0; array[i] && other.array[i]; ++i)
-			if (array[i] != other.array[i])
-				return (array[i] < other.array[i]);
-
-		return used < other.used;
-	}
-
-
-
-	//! Equals not operator
-	bool operator !=(const string<T>& other) const
-	{
-		return !(*this == other);
-	}
-
-
-    
-	//! Returns length of string
-	/** \return Returns length of the string in characters. */
-	s32 size() const
-	{
-		return used-1;
-	}
-
-
-
-	//! Returns character string
-	/** \return Returns pointer to C-style zero terminated string. */
-	const T* c_str() const
-	{
-		return array;
-	}
-
-
-
-	//! Makes the string lower case.
-	void make_lower()
-	{
-		const T A = (T)'A';
-		const T Z = (T)'Z';
-		const T diff = (T)'a' - A;
-
-		for (s32 i=0; i<used; ++i)
-		{
-			if (array[i]>=A && array[i]<=Z)
-				array[i] += diff;
-		}
-	}
-
-
-
-	//! Makes the string upper case.
-	void make_upper()
-	{
-		const T a = (T)'a';
-		const T z = (T)'z';
-		const T diff = (T)'A' - a;
-
-		for (s32 i=0; i<used; ++i)
-		{
-			if (array[i]>=a && array[i]<=z)
-				array[i] += diff;
-		}
-	}
-
-
-
-	//! Compares the string ignoring case.
-	/** \param other: Other string to compare.
-	\return Returns true if the string are equal ignoring case. */
-	bool equals_ignore_case(const string<T>& other) const
-	{
-		for(s32 i=0; array[i] && other[i]; ++i)
-			if (toLower(array[i]) != toLower(other[i]))
-				return false;
-
-		return used == other.used;
-	}
-
-
-	//! compares the first n characters of the strings
-	bool equalsn(const string<T>& other, int len)
-	{
-		int i;
-		for(i=0; array[i] && other[i] && i < len; ++i)
-			if (array[i] != other[i])
-				return false;
-
-		// if one (or both) of the strings was smaller then they
-		// are only equal if they have the same lenght
-		return (i == len) || (used == other.used);
-	}
-
-
-	//! compares the first n characters of the strings
-	bool equalsn(const T* str, int len)
-	{
-		int i;	
-		for(i=0; array[i] && str[i] && i < len; ++i)
-			if (array[i] != str[i])
-				return false;
-
-		// if one (or both) of the strings was smaller then they
-		// are only equal if they have the same lenght
-		return (i == len) || (array[i] == 0 && str[i] == 0);
-	}
-
-
-	//! Appends a character to this string
-	/** \param character: Character to append. */
-	void append(T character)
-	{
-		if (used + 1 > allocated)
-			reallocate((s32)used + 1);
-
-		used += 1;
-
-		array[used-2] = character;
-		array[used-1] = 0;
-	}
-
-	//! Appends a string to this string
-	/** \param other: String to append. */
-	void append(const string<T>& other)
-	{
-		--used;
-
-		s32 len = other.size();
-		
-		if (used + len + 1 > allocated)
-			reallocate((s32)used + (s32)len + 1);
-
-		for (s32 l=0; l<len+1; ++l)
-			array[l+used] = other[l];
-
-		used = used + len + 1;
-	}
-
-
-	//! Appends a string of the length l to this string.
-	/** \param other: other String to append to this string.
-	 \param length: How much characters of the other string to add to this one. */
-	void append(const string<T>& other, s32 length)
-	{
-		s32 len = other.size();
-
-		if (len < length)
-		{
-			append(other);
-			return;
-		}
-
-		len = length;
-		--used;
-		
-		if (used + len > allocated)
-			reallocate((s32)used + (s32)len);
-
-		for (s32 l=0; l<len; ++l)
-			array[l+used] = other[l];
-
-		used = used + len;
-	}
-
-
-	//! Reserves some memory.
-	/** \param count: Amount of characters to reserve. */
-	void reserve(s32 count)
-	{
-		if (count < allocated)
-			return;
-
-		reallocate(count);
-	}
-
-
-	//! finds first occurrence of character in string
-	/** \param c: Character to search for.
-	\return Returns position where the character has been found,
-	or -1 if not found. */
-	s32 findFirst(T c) const
-	{
-		for (s32 i=0; i<used; ++i)
-			if (array[i] == c)
-				return i;
-
-		return -1;
-	}
-
-	//! finds first occurrence of a character of a list in string
-	/** \param c: List of strings to find. For example if the method
-	should find the first occurance of 'a' or 'b', this parameter should be "ab".
-	\param count: Amount of characters in the list. Ususally, 
-	this should be strlen(ofParameter1)
-	\return Returns position where one of the character has been found,
-	or -1 if not found. */
-	s32 findFirstChar(T* c, int count) const
-	{
-		for (s32 i=0; i<used; ++i)
-			for (int j=0; j<count; ++j)
-				if (array[i] == c[j])
-					return i;
-
-		return -1;
-	}
-
-
-	//! Finds first position of a character not in a given list.
-	/** \param c: List of characters not to find. For example if the method
-	 should find the first occurance of a character not 'a' or 'b', this parameter should be "ab".
-	\param count: Amount of characters in the list. Ususally, 
-	this should be strlen(ofParameter1)
-	\return Returns position where the character has been found,
-	or -1 if not found. */
-	template <class B> 
-	s32 findFirstCharNotInList(B* c, int count) const
-	{
-		for (int i=0; i<used; ++i)
-		{
-            int j;
-			for (j=0; j<count; ++j)
-				if (array[i] == c[j])
-					break;
-
-			if (j==count)
-				return i;
-		}
-
-		return -1;
-	}
-
-	//! Finds last position of a character not in a given list.
-	/** \param c: List of characters not to find. For example if the method
-	 should find the first occurance of a character not 'a' or 'b', this parameter should be "ab".
-	\param count: Amount of characters in the list. Ususally, 
-	this should be strlen(ofParameter1)
-	\return Returns position where the character has been found,
-	or -1 if not found. */
-	template <class B> 
-	s32 findLastCharNotInList(B* c, int count) const
-	{
-		for (int i=used-2; i>=0; --i)
-		{
-            int j;
-			for (j=0; j<count; ++j)
-				if (array[i] == c[j])
-					break;
-
-			if (j==count)
-				return i;
-		}
-
-		return -1;
-	}
-
-	//! finds next occurrence of character in string
-	/** \param c: Character to search for.
-	\param startPos: Position in string to start searching. 
-	\return Returns position where the character has been found,
-	or -1 if not found. */
-	s32 findNext(T c, s32 startPos) const
-	{
-		for (s32 i=startPos; i<used; ++i)
-			if (array[i] == c)
-				return i;
-
-		return -1;
-	}
-
-
-	//! finds last occurrence of character in string
-	//! \param c: Character to search for.
-	//! \return Returns position where the character has been found,
-	//! or -1 if not found.
-	s32 findLast(T c) const
-	{
-		for (s32 i=used-1; i>=0; --i)
-			if (array[i] == c)
-				return i;
-
-		return -1;
-	}
-
-
-	//! Returns a substring
-	//! \param begin: Start of substring.
-	//! \param length: Length of substring.
-	string<T> subString(s32 begin, s32 length)
-	{
-		if (length <= 0)
-			return string<T>("");
-
-		string<T> o;
-		o.reserve(length+1);
-
-		for (s32 i=0; i<length; ++i)
-			o.array[i] = array[i+begin];
-
-		o.array[length] = 0;
-		o.used = o.allocated;
-
-		return o;
-	}
-
-
-	void operator += (T c)
-	{
-		append(c);
-	}
-
-	void operator += (const string<T>& other)
-	{
-		append(other);
-	}
-
-	void operator += (int i)
-	{
-		append(string<T>(i));
-	}
-
-	//! replaces all characters of a special type with another one
-	void replace(T toReplace, T replaceWith)
-	{
-		for (s32 i=0; i<used; ++i)
-			if (array[i] == toReplace)
-				array[i] = replaceWith;
-	}
-
-	//! trims the string.
-	/** Removes whitespace from begin and end of the string. */
-	void trim()
-	{
-		const char whitespace[] = " \t\n";
-		const int whitespacecount = 3;
-
-		// find start and end of real string without whitespace
-		int begin = findFirstCharNotInList(whitespace, whitespacecount);
-		if (begin == -1)
-			return;
-
-		int end = findLastCharNotInList(whitespace, whitespacecount);
-		if (end == -1)
-			return;
-
-		*this = subString(begin, (end +1) - begin);
-	}
-
-
-	//! Erases a character from the string. May be slow, because all elements 
-	//! following after the erased element have to be copied.
-	//! \param index: Index of element to be erased.
-	void erase(int index)
-	{
-		_IRR_DEBUG_BREAK_IF(index>=used || index<0) // access violation
-
-		for (int i=index+1; i<used; ++i)
-			array[i-1] = array[i];
-
-		--used;
-	}
-
-    	
-
-private:
-
-	//! Returns a character converted to lower case
-	T toLower(const T& t) const
-	{
-		if (t>=(T)'A' && t<=(T)'Z')
-			return t + ((T)'a' - (T)'A');
-		else
-			return t;
-	}
-
-	//! Reallocate the array, make it bigger or smaler
-	void reallocate(s32 new_size)
-	{
-		T* old_array = array;
-
-		array = new T[new_size];
-		allocated = new_size;
-		
-		s32 amount = used < new_size ? used : new_size;
-		for (s32 i=0; i<amount; ++i)
-			array[i] = old_array[i];
-
-		if (allocated < used)
-			used = allocated;
-		
-		delete [] old_array;
-	}
-
-
-	//--- member variables
-
-	T* array;
-	s32 allocated;
-	s32 used;
-};
-
-
-//! Typedef for character strings
-typedef string<irr::c8> stringc;
-
-//! Typedef for wide character strings
-typedef string<wchar_t> stringw;
-
-} // end namespace core
-} // end namespace irr
-
-#endif
-

+ 0 - 108
contrib/irrXML/irrTypes.h

@@ -1,108 +0,0 @@
-// Copyright (C) 2002-2005 Nikolaus Gebhardt
-// This file is part of the "Irrlicht Engine".
-// For conditions of distribution and use, see copyright notice in irrlicht.h
-
-#ifndef __IRR_TYPES_H_INCLUDED__
-#define __IRR_TYPES_H_INCLUDED__
-
-namespace irr
-{
-
-//! 8 bit unsigned variable.
-/** This is a typedef for unsigned char, it ensures portability of the engine. */
-typedef unsigned char		u8; 
-
-//! 8 bit signed variable.
-/** This is a typedef for signed char, it ensures portability of the engine. */
-typedef signed char			s8; 
-
-//! 8 bit character variable.
-/** This is a typedef for char, it ensures portability of the engine. */
-typedef char				c8; 
-
-
-
-//! 16 bit unsigned variable.
-/** This is a typedef for unsigned short, it ensures portability of the engine. */
-typedef unsigned short		u16;
-
-//! 16 bit signed variable.
-/** This is a typedef for signed short, it ensures portability of the engine. */
-typedef signed short		s16; 
-
-
-
-//! 32 bit unsigned variable.
-/** This is a typedef for unsigned int, it ensures portability of the engine. */
-typedef unsigned int		u32;
-
-//! 32 bit signed variable.
-/** This is a typedef for signed int, it ensures portability of the engine. */
-typedef signed int			s32; 
-
-
-
-// 64 bit signed variable.
-// This is a typedef for __int64, it ensures portability of the engine. 
-// This type is currently not used by the engine and not supported by compilers
-// other than Microsoft Compilers, so it is outcommented.
-//typedef __int64				s64; 
-
-
-
-//! 32 bit floating point variable.
-/** This is a typedef for float, it ensures portability of the engine. */
-typedef float				f32; 
-
-//! 64 bit floating point variable.
-/** This is a typedef for double, it ensures portability of the engine. */
-typedef double				f64; 
-
-
-} // end namespace
-
-
-// define the wchar_t type if not already built in.
-#ifdef _MSC_VER 
-#ifndef _WCHAR_T_DEFINED
-//! A 16 bit wide character type.
-/**
-	Defines the wchar_t-type.
-	In VS6, its not possible to tell
-	the standard compiler to treat wchar_t as a built-in type, and 
-	sometimes we just don't want to include the huge stdlib.h or wchar.h,
-	so we'll use this.
-*/
-typedef unsigned short wchar_t;
-#define _WCHAR_T_DEFINED
-#endif // wchar is not defined
-#endif // microsoft compiler
-
-//! define a break macro for debugging only in Win32 mode.
-// WORKAROUND (assimp): remove __asm
-#if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG)
-#if defined(_M_IX86)
-#define _IRR_DEBUG_BREAK_IF( _CONDITION_ ) /*if (_CONDITION_) {_asm int 3}*/
-#else
-#define _IRR_DEBUG_BREAK_IF( _CONDITION_ )
-#endif
-#else 
-#define _IRR_DEBUG_BREAK_IF( _CONDITION_ )
-#endif
-
-//! Defines a small statement to work around a microsoft compiler bug.
-/** The microsft compiler 7.0 - 7.1 has a bug:
-When you call unmanaged code that returns a bool type value of false from managed code, 
-the return value may appear as true. See 
-http://support.microsoft.com/default.aspx?kbid=823071 for details. 
-Compiler version defines: VC6.0 : 1200, VC7.0 : 1300, VC7.1 : 1310, VC8.0 : 1400*/
-
-// WORKAROUND (assimp): remove __asm 
-#if defined(WIN32) && defined(_MSC_VER) && (_MSC_VER > 1299) && (_MSC_VER < 1400)
-#define _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX /*__asm mov eax,100*/
-#else
-#define _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX
-#endif // _IRR_MANAGED_MARSHALLING_BUGFIX
-
-#endif // __IRR_TYPES_H_INCLUDED__
-

+ 0 - 151
contrib/irrXML/irrXML.cpp

@@ -1,151 +0,0 @@
-// Copyright (C) 2002-2005 Nikolaus Gebhardt
-// This file is part of the "Irrlicht Engine" and the "irrXML" project.
-// For conditions of distribution and use, see copyright notice in irrlicht.h and/or irrXML.h
-
-// Need to include Assimp, too. We're using Assimp's version of fast_atof
-// so we need stdint.h. But no PCH.
-
-
-#include "irrXML.h"
-#include "irrString.h"
-#include "irrArray.h"
-//#include <assimp/fast_atof.h>
-#include "CXMLReaderImpl.h"
-
-namespace irr
-{
-namespace io
-{
-
-//! Implementation of the file read callback for ordinary files
-class IRRXML_API CFileReadCallBack : public IFileReadCallBack
-{
-public:
-
-	//! construct from filename
-	CFileReadCallBack(const char* filename)
-		: File(0), Size(0), Close(true)
-	{
-		// open file
-		File = fopen(filename, "rb");
-
-		if (File)
-			getFileSize();
-	}
-
-	//! construct from FILE pointer
-	CFileReadCallBack(FILE* file)
-		: File(file), Size(0), Close(false)
-	{
-		if (File)
-			getFileSize();
-	}
-
-	//! destructor
-	virtual ~CFileReadCallBack()
-	{
-		if (Close && File)
-			fclose(File);
-	}
-
-	//! Reads an amount of bytes from the file.
-	virtual int read(void* buffer, int sizeToRead)
-	{
-		if (!File)
-			return 0;
-
-		return (int)fread(buffer, 1, sizeToRead, File);
-	}
-
-	//! Returns size of file in bytes
-	virtual int getSize()
-	{
-		return Size;
-	}
-
-private:
-
-	//! retrieves the file size of the open file
-	void getFileSize()
-	{
-		fseek(File, 0, SEEK_END);
-		Size = ftell(File);
-		fseek(File, 0, SEEK_SET);
-	}
-
-	FILE* File;
-	int Size;
-	bool Close;
-
-}; // end class CFileReadCallBack
-
-
-
-// FACTORY FUNCTIONS:
-
-
-//! Creates an instance of an UFT-8 or ASCII character xml parser. 
-IrrXMLReader* createIrrXMLReader(const char* filename)
-{
-	return new CXMLReaderImpl<char, IXMLBase>(new CFileReadCallBack(filename)); 
-}
-
-
-//! Creates an instance of an UFT-8 or ASCII character xml parser. 
-IrrXMLReader* createIrrXMLReader(FILE* file)
-{
-	return new CXMLReaderImpl<char, IXMLBase>(new CFileReadCallBack(file)); 
-}
-
-
-//! Creates an instance of an UFT-8 or ASCII character xml parser. 
-IrrXMLReader* createIrrXMLReader(IFileReadCallBack* callback)
-{
-	return new CXMLReaderImpl<char, IXMLBase>(callback, false); 
-}
-
-
-//! Creates an instance of an UTF-16 xml parser. 
-IrrXMLReaderUTF16* createIrrXMLReaderUTF16(const char* filename)
-{
-	return new CXMLReaderImpl<char16, IXMLBase>(new CFileReadCallBack(filename)); 
-}
-
-
-//! Creates an instance of an UTF-16 xml parser. 
-IrrXMLReaderUTF16* createIrrXMLReaderUTF16(FILE* file)
-{
-	return new CXMLReaderImpl<char16, IXMLBase>(new CFileReadCallBack(file)); 
-}
-
-
-//! Creates an instance of an UTF-16 xml parser. 
-IrrXMLReaderUTF16* createIrrXMLReaderUTF16(IFileReadCallBack* callback)
-{
-	return new CXMLReaderImpl<char16, IXMLBase>(callback, false); 
-}
-
-
-//! Creates an instance of an UTF-32 xml parser. 
-IrrXMLReaderUTF32* createIrrXMLReaderUTF32(const char* filename)
-{
-	return new CXMLReaderImpl<char32, IXMLBase>(new CFileReadCallBack(filename)); 
-}
-
-
-//! Creates an instance of an UTF-32 xml parser. 
-IrrXMLReaderUTF32* createIrrXMLReaderUTF32(FILE* file)
-{
-	return new CXMLReaderImpl<char32, IXMLBase>(new CFileReadCallBack(file)); 
-}
-
-
-//! Creates an instance of an UTF-32 xml parser. 
-IrrXMLReaderUTF32* createIrrXMLReaderUTF32(IFileReadCallBack* callback)
-{
-	return new CXMLReaderImpl<char32, IXMLBase>(callback, false); 
-}
-
-
-} // end namespace io
-} // end namespace irr

+ 0 - 546
contrib/irrXML/irrXML.h

@@ -1,546 +0,0 @@
-// Copyright (C) 2002-2005 Nikolaus Gebhardt
-// This file is part of the "Irrlicht Engine" and the "irrXML" project.
-// For conditions of distribution and use, see copyright notice in irrlicht.h and/or irrXML.h
-
-#ifndef __IRR_XML_H_INCLUDED__
-#define __IRR_XML_H_INCLUDED__
-
-#include <stdio.h>
-
-#ifdef _WIN32
-#   define IRRXML_API __declspec(dllexport)
-#else
-#   define IRRXML_API __attribute__ ((visibility("default")))
-#endif // _WIN32
-
-/** \mainpage irrXML 1.2 API documentation
- <div align="center"><img src="logobig.png" ></div>
-
- \section intro Introduction
-
-  Welcome to the irrXML API documentation.
-  Here you'll find any information you'll need to develop applications with
-  irrXML. If you look for a tutorial on how to start, take a look at the \ref irrxmlexample,
-  at the homepage of irrXML at <A HREF="http://xml.irrlicht3d.org" >xml.irrlicht3d.org</A> 
-  or into the SDK in the directory \example.
- 
-  irrXML is intended to be a high speed and easy-to-use XML Parser for C++, and
-  this documentation is an important part of it. If you have any questions or
-  suggestions, just send a email to the author of the engine, Nikolaus Gebhardt
-  (niko (at) irrlicht3d.org). For more informations about this parser, see \ref history.
-
-  \section features Features
-
-  irrXML provides forward-only, read-only 
-     access to a stream of non validated XML data. It was fully implemented by
-	 Nikolaus Gebhardt. Its current features are:
-
-	 - It it fast as lighting and has very low memory usage. It was 
-	   developed with the intention of being used in 3D games, as it already has been.
-	 - irrXML is very small: It only consists of 60 KB of code and can be added easily
-	   to your existing project.
-	 - Of course, it is platform independent and works with lots of compilers.
-	 - It is able to parse ASCII, UTF-8, UTF-16 and UTF-32 text files, both in 
-	   little and big endian format. 
-	 - Independent of the input file format, the parser can return all strings in ASCII, UTF-8,
-	   UTF-16 and UTF-32 format. 
-	 - With its optional file access abstraction it has the advantage that it can read not
-	   only from files but from any type of data (memory, network, ...). For example when 
-	   used with the Irrlicht Engine, it directly reads from compressed .zip files. 
-	 - Just like the Irrlicht Engine for which it was originally created, it is extremely easy 
-	   to use.
-	 - It has no external dependencies, it does not even need the STL. 
-
-	 Although irrXML has some strenghts, it currently also has the following limitations:
-
-	 - The input xml file is not validated and assumed to be correct. 
-
-    \section irrxmlexample Example
-
-    The following code demonstrates the basic usage of irrXML. A simple xml
-	file like this is parsed:
-    \code
-	<?xml version="1.0"?>
-	<config>
-		<!-- This is a config file for the mesh viewer -->
-		<model file="dwarf.dea" />
-		<messageText caption="Irrlicht Engine Mesh Viewer">
-		Welcome to the Mesh Viewer of the &quot;Irrlicht Engine&quot;.
-		</messageText>
-	</config>
-	\endcode
-
-	The code for parsing this file would look like this:
-	\code
-	#include <irrXML.h>
-	using namespace irr; // irrXML is located in the namespace irr::io
-	using namespace io;
-
-	#include <string> // we use STL strings to store data in this example
-
-	void main()
-	{
-		// create the reader using one of the factory functions
-
-		IrrXMLReader* xml = createIrrXMLReader("config.xml");
-
-		// strings for storing the data we want to get out of the file
-		std::string modelFile;
-		std::string messageText;
-		std::string caption;
-
-		// parse the file until end reached
-
-		while(xml && xml->read())
-		{
-			switch(xml->getNodeType())
-			{
-			case EXN_TEXT:
-				// in this xml file, the only text which occurs is the messageText
-				messageText = xml->getNodeData();
-				break;
-			case EXN_ELEMENT:
-				{
-					if (!strcmp("model", xml->getNodeName()))
-						modelFile = xml->getAttributeValue("file");
-					else
-					if (!strcmp("messageText", xml->getNodeName()))
-						caption = xml->getAttributeValue("caption");
-				}
-				break;
-			}
-		}
-
-		// delete the xml parser after usage
-		delete xml;
-	}
-	\endcode
-
-	\section howto How to use
-
-	Simply add the source files in the /src directory of irrXML to your project. Done.
-
-	\section license License
-
-	The irrXML license is based on the zlib license. Basicly, this means you can do with
-	irrXML whatever you want:
-
-	Copyright (C) 2002-2005 Nikolaus Gebhardt
-
-	This software is provided 'as-is', without any express or implied
-	warranty.  In no event will the authors be held liable for any damages
-	arising from the use of this software.
-
-	Permission is granted to anyone to use this software for any purpose,
-	including commercial applications, and to alter it and redistribute it
-	freely, subject to the following restrictions:
-
-	1. The origin of this software must not be misrepresented; you must not
-		claim that you wrote the original software. If you use this software
-		in a product, an acknowledgment in the product documentation would be
-		appreciated but is not required.
-
-	2. Altered source versions must be plainly marked as such, and must not be
-		misrepresented as being the original software.
-
-	3. This notice may not be removed or altered from any source distribution.
-
-	\section history History
-
-	As lots of references in this documentation and the source show, this xml 
-	parser has originally been a part of the 
-	<A HREF="http://irrlicht.sourceforge.net" >Irrlicht Engine</A>. But because
-	the parser has become very useful with the latest release, people asked for a 
-	separate version of it, to be able to use it in non Irrlicht projects. With
-	irrXML 1.0, this has now been done.
-*/
-
-namespace irr
-{
-namespace io
-{
-	//! Enumeration of all supported source text file formats 
-	enum ETEXT_FORMAT
-	{
-		//! ASCII, file without byte order mark, or not a text file
-		ETF_ASCII,
-
-		//! UTF-8 format
-		ETF_UTF8,
-
-		//! UTF-16 format, big endian
-		ETF_UTF16_BE,
-
-		//! UTF-16 format, little endian
-		ETF_UTF16_LE,
-
-		//! UTF-32 format, big endian
-		ETF_UTF32_BE,
-
-		//! UTF-32 format, little endian
-		ETF_UTF32_LE
-	};
-
-
-	//! Enumeration for all xml nodes which are parsed by IrrXMLReader
-	enum EXML_NODE
-	{
-		//! No xml node. This is usually the node if you did not read anything yet.
-		EXN_NONE,
-
-		//! A xml element, like <foo>
-		EXN_ELEMENT,
-
-		//! End of an xml element, like </foo>
-		EXN_ELEMENT_END,
-
-		//! Text within a xml element: <foo> this is the text. </foo>
-		EXN_TEXT,
-
-		//! An xml comment like &lt;!-- I am a comment --&gt; or a DTD definition.
-		EXN_COMMENT,
-
-		//! An xml cdata section like &lt;![CDATA[ this is some CDATA ]]&gt;
-		EXN_CDATA,
-
-		//! Unknown element.
-		EXN_UNKNOWN
-	};
-
-	//! Callback class for file read abstraction. 
-	/** With this, it is possible to make the xml parser read in other things 
-	than just files. The Irrlicht engine is using this for example to 
-	read xml from compressed .zip files. To make the parser read in 
-	any other data, derive a class from this interface, implement the 
-	two methods to read your data and give a pointer to an instance of
-	your implementation when calling createIrrXMLReader(), 
-	createIrrXMLReaderUTF16() or createIrrXMLReaderUTF32() */
-	class IRRXML_API IFileReadCallBack
-	{
-	public:
-
-		//! virtual destructor
-		virtual ~IFileReadCallBack() {};
-
-		//! Reads an amount of bytes from the file.
-		/** \param buffer: Pointer to buffer where to read bytes will be written to.
-		\param sizeToRead: Amount of bytes to read from the file.
-		\return Returns how much bytes were read. */
-		virtual int read(void* buffer, int sizeToRead) = 0;
-
-		//! Returns size of file in bytes
-		virtual int getSize() = 0;
-	};
-
-	//! Empty class to be used as parent class for IrrXMLReader.
-	/** If you need another class as base class for the xml reader, you can do this by creating
-	the reader using for example new CXMLReaderImpl<char, YourBaseClass>(yourcallback);
-	The Irrlicht Engine for example needs IUnknown as base class for every object to
-	let it automaticly reference countend, hence it replaces IXMLBase with IUnknown.
-	See irrXML.cpp on how this can be done in detail. */
-	class IXMLBase
-	{
-	};	
-
-	//! Interface providing easy read access to a XML file.
-	/** You can create an instance of this reader using one of the factory functions
-	createIrrXMLReader(), createIrrXMLReaderUTF16() and createIrrXMLReaderUTF32().
-	If using the parser from the Irrlicht Engine, please use IFileSystem::createXMLReader() 
-	instead.
-	For a detailed intro how to use the parser, see \ref irrxmlexample and \ref features.
-
-	The typical usage of this parser looks like this:
-	\code
-	#include <irrXML.h>
-	using namespace irr; // irrXML is located in the namespace irr::io
-	using namespace io;
-
-	void main()
-	{
-		// create the reader using one of the factory functions
-		IrrXMLReader* xml = createIrrXMLReader("config.xml");
-
-		if (xml == 0)
-			return; // file could not be opened
-
-		// parse the file until end reached
-		while(xml->read())
-		{
-			// based on xml->getNodeType(), do something.
-		}
-
-		// delete the xml parser after usage
-		delete xml;
-	}
-	\endcode
-	See \ref irrxmlexample for a more detailed example.
-	*/
-	template<class char_type, class super_class>
-	class IIrrXMLReader : public super_class
-	{
-	public:
-
-		//! Destructor
-		virtual ~IIrrXMLReader() {};
-
-		//! Reads forward to the next xml node. 
-		/** \return Returns false, if there was no further node.  */
-		virtual bool read() = 0;
-
-		//! Returns the type of the current XML node.
-		virtual EXML_NODE getNodeType() const = 0;
-
-        //! Returns attribute count of the current XML node. 
-		/** This is usually
-		non null if the current node is EXN_ELEMENT, and the element has attributes.
-		\return Returns amount of attributes of this xml node. */
-		virtual int getAttributeCount() const = 0;
-
-		//! Returns name of an attribute. 
-		/** \param idx: Zero based index, should be something between 0 and getAttributeCount()-1.
-		\return Name of the attribute, 0 if an attribute with this index does not exist. */
-		virtual const char_type* getAttributeName(int idx) const = 0;
-
-		//! Returns the value of an attribute. 
-		/** \param idx: Zero based index, should be something between 0 and getAttributeCount()-1.
-		\return Value of the attribute, 0 if an attribute with this index does not exist. */
-		virtual const char_type* getAttributeValue(int idx) const = 0;
-
-		//! Returns the value of an attribute. 
-		/** \param name: Name of the attribute.
-		\return Value of the attribute, 0 if an attribute with this name does not exist. */
-		virtual const char_type* getAttributeValue(const char_type* name) const = 0;
-
-		//! Returns the value of an attribute in a safe way.
-		/** Like getAttributeValue(), but does not 
-		return 0 if the attribute does not exist. An empty string ("") is returned then.
-		\param name: Name of the attribute.
-		\return Value of the attribute, and "" if an attribute with this name does not exist */
-		virtual const char_type* getAttributeValueSafe(const char_type* name) const = 0;
-
-		//! Returns the value of an attribute as integer. 
-		/** \param name Name of the attribute.
-		\return Value of the attribute as integer, and 0 if an attribute with this name does not exist or
-		the value could not be interpreted as integer. */
-		virtual int getAttributeValueAsInt(const char_type* name) const = 0;
-
-		//! Returns the value of an attribute as integer. 
-		/** \param idx: Zero based index, should be something between 0 and getAttributeCount()-1.
-		\return Value of the attribute as integer, and 0 if an attribute with this index does not exist or
-		the value could not be interpreted as integer. */
-		virtual int getAttributeValueAsInt(int idx) const = 0;
-
-		//! Returns the value of an attribute as float. 
-		/** \param name: Name of the attribute.
-		\return Value of the attribute as float, and 0 if an attribute with this name does not exist or
-		the value could not be interpreted as float. */
-		virtual float getAttributeValueAsFloat(const char_type* name) const = 0;
-
-		//! Returns the value of an attribute as float. 
-		/** \param idx: Zero based index, should be something between 0 and getAttributeCount()-1.
-		\return Value of the attribute as float, and 0 if an attribute with this index does not exist or
-		the value could not be interpreted as float. */
-		virtual float getAttributeValueAsFloat(int idx) const = 0;
-
-		//! Returns the name of the current node. 
-		/** Only non null, if the node type is EXN_ELEMENT.
-		\return Name of the current node or 0 if the node has no name. */
-		virtual const char_type* getNodeName() const = 0;
-
-		//! Returns data of the current node. 
-		/** Only non null if the node has some
-		data and it is of type EXN_TEXT or EXN_UNKNOWN. */
-		virtual const char_type* getNodeData() const = 0;
-
-		//! Returns if an element is an empty element, like <foo />
-		virtual bool isEmptyElement() const = 0;
-
-		//! Returns format of the source xml file. 
-		/** It is not necessary to use
-		this method because the parser will convert the input file format
-		to the format wanted by the user when creating the parser. This
-		method is useful to get/display additional informations. */
-		virtual ETEXT_FORMAT getSourceFormat() const = 0;
-
-		//! Returns format of the strings returned by the parser. 
-		/** This will be UTF8 for example when you created a parser with
-		IrrXMLReaderUTF8() and UTF32 when it has been created using 
-		IrrXMLReaderUTF32. It should not be necessary to call this
-		method and only exists for informational purposes. */
-		virtual ETEXT_FORMAT getParserFormat() const = 0;
-	};
-
-
-	//! defines the utf-16 type.
-	/** Not using wchar_t for this because 
-	wchar_t has 16 bit on windows and 32 bit on other operating systems. */
-	typedef unsigned short char16;
-
-	//! defines the utf-32 type. 
-	/** Not using wchar_t for this because 
-	wchar_t has 16 bit on windows and 32 bit on other operating systems. */
-	typedef unsigned long char32;
-
-	//! A UTF-8 or ASCII character xml parser.
-	/** This means that all character data will be returned in 8 bit ASCII or UTF-8 by this parser. 
-	The file to read can be in any format, it will be converted to UTF-8 if it is not
-	in this format.
-	Create an instance of this with createIrrXMLReader(); 
-	See IIrrXMLReader for description on how to use it. */
-	typedef IIrrXMLReader<char, IXMLBase> IrrXMLReader;
-
-	//! A UTF-16 xml parser. 
-	/** This means that all character data will be returned in UTF-16 by this parser. 
-	The file to read can be in any format, it will be converted to UTF-16 if it is not
-	in this format.
-	Create an instance of this with createIrrXMLReaderUTF16(); 
-	See IIrrXMLReader for description on how to use it.  */
-	typedef IIrrXMLReader<char16, IXMLBase> IrrXMLReaderUTF16;
-
-	//! A UTF-32 xml parser. 
-	/** This means that all character data will be returned in UTF-32 by this parser. 
-	The file to read can be in any format, it will be converted to UTF-32 if it is not
-	in this format.
-	Create an instance of this with createIrrXMLReaderUTF32(); 
-	See IIrrXMLReader for description on how to use it. */
-	typedef IIrrXMLReader<char32, IXMLBase> IrrXMLReaderUTF32;
-
-
-	//! Creates an instance of an UFT-8 or ASCII character xml parser.
-	/** This means that all character data will be returned in 8 bit ASCII or UTF-8. 
-	The file to read can be in any format, it will be converted to UTF-8 if it is not in this format.
-	If you are using the Irrlicht Engine, it is better not to use this function but
-	IFileSystem::createXMLReaderUTF8() instead.
-	\param filename: Name of file to be opened.
-	\return Returns a pointer to the created xml parser. This pointer should be 
-	deleted using 'delete' after no longer needed. Returns 0 if an error occured
-	and the file could not be opened. */
-    IRRXML_API IrrXMLReader* createIrrXMLReader(const char* filename);
-
-	//! Creates an instance of an UFT-8 or ASCII character xml parser.
-	/** This means that all character data will be returned in 8 bit ASCII or UTF-8. The file to read can 
-	be in any format, it will be converted to UTF-8 if it is not in this format.
-	If you are using the Irrlicht Engine, it is better not to use this function but
-	IFileSystem::createXMLReaderUTF8() instead.
-	\param file: Pointer to opened file, must have been opened in binary mode, e.g.
-	using fopen("foo.bar", "wb"); The file will not be closed after it has been read.
-	\return Returns a pointer to the created xml parser. This pointer should be 
-	deleted using 'delete' after no longer needed. Returns 0 if an error occured
-	and the file could not be opened. */
-    IRRXML_API IrrXMLReader* createIrrXMLReader(FILE* file);
-
-	//! Creates an instance of an UFT-8 or ASCII character xml parser. 
-	/** This means that all character data will be returned in 8 bit ASCII or UTF-8. The file to read can 
-	 be in any format, it will be converted to UTF-8 if it is not in this format.
-	 If you are using the Irrlicht Engine, it is better not to use this function but
-	 IFileSystem::createXMLReaderUTF8() instead.
-	 \param callback: Callback for file read abstraction. Implement your own
-	 callback to make the xml parser read in other things than just files. See
-	 IFileReadCallBack for more information about this.
-	 \return Returns a pointer to the created xml parser. This pointer should be 
-	 deleted using 'delete' after no longer needed. Returns 0 if an error occured
-	 and the file could not be opened. */
-    IRRXML_API IrrXMLReader* createIrrXMLReader(IFileReadCallBack* callback);
-
-	//! Creates an instance of an UFT-16 xml parser. 
-	/** This means that
-	all character data will be returned in UTF-16. The file to read can 
-	be in any format, it will be converted to UTF-16 if it is not in this format.
-	If you are using the Irrlicht Engine, it is better not to use this function but
-	IFileSystem::createXMLReader() instead.
-	\param filename: Name of file to be opened.
-	\return Returns a pointer to the created xml parser. This pointer should be 
-	deleted using 'delete' after no longer needed. Returns 0 if an error occured
-	and the file could not be opened. */
-    IRRXML_API IrrXMLReaderUTF16* createIrrXMLReaderUTF16(const char* filename);
-
-	//! Creates an instance of an UFT-16 xml parser. 
-	/** This means that all character data will be returned in UTF-16. The file to read can 
-	be in any format, it will be converted to UTF-16 if it is not in this format.
-	If you are using the Irrlicht Engine, it is better not to use this function but
-	IFileSystem::createXMLReader() instead.
-	\param file: Pointer to opened file, must have been opened in binary mode, e.g.
-	using fopen("foo.bar", "wb"); The file will not be closed after it has been read.
-	\return Returns a pointer to the created xml parser. This pointer should be 
-	deleted using 'delete' after no longer needed. Returns 0 if an error occured
-	and the file could not be opened. */
-    IRRXML_API IrrXMLReaderUTF16* createIrrXMLReaderUTF16(FILE* file);
-
-	//! Creates an instance of an UFT-16 xml parser. 
-	/** This means that all character data will be returned in UTF-16. The file to read can 
-	be in any format, it will be converted to UTF-16 if it is not in this format.
-	If you are using the Irrlicht Engine, it is better not to use this function but
-	IFileSystem::createXMLReader() instead.
-	\param callback: Callback for file read abstraction. Implement your own
-	callback to make the xml parser read in other things than just files. See
-	IFileReadCallBack for more information about this.
-	\return Returns a pointer to the created xml parser. This pointer should be 
-	deleted using 'delete' after no longer needed. Returns 0 if an error occured
-	and the file could not be opened. */
-    IRRXML_API IrrXMLReaderUTF16* createIrrXMLReaderUTF16(IFileReadCallBack* callback);
-
-
-	//! Creates an instance of an UFT-32 xml parser. 
-	/** This means that all character data will be returned in UTF-32. The file to read can 
-	be in any format, it will be converted to UTF-32 if it is not in this format.
-	If you are using the Irrlicht Engine, it is better not to use this function but
-	IFileSystem::createXMLReader() instead.
-	\param filename: Name of file to be opened.
-	\return Returns a pointer to the created xml parser. This pointer should be 
-	deleted using 'delete' after no longer needed. Returns 0 if an error occured
-	and the file could not be opened. */
-    IRRXML_API IrrXMLReaderUTF32* createIrrXMLReaderUTF32(const char* filename);
-
-	//! Creates an instance of an UFT-32 xml parser. 
-	/** This means that all character data will be returned in UTF-32. The file to read can 
-	be in any format, it will be converted to UTF-32 if it is not in this format.
-	if you are using the Irrlicht Engine, it is better not to use this function but
-	IFileSystem::createXMLReader() instead.
-	\param file: Pointer to opened file, must have been opened in binary mode, e.g.
-	using fopen("foo.bar", "wb"); The file will not be closed after it has been read.
-	\return Returns a pointer to the created xml parser. This pointer should be 
-	deleted using 'delete' after no longer needed. Returns 0 if an error occured
-	and the file could not be opened. */
-    IRRXML_API IrrXMLReaderUTF32* createIrrXMLReaderUTF32(FILE* file);
-
-	//! Creates an instance of an UFT-32 xml parser. 
-	/** This means that
-	all character data will be returned in UTF-32. The file to read can 
-	be in any format, it will be converted to UTF-32 if it is not in this format.
-	If you are using the Irrlicht Engine, it is better not to use this function but
-	IFileSystem::createXMLReader() instead.
-	\param callback: Callback for file read abstraction. Implement your own
-	callback to make the xml parser read in other things than just files. See
-	IFileReadCallBack for more information about this.
-	\return Returns a pointer to the created xml parser. This pointer should be 
-	deleted using 'delete' after no longer needed. Returns 0 if an error occured
-	and the file could not be opened. */
-    IRRXML_API IrrXMLReaderUTF32* createIrrXMLReaderUTF32(IFileReadCallBack* callback);
-	
-
-	/*! \file irrxml.h
-    \brief Header file of the irrXML, the Irrlicht XML parser.
-    
-    This file includes everything needed for using irrXML, 
-    the XML parser of the Irrlicht Engine. To use irrXML,
-	you only need to include this file in your project:
-
-	\code
-	#include <irrXML.h>
-	\endcode
-
-	It is also common to use the two namespaces in which irrXML is included, 
-	directly after #including irrXML.h:
-
-	\code
-	#include <irrXML.h>
-	using namespace irr;
-	using namespace io;
-	\endcode
-	*/
-
-} // end namespace io
-} // end namespace irr
-
-#endif // __IRR_XML_H_INCLUDED__
-

+ 54 - 14
include/assimp/irrXMLWrapper.h → include/assimp/XmlParser.h

@@ -44,16 +44,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #define INCLUDED_AI_IRRXML_WRAPPER
 
 // some long includes ....
-#ifdef ASSIMP_USE_HUNTER
-#  include <irrXML/irrXML.h>
-#else
-#  include <irrXML.h>
-#endif
-#include "IOStream.hpp"
 #include "BaseImporter.h"
+#include "IOStream.hpp"
+#include <pugixml.hpp>
 #include <vector>
 
-namespace Assimp    {
+namespace Assimp {
 
 // ---------------------------------------------------------------------------------
 /** @brief Utility class to make IrrXML work together with our custom IO system
@@ -75,7 +71,7 @@ namespace Assimp    {
  * }
  * @endcode
  **/
-class CIrrXML_IOStreamReader : public irr::io::IFileReadCallBack {
+/*class CIrrXML_IOStreamReader : public irr::io::IFileReadCallBack {
 public:
 
     // ----------------------------------------------------------------------------------
@@ -110,14 +106,14 @@ public:
 
     // ----------------------------------------------------------------------------------
     //! Virtual destructor
-    virtual ~CIrrXML_IOStreamReader() {}
+    virtual ~CIrrXML_IOStreamReader() {}*/
 
-    // ----------------------------------------------------------------------------------
-    //!   Reads an amount of bytes from the file.
-    /**  @param buffer:       Pointer to output buffer.
+// ----------------------------------------------------------------------------------
+//!   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)  {
+/*virtual int read(void* buffer, int sizeToRead)  {
         if(sizeToRead<0) {
             return 0;
         }
@@ -143,7 +139,51 @@ private:
     size_t t;
 
 }; // ! class CIrrXML_IOStreamReader
+*/
+
+class XmlParser {
+public:
+	XmlParser() :
+			mDoc(nullptr), mRoot(nullptr), mData() {
+        // empty
+	}
+
+    ~XmlParser() {
+		clear();
+    }
+
+    void clear() {
+		mData.resize(0);
+		delete mDoc;
+		mDoc = nullptr;
+    }
+
+    pugi::xml_node *parse(IOStream *stream) {
+		if (nullptr == stream) {
+			return nullptr;
+		}
+
+        mData.resize(stream->FileSize());
+		stream->Read(&mData[0], mData.size(), 1);
+		mDoc = new pugi::xml_document();
+		pugi::xml_parse_result result = mDoc->load_string(&mData[0]);
+        if (result.status == pugi::status_ok) {
+			mRoot = &mDoc->root();
+        }
+
+        return mRoot;
+    }
+
+    pugi::xml_document *getDocument() const {
+		return mDoc;
+    }
+
+private:
+	pugi::xml_document *mDoc;
+	pugi::xml_node *mRoot;
+	std::vector<char> mData;
+};
 
-} // ! Assimp
+} // namespace Assimp
 
 #endif // !! INCLUDED_AI_IRRXML_WRAPPER