Selaa lähdekoodia

- Bugfix: ColladaLoader node rotation was miscalculated
- ColladaLoader now supports more primitive types
- ColladaLoader now honours the up-vector specification
- moved Collada temporary structures to separate Helper header
- fast_atof_move() now also eats localized numbers with comma separator (e.g. 0,3210) correctly

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@251 67173fc5-114c-0410-ac8e-9d2fd5bffc1f

ulfjorensen 17 vuotta sitten
vanhempi
commit
85a487f6b8
7 muutettua tiedostoa jossa 298 lisäystä ja 152 poistoa
  1. 172 0
      code/ColladaHelper.h
  2. 18 3
      code/ColladaLoader.cpp
  3. 2 2
      code/ColladaLoader.h
  4. 83 24
      code/ColladaParser.cpp
  5. 18 122
      code/ColladaParser.h
  6. 1 1
      code/fast_atof.h
  7. 4 0
      workspaces/vc8/assimp.vcproj

+ 172 - 0
code/ColladaHelper.h

@@ -0,0 +1,172 @@
+/** Helper structures 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_COLLADAHELPER_H_INC
+#define AI_COLLADAHELPER_H_INC
+
+namespace Assimp
+{
+namespace Collada
+{
+
+/** 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<Node*> mChildren;
+
+	/** Operations in order to calculate the resulting transformation to parent. */
+	std::vector<Transform> mTransforms;
+
+	std::vector<std::string> mMeshes; ///< Meshes at this node
+
+	Node() { mParent = NULL; }
+	~Node() { for( std::vector<Node*>::iterator it = mChildren.begin(); it != mChildren.end(); ++it) delete *it; }
+};
+
+/** Data source array */
+struct Data
+{
+	std::vector<float> mValues;
+};
+
+/** Accessor to a data array */
+struct Accessor
+{
+	size_t mCount;   // in number of objects
+	size_t mOffset;  // in number of values
+	size_t mStride;  // Stride in number of values
+	std::vector<std::string> mParams; // names of the data streams in the accessors. Empty string tells to ignore. 
+	size_t mSubOffset[4]; // Suboffset inside the object for the common 4 elements. For a vector, thats XYZ, for a color RGBA and so on.
+						  // For example, SubOffset[0] denotes which of the values inside the object is the vector X component.
+	std::string mSource;   // URL of the source array
+	mutable const Data* mData; // Pointer to the source array, if resolved. NULL else
+
+	Accessor() 
+	{ 
+		mCount = 0; mOffset = 0; mStride = 0; mData = NULL; 
+		mSubOffset[0] = mSubOffset[1] = mSubOffset[2] = mSubOffset[3] = 0;
+	}
+};
+
+/** A single face in a mesh */
+struct Face
+{
+	std::vector<size_t> mIndices;
+};
+
+/** Different types of input data to a vertex or face */
+enum InputType
+{
+	IT_Invalid,
+	IT_Vertex,  // special type for per-index data referring to the <vertices> element carrying the per-vertex data.
+	IT_Position,
+	IT_Normal,
+	IT_Texcoord,
+	IT_Color
+};
+
+/** An input channel for mesh data, referring to a single accessor */
+struct InputChannel
+{
+	InputType mType;      // Type of the data
+	size_t mIndex;		  // Optional index, if multiple sets of the same data type are given
+	size_t mOffset;       // Index offset in the indices array of per-face indices. Don't ask, can't explain that any better.
+	std::string mAccessor; // ID of the accessor where to read the actual values from.
+	mutable const Accessor* mResolved; // Pointer to the accessor, if resolved. NULL else
+
+	InputChannel() { mType = IT_Invalid; mIndex = 0; mOffset = 0; mResolved = NULL; }
+};
+
+/** Contains data for a single mesh */
+struct Mesh
+{
+	std::string mVertexID; // just to check if there's some sophisticated addressing involved... which we don't support, and therefore should warn about.
+	std::vector<InputChannel> mPerVertexData; // Vertex data addressed by vertex indices
+
+	// actual mesh data, assembled on encounter of a <p> element. Verbose format, not indexed
+	std::vector<aiVector3D> mPositions;
+	std::vector<aiVector3D> mNormals;
+	std::vector<aiVector2D> mTexCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
+	std::vector<aiColor4D> mColors[AI_MAX_NUMBER_OF_COLOR_SETS];
+
+	// Faces. Stored are only the number of vertices for each face. 1 == point, 2 == line, 3 == triangle, 4+ == poly
+	std::vector<size_t> mFaceSize;
+};
+
+/** Which type of primitives the ReadPrimitives() function is going to read */
+enum PrimitiveType
+{
+	Prim_Invalid,
+	Prim_Lines,
+	Prim_LineStrip,
+	Prim_Triangles,
+	Prim_TriStrips,
+	Prim_TriFans,
+	Prim_Polylist,
+	Prim_Polygon
+};
+
+} // end of namespace Collada
+} // end of namespace Assimp
+
+#endif // AI_COLLADAHELPER_H_INC

+ 18 - 3
code/ColladaLoader.cpp

@@ -90,6 +90,21 @@ void ColladaLoader::InternReadFile( const std::string& pFile, aiScene* pScene, I
 	// build the node hierarchy from it
 	pScene->mRootNode = BuildHierarchy( parser, parser.mRootNode);
 
+	// Convert to Z_UP, if different orientation
+	if( parser.mUpDirection == ColladaParser::UP_X)
+		pScene->mRootNode->mTransformation *= aiMatrix4x4( 
+			 0, -1,  0,  0, 
+			 0,  0, -1,  0,
+			 1,  0,  0,  0,
+			 0,  0,  0,  1);
+	else if( parser.mUpDirection == ColladaParser::UP_Y)
+		pScene->mRootNode->mTransformation *= aiMatrix4x4( 
+			 1,  0,  0,  0, 
+			 0,  0, -1,  0,
+			 0,  1,  0,  0,
+			 0,  0,  0,  1);
+
+
 	// store all meshes
 	StoreSceneMeshes( pScene);
 
@@ -113,7 +128,7 @@ void ColladaLoader::InternReadFile( const std::string& pFile, aiScene* pScene, I
 
 // ------------------------------------------------------------------------------------------------
 // Recursively constructs a scene node for the given parser node and returns it.
-aiNode* ColladaLoader::BuildHierarchy( const ColladaParser& pParser, const ColladaParser::Node* pNode)
+aiNode* ColladaLoader::BuildHierarchy( const ColladaParser& pParser, const Collada::Node* pNode)
 {
 	// create a node for it
 	aiNode* node = new aiNode( pNode->mName);
@@ -138,7 +153,7 @@ aiNode* ColladaLoader::BuildHierarchy( const ColladaParser& pParser, const Colla
 
 // ------------------------------------------------------------------------------------------------
 // Builds meshes for the given node and references them
-void ColladaLoader::BuildMeshesForNode( const ColladaParser& pParser, const ColladaParser::Node* pNode, aiNode* pTarget)
+void ColladaLoader::BuildMeshesForNode( const ColladaParser& pParser, const Collada::Node* pNode, aiNode* pTarget)
 {
 	// accumulated mesh references by this node
 	std::vector<size_t> newMeshRefs;
@@ -163,7 +178,7 @@ void ColladaLoader::BuildMeshesForNode( const ColladaParser& pParser, const Coll
 		{
 			// else we have to add the mesh to the collection and store its newly assigned index at the node
 			aiMesh* dstMesh = new aiMesh;
-			const ColladaParser::Mesh* srcMesh = srcMeshIt->second;
+			const Collada::Mesh* srcMesh = srcMeshIt->second;
 
 			// copy positions
 			dstMesh->mNumVertices = srcMesh->mPositions.size();

+ 2 - 2
code/ColladaLoader.h

@@ -83,10 +83,10 @@ protected:
 	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);
+	aiNode* BuildHierarchy( const ColladaParser& pParser, const Collada::Node* pNode);
 
 	/** Builds meshes for the given node and references them */
-	void BuildMeshesForNode( const ColladaParser& pParser, const ColladaParser::Node* pNode, aiNode* pTarget);
+	void BuildMeshesForNode( const ColladaParser& pParser, const Collada::Node* pNode, aiNode* pTarget);
 
 	/** Stores all meshes in the given scene */
 	void StoreSceneMeshes( aiScene* pScene);

+ 83 - 24
code/ColladaParser.cpp

@@ -46,6 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "ParsingUtils.h"
 
 using namespace Assimp;
+using namespace Assimp::Collada;
 
 // ------------------------------------------------------------------------------------------------
 // Constructor to be privately used by Importer
@@ -253,7 +254,8 @@ void ColladaParser::ReadMesh( Mesh* pMesh)
 				// read per-vertex mesh data
 				ReadVertexData( pMesh);
 			}
-			else if( IsElement( "polylist") || IsElement( "triangles"))
+			else if( IsElement( "triangles") || IsElement( "lines") || IsElement( "linestrips")
+				|| IsElement( "polygons") || IsElement( "polylist") || IsElement( "trifans") || IsElement( "tristrips")) 
 			{
 				// read per-index mesh data and faces setup
 				ReadIndexData( pMesh);
@@ -438,7 +440,23 @@ void ColladaParser::ReadIndexData( Mesh* pMesh)
 
 	// distinguish between polys and triangles
 	std::string elementName = mReader->getNodeName();
-	bool isPolylist = IsElement( "polylist");
+	PrimitiveType primType = Prim_Invalid;
+	if( IsElement( "lines"))
+		primType = Prim_Lines;
+	else if( IsElement( "linestrips"))
+		primType = Prim_LineStrip;
+	else if( IsElement( "polygons"))
+		primType = Prim_Polygon;
+	else if( IsElement( "polylist"))
+		primType = Prim_Polylist;
+	else if( IsElement( "triangles"))
+		primType = Prim_Triangles;
+	else if( IsElement( "trifans"))
+		primType = Prim_TriFans;
+	else if( IsElement( "tristrips"))
+		primType = Prim_TriStrips;
+
+	assert( primType != Prim_Invalid);
 
 	// also a number of <input> elements, but in addition a <p> primitive collection and propably index counts for all primitives
 	while( mReader->read())
@@ -469,7 +487,7 @@ void ColladaParser::ReadIndexData( Mesh* pMesh)
 			else if( IsElement( "p"))
 			{
 				// now here the actual fun starts - these are the indices to construct the mesh data from
-				ReadPrimitives( pMesh, perIndexData, numPrimitives, vcount, isPolylist);
+				ReadPrimitives( pMesh, perIndexData, numPrimitives, vcount, primType);
 			} else
 			{
 				ThrowException( "Unexpected sub element in tag \"vertices\".");
@@ -519,7 +537,7 @@ void ColladaParser::ReadInputChannel( std::vector<InputChannel>& poChannels)
 // ------------------------------------------------------------------------------------------------
 // Reads a <p> primitive index list and assembles the mesh data into the given mesh
 void ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector<InputChannel>& pPerIndexChannels, 
-								   size_t pNumPrimitives, const std::vector<size_t>& pVCount, bool pIsPolylist)
+								   size_t pNumPrimitives, const std::vector<size_t>& pVCount, PrimitiveType pPrimType)
 {
 	// determine number of indices coming per vertex 
 	// find the offset index for all per-vertex channels
@@ -534,32 +552,52 @@ void ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector<InputChannel>& pPer
 
 	// determine the expected number of indices 
 	size_t expectedPointCount = 0;
-	if( pIsPolylist)
+	switch( pPrimType)
 	{
-		BOOST_FOREACH( size_t i, pVCount)
-			expectedPointCount += i;
-	} else
-	{
-		// everything triangles
-		expectedPointCount = 3 * pNumPrimitives;
+		case Prim_Polylist:
+		{
+			BOOST_FOREACH( size_t i, pVCount)
+				expectedPointCount += i;
+			break;
+		}
+		case Prim_Lines:
+			expectedPointCount = 2 * pNumPrimitives;
+			break;
+		case Prim_Triangles:
+			expectedPointCount = 3 * pNumPrimitives;
+			break;
+		default:
+			// other primitive types don't state the index count upfront... we need to guess
+			break;
 	}
 
 	// and read all indices into a temporary array
-	std::vector<size_t> indices( expectedPointCount * numOffsets);
+	std::vector<size_t> indices;
+	if( expectedPointCount > 0)
+		indices.reserve( expectedPointCount * numOffsets);
+
 	const char* content = GetTextContent();
-	BOOST_FOREACH( size_t& value, indices)
+	while( *content != 0)
 	{
-		if( *content == 0)
-			ThrowException( "Expected more values while reading primitive indices.");
-		// read a value in place
-		value = strtol10( content, &content);
+		// read a value 
+		unsigned int value = strtol10( content, &content);
+		indices.push_back( size_t( value));
 		// skip whitespace after it
 		SkipSpacesAndLineEnd( &content);
 	}
 
+	// complain if the index count doesn't fit
+	if( expectedPointCount > 0 && indices.size() != expectedPointCount * numOffsets)
+		ThrowException( "Expected different index count in <p> element.");
+	else if( expectedPointCount == 0 && (indices.size() % numOffsets) != 0)
+		ThrowException( "Expected different index count in <p> element.");
+
 	// find the data for all sources
 	BOOST_FOREACH( InputChannel& input, pMesh->mPerVertexData)
 	{
+		if( input.mResolved)
+			continue;
+
 		// find accessor
 		input.mResolved = &ResolveLibraryReference( mAccessorLibrary, input.mAccessor);
 		// resolve accessor's data pointer as well, if neccessary
@@ -570,6 +608,9 @@ void ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector<InputChannel>& pPer
 	// and the same for the per-index channels
 	BOOST_FOREACH( InputChannel& input, pPerIndexChannels)
 	{
+		if( input.mResolved)
+			continue;
+
 		// ignore vertex pointer, it doesn't refer to an accessor
 		if( input.mType == IT_Vertex)
 		{
@@ -590,12 +631,28 @@ void ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector<InputChannel>& pPer
 
 	// now assemble vertex data according to those indices
 	std::vector<size_t>::const_iterator idx = indices.begin();
-	for( size_t a = 0; a < pNumPrimitives; a++)
+
+	// For continued primitives, the given count does not come all in one <p>, but only one primitive per <p>
+	size_t numPrimitives = pNumPrimitives;
+	if( pPrimType == Prim_TriFans || pPrimType == Prim_Polygon)
+		numPrimitives = 1;
+
+	for( size_t a = 0; a < numPrimitives; a++)
 	{
 		// determine number of points for this primitive
-		size_t numPoints = 3;
-		if( pIsPolylist)
-			numPoints = pVCount[a];
+		size_t numPoints = 0;
+		switch( pPrimType)
+		{
+			case Prim_Lines: numPoints = 2; break;
+			case Prim_Triangles: numPoints = 3; break;
+			case Prim_Polylist: numPoints = pVCount[a]; break;
+			case Prim_TriFans: 
+			case Prim_Polygon: numPoints = indices.size() / numOffsets; break;
+			default:
+				// LineStrip and TriStrip not supported due to expected index unmangling
+				ThrowException( "Unsupported primitive type.");
+				break;
+		}
 
 		// store the face size to later reconstruct the face from
 		pMesh->mFaceSize.push_back( numPoints);
@@ -618,7 +675,7 @@ void ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector<InputChannel>& pPer
 		}
 	}
 
-	// if I ever get my hands on that guy how invented this steaming pile of indirection...
+	// if I ever get my hands on that guy who invented this steaming pile of indirection...
 	TestClosing( "p");
 }
 
@@ -979,7 +1036,9 @@ aiMatrix4x4 ColladaParser::CalculateResultTransform( const std::vector<Transform
 			case TF_ROTATE:
 			{
 				aiMatrix4x4 rot;
-				aiMatrix4x4::Rotation( tf.f[3], aiVector3D( tf.f[0], tf.f[1], tf.f[2]), rot);
+				float angle = tf.f[3] * float( AI_MATH_PI) / 180.0f;
+				aiVector3D axis( tf.f[0], tf.f[1], tf.f[2]);
+				aiMatrix4x4::Rotation( angle, axis, rot);
 				res *= rot;
 				break;
 			}
@@ -1019,7 +1078,7 @@ aiMatrix4x4 ColladaParser::CalculateResultTransform( const std::vector<Transform
 
 // ------------------------------------------------------------------------------------------------
 // Determines the input data type for the given semantic string
-ColladaParser::InputType ColladaParser::GetTypeForSemantic( const std::string& pSemantic)
+Collada::InputType ColladaParser::GetTypeForSemantic( const std::string& pSemantic)
 {
 	if( pSemantic == "POSITION")
 		return IT_Position;

+ 18 - 122
code/ColladaParser.h

@@ -44,6 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #define AI_COLLADAPARSER_H_INC
 
 #include "./irrXML/irrXMLWrapper.h"
+#include "ColladaHelper.h"
 
 namespace Assimp
 {
@@ -54,111 +55,6 @@ namespace Assimp
 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<Node*> mChildren;
-
-		/** Operations in order to calculate the resulting transformation to parent. */
-		std::vector<Transform> mTransforms;
-
-		std::vector<std::string> mMeshes; ///< Meshes at this node
-
-		Node() { mParent = NULL; }
-		~Node() { for( std::vector<Node*>::iterator it = mChildren.begin(); it != mChildren.end(); ++it) delete *it; }
-	};
-
-	/** Data source array */
-	struct Data
-	{
-		std::vector<float> mValues;
-	};
-
-	/** Accessor to a data array */
-	struct Accessor
-	{
-		size_t mCount;   // in number of objects
-		size_t mOffset;  // in number of values
-		size_t mStride;  // Stride in number of values
-		std::vector<std::string> mParams; // names of the data streams in the accessors. Empty string tells to ignore. 
-		size_t mSubOffset[4]; // Suboffset inside the object for the common 4 elements. For a vector, thats XYZ, for a color RGBA and so on.
-							  // For example, SubOffset[0] denotes which of the values inside the object is the vector X component.
-		std::string mSource;   // URL of the source array
-		mutable const Data* mData; // Pointer to the source array, if resolved. NULL else
-
-		Accessor() 
-		{ 
-			mCount = 0; mOffset = 0; mStride = 0; mData = NULL; 
-			mSubOffset[0] = mSubOffset[1] = mSubOffset[2] = mSubOffset[3] = 0;
-		}
-	};
-
-	/** A single face in a mesh */
-	struct Face
-	{
-		std::vector<size_t> mIndices;
-	};
-
-	/** Different types of input data to a vertex or face */
-	enum InputType
-	{
-		IT_Invalid,
-		IT_Vertex,  // special type for per-index data referring to the <vertices> element carrying the per-vertex data.
-		IT_Position,
-		IT_Normal,
-		IT_Texcoord,
-		IT_Color
-	};
-
-	/** An input channel for mesh data, referring to a single accessor */
-	struct InputChannel
-	{
-		InputType mType;      // Type of the data
-		size_t mIndex;		  // Optional index, if multiple sets of the same data type are given
-		size_t mOffset;       // Index offset in the indices array of per-face indices. Don't ask, can't explain that any better.
-		std::string mAccessor; // ID of the accessor where to read the actual values from.
-		mutable const Accessor* mResolved; // Pointer to the accessor, if resolved. NULL else
-
-		InputChannel() { mType = IT_Invalid; mIndex = 0; mOffset = 0; mResolved = NULL; }
-	};
-
-	/** Contains data for a single mesh */
-	struct Mesh
-	{
-		std::string mVertexID; // just to check if there's some sophisticated addressing involved... which we don't support, and therefore should warn about.
-		std::vector<InputChannel> mPerVertexData; // Vertex data addressed by vertex indices
-
-		// actual mesh data, assembled on encounter of a <p> element. Verbose format, not indexed
-		std::vector<aiVector3D> mPositions;
-		std::vector<aiVector3D> mNormals;
-		std::vector<aiVector2D> mTexCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
-		std::vector<aiColor4D> mColors[AI_MAX_NUMBER_OF_COLOR_SETS];
-
-		// Faces. Stored are only the number of vertices for each face. 1 == point, 2 == line, 3 == triangle, 4+ == poly
-		std::vector<size_t> mFaceSize;
-	};
 
 protected:
 	/** Constructor from XML file */
@@ -180,7 +76,7 @@ protected:
 	void ReadGeometryLibrary();
 
 	/** Reads a mesh from the geometry library */
-	void ReadMesh( Mesh* pMesh);
+	void ReadMesh( Collada::Mesh* pMesh);
 
 	/** Reads a data array holding a number of floats, and stores it in the global library */
 	void ReadFloatArray();
@@ -191,32 +87,32 @@ protected:
 	void ReadAccessor( const std::string& pID);
 
 	/** Reads input declarations of per-vertex mesh data into the given mesh */
-	void ReadVertexData( Mesh* pMesh);
+	void ReadVertexData( Collada::Mesh* pMesh);
 
 	/** Reads input declarations of per-index mesh data into the given mesh */
-	void ReadIndexData( Mesh* pMesh);
+	void ReadIndexData( Collada::Mesh* pMesh);
 
 	/** Reads a single input channel element and stores it in the given array, if valid */
-	void ReadInputChannel( std::vector<InputChannel>& poChannels);
+	void ReadInputChannel( std::vector<Collada::InputChannel>& poChannels);
 
 	/** Reads a <p> primitive index list and assembles the mesh data into the given mesh */
-	void ReadPrimitives( Mesh* pMesh, std::vector<InputChannel>& pPerIndexChannels, 
-		size_t pNumPrimitives, const std::vector<size_t>& pVCount, bool pIsPolylist);
+	void ReadPrimitives( Collada::Mesh* pMesh, std::vector<Collada::InputChannel>& pPerIndexChannels, 
+		size_t pNumPrimitives, const std::vector<size_t>& pVCount, Collada::PrimitiveType pPrimType);
 
 	/** Extracts a single object from an input channel and stores it in the appropriate mesh data array */
-	void ExtractDataObjectFromChannel( const InputChannel& pInput, size_t pLocalIndex, Mesh* pMesh);
+	void ExtractDataObjectFromChannel( const Collada::InputChannel& pInput, size_t pLocalIndex, Collada::Mesh* pMesh);
 
 	/** 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);
+	void ReadSceneNode( Collada::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);
+	void ReadNodeTransformation( Collada::Node* pNode, Collada::TransformType pType);
 
 	/** Reads a mesh reference in a node and adds it to the node's mesh list */
-	void ReadNodeGeometry( Node* pNode);
+	void ReadNodeGeometry( Collada::Node* pNode);
 
 	/** Reads the collada scene */
 	void ReadScene();
@@ -247,10 +143,10 @@ protected:
 	const char* GetTextContent();
 
 	/** Calculates the resulting transformation fromm all the given transform steps */
-	aiMatrix4x4 CalculateResultTransform( const std::vector<Transform>& pTransforms) const;
+	aiMatrix4x4 CalculateResultTransform( const std::vector<Collada::Transform>& pTransforms) const;
 
 	/** Determines the input data type for the given semantic string */
-	InputType GetTypeForSemantic( const std::string& pSemantic);
+	Collada::InputType GetTypeForSemantic( const std::string& pSemantic);
 
 	/** Finds the item in the given library by its reference, throws if not found */
 	template <typename Type> const Type& ResolveLibraryReference( const std::map<std::string, Type>& pLibrary, const std::string& pURL) const;
@@ -263,23 +159,23 @@ protected:
 	irr::io::IrrXMLReader* mReader;
 
 	/** All data arrays found in the file by ID. Might be referred to by actually everyone. Collada, you are a steaming pile of indirection. */
-	typedef std::map<std::string, Data> DataLibrary;
+	typedef std::map<std::string, Collada::Data> DataLibrary;
 	DataLibrary mDataLibrary;
 
 	/** Same for accessors which define how the data in a data array is accessed. */
-	typedef std::map<std::string, Accessor> AccessorLibrary;
+	typedef std::map<std::string, Collada::Accessor> AccessorLibrary;
 	AccessorLibrary mAccessorLibrary;
 
 	/** Mesh library: mesh by ID */
-	typedef std::map<std::string, Mesh*> MeshLibrary;
+	typedef std::map<std::string, Collada::Mesh*> MeshLibrary;
 	MeshLibrary mMeshLibrary;
 
 	/** node library: root node of the hierarchy part by ID */
-	typedef std::map<std::string, Node*> NodeLibrary;
+	typedef std::map<std::string, Collada::Node*> 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;
+	Collada::Node* mRootNode;
 
 	/** Size unit: how large compared to a meter */
 	float mUnitSize;

+ 1 - 1
code/fast_atof.h

@@ -194,7 +194,7 @@ inline const char* fast_atof_move( const char* c, float& out)
 	else if (*c=='+')++c;
 
 	f = (float) strtol10_64 ( c, &c );
-	if (*c == '.')
+	if (*c == '.' || (c[0] == ',' && isdigit( c[1])))
 	{
 		++c;
 

+ 4 - 0
workspaces/vc8/assimp.vcproj

@@ -1437,6 +1437,10 @@
 				<Filter
 					Name="Collada"
 					>
+					<File
+						RelativePath="..\..\code\ColladaHelper.h"
+						>
+					</File>
 					<File
 						RelativePath="..\..\code\ColladaLoader.cpp"
 						>