diff --git a/code/ColladaLoader.cpp b/code/ColladaLoader.cpp
new file mode 100644
index 000000000..9d5dbd313
--- /dev/null
+++ b/code/ColladaLoader.cpp
@@ -0,0 +1,116 @@
+/** Implementation of the Collada loader */
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development Team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the ASSIMP team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the ASSIMP Development Team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+#include "AssimpPCH.h"
+#include "../include/aiAnim.h"
+#include "ColladaLoader.h"
+#include "ColladaParser.h"
+
+using namespace Assimp;
+
+// ------------------------------------------------------------------------------------------------
+// Constructor to be privately used by Importer
+ColladaLoader::ColladaLoader()
+{
+}
+
+// ------------------------------------------------------------------------------------------------
+// Destructor, private as well
+ColladaLoader::~ColladaLoader()
+{
+}
+
+// ------------------------------------------------------------------------------------------------
+// Returns whether the class can handle the format of the given file.
+bool ColladaLoader::CanRead( const std::string& pFile, IOSystem* pIOHandler) const
+{
+ // check file extension
+ std::string::size_type pos = pFile.find_last_of('.');
+ // no file extension - can't read
+ if( pos == std::string::npos)
+ return false;
+ std::string extension = pFile.substr( pos);
+ for( std::string::iterator it = extension.begin(); it != extension.end(); ++it)
+ *it = tolower( *it);
+
+ if( extension == ".dae")
+ return true;
+
+ return false;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Imports the given file into the given scene structure.
+void ColladaLoader::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
+{
+ mFileName = pFile;
+
+ // parse the input file
+ ColladaParser parser( pFile);
+
+ // build the node hierarchy from it
+ pScene->mRootNode = BuildHierarchy( parser, parser.mRootNode);
+
+ pScene->mFlags = AI_SCENE_FLAGS_INCOMPLETE;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Recursively constructs a scene node for the given parser node and returns it.
+aiNode* ColladaLoader::BuildHierarchy( const ColladaParser& pParser, const ColladaParser::Node* pNode)
+{
+ // create a node for it
+ aiNode* node = new aiNode( pNode->mName);
+
+ // calculate the transformation matrix for it
+ node->mTransformation = pParser.CalculateResultTransform( pNode->mTransforms);
+
+ // add children
+ node->mNumChildren = pNode->mChildren.size();
+ node->mChildren = new aiNode*[node->mNumChildren];
+ for( unsigned int a = 0; a < pNode->mChildren.size(); a++)
+ {
+ node->mChildren[a] = BuildHierarchy( pParser, pNode->mChildren[a]);
+ node->mChildren[a]->mParent = node;
+ }
+
+ return node;
+}
diff --git a/code/ColladaLoader.h b/code/ColladaLoader.h
new file mode 100644
index 000000000..7ccbb0df6
--- /dev/null
+++ b/code/ColladaLoader.h
@@ -0,0 +1,95 @@
+/** Defines the collada loader class */
+
+/*
+Open Asset Import Library (ASSIMP)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development Team
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the ASSIMP team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the ASSIMP Development Team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+#ifndef AI_COLLADALOADER_H_INC
+#define AI_COLLADALOADER_H_INC
+
+#include "BaseImporter.h"
+#include "ColladaParser.h"
+
+namespace Assimp
+{
+
+/** Loader class to read Collada scenes. Collada is over-engineered to death, with every new iteration bringing
+ * more useless stuff, so I limited the data to what I think is useful for games.
+*/
+class ColladaLoader : public BaseImporter
+{
+ friend class Importer;
+
+protected:
+ /** Constructor to be privately used by Importer */
+ ColladaLoader();
+
+ /** Destructor, private as well */
+ ~ColladaLoader();
+
+public:
+ /** Returns whether the class can handle the format of the given file.
+ * See BaseImporter::CanRead() for details. */
+ bool CanRead( const std::string& pFile, IOSystem* pIOHandler) const;
+
+protected:
+ /** Called by Importer::GetExtensionList() for each loaded importer.
+ * See BaseImporter::GetExtensionList() for details
+ */
+ void GetExtensionList( std::string& append)
+ {
+ append.append("*.dae");
+ }
+
+ /** Imports the given file into the given scene structure.
+ * See BaseImporter::InternReadFile() for details
+ */
+ void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
+
+ /** Recursively constructs a scene node for the given parser node and returns it. */
+ aiNode* BuildHierarchy( const ColladaParser& pParser, const ColladaParser::Node* pNode);
+
+protected:
+ /** Filename, for a verbose error message */
+ std::string mFileName;
+};
+
+} // end of namespace Assimp
+
+#endif // AI_COLLADALOADER_H_INC
diff --git a/code/ColladaParser.cpp b/code/ColladaParser.cpp
new file mode 100644
index 000000000..02beb3d16
--- /dev/null
+++ b/code/ColladaParser.cpp
@@ -0,0 +1,484 @@
+/** Implementation of the Collada parser helper*/
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development Team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the ASSIMP team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the ASSIMP Development Team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+#include "AssimpPCH.h"
+#include "ColladaParser.h"
+#include "fast_atof.h"
+#include "ParsingUtils.h"
+
+using namespace Assimp;
+
+// ------------------------------------------------------------------------------------------------
+// Constructor to be privately used by Importer
+ColladaParser::ColladaParser( const std::string& pFile)
+ : mFileName( pFile)
+{
+ mRootNode = NULL;
+ mUnitSize = 1.0f;
+ mUpDirection = UP_Z;
+
+ // generate a XML reader for it
+ mReader = irr::io::createIrrXMLReader( pFile.c_str());
+ if( !mReader)
+ ThrowException( "Unable to open file.");
+
+ // start reading
+ ReadContents();
+}
+
+// ------------------------------------------------------------------------------------------------
+// Destructor, private as well
+ColladaParser::~ColladaParser()
+{
+ delete mReader;
+ for( NodeLibrary::iterator it = mNodeLibrary.begin(); it != mNodeLibrary.end(); ++it)
+ delete it->second;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Reads the contents of the file
+void ColladaParser::ReadContents()
+{
+ while( mReader->read())
+ {
+ // handle the root element "COLLADA"
+ if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
+ {
+ if( IsElement( "COLLADA"))
+ {
+ ReadStructure();
+ } else
+ {
+ DefaultLogger::get()->debug( boost::str( boost::format( "Ignoring global element \"%s\".") % mReader->getNodeName()));
+ SkipElement();
+ }
+ } else
+ {
+ // skip everything else silently
+ }
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Reads the structure of the file
+void ColladaParser::ReadStructure()
+{
+ while( mReader->read())
+ {
+ // beginning of elements
+ if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
+ {
+ if( IsElement( "asset"))
+ ReadAssetInfo();
+ else if( IsElement( "library_geometries"))
+ ReadGeometryLibrary();
+ else if( IsElement( "library_visual_scenes"))
+ ReadSceneLibrary();
+ else if( IsElement( "scene"))
+ ReadScene();
+ else
+ SkipElement();
+ }
+ else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
+ {
+ break;
+ }
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Reads asset informations such as coordinate system informations and legal blah
+void ColladaParser::ReadAssetInfo()
+{
+ while( mReader->read())
+ {
+ if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
+ {
+ if( IsElement( "unit"))
+ {
+ // read unit data from the element's attributes
+ int attrIndex = GetAttribute( "meter");
+ mUnitSize = mReader->getAttributeValueAsFloat( attrIndex);
+
+ // consume the trailing stuff
+ if( !mReader->isEmptyElement())
+ SkipElement();
+ }
+ else if( IsElement( "up_axis"))
+ {
+ // read content, strip whitespace, compare
+ const char* content = GetTextContent();
+ if( strncmp( content, "X_UP", 4) == 0)
+ mUpDirection = UP_X;
+ else if( strncmp( content, "Y_UP", 4) == 0)
+ mUpDirection = UP_Y;
+ else
+ mUpDirection = UP_Z;
+
+ // check element end
+ TestClosing( "up_axis");
+ } else
+ {
+ SkipElement();
+ }
+ }
+ else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
+ {
+ break;
+ }
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Reads the geometry library contents
+void ColladaParser::ReadGeometryLibrary()
+{
+ SkipElement();
+}
+
+// ------------------------------------------------------------------------------------------------
+// Reads the library of node hierarchies and scene parts
+void ColladaParser::ReadSceneLibrary()
+{
+ while( mReader->read())
+ {
+ if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
+ {
+ // a visual scene - generate root node under its ID and let ReadNode() do the recursive work
+ if( IsElement( "visual_scene"))
+ {
+ // read ID. Is optional according to the spec, but how on earth should a scene_instance refer to it then?
+ int indexID = GetAttribute( "id");
+ const char* attrID = mReader->getAttributeValue( indexID);
+
+ // read name if given.
+ int indexName = TestAttribute( "name");
+ const char* attrName = "unnamed";
+ if( indexName > -1)
+ attrName = mReader->getAttributeValue( indexName);
+
+ // TODO: (thom) support SIDs
+ assert( TestAttribute( "sid") == -1);
+
+ // create a node and store it in the library under its ID
+ Node* node = new Node;
+ node->mID = attrID;
+ node->mName = attrName;
+ mNodeLibrary[node->mID] = node;
+
+ ReadSceneNode( node);
+ } else
+ {
+ // ignore the rest
+ SkipElement();
+ }
+ }
+ else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
+ {
+ break;
+ }
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Reads a scene node's contents including children and stores it in the given node
+void ColladaParser::ReadSceneNode( Node* pNode)
+{
+ // quit immediately on elements
+ if( mReader->isEmptyElement())
+ return;
+
+ while( mReader->read())
+ {
+ if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
+ {
+ if( IsElement( "lookat"))
+ ReadNodeTransformation( pNode, TF_LOOKAT);
+ else if( IsElement( "matrix"))
+ ReadNodeTransformation( pNode, TF_MATRIX);
+ else if( IsElement( "rotate"))
+ ReadNodeTransformation( pNode, TF_ROTATE);
+ else if( IsElement( "scale"))
+ ReadNodeTransformation( pNode, TF_SCALE);
+ else if( IsElement( "skew"))
+ ReadNodeTransformation( pNode, TF_SKEW);
+ else if( IsElement( "translate"))
+ ReadNodeTransformation( pNode, TF_TRANSLATE);
+ else if( IsElement( "node"))
+ {
+ Node* child = new Node;
+ int attrID = TestAttribute( "id");
+ if( attrID > -1)
+ child->mID = mReader->getAttributeValue( attrID);
+
+ int attrName = TestAttribute( "name");
+ if( attrName > -1)
+ child->mName = mReader->getAttributeValue( attrName);
+
+ // TODO: (thom) support SIDs
+ assert( TestAttribute( "sid") == -1);
+
+ pNode->mChildren.push_back( child);
+ child->mParent = pNode;
+
+ // read on recursively from there
+ ReadSceneNode( child);
+ } else if( IsElement( "instance_node"))
+ {
+ // test for it, in case we need to implement it
+ assert( false);
+ SkipElement();
+ } else
+ {
+ // skip everything else for the moment
+ SkipElement();
+ }
+ }
+ else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
+ {
+ break;
+ }
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Reads a node transformation entry of the given type and adds it to the given node's transformation list.
+void ColladaParser::ReadNodeTransformation( Node* pNode, TransformType pType)
+{
+ std::string tagName = mReader->getNodeName();
+
+ // how many parameters to read per transformation type
+ static const unsigned int sNumParameters[] = { 9, 4, 3, 3, 7, 16 };
+ const char* content = GetTextContent();
+
+ // read as many parameters and store in the transformation
+ Transform tf;
+ tf.mType = pType;
+ for( unsigned int a = 0; a < sNumParameters[pType]; a++)
+ {
+ // read a number
+ content = fast_atof_move( content, tf.f[a]);
+ // skip whitespace after it
+ SkipSpacesAndLineEnd( &content);
+ }
+
+ // place the transformation at the queue of the node
+ pNode->mTransforms.push_back( tf);
+
+ // and consum the closing tag
+ TestClosing( tagName.c_str());
+}
+
+// ------------------------------------------------------------------------------------------------
+// Reads the collada scene
+void ColladaParser::ReadScene()
+{
+ while( mReader->read())
+ {
+ if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
+ {
+ if( IsElement( "instance_visual_scene"))
+ {
+ // should be the first and only occurence
+ if( mRootNode)
+ ThrowException( "Invalid scene containing multiple root nodes");
+
+ // read the url of the scene to instance. Should be of format "#some_name"
+ int urlIndex = GetAttribute( "url");
+ const char* url = mReader->getAttributeValue( urlIndex);
+ if( url[0] != '#')
+ ThrowException( "Unknown reference format");
+
+ // find the referred scene, skip the leading #
+ NodeLibrary::const_iterator sit = mNodeLibrary.find( url+1);
+ if( sit == mNodeLibrary.end())
+ ThrowException( boost::str( boost::format( "Unable to resolve visual_scene reference \"%s\".") % url));
+ mRootNode = sit->second;
+ } else
+ {
+ SkipElement();
+ }
+ }
+ else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
+ {
+ break;
+ }
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Aborts the file reading with an exception
+void ColladaParser::ThrowException( const std::string& pError) const
+{
+ throw new ImportErrorException( boost::str( boost::format( "%s - %s") % mFileName % pError));
+}
+
+// ------------------------------------------------------------------------------------------------
+// Skips all data until the end node of the current element
+void ColladaParser::SkipElement()
+{
+ // nothing to skip if it's an
+ if( mReader->isEmptyElement())
+ return;
+
+ // copy the current node's name because it'a pointer to the reader's internal buffer,
+ // which is going to change with the upcoming parsing
+ std::string element = mReader->getNodeName();
+ while( mReader->read())
+ {
+ if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
+ if( mReader->getNodeName() == element)
+ break;
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Tests for the closing tag of the given element, throws an exception if not found
+void ColladaParser::TestClosing( const char* pName)
+{
+ // read closing tag
+ if( !mReader->read())
+ ThrowException( boost::str( boost::format( "Unexpected end of file while reading end of \"%s\" element.") % pName));
+ if( mReader->getNodeType() != irr::io::EXN_ELEMENT_END || strcmp( mReader->getNodeName(), pName) != 0)
+ ThrowException( boost::str( boost::format( "Expected end of \"%s\" element.") % pName));
+}
+
+// ------------------------------------------------------------------------------------------------
+// Returns the index of the named attribute or -1 if not found. Does not throw, therefore useful for optional attributes
+int ColladaParser::GetAttribute( const char* pAttr) const
+{
+ int index = TestAttribute( pAttr);
+ if( index != -1)
+ return index;
+
+ // attribute not found -> throw an exception
+ ThrowException( boost::str( boost::format( "Expected attribute \"%s\" at element \"%s\".") % pAttr % mReader->getNodeName()));
+ return -1;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Tests the present element for the presence of one attribute, returns its index or throws an exception if not found
+int ColladaParser::TestAttribute( const char* pAttr) const
+{
+ for( int a = 0; a < mReader->getAttributeCount(); a++)
+ if( strcmp( mReader->getAttributeName( a), pAttr) == 0)
+ return a;
+
+ return -1;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Reads the text contents of an element, throws an exception if not given. Skips leading whitespace.
+const char* ColladaParser::GetTextContent()
+{
+ // present node should be the beginning of an element
+ if( mReader->getNodeType() != irr::io::EXN_ELEMENT || mReader->isEmptyElement())
+ ThrowException( "Expected opening element");
+
+ // read contents of the element
+ if( !mReader->read())
+ ThrowException( "Unexpected end of file while reading asset up_axis element.");
+ if( mReader->getNodeType() != irr::io::EXN_TEXT)
+ ThrowException( "Invalid contents in element \"up_axis\".");
+
+ // skip leading whitespace
+ const char* text = mReader->getNodeData();
+ SkipSpacesAndLineEnd( &text);
+
+ return text;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Calculates the resulting transformation fromm all the given transform steps
+aiMatrix4x4 ColladaParser::CalculateResultTransform( const std::vector& pTransforms) const
+{
+ aiMatrix4x4 res;
+
+ for( std::vector::const_iterator it = pTransforms.begin(); it != pTransforms.end(); ++it)
+ {
+ const Transform& tf = *it;
+ switch( tf.mType)
+ {
+ case TF_LOOKAT:
+ // TODO: (thom)
+ assert( false);
+ break;
+ case TF_ROTATE:
+ {
+ aiMatrix4x4 rot;
+ aiMatrix4x4::Rotation( tf.f[3], aiVector3D( tf.f[0], tf.f[1], tf.f[2]), rot);
+ res *= rot;
+ break;
+ }
+ case TF_TRANSLATE:
+ {
+ aiMatrix4x4 trans;
+ aiMatrix4x4::Translation( aiVector3D( tf.f[0], tf.f[1], tf.f[2]), trans);
+ res *= trans;
+ break;
+ }
+ case TF_SCALE:
+ {
+ aiMatrix4x4 scale( tf.f[0], 0.0f, 0.0f, 0.0f, 0.0f, tf.f[1], 0.0f, 0.0f, 0.0f, 0.0f, tf.f[2], 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f);
+ res *= scale;
+ break;
+ }
+ case TF_SKEW:
+ // TODO: (thom)
+ assert( false);
+ break;
+ case TF_MATRIX:
+ {
+ aiMatrix4x4 mat( tf.f[0], tf.f[1], tf.f[2], tf.f[3], tf.f[4], tf.f[5], tf.f[6], tf.f[7],
+ tf.f[8], tf.f[9], tf.f[10], tf.f[11], tf.f[12], tf.f[13], tf.f[14], tf.f[15]);
+ res *= mat;
+ break;
+ }
+ default:
+ assert( false);
+ break;
+ }
+ }
+
+ return res;
+}
diff --git a/code/ColladaParser.h b/code/ColladaParser.h
new file mode 100644
index 000000000..177e2580f
--- /dev/null
+++ b/code/ColladaParser.h
@@ -0,0 +1,194 @@
+/** Defines the parser helper class for the collada loader */
+
+/*
+Open Asset Import Library (ASSIMP)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development Team
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the ASSIMP team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the ASSIMP Development Team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+#ifndef AI_COLLADAPARSER_H_INC
+#define AI_COLLADAPARSER_H_INC
+
+#include "./irrXML/irrXMLWrapper.h"
+
+namespace Assimp
+{
+
+/** Parser helper class for the Collada loader. Does all the XML reading and builds internal data structures from it,
+ * but leaves the resolving of all the references to the loader.
+*/
+class ColladaParser
+{
+ friend class ColladaLoader;
+public:
+ /** Transformation types that can be applied to a node */
+ enum TransformType
+ {
+ TF_LOOKAT,
+ TF_ROTATE,
+ TF_TRANSLATE,
+ TF_SCALE,
+ TF_SKEW,
+ TF_MATRIX
+ };
+
+ /** Contains all data for one of the different transformation types */
+ struct Transform
+ {
+ TransformType mType;
+ float f[16]; ///< Interpretation of data depends on the type of the transformation
+ };
+
+ /** A node in a scene hierarchy */
+ struct Node
+ {
+ std::string mName;
+ std::string mID;
+ Node* mParent;
+ std::vector mChildren;
+
+ /** Operations in order to calculate the resulting transformation to parent. */
+ std::vector mTransforms;
+
+ Node() { mParent = NULL; }
+ ~Node() { for( std::vector::iterator it = mChildren.begin(); it != mChildren.end(); ++it) delete *it; }
+ };
+
+ /** Data source array */
+ struct Data
+ {
+ std::vector mValues;
+ };
+
+ /** Accessor to a data array */
+ struct Accessor
+ {
+ unsigned int mCount; // in number of objects
+ unsigned int mOffset; // in number of values
+ unsigned int mStride; // Stride in number of values
+ std::string mSource; // URL of the source array
+ };
+
+ /** Contains data for a single mesh */
+ struct Mesh
+ {
+
+ };
+
+protected:
+ /** Constructor from XML file */
+ ColladaParser( const std::string& pFile);
+
+ /** Destructor */
+ ~ColladaParser();
+
+ /** Reads the contents of the file */
+ void ReadContents();
+
+ /** Reads the structure of the file */
+ void ReadStructure();
+
+ /** Reads asset informations such as coordinate system informations and legal blah */
+ void ReadAssetInfo();
+
+ /** Reads the geometry library contents */
+ void ReadGeometryLibrary();
+
+ /** Reads a mesh from the geometry library */
+ void ReadGeometry();
+
+ /** Reads the library of node hierarchies and scene parts */
+ void ReadSceneLibrary();
+
+ /** Reads a scene node's contents including children and stores it in the given node */
+ void ReadSceneNode( Node* pNode);
+
+ /** Reads a node transformation entry of the given type and adds it to the given node's transformation list. */
+ void ReadNodeTransformation( Node* pNode, TransformType pType);
+
+ /** Reads the collada scene */
+ void ReadScene();
+
+protected:
+ /** Aborts the file reading with an exception */
+ void ThrowException( const std::string& pError) const;
+
+ /** Skips all data until the end node of the current element */
+ void SkipElement();
+
+ /** Compares the current xml element name to the given string and returns true if equal */
+ bool IsElement( const char* pName) const { assert( mReader->getNodeType() == irr::io::EXN_ELEMENT); return strcmp( mReader->getNodeName(), pName) == 0; }
+
+ /** Tests for the closing tag of the given element, throws an exception if not found */
+ void TestClosing( const char* pName);
+
+ /** Checks the present element for the presence of the attribute, returns its index or throws an exception if not found */
+ int GetAttribute( const char* pAttr) const;
+
+ /** Returns the index of the named attribute or -1 if not found. Does not throw, therefore useful for optional attributes */
+ int TestAttribute( const char* pAttr) const;
+
+ /** Reads the text contents of an element, throws an exception if not given. Skips leading whitespace. */
+ const char* GetTextContent();
+
+ /** Calculates the resulting transformation fromm all the given transform steps */
+ aiMatrix4x4 CalculateResultTransform( const std::vector& pTransforms) const;
+
+protected:
+ /** Filename, for a verbose error message */
+ std::string mFileName;
+
+ /** XML reader */
+ irr::io::IrrXMLReader* mReader;
+
+ /** node library: root node of the hierarchy part by ID */
+ typedef std::map NodeLibrary;
+ NodeLibrary mNodeLibrary;
+
+ /** Pointer to the root node. Don't delete, it just points to one of the nodes in the node library. */
+ Node* mRootNode;
+
+ /** Size unit: how large compared to a meter */
+ float mUnitSize;
+
+ /** Which is the up vector */
+ enum { UP_X, UP_Y, UP_Z } mUpDirection;
+};
+
+} // end of namespace Assimp
+
+#endif // AI_COLLADAPARSER_H_INC
diff --git a/code/Importer.cpp b/code/Importer.cpp
index 513795095..cdfe25d6c 100644
--- a/code/Importer.cpp
+++ b/code/Importer.cpp
@@ -129,6 +129,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_BUILD_NO_B3D_IMPORTER
# include "B3DImporter.h"
#endif
+#ifndef AI_BUILD_NO_COLLADA_IMPORTER
+# include "ColladaLoader.h"
+#endif
// PostProcess-Steps
@@ -283,6 +286,9 @@ Importer::Importer() :
#if (!defined AI_BUILD_NO_B3D_IMPORTER)
mImporter.push_back( new B3DImporter());
#endif
+#if (!defined AI_BUILD_NO_COLLADA_IMPORTER)
+ mImporter.push_back( new ColladaLoader());
+#endif
// add an instance of each post processing step here in the order
// of sequence it is executed. steps that are added here are not validated -
diff --git a/include/aiMatrix4x4.h b/include/aiMatrix4x4.h
index aef13d77a..5ba02468d 100644
--- a/include/aiMatrix4x4.h
+++ b/include/aiMatrix4x4.h
@@ -142,6 +142,14 @@ struct aiMatrix4x4
*/
static aiMatrix4x4& RotationZ(float a, aiMatrix4x4& out);
+ /** Returns a rotation matrix for a rotation around an arbitrary axis.
+ * @param a Rotation angle, in radians
+ * @param axis Rotation axis, should be a normalized vector.
+ * @param out Receives the output matrix
+ * \return Reference to the output matrix
+ */
+ static aiMatrix4x4& Rotation(float a, const aiVector3D& axis, aiMatrix4x4& out);
+
/** \brief Returns a translation matrix
* \param v Translation vector
* \param out Receives the output matrix
diff --git a/include/aiMatrix4x4.inl b/include/aiMatrix4x4.inl
index 04294a667..6fcd0dce0 100644
--- a/include/aiMatrix4x4.inl
+++ b/include/aiMatrix4x4.inl
@@ -282,6 +282,25 @@ inline aiMatrix4x4& aiMatrix4x4::RotationZ(float a, aiMatrix4x4& out)
out.a2 = -(out.b1 = sin(a));
return out;
}
+
+// ---------------------------------------------------------------------------
+// Returns a rotation matrix for a rotation around an arbitrary axis.
+inline aiMatrix4x4& aiMatrix4x4::Rotation( float a, const aiVector3D& axis, aiMatrix4x4& out)
+{
+ float c = cos( a), s = sin( a), t = 1 - c;
+ float x = axis.x, y = axis.y, z = axis.z;
+
+ // Many thanks to MathWorld and Wikipedia
+ out.a1 = t*x*x + c; out.a2 = t*x*y - s*z; out.a3 = t*x*z + s*y;
+ out.b1 = t*x*y + s*z; out.b2 = t*y*y + c; out.b3 = t*y*z - s*x;
+ out.c1 = t*x*z - s*y; out.c2 = t*y*z + s*x; out.c3 = t*z*z + c;
+ out.a4 = out.b4 = out.c4 = 0.0f;
+ out.d1 = out.d2 = out.d3 = 0.0f;
+ out.d4 = 1.0f;
+
+ return out;
+}
+
// ---------------------------------------------------------------------------
inline aiMatrix4x4& aiMatrix4x4::Translation( const aiVector3D& v, aiMatrix4x4& out)
{
diff --git a/workspaces/vc8/assimp.sln b/workspaces/vc8/assimp.sln
index 948c9fc3e..633a238c9 100644
--- a/workspaces/vc8/assimp.sln
+++ b/workspaces/vc8/assimp.sln
@@ -76,30 +76,21 @@ Global
{5691E159-2D9B-407F-971F-EA5C592DC524}.Release|x64.ActiveCfg = Release|x64
{5691E159-2D9B-407F-971F-EA5C592DC524}.Release|x64.Build.0 = Release|x64
{9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Debug_DLL|Win32.ActiveCfg = Debug_DLL|Win32
- {9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Debug_DLL|Win32.Build.0 = Debug_DLL|Win32
{9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Debug_DLL|x64.ActiveCfg = Debug_DLL|x64
- {9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Debug_DLL|x64.Build.0 = Debug_DLL|x64
{9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Debug|Win32.ActiveCfg = Debug|Win32
{9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Debug|x64.ActiveCfg = Debug|x64
- {9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Debug|x64.Build.0 = Debug|x64
{9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Release_DLL|Win32.ActiveCfg = Release_DLL|Win32
- {9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Release_DLL|Win32.Build.0 = Release_DLL|Win32
{9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Release_DLL|x64.ActiveCfg = Release_DLL|x64
- {9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Release_DLL|x64.Build.0 = Release_DLL|x64
{9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Release|Win32.ActiveCfg = Release|Win32
- {9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Release|Win32.Build.0 = Release|Win32
{9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Release|x64.ActiveCfg = Release|x64
- {9B9D1C90-8A03-409A-B547-AE7B48B90F1A}.Release|x64.Build.0 = Release|x64
{FE78BFBA-4BA5-457D-8602-B800D498102D}.Debug_DLL|Win32.ActiveCfg = Debug|Win32
{FE78BFBA-4BA5-457D-8602-B800D498102D}.Debug_DLL|x64.ActiveCfg = Debug|x64
{FE78BFBA-4BA5-457D-8602-B800D498102D}.Debug|Win32.ActiveCfg = Debug|Win32
{FE78BFBA-4BA5-457D-8602-B800D498102D}.Debug|x64.ActiveCfg = Debug|x64
- {FE78BFBA-4BA5-457D-8602-B800D498102D}.Debug|x64.Build.0 = Debug|x64
{FE78BFBA-4BA5-457D-8602-B800D498102D}.Release_DLL|Win32.ActiveCfg = Release|Win32
{FE78BFBA-4BA5-457D-8602-B800D498102D}.Release_DLL|x64.ActiveCfg = Release|x64
{FE78BFBA-4BA5-457D-8602-B800D498102D}.Release|Win32.ActiveCfg = Release|Win32
{FE78BFBA-4BA5-457D-8602-B800D498102D}.Release|x64.ActiveCfg = Release|x64
- {FE78BFBA-4BA5-457D-8602-B800D498102D}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/workspaces/vc8/assimp.vcproj b/workspaces/vc8/assimp.vcproj
index 5d1a25735..845a98353 100644
--- a/workspaces/vc8/assimp.vcproj
+++ b/workspaces/vc8/assimp.vcproj
@@ -1422,6 +1422,26 @@
>
+
+
+
+
+
+
+
+
+
+