Browse Source

- templatize math library. All standard math classes (i.e. aiMatrix4x4) have been replaced by templates which are usually named like the old type with a 't' postfix. For compatibility, typedefs to replace the old types exist. For the C interface, these still map to raw structures.

While principally backwards-compatible, this is still a breaking change since I also changed some method signatures (i.e. aiVector3t<TReal>(TReal) is now explicit). Normal users should not be affected, though.

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@1129 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
aramis_acg 13 years ago
parent
commit
ea3f655c57

+ 2 - 0
code/CMakeLists.txt

@@ -36,10 +36,12 @@ SET( PUBLIC_HEADERS
 	${HEADER_PATH}/aiMesh.h
 	${HEADER_PATH}/aiPostProcess.h
 	${HEADER_PATH}/aiQuaternion.h
+	${HEADER_PATH}/aiQuaternion.inl
 	${HEADER_PATH}/aiScene.h
 	${HEADER_PATH}/aiTexture.h
 	${HEADER_PATH}/aiTypes.h
 	${HEADER_PATH}/aiVector2D.h
+	${HEADER_PATH}/aiVector2D.inl
 	${HEADER_PATH}/aiVector3D.h
 	${HEADER_PATH}/aiVector3D.inl
 	${HEADER_PATH}/aiVersion.h

+ 2 - 2
code/CalcTangentsProcess.cpp

@@ -160,8 +160,8 @@ bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
 			{
 				register unsigned int idx = face.mIndices[i];
 				vertexDone  [idx] = true;
-				meshTang    [idx] = qnan;
-				meshBitang  [idx] = qnan;
+				meshTang    [idx] = aiVector3D(qnan);
+				meshBitang  [idx] = aiVector3D(qnan);
 			}
 
 			continue;

+ 4 - 4
code/ComputeUVMappingProcess.cpp

@@ -337,7 +337,7 @@ void ComputeUVMappingProcess::ComputePlaneMapping(aiMesh* mesh,const aiVector3D&
 
 		for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)	{
 			const aiVector3D& pos = mesh->mVertices[pnt];
-			out[pnt].Set((pos.z - min.z) / diffu,(pos.y - min.y) / diffv);
+			out[pnt].Set((pos.z - min.z) / diffu,(pos.y - min.y) / diffv,0.f);
 		}
 	}
 	else if (axis * base_axis_y >= angle_epsilon)	{
@@ -347,7 +347,7 @@ void ComputeUVMappingProcess::ComputePlaneMapping(aiMesh* mesh,const aiVector3D&
 
 		for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)	{
 			const aiVector3D& pos = mesh->mVertices[pnt];
-			out[pnt].Set((pos.x - min.x) / diffu,(pos.z - min.z) / diffv);
+			out[pnt].Set((pos.x - min.x) / diffu,(pos.z - min.z) / diffv,0.f);
 		}
 	}
 	else if (axis * base_axis_z >= angle_epsilon)	{
@@ -357,7 +357,7 @@ void ComputeUVMappingProcess::ComputePlaneMapping(aiMesh* mesh,const aiVector3D&
 
 		for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)	{
 			const aiVector3D& pos = mesh->mVertices[pnt];
-			out[pnt].Set((pos.y - min.y) / diffu,(pos.x - min.x) / diffv);
+			out[pnt].Set((pos.y - min.y) / diffu,(pos.x - min.x) / diffv,0.f);
 		}
 	}
 	// slower code path in case the mapping axis is not one of the coordinate system axes
@@ -372,7 +372,7 @@ void ComputeUVMappingProcess::ComputePlaneMapping(aiMesh* mesh,const aiVector3D&
 		// again the same, except we're applying a transformation now
 		for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)	{
 			const aiVector3D pos = mTrafo * mesh->mVertices[pnt];
-			out[pnt].Set((pos.x - min.x) / diffu,(pos.z - min.z) / diffv);
+			out[pnt].Set((pos.x - min.x) / diffu,(pos.z - min.z) / diffv,0.f);
 		}
 	}
 

+ 2 - 2
code/GenFaceNormalsProcess.cpp

@@ -120,7 +120,7 @@ bool GenFaceNormalsProcess::GenMeshFaceNormals (aiMesh* pMesh)
 		if (face.mNumIndices < 3)	{
 			// either a point or a line -> no well-defined normal vector
 			for (unsigned int i = 0;i < face.mNumIndices;++i) {
-				pMesh->mNormals[face.mIndices[i]] = qnan;
+				pMesh->mNormals[face.mIndices[i]] = aiVector3D(qnan);
 			}
 			continue;
 		}
@@ -128,7 +128,7 @@ bool GenFaceNormalsProcess::GenMeshFaceNormals (aiMesh* pMesh)
 		const aiVector3D* pV1 = &pMesh->mVertices[face.mIndices[0]];
 		const aiVector3D* pV2 = &pMesh->mVertices[face.mIndices[1]];
 		const aiVector3D* pV3 = &pMesh->mVertices[face.mIndices[face.mNumIndices-1]];
-		aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1)).Normalize();
+		const aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1)).Normalize();
 
 		for (unsigned int i = 0;i < face.mNumIndices;++i) {
 			pMesh->mNormals[face.mIndices[i]] = vNor;

+ 13 - 8
code/GenVertexNormalsProcess.cpp

@@ -132,18 +132,21 @@ bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int
 		if (face.mNumIndices < 3)
 		{
 			// either a point or a line -> no normal vector
-			for (unsigned int i = 0;i < face.mNumIndices;++i)
-				pMesh->mNormals[face.mIndices[i]] = qnan;
+			for (unsigned int i = 0;i < face.mNumIndices;++i) {
+				pMesh->mNormals[face.mIndices[i]] = aiVector3D(qnan);
+			}
+
 			continue;
 		}
 
-		aiVector3D* pV1 = &pMesh->mVertices[face.mIndices[0]];
-		aiVector3D* pV2 = &pMesh->mVertices[face.mIndices[1]];
-		aiVector3D* pV3 = &pMesh->mVertices[face.mIndices[face.mNumIndices-1]];
-		aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1)).Normalize();
+		const aiVector3D* pV1 = &pMesh->mVertices[face.mIndices[0]];
+		const aiVector3D* pV2 = &pMesh->mVertices[face.mIndices[1]];
+		const aiVector3D* pV3 = &pMesh->mVertices[face.mIndices[face.mNumIndices-1]];
+		const aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1)).Normalize();
 
-		for (unsigned int i = 0;i < face.mNumIndices;++i)
+		for (unsigned int i = 0;i < face.mNumIndices;++i) {
 			pMesh->mNormals[face.mIndices[i]] = vNor;
+		}
 	}
 
 	// Set up a SpatialSort to quickly find all vertices close to a given position
@@ -175,7 +178,9 @@ bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int
 		// to optimize the whole algorithm a little bit ...
 		std::vector<bool> abHad(pMesh->mNumVertices,false);
 		for (unsigned int i = 0; i < pMesh->mNumVertices;++i)	{
-			if (abHad[i])continue;
+			if (abHad[i]) {
+				continue;
+			}
 
 			// Get all vertices that share this one ...
 			vertexFinder->FindPositions( pMesh->mVertices[i], posEpsilon, verticesFound);

+ 31 - 22
include/aiColor4D.h

@@ -44,51 +44,60 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef AI_COLOR4D_H_INC
 #define AI_COLOR4D_H_INC
 
+#include "./Compiler/pushpack1.h"
+
 #ifdef __cplusplus
-extern "C" {
-#endif
 
-#include "./Compiler/pushpack1.h"
 // ----------------------------------------------------------------------------------
 /** Represents a color in Red-Green-Blue space including an 
 *   alpha component. Color values range from 0 to 1. */
 // ----------------------------------------------------------------------------------
-struct aiColor4D
+template <typename TReal>
+class aiColor4t
 {
-#ifdef __cplusplus
-	aiColor4D () : r(0.0f), g(0.0f), b(0.0f), a(0.0f) {}
-	aiColor4D (float _r, float _g, float _b, float _a) 
+public:
+	aiColor4t () : r(), g(), b(), a() {}
+	aiColor4t (TReal _r, TReal _g, TReal _b, TReal _a) 
 		: r(_r), g(_g), b(_b), a(_a) {}
-	aiColor4D (float _r) : r(_r), g(_r), b(_r), a(_r) {}
-	aiColor4D (const aiColor4D& o) 
+	aiColor4t (TReal _r) : r(_r), g(_r), b(_r), a(_r) {}
+	aiColor4t (const aiColor4t& o) 
 		: r(o.r), g(o.g), b(o.b), a(o.a) {}
 
+public:
 	// combined operators
-	const aiColor4D& operator += (const aiColor4D& o);
-	const aiColor4D& operator -= (const aiColor4D& o);
-	const aiColor4D& operator *= (float f);
-	const aiColor4D& operator /= (float f);
+	const aiColor4t& operator += (const aiColor4t& o);
+	const aiColor4t& operator -= (const aiColor4t& o);
+	const aiColor4t& operator *= (TReal f);
+	const aiColor4t& operator /= (TReal f);
 
+public:
 	// comparison
-	bool operator == (const aiColor4D& other) const;
-	bool operator != (const aiColor4D& other) const;
+	bool operator == (const aiColor4t& other) const;
+	bool operator != (const aiColor4t& other) const;
 
 	// color tuple access, rgba order
-	inline float operator[](unsigned int i) const;
-	inline float& operator[](unsigned int i);
+	inline TReal operator[](unsigned int i) const;
+	inline TReal& operator[](unsigned int i);
 
 	/** check whether a color is (close to) black */
 	inline bool IsBlack() const;
 
-#endif // !__cplusplus
+public:
 
 	// Red, green, blue and alpha color values 
-	float r, g, b, a;
+	TReal r, g, b, a;
 } PACK_STRUCT;  // !struct aiColor4D
 
-#include "./Compiler/poppack1.h"
-#ifdef __cplusplus
-} // end extern "C"
+typedef aiColor4t<float> aiColor4D;
+
+#else
+
+struct aiColor4D {
+	float r, g, b, a;
+} PACK_STRUCT;
 
 #endif // __cplusplus
+
+#include "./Compiler/poppack1.h"
+
 #endif // AI_VECTOR3D_H_INC

+ 64 - 39
include/aiColor4D.inl

@@ -40,99 +40,124 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 /** @file  aiColor4D.inl
- *  @brief Inline implementation of aiColor4D operators
+ *  @brief Inline implementation of aiColor4t<TReal> operators
  */
 #ifndef AI_COLOR4D_INL_INC
 #define AI_COLOR4D_INL_INC
 
-#include "aiColor4D.h"
 #ifdef __cplusplus
+#include "aiColor4D.h"
 
 // ------------------------------------------------------------------------------------------------
-AI_FORCE_INLINE const aiColor4D& aiColor4D::operator += (const aiColor4D& o) {
-	r += o.r; g += o.g; b += o.b; a += o.a; return *this; 
+template <typename TReal>
+AI_FORCE_INLINE const aiColor4t<TReal>& aiColor4t<TReal>::operator += (const aiColor4t<TReal>& o) {
+	r += o.r; g += o.g; b += o.b; a += o.a; 
+	return *this; 
 }
 // ------------------------------------------------------------------------------------------------
-AI_FORCE_INLINE const aiColor4D& aiColor4D::operator -= (const aiColor4D& o) {
-	r -= o.r; g -= o.g; b -= o.b; a -= o.a; return *this;
+template <typename TReal>
+AI_FORCE_INLINE const aiColor4t<TReal>& aiColor4t<TReal>::operator -= (const aiColor4t<TReal>& o) {
+	r -= o.r; g -= o.g; b -= o.b; a -= o.a; 
+	return *this;
 }
 // ------------------------------------------------------------------------------------------------
-AI_FORCE_INLINE const aiColor4D& aiColor4D::operator *= (float f) {
-	r *= f; g *= f; b *= f; a *= f; return *this; 
+template <typename TReal>
+AI_FORCE_INLINE const aiColor4t<TReal>& aiColor4t<TReal>::operator *= (TReal f) {
+	r *= f; g *= f; b *= f; a *= f; 
+	return *this; 
 }
 // ------------------------------------------------------------------------------------------------
-AI_FORCE_INLINE const aiColor4D& aiColor4D::operator /= (float f) {
-	r /= f; g /= f; b /= f; a /= f; return *this; 
+template <typename TReal>
+AI_FORCE_INLINE const aiColor4t<TReal>& aiColor4t<TReal>::operator /= (TReal f) {
+	r /= f; g /= f; b /= f; a /= f; 
+	return *this; 
 }
 // ------------------------------------------------------------------------------------------------
-AI_FORCE_INLINE float aiColor4D::operator[](unsigned int i) const {
+template <typename TReal>
+AI_FORCE_INLINE TReal aiColor4t<TReal>::operator[](unsigned int i) const {
 	return *(&r + i);
 }
 // ------------------------------------------------------------------------------------------------
-AI_FORCE_INLINE float& aiColor4D::operator[](unsigned int i) {
+template <typename TReal>
+AI_FORCE_INLINE TReal& aiColor4t<TReal>::operator[](unsigned int i) {
 	return *(&r + i);
 }
 // ------------------------------------------------------------------------------------------------
-AI_FORCE_INLINE bool aiColor4D::operator== (const aiColor4D& other) const {
+template <typename TReal>
+AI_FORCE_INLINE bool aiColor4t<TReal>::operator== (const aiColor4t<TReal>& other) const {
 	return r == other.r && g == other.g && b == other.b && a == other.a;
 }
 // ------------------------------------------------------------------------------------------------
-AI_FORCE_INLINE bool aiColor4D::operator!= (const aiColor4D& other) const {
+template <typename TReal>
+AI_FORCE_INLINE bool aiColor4t<TReal>::operator!= (const aiColor4t<TReal>& other) const {
 	return r != other.r || g != other.g || b != other.b || a != other.a;
 }
 // ------------------------------------------------------------------------------------------------
-AI_FORCE_INLINE aiColor4D operator + (const aiColor4D& v1, const aiColor4D& v2)	{
-	return aiColor4D( v1.r + v2.r, v1.g + v2.g, v1.b + v2.b, v1.a + v2.a);
+template <typename TReal>
+AI_FORCE_INLINE aiColor4t<TReal> operator + (const aiColor4t<TReal>& v1, const aiColor4t<TReal>& v2)	{
+	return aiColor4t<TReal>( v1.r + v2.r, v1.g + v2.g, v1.b + v2.b, v1.a + v2.a);
 }
 // ------------------------------------------------------------------------------------------------
-AI_FORCE_INLINE aiColor4D operator - (const aiColor4D& v1, const aiColor4D& v2)	{
-	return aiColor4D( v1.r - v2.r, v1.g - v2.g, v1.b - v2.b, v1.a - v2.a);
+template <typename TReal>
+AI_FORCE_INLINE aiColor4t<TReal> operator - (const aiColor4t<TReal>& v1, const aiColor4t<TReal>& v2)	{
+	return aiColor4t<TReal>( v1.r - v2.r, v1.g - v2.g, v1.b - v2.b, v1.a - v2.a);
 }
 // ------------------------------------------------------------------------------------------------
-AI_FORCE_INLINE aiColor4D operator * (const aiColor4D& v1, const aiColor4D& v2)	{
-	return aiColor4D( v1.r * v2.r, v1.g * v2.g, v1.b * v2.b, v1.a * v2.a);
+template <typename TReal>
+AI_FORCE_INLINE aiColor4t<TReal> operator * (const aiColor4t<TReal>& v1, const aiColor4t<TReal>& v2)	{
+	return aiColor4t<TReal>( v1.r * v2.r, v1.g * v2.g, v1.b * v2.b, v1.a * v2.a);
 }
 // ------------------------------------------------------------------------------------------------
-AI_FORCE_INLINE aiColor4D operator / (const aiColor4D& v1, const aiColor4D& v2)	{
-	return aiColor4D( v1.r / v2.r, v1.g / v2.g, v1.b / v2.b, v1.a / v2.a);
+template <typename TReal>
+AI_FORCE_INLINE aiColor4t<TReal> operator / (const aiColor4t<TReal>& v1, const aiColor4t<TReal>& v2)	{
+	return aiColor4t<TReal>( v1.r / v2.r, v1.g / v2.g, v1.b / v2.b, v1.a / v2.a);
 }
 // ------------------------------------------------------------------------------------------------
-AI_FORCE_INLINE aiColor4D operator * ( float f, const aiColor4D& v)	{
-	return aiColor4D( f*v.r, f*v.g, f*v.b, f*v.a);
+template <typename TReal>
+AI_FORCE_INLINE aiColor4t<TReal> operator * ( TReal f, const aiColor4t<TReal>& v)	{
+	return aiColor4t<TReal>( f*v.r, f*v.g, f*v.b, f*v.a);
 }
 // ------------------------------------------------------------------------------------------------
-AI_FORCE_INLINE  aiColor4D operator * ( const aiColor4D& v, float f)	{
-	return aiColor4D( f*v.r, f*v.g, f*v.b, f*v.a);
+template <typename TReal>
+AI_FORCE_INLINE  aiColor4t<TReal> operator * ( const aiColor4t<TReal>& v, TReal f)	{
+	return aiColor4t<TReal>( f*v.r, f*v.g, f*v.b, f*v.a);
 }
 // ------------------------------------------------------------------------------------------------
-AI_FORCE_INLINE  aiColor4D operator / ( const aiColor4D& v, float f)	{
+template <typename TReal>
+AI_FORCE_INLINE  aiColor4t<TReal> operator / ( const aiColor4t<TReal>& v, TReal f)	{
 	return v * (1/f);
 }
 // ------------------------------------------------------------------------------------------------
-AI_FORCE_INLINE  aiColor4D operator / ( float f,const aiColor4D& v)	{
-	return aiColor4D(f,f,f,f)/v;
+template <typename TReal>
+AI_FORCE_INLINE  aiColor4t<TReal> operator / ( TReal f,const aiColor4t<TReal>& v)	{
+	return aiColor4t<TReal>(f,f,f,f)/v;
 }
 // ------------------------------------------------------------------------------------------------
-AI_FORCE_INLINE  aiColor4D operator + ( const aiColor4D& v, float f)	{
-	return aiColor4D( f+v.r, f+v.g, f+v.b, f+v.a);
+template <typename TReal>
+AI_FORCE_INLINE  aiColor4t<TReal> operator + ( const aiColor4t<TReal>& v, TReal f)	{
+	return aiColor4t<TReal>( f+v.r, f+v.g, f+v.b, f+v.a);
 }
 // ------------------------------------------------------------------------------------------------
-AI_FORCE_INLINE  aiColor4D operator - ( const aiColor4D& v, float f)	{
-	return aiColor4D( v.r-f, v.g-f, v.b-f, v.a-f);
+template <typename TReal>
+AI_FORCE_INLINE  aiColor4t<TReal> operator - ( const aiColor4t<TReal>& v, TReal f)	{
+	return aiColor4t<TReal>( v.r-f, v.g-f, v.b-f, v.a-f);
 }
 // ------------------------------------------------------------------------------------------------
-AI_FORCE_INLINE  aiColor4D operator + ( float f, const aiColor4D& v)	{
-	return aiColor4D( f+v.r, f+v.g, f+v.b, f+v.a);
+template <typename TReal>
+AI_FORCE_INLINE  aiColor4t<TReal> operator + ( TReal f, const aiColor4t<TReal>& v)	{
+	return aiColor4t<TReal>( f+v.r, f+v.g, f+v.b, f+v.a);
 }
 // ------------------------------------------------------------------------------------------------
-AI_FORCE_INLINE  aiColor4D operator - ( float f, const aiColor4D& v)	{
-	return aiColor4D( f-v.r, f-v.g, f-v.b, f-v.a);
+template <typename TReal>
+AI_FORCE_INLINE  aiColor4t<TReal> operator - ( TReal f, const aiColor4t<TReal>& v)	{
+	return aiColor4t<TReal>( f-v.r, f-v.g, f-v.b, f-v.a);
 }
 
 // ------------------------------------------------------------------------------------------------
-inline bool aiColor4D :: IsBlack() const	{
+template <typename TReal>
+inline bool aiColor4t<TReal> :: IsBlack() const	{
 	// The alpha component doesn't care here. black is black.
-	static const float epsilon = 10e-3f;
+	static const TReal epsilon = 10e-3f;
 	return fabs( r ) < epsilon && fabs( g ) < epsilon && fabs( b ) < epsilon;
 }
 

+ 55 - 38
include/aiMatrix3x3.h

@@ -45,32 +45,35 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef AI_MATRIX3x3_H_INC
 #define AI_MATRIX3x3_H_INC
 
+#include "./Compiler/pushpack1.h"
+
 #ifdef __cplusplus
-extern "C" {
-#endif
 
-struct aiMatrix4x4;
-struct aiVector2D;
+template <typename T> class aiMatrix4x4t;
+template <typename T> class aiVector2t;
 
 // ---------------------------------------------------------------------------
 /** @brief Represents a row-major 3x3 matrix
  *
- *  There's much confusion about matrix layouts (colum vs. row order). 
- *  This is *always* a row-major matrix. Even with the
- *  aiProcess_ConvertToLeftHanded flag.
+ *  There's much confusion about matrix layouts (column vs. row order). 
+ *  This is *always* a row-major matrix. Not even with the
+ *  #aiProcess_ConvertToLeftHanded flag, which absolutely does not affect
+ *  matrix order - it just affects the handedness of the coordinate system
+ *  defined thereby.
  */
-struct aiMatrix3x3
+template <typename TReal>
+class aiMatrix3x3t
 {
-#ifdef __cplusplus
+public:
 
-	aiMatrix3x3 () :	
-		a1(1.0f), a2(0.0f), a3(0.0f), 
-		b1(0.0f), b2(1.0f), b3(0.0f), 
-		c1(0.0f), c2(0.0f), c3(1.0f) {}
+	aiMatrix3x3t () :	
+		a1(static_cast<TReal>(1.0f)), a2(), a3(), 
+		b1(), b2(static_cast<TReal>(1.0f)), b3(), 
+		c1(), c2(), c3(static_cast<TReal>(1.0f)) {}
 
-	aiMatrix3x3 (	float _a1, float _a2, float _a3,
-					float _b1, float _b2, float _b3,
-					float _c1, float _c2, float _c3) :	
+	aiMatrix3x3t (	TReal _a1, TReal _a2, TReal _a3,
+					TReal _b1, TReal _b2, TReal _b3,
+					TReal _c1, TReal _c2, TReal _c3) :	
 		a1(_a1), a2(_a2), a3(_a3), 
 		b1(_b1), b2(_b2), b3(_b3), 
 		c1(_c1), c2(_c2), c3(_c3)
@@ -78,17 +81,20 @@ struct aiMatrix3x3
 
 public:
 
-	// matrix multiplication. beware, not commutative
-	aiMatrix3x3& operator *= (const aiMatrix3x3& m);
-	aiMatrix3x3  operator  * (const aiMatrix3x3& m) const;
+	// matrix multiplication. 
+	aiMatrix3x3t& operator *= (const aiMatrix3x3t& m);
+	aiMatrix3x3t  operator  * (const aiMatrix3x3t& m) const;
 
 	// array access operators
-	float* operator[]       (unsigned int p_iIndex);
-	const float* operator[] (unsigned int p_iIndex) const;
+	TReal* operator[]       (unsigned int p_iIndex);
+	const TReal* operator[] (unsigned int p_iIndex) const;
 
 	// comparison operators
-	bool operator== (const aiMatrix4x4 m) const;
-	bool operator!= (const aiMatrix4x4 m) const;
+	bool operator== (const aiMatrix4x4t<TReal> m) const;
+	bool operator!= (const aiMatrix4x4t<TReal> m) const;
+
+	template <typename TOther>
+	operator aiMatrix3x3t<TOther> () const;
 
 public:
 
@@ -96,20 +102,20 @@ public:
 	/** @brief Construction from a 4x4 matrix. The remaining parts 
 	 *  of the matrix are ignored.
 	 */
-	explicit aiMatrix3x3( const aiMatrix4x4& pMatrix);
+	explicit aiMatrix3x3t( const aiMatrix4x4t<TReal>& pMatrix);
 
 	// -------------------------------------------------------------------
 	/** @brief Transpose the matrix
 	 */
-	aiMatrix3x3& Transpose();
+	aiMatrix3x3t& Transpose();
 
 	// -------------------------------------------------------------------
 	/** @brief Invert the matrix.
 	 *  If the matrix is not invertible all elements are set to qnan.
-	 *  Beware, use (f != f) to check whether a float f is qnan.
+	 *  Beware, use (f != f) to check whether a TReal f is qnan.
 	 */
-	aiMatrix3x3& Inverse();
-	float Determinant() const;
+	aiMatrix3x3t& Inverse();
+	TReal Determinant() const;
 
 public:
 	// -------------------------------------------------------------------
@@ -118,7 +124,7 @@ public:
 	 *  @param out Receives the output matrix
 	 *  @return Reference to the output matrix
 	 */
-	static aiMatrix3x3& RotationZ(float a, aiMatrix3x3& out);
+	static aiMatrix3x3t& RotationZ(TReal a, aiMatrix3x3t& out);
 
 	// -------------------------------------------------------------------
 	/** @brief Returns a rotation matrix for a rotation around
@@ -128,8 +134,8 @@ public:
 	 *  @param axis Axis to rotate around
 	 *  @param out To be filled
 	 */
-	static aiMatrix3x3& Rotation( float a, 
-		const aiVector3D& axis, aiMatrix3x3& out);
+	static aiMatrix3x3t& Rotation( TReal a, 
+		const aiVector3t<TReal>& axis, aiMatrix3x3t& out);
 
 	// -------------------------------------------------------------------
 	/** @brief Returns a translation matrix 
@@ -137,7 +143,7 @@ public:
 	 *  @param out Receives the output matrix
 	 *  @return Reference to the output matrix
 	 */
-	static aiMatrix3x3& Translation( const aiVector2D& v, aiMatrix3x3& out);
+	static aiMatrix3x3t& Translation( const aiVector2t<TReal>& v, aiMatrix3x3t& out);
 
 	// -------------------------------------------------------------------
 	/** @brief A function for creating a rotation matrix that rotates a
@@ -148,19 +154,30 @@ public:
 	 *          "Efficiently Building a Matrix to Rotate One Vector to Another"
 	 *          Journal of Graphics Tools, 4(4):1-4, 1999
 	 */
-	static aiMatrix3x3& FromToMatrix(const aiVector3D& from, 
-		const aiVector3D& to, aiMatrix3x3& out);
+	static aiMatrix3x3t& FromToMatrix(const aiVector3t<TReal>& from, 
+		const aiVector3t<TReal>& to, aiMatrix3x3t& out);
+
+public:
+
+
+	TReal a1, a2, a3;
+	TReal b1, b2, b3;
+	TReal c1, c2, c3;
+} PACK_STRUCT;
 
-#endif // __cplusplus
+typedef aiMatrix3x3t<float> aiMatrix3x3;
 
+#else
+
+struct aiMatrix3x3 {
 
 	float a1, a2, a3;
 	float b1, b2, b3;
 	float c1, c2, c3;
-};
+} PACK_STRUCT;
 
-#ifdef __cplusplus
-} // end of extern C
 #endif
 
+#include "./Compiler/poppack1.h"
+
 #endif // AI_MATRIX3x3_H_INC

+ 116 - 50
include/aiMatrix3x3.inl

@@ -1,19 +1,61 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2010, 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.
+---------------------------------------------------------------------------
+*/
+
 /** @file aiMatrix3x3.inl
  *  @brief Inline implementation of the 3x3 matrix operators
  */
 #ifndef AI_MATRIX3x3_INL_INC
 #define AI_MATRIX3x3_INL_INC
 
+#ifdef __cplusplus
 #include "aiMatrix3x3.h"
 
-#ifdef __cplusplus
 #include "aiMatrix4x4.h"
 #include <algorithm>
 #include <limits>
 
 // ------------------------------------------------------------------------------------------------
 // Construction from a 4x4 matrix. The remaining parts of the matrix are ignored.
-inline aiMatrix3x3::aiMatrix3x3( const aiMatrix4x4& pMatrix)
+template <typename TReal>
+inline aiMatrix3x3t<TReal>::aiMatrix3x3t( const aiMatrix4x4t<TReal>& pMatrix)
 {
 	a1 = pMatrix.a1; a2 = pMatrix.a2; a3 = pMatrix.a3;
 	b1 = pMatrix.b1; b2 = pMatrix.b2; b3 = pMatrix.b3;
@@ -21,9 +63,10 @@ inline aiMatrix3x3::aiMatrix3x3( const aiMatrix4x4& pMatrix)
 }
 
 // ------------------------------------------------------------------------------------------------
-inline aiMatrix3x3& aiMatrix3x3::operator *= (const aiMatrix3x3& m)
+template <typename TReal>
+inline aiMatrix3x3t<TReal>& aiMatrix3x3t<TReal>::operator *= (const aiMatrix3x3t<TReal>& m)
 {
-	*this = aiMatrix3x3(m.a1 * a1 + m.b1 * a2 + m.c1 * a3,
+	*this = aiMatrix3x3t<TReal>(m.a1 * a1 + m.b1 * a2 + m.c1 * a3,
 		m.a2 * a1 + m.b2 * a2 + m.c2 * a3,
 		m.a3 * a1 + m.b3 * a2 + m.c3 * a3,
 		m.a1 * b1 + m.b1 * b2 + m.c1 * b3,
@@ -36,27 +79,41 @@ inline aiMatrix3x3& aiMatrix3x3::operator *= (const aiMatrix3x3& m)
 }
 
 // ------------------------------------------------------------------------------------------------
-inline aiMatrix3x3 aiMatrix3x3::operator* (const aiMatrix3x3& m) const
+template <typename TReal>
+template <typename TOther>
+aiMatrix3x3t<TReal>::operator aiMatrix3x3t<TOther> () const
+{
+	return aiMatrix3x3t<TOther>(static_cast<TOther>(a1),static_cast<TOther>(a2),static_cast<TOther>(a3),
+		static_cast<TOther>(b1),static_cast<TOther>(b2),static_cast<TOther>(b3),
+		static_cast<TOther>(c1),static_cast<TOther>(c2),static_cast<TOther>(c3));
+}
+
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+inline aiMatrix3x3t<TReal> aiMatrix3x3t<TReal>::operator* (const aiMatrix3x3t<TReal>& m) const
 {
-	aiMatrix3x3 temp( *this);
+	aiMatrix3x3t<TReal> temp( *this);
 	temp *= m;
 	return temp;
 }
 
 // ------------------------------------------------------------------------------------------------
-inline float* aiMatrix3x3::operator[] (unsigned int p_iIndex)
+template <typename TReal>
+inline TReal* aiMatrix3x3t<TReal>::operator[] (unsigned int p_iIndex)
 {
 	return &this->a1 + p_iIndex * 3;
 }
 
 // ------------------------------------------------------------------------------------------------
-inline const float* aiMatrix3x3::operator[] (unsigned int p_iIndex) const
+template <typename TReal>
+inline const TReal* aiMatrix3x3t<TReal>::operator[] (unsigned int p_iIndex) const
 {
 	return &this->a1 + p_iIndex * 3;
 }
 
 // ------------------------------------------------------------------------------------------------
-inline bool aiMatrix3x3::operator== (const aiMatrix4x4 m) const
+template <typename TReal>
+inline bool aiMatrix3x3t<TReal>::operator== (const aiMatrix4x4t<TReal> m) const
 {
 	return a1 == m.a1 && a2 == m.a2 && a3 == m.a3 &&
 		   b1 == m.b1 && b2 == m.b2 && b3 == m.b3 &&
@@ -64,46 +121,51 @@ inline bool aiMatrix3x3::operator== (const aiMatrix4x4 m) const
 }
 
 // ------------------------------------------------------------------------------------------------
-inline bool aiMatrix3x3::operator!= (const aiMatrix4x4 m) const
+template <typename TReal>
+inline bool aiMatrix3x3t<TReal>::operator!= (const aiMatrix4x4t<TReal> m) const
 {
 	return !(*this == m);
 }
 
 // ------------------------------------------------------------------------------------------------
-inline aiMatrix3x3& aiMatrix3x3::Transpose()
+template <typename TReal>
+inline aiMatrix3x3t<TReal>& aiMatrix3x3t<TReal>::Transpose()
 {
-	// (float&) don't remove, GCC complains cause of packed fields
-	std::swap( (float&)a2, (float&)b1);
-	std::swap( (float&)a3, (float&)c1);
-	std::swap( (float&)b3, (float&)c2);
+	// (TReal&) don't remove, GCC complains cause of packed fields
+	std::swap( (TReal&)a2, (TReal&)b1);
+	std::swap( (TReal&)a3, (TReal&)c1);
+	std::swap( (TReal&)b3, (TReal&)c2);
 	return *this;
 }
 
 // ----------------------------------------------------------------------------------------
-inline float aiMatrix3x3::Determinant() const
+template <typename TReal>
+inline TReal aiMatrix3x3t<TReal>::Determinant() const
 {
 	return a1*b2*c3 - a1*b3*c2 + a2*b3*c1 - a2*b1*c3 + a3*b1*c2 - a3*b2*c1;
 }
 
 // ----------------------------------------------------------------------------------------
-inline aiMatrix3x3& aiMatrix3x3::Inverse()
+template <typename TReal>
+inline aiMatrix3x3t<TReal>& aiMatrix3x3t<TReal>::Inverse()
 {
 	// Compute the reciprocal determinant
-	float det = Determinant();
-	if(det == 0.0f) 
+	TReal det = Determinant();
+	if(det == static_cast<TReal>(0.0)) 
 	{
 		// Matrix not invertible. Setting all elements to nan is not really
-		// correct in a mathematical sense but it is easy to debug for the
-		// programmer.
-		const float nan = std::numeric_limits<float>::quiet_NaN();
-		*this = aiMatrix3x3( nan,nan,nan,nan,nan,nan,nan,nan,nan);
+		// correct in a mathematical sense; but at least qnans are easy to 
+		// spot. XXX we might throw an exception instead, which would
+		// be even much better to spot :/.
+		const TReal nan = std::numeric_limits<TReal>::quiet_NaN();
+		*this = aiMatrix3x3t<TReal>( nan,nan,nan,nan,nan,nan,nan,nan,nan);
 
 		return *this;
 	}
 
-	float invdet = 1.0f / det;
+	TReal invdet = static_cast<TReal>(1.0) / det;
 
-	aiMatrix3x3 res;
+	aiMatrix3x3t<TReal> res;
 	res.a1 = invdet  * (b2 * c3 - b3 * c2);
 	res.a2 = -invdet * (a2 * c3 - a3 * c2);
 	res.a3 = invdet  * (a2 * b3 - a3 * b2);
@@ -119,7 +181,8 @@ inline aiMatrix3x3& aiMatrix3x3::Inverse()
 }
 
 // ------------------------------------------------------------------------------------------------
-inline aiMatrix3x3& aiMatrix3x3::RotationZ(float a, aiMatrix3x3& out)
+template <typename TReal>
+inline aiMatrix3x3t<TReal>& aiMatrix3x3t<TReal>::RotationZ(TReal a, aiMatrix3x3t<TReal>& out)
 {
 	out.a1 = out.b2 = ::cos(a);
 	out.b1 = ::sin(a);
@@ -133,10 +196,11 @@ inline aiMatrix3x3& aiMatrix3x3::RotationZ(float a, aiMatrix3x3& out)
 
 // ------------------------------------------------------------------------------------------------
 // Returns a rotation matrix for a rotation around an arbitrary axis.
-inline aiMatrix3x3& aiMatrix3x3::Rotation( float a, const aiVector3D& axis, aiMatrix3x3& out)
+template <typename TReal>
+inline aiMatrix3x3t<TReal>& aiMatrix3x3t<TReal>::Rotation( TReal a, const aiVector3t<TReal>& axis, aiMatrix3x3t<TReal>& out)
 {
-  float c = cos( a), s = sin( a), t = 1 - c;
-  float x = axis.x, y = axis.y, z = axis.z;
+  TReal c = cos( a), s = sin( a), t = 1 - c;
+  TReal 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;
@@ -147,9 +211,10 @@ inline aiMatrix3x3& aiMatrix3x3::Rotation( float a, const aiVector3D& axis, aiMa
 }
 
 // ------------------------------------------------------------------------------------------------
-inline aiMatrix3x3& aiMatrix3x3::Translation( const aiVector2D& v, aiMatrix3x3& out)
+template <typename TReal>
+inline aiMatrix3x3t<TReal>& aiMatrix3x3t<TReal>::Translation( const aiVector2t<TReal>& v, aiMatrix3x3t<TReal>& out)
 {
-	out = aiMatrix3x3();
+	out = aiMatrix3x3t<TReal>();
 	out.a3 = v.x;
 	out.b3 = v.y;
 	return out;
@@ -165,13 +230,14 @@ inline aiMatrix3x3& aiMatrix3x3::Translation( const aiVector2D& v, aiMatrix3x3&
  *          Journal of Graphics Tools, 4(4):1-4, 1999
  */
 // ----------------------------------------------------------------------------------------
-inline aiMatrix3x3& aiMatrix3x3::FromToMatrix(const aiVector3D& from, 
-	const aiVector3D& to, aiMatrix3x3& mtx)
+template <typename TReal>
+inline aiMatrix3x3t<TReal>& aiMatrix3x3t<TReal>::FromToMatrix(const aiVector3t<TReal>& from, 
+	const aiVector3t<TReal>& to, aiMatrix3x3t<TReal>& mtx)
 {
-	const float e = from * to;
-	const float f = (e < 0)? -e:e;
+	const TReal e = from * to;
+	const TReal f = (e < 0)? -e:e;
 
-	if (f > 1.0 - 0.00001f)     /* "from" and "to"-vector almost parallel */
+	if (f > static_cast<TReal>(1.0) - static_cast<TReal>(0.00001))     /* "from" and "to"-vector almost parallel */
 	{
 		aiVector3D u,v;     /* temporary storage vectors */
 		aiVector3D x;       /* vector most nearly orthogonal to "from" */
@@ -184,31 +250,31 @@ inline aiMatrix3x3& aiMatrix3x3::FromToMatrix(const aiVector3D& from,
 		{
 			if (x.x < x.z)
 			{
-				x.x = 1.0; x.y = x.z = 0.0;
+				x.x = static_cast<TReal>(1.0); x.y = x.z = static_cast<TReal>(0.0);
 			}
 			else
 			{
-				x.z = 1.0; x.y = x.z = 0.0;
+				x.z = static_cast<TReal>(1.0); x.y = x.z = static_cast<TReal>(0.0);
 			}
 		}
 		else
 		{
 			if (x.y < x.z)
 			{
-				x.y = 1.0; x.x = x.z = 0.0;
+				x.y = static_cast<TReal>(1.0); x.x = x.z = static_cast<TReal>(0.0);
 			}
 			else
 			{
-				x.z = 1.0; x.x = x.y = 0.0;
+				x.z = static_cast<TReal>(1.0); x.x = x.y = static_cast<TReal>(0.0);
 			}
 		}
 
 		u.x = x.x - from.x; u.y = x.y - from.y; u.z = x.z - from.z;
 		v.x = x.x - to.x;   v.y = x.y - to.y;   v.z = x.z - to.z;
 
-		const float c1 = 2.0f / (u * u);
-		const float c2 = 2.0f / (v * v);
-		const float c3 = c1 * c2  * (u * v);
+		const TReal c1 = static_cast<TReal>(2.0) / (u * u);
+		const TReal c2 = static_cast<TReal>(2.0) / (v * v);
+		const TReal c3 = c1 * c2  * (u * v);
 
 		for (unsigned int i = 0; i < 3; i++) 
 		{
@@ -217,19 +283,19 @@ inline aiMatrix3x3& aiMatrix3x3::FromToMatrix(const aiVector3D& from,
 				mtx[i][j] =  - c1 * u[i] * u[j] - c2 * v[i] * v[j]
 					+ c3 * v[i] * u[j];
 			}
-			mtx[i][i] += 1.0;
+			mtx[i][i] += static_cast<TReal>(1.0);
 		}
 	}
 	else  /* the most common case, unless "from"="to", or "from"=-"to" */
 	{
 		const aiVector3D v = from ^ to;
 		/* ... use this hand optimized version (9 mults less) */
-		const float h = 1.0f/(1.0f + e);      /* optimization by Gottfried Chen */
-		const float hvx = h * v.x;
-		const float hvz = h * v.z;
-		const float hvxy = hvx * v.y;
-		const float hvxz = hvx * v.z;
-		const float hvyz = hvz * v.y;
+		const TReal h = static_cast<TReal>(1.0)/(static_cast<TReal>(1.0) + e);      /* optimization by Gottfried Chen */
+		const TReal hvx = h * v.x;
+		const TReal hvz = h * v.z;
+		const TReal hvxy = hvx * v.y;
+		const TReal hvxz = hvx * v.z;
+		const TReal hvyz = hvz * v.y;
 		mtx[0][0] = e + hvx * v.x;
 		mtx[0][1] = hvxy - v.z;
 		mtx[0][2] = hvxz + v.y;

+ 67 - 69
include/aiMatrix4x4.h

@@ -44,81 +44,71 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef AI_MATRIX4X4_H_INC
 #define AI_MATRIX4X4_H_INC
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+#include "./Compiler/pushpack1.h"
 
-struct aiMatrix3x3;
-struct aiQuaternion;
+#ifdef __cplusplus
 
-#include "./Compiler/pushpack1.h"
+template<typename TReal> class aiMatrix3x3t;
+template<typename TReal> class aiQuaterniont;
 
 // ---------------------------------------------------------------------------
 /** @brief Represents a row-major 4x4 matrix, use this for homogeneous
  *   coordinates.
  *
- *  There's much confusion about matrix layouts (colum vs. row order). 
- *  This is *always* a row-major matrix. Even with the
- *  aiProcess_ConvertToLeftHanded flag.
+ *  There's much confusion about matrix layouts (column vs. row order). 
+ *  This is *always* a row-major matrix. Not even with the
+ *  #aiProcess_ConvertToLeftHanded flag, which absolutely does not affect
+ *  matrix order - it just affects the handedness of the coordinate system
+ *  defined thereby.
  */
-struct aiMatrix4x4
+template<typename TReal>
+class aiMatrix4x4t
 {
-#ifdef __cplusplus
+public:
+	
+	/** set to identity */
+	aiMatrix4x4t ();
 
-		// default c'tor, init to zero
-	aiMatrix4x4 () :	
-		a1(1.0f), a2(0.0f), a3(0.0f), a4(0.0f), 
-		b1(0.0f), b2(1.0f), b3(0.0f), b4(0.0f), 
-		c1(0.0f), c2(0.0f), c3(1.0f), c4(0.0f),
-		d1(0.0f), d2(0.0f), d3(0.0f), d4(1.0f)
-	{}
-
-		// from single values
-	aiMatrix4x4 (	float _a1, float _a2, float _a3, float _a4,
-					float _b1, float _b2, float _b3, float _b4,
-					float _c1, float _c2, float _c3, float _c4,
-					float _d1, float _d2, float _d3, float _d4) :	
-		a1(_a1), a2(_a2), a3(_a3), a4(_a4),  
-		b1(_b1), b2(_b2), b3(_b3), b4(_b4), 
-		c1(_c1), c2(_c2), c3(_c3), c4(_c4),
-		d1(_d1), d2(_d2), d3(_d3), d4(_d4)
-	{}
+	/** construction from single values */
+	aiMatrix4x4t (	TReal _a1, TReal _a2, TReal _a3, TReal _a4,
+					TReal _b1, TReal _b2, TReal _b3, TReal _b4,
+					TReal _c1, TReal _c2, TReal _c3, TReal _c4,
+					TReal _d1, TReal _d2, TReal _d3, TReal _d4);
 
 
-	// -------------------------------------------------------------------
-	/** @brief Constructor from 3x3 matrix. 
-	 *  The remaining elements are set to identity.
-	 */
-	explicit aiMatrix4x4( const aiMatrix3x3& m);
+	/** construction from 3x3 matrix, remaining elements are set to identity */
+	explicit aiMatrix4x4t( const aiMatrix3x3t<TReal>& m);
 
 public:
 
 	// array access operators
-	float* operator[]       (unsigned int p_iIndex);
-	const float* operator[] (unsigned int p_iIndex) const;
+	TReal* operator[]       (unsigned int p_iIndex);
+	const TReal* operator[] (unsigned int p_iIndex) const;
 
 	// comparison operators
-	bool operator== (const aiMatrix4x4 m) const;
-	bool operator!= (const aiMatrix4x4 m) const;
+	bool operator== (const aiMatrix4x4t m) const;
+	bool operator!= (const aiMatrix4x4t m) const;
+
+	// matrix multiplication. 
+	aiMatrix4x4t& operator *= (const aiMatrix4x4t& m);
+	aiMatrix4x4t  operator *  (const aiMatrix4x4t& m) const;
 
-	// Matrix multiplication. Not commutative.
-	aiMatrix4x4& operator *= (const aiMatrix4x4& m);
-	aiMatrix4x4  operator *  (const aiMatrix4x4& m) const;
+	template <typename TOther>
+	operator aiMatrix4x4t<TOther> () const;
 
 public:
 
 	// -------------------------------------------------------------------
-	/** @brief Transpose the matrix
-	 */
-	aiMatrix4x4& Transpose();
+	/** @brief Transpose the matrix */
+	aiMatrix4x4t& Transpose();
 
 	// -------------------------------------------------------------------
 	/** @brief Invert the matrix.
 	 *  If the matrix is not invertible all elements are set to qnan.
-	 *  Beware, use (f != f) to check whether a float f is qnan.
+	 *  Beware, use (f != f) to check whether a TReal f is qnan.
 	 */
-	aiMatrix4x4& Inverse();
-	float Determinant() const;
+	aiMatrix4x4t& Inverse();
+	TReal Determinant() const;
 
 
 	// -------------------------------------------------------------------
@@ -134,8 +124,8 @@ public:
 	 *   quaternion 
 	 *  @param position Receives the output position for the x,y,z axes
 	 */
-	void Decompose (aiVector3D& scaling, aiQuaternion& rotation,
-		aiVector3D& position) const;
+	void Decompose (aiVector3t<TReal>& scaling, aiQuaterniont<TReal>& rotation,
+		aiVector3t<TReal>& position) const;
 
 	// -------------------------------------------------------------------
 	/** @brief Decompose a trafo matrix with no scaling into its 
@@ -144,8 +134,8 @@ public:
 	 *    quaternion 
 	 *  @param position Receives the output position for the x,y,z axes
 	 */
-	void DecomposeNoScaling (aiQuaternion& rotation,
-		aiVector3D& position) const;
+	void DecomposeNoScaling (aiQuaterniont<TReal>& rotation,
+		aiVector3t<TReal>& position) const;
 
 
 	// -------------------------------------------------------------------
@@ -154,8 +144,8 @@ public:
 	 *  @param y Rotation angle for the y-axis, in radians
 	 *  @param z Rotation angle for the z-axis, in radians
 	 */
-	aiMatrix4x4& FromEulerAnglesXYZ(float x, float y, float z);
-	aiMatrix4x4& FromEulerAnglesXYZ(const aiVector3D& blubb);
+	aiMatrix4x4t& FromEulerAnglesXYZ(TReal x, TReal y, TReal z);
+	aiMatrix4x4t& FromEulerAnglesXYZ(const aiVector3t<TReal>& blubb);
 
 public:
 	// -------------------------------------------------------------------
@@ -164,7 +154,7 @@ public:
 	 *  @param out Receives the output matrix
 	 *  @return Reference to the output matrix
 	 */
-	static aiMatrix4x4& RotationX(float a, aiMatrix4x4& out);
+	static aiMatrix4x4t& RotationX(TReal a, aiMatrix4x4t& out);
 
 	// -------------------------------------------------------------------
 	/** @brief Returns a rotation matrix for a rotation around the y axis
@@ -172,7 +162,7 @@ public:
 	 *  @param out Receives the output matrix
 	 *  @return Reference to the output matrix
 	 */
-	static aiMatrix4x4& RotationY(float a, aiMatrix4x4& out);
+	static aiMatrix4x4t& RotationY(TReal a, aiMatrix4x4t& out);
 
 	// -------------------------------------------------------------------
 	/** @brief Returns a rotation matrix for a rotation around the z axis
@@ -180,7 +170,7 @@ public:
 	 *  @param out Receives the output matrix
 	 *  @return Reference to the output matrix
 	 */
-	static aiMatrix4x4& RotationZ(float a, aiMatrix4x4& out);
+	static aiMatrix4x4t& RotationZ(TReal a, aiMatrix4x4t& out);
 
 	// -------------------------------------------------------------------
 	/** Returns a rotation matrix for a rotation around an arbitrary axis.
@@ -189,8 +179,8 @@ public:
 	 *  @param out Receives the output matrix
 	 *  @return Reference to the output matrix
 	 */
-	static aiMatrix4x4& Rotation(float a, const aiVector3D& axis, 
-		aiMatrix4x4& out);
+	static aiMatrix4x4t& Rotation(TReal a, const aiVector3t<TReal>& axis, 
+		aiMatrix4x4t& out);
 
 	// -------------------------------------------------------------------
 	/** @brief Returns a translation matrix 
@@ -198,7 +188,7 @@ public:
 	 *  @param out Receives the output matrix
 	 *  @return Reference to the output matrix
 	 */
-	static aiMatrix4x4& Translation( const aiVector3D& v, aiMatrix4x4& out);
+	static aiMatrix4x4t& Translation( const aiVector3t<TReal>& v, aiMatrix4x4t& out);
 
 	// -------------------------------------------------------------------
 	/** @brief Returns a scaling matrix 
@@ -206,7 +196,7 @@ public:
 	 *  @param out Receives the output matrix
 	 *  @return Reference to the output matrix
 	 */
-	static aiMatrix4x4& Scaling( const aiVector3D& v, aiMatrix4x4& out);
+	static aiMatrix4x4t& Scaling( const aiVector3t<TReal>& v, aiMatrix4x4t& out);
 
 	// -------------------------------------------------------------------
 	/** @brief A function for creating a rotation matrix that rotates a
@@ -217,24 +207,32 @@ public:
 	 *          "Efficiently Building a Matrix to Rotate One Vector to Another"
 	 *          Journal of Graphics Tools, 4(4):1-4, 1999
 	 */
-	static aiMatrix4x4& FromToMatrix(const aiVector3D& from, 
-		const aiVector3D& to, aiMatrix4x4& out);
+	static aiMatrix4x4t& FromToMatrix(const aiVector3t<TReal>& from, 
+		const aiVector3t<TReal>& to, aiMatrix4x4t& out);
 
-#endif // __cplusplus
+public:
+
+	TReal a1, a2, a3, a4;
+	TReal b1, b2, b3, b4;
+	TReal c1, c2, c3, c4;
+	TReal d1, d2, d3, d4;
+
+} PACK_STRUCT; 
+
+typedef aiMatrix4x4t<float> aiMatrix4x4;
+
+#else
 
+struct aiMatrix4x4 {
 	float a1, a2, a3, a4;
 	float b1, b2, b3, b4;
 	float c1, c2, c3, c4;
 	float d1, d2, d3, d4;
+};
 
-} PACK_STRUCT; // !class aiMatrix4x4
 
+#endif // __cplusplus
 
 #include "./Compiler/poppack1.h"
 
-#ifdef __cplusplus
-} // end extern "C"
-
-
-#endif // __cplusplus
 #endif // AI_MATRIX4X4_H_INC

+ 140 - 81
include/aiMatrix4x4.inl

@@ -39,37 +39,74 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ---------------------------------------------------------------------------
 */
 
-/** @file aiMatrix4x4.inl
+/** @file aiMatrix4x4t<TReal>.inl
  *  @brief Inline implementation of the 4x4 matrix operators
  */
 #ifndef AI_MATRIX4x4_INL_INC
 #define AI_MATRIX4x4_INL_INC
 
-#include "aiMatrix4x4.h"
-
 #ifdef __cplusplus
+
+#include "aiMatrix4x4.h"
 #include "aiMatrix3x3.h"
+#include "aiQuaternion.h"
 
 #include <algorithm>
 #include <limits>
 #include <math.h>
 
-#include "aiAssert.h"
-#include "aiQuaternion.h"
+// ----------------------------------------------------------------------------------------
+template <typename TReal>
+aiMatrix4x4t<TReal> ::aiMatrix4x4t () :	
+	a1(1.0f), a2(), a3(), a4(), 
+	b1(), b2(1.0f), b3(), b4(), 
+	c1(), c2(), c3(1.0f), c4(),
+	d1(), d2(), d3(), d4(1.0f)
+{
+
+}
+
+// ----------------------------------------------------------------------------------------
+template <typename TReal>
+aiMatrix4x4t<TReal> ::aiMatrix4x4t (TReal _a1, TReal _a2, TReal _a3, TReal _a4,
+			  TReal _b1, TReal _b2, TReal _b3, TReal _b4,
+			  TReal _c1, TReal _c2, TReal _c3, TReal _c4,
+			  TReal _d1, TReal _d2, TReal _d3, TReal _d4) :	
+	a1(_a1), a2(_a2), a3(_a3), a4(_a4),  
+	b1(_b1), b2(_b2), b3(_b3), b4(_b4), 
+	c1(_c1), c2(_c2), c3(_c3), c4(_c4),
+	d1(_d1), d2(_d2), d3(_d3), d4(_d4)
+{
+	
+}
+
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+template <typename TOther>
+aiMatrix4x4t<TReal>::operator aiMatrix4x4t<TOther> () const
+{
+	return aiMatrix4x4t<TOther>(static_cast<TOther>(a1),static_cast<TOther>(a2),static_cast<TOther>(a3),static_cast<TOther>(a4),
+		static_cast<TOther>(b1),static_cast<TOther>(b2),static_cast<TOther>(b3),static_cast<TOther>(b4),
+		static_cast<TOther>(c1),static_cast<TOther>(c2),static_cast<TOther>(c3),static_cast<TOther>(c4),
+		static_cast<TOther>(d1),static_cast<TOther>(d2),static_cast<TOther>(d3),static_cast<TOther>(d4));
+}
+
 
 // ----------------------------------------------------------------------------------------
-inline aiMatrix4x4::aiMatrix4x4( const aiMatrix3x3& m)
+template <typename TReal>
+inline aiMatrix4x4t<TReal>::aiMatrix4x4t (const aiMatrix3x3t<TReal>& m)
 {
-	a1 = m.a1; a2 = m.a2; a3 = m.a3; a4 = 0.0f;
-	b1 = m.b1; b2 = m.b2; b3 = m.b3; b4 = 0.0f;
-	c1 = m.c1; c2 = m.c2; c3 = m.c3; c4 = 0.0f;
-	d1 = 0.0f; d2 = 0.0f; d3 = 0.0f; d4 = 1.0f;
+	a1 = m.a1; a2 = m.a2; a3 = m.a3; a4 = static_cast<TReal>(0.0);
+	b1 = m.b1; b2 = m.b2; b3 = m.b3; b4 = static_cast<TReal>(0.0);
+	c1 = m.c1; c2 = m.c2; c3 = m.c3; c4 = static_cast<TReal>(0.0);
+	d1 = static_cast<TReal>(0.0); d2 = static_cast<TReal>(0.0); d3 = static_cast<TReal>(0.0); d4 = static_cast<TReal>(1.0);
 }
 
 // ----------------------------------------------------------------------------------------
-inline aiMatrix4x4& aiMatrix4x4::operator *= (const aiMatrix4x4& m)
+template <typename TReal>
+inline aiMatrix4x4t<TReal>& aiMatrix4x4t<TReal>::operator *= (const aiMatrix4x4t<TReal>& m)
 {
-	*this = aiMatrix4x4(
+	*this = aiMatrix4x4t<TReal>(
 		m.a1 * a1 + m.b1 * a2 + m.c1 * a3 + m.d1 * a4,
 		m.a2 * a1 + m.b2 * a2 + m.c2 * a3 + m.d2 * a4,
 		m.a3 * a1 + m.b3 * a2 + m.c3 * a3 + m.d3 * a4,
@@ -90,30 +127,33 @@ inline aiMatrix4x4& aiMatrix4x4::operator *= (const aiMatrix4x4& m)
 }
 
 // ----------------------------------------------------------------------------------------
-inline aiMatrix4x4 aiMatrix4x4::operator* (const aiMatrix4x4& m) const
+template <typename TReal>
+inline aiMatrix4x4t<TReal> aiMatrix4x4t<TReal>::operator* (const aiMatrix4x4t<TReal>& m) const
 {
-	aiMatrix4x4 temp( *this);
+	aiMatrix4x4t<TReal> temp( *this);
 	temp *= m;
 	return temp;
 }
 
 
 // ----------------------------------------------------------------------------------------
-inline aiMatrix4x4& aiMatrix4x4::Transpose()
+template <typename TReal>
+inline aiMatrix4x4t<TReal>& aiMatrix4x4t<TReal>::Transpose()
 {
-	// (float&) don't remove, GCC complains cause of packed fields
-	std::swap( (float&)b1, (float&)a2);
-	std::swap( (float&)c1, (float&)a3);
-	std::swap( (float&)c2, (float&)b3);
-	std::swap( (float&)d1, (float&)a4);
-	std::swap( (float&)d2, (float&)b4);
-	std::swap( (float&)d3, (float&)c4);
+	// (TReal&) don't remove, GCC complains cause of packed fields
+	std::swap( (TReal&)b1, (TReal&)a2);
+	std::swap( (TReal&)c1, (TReal&)a3);
+	std::swap( (TReal&)c2, (TReal&)b3);
+	std::swap( (TReal&)d1, (TReal&)a4);
+	std::swap( (TReal&)d2, (TReal&)b4);
+	std::swap( (TReal&)d3, (TReal&)c4);
 	return *this;
 }
 
 
 // ----------------------------------------------------------------------------------------
-inline float aiMatrix4x4::Determinant() const
+template <typename TReal>
+inline TReal aiMatrix4x4t<TReal>::Determinant() const
 {
 	return a1*b2*c3*d4 - a1*b2*c4*d3 + a1*b3*c4*d2 - a1*b3*c2*d4 
 		+ a1*b4*c2*d3 - a1*b4*c3*d2 - a2*b3*c4*d1 + a2*b3*c1*d4 
@@ -124,17 +164,18 @@ inline float aiMatrix4x4::Determinant() const
 }
 
 // ----------------------------------------------------------------------------------------
-inline aiMatrix4x4& aiMatrix4x4::Inverse()
+template <typename TReal>
+inline aiMatrix4x4t<TReal>& aiMatrix4x4t<TReal>::Inverse()
 {
 	// Compute the reciprocal determinant
-	float det = Determinant();
-	if(det == 0.0f) 
+	const TReal det = Determinant();
+	if(det == static_cast<TReal>(0.0)) 
 	{
 		// Matrix not invertible. Setting all elements to nan is not really
 		// correct in a mathematical sense but it is easy to debug for the
 		// programmer.
-		const float nan = std::numeric_limits<float>::quiet_NaN();
-		*this = aiMatrix4x4(
+		const TReal nan = std::numeric_limits<TReal>::quiet_NaN();
+		*this = aiMatrix4x4t<TReal>(
 			nan,nan,nan,nan,
 			nan,nan,nan,nan,
 			nan,nan,nan,nan,
@@ -143,9 +184,9 @@ inline aiMatrix4x4& aiMatrix4x4::Inverse()
 		return *this;
 	}
 
-	float invdet = 1.0f / det;
+	const TReal invdet = static_cast<TReal>(1.0) / det;
 
-	aiMatrix4x4 res;
+	aiMatrix4x4t<TReal> res;
 	res.a1 = invdet  * (b2 * (c3 * d4 - c4 * d3) + b3 * (c4 * d2 - c2 * d4) + b4 * (c2 * d3 - c3 * d2));
 	res.a2 = -invdet * (a2 * (c3 * d4 - c4 * d3) + a3 * (c4 * d2 - c2 * d4) + a4 * (c2 * d3 - c3 * d2));
 	res.a3 = invdet  * (a2 * (b3 * d4 - b4 * d3) + a3 * (b4 * d2 - b2 * d4) + a4 * (b2 * d3 - b3 * d2));
@@ -168,19 +209,24 @@ inline aiMatrix4x4& aiMatrix4x4::Inverse()
 }
 
 // ----------------------------------------------------------------------------------------
-inline float* aiMatrix4x4::operator[](unsigned int p_iIndex)
+template <typename TReal>
+inline TReal* aiMatrix4x4t<TReal>::operator[](unsigned int p_iIndex)
 {
+	// XXX this is UB. Has been for years. The fact that it works now does not make it better.
 	return &this->a1 + p_iIndex * 4;
 }
 
 // ----------------------------------------------------------------------------------------
-inline const float* aiMatrix4x4::operator[](unsigned int p_iIndex) const
+template <typename TReal>
+inline const TReal* aiMatrix4x4t<TReal>::operator[](unsigned int p_iIndex) const
 {
+	// XXX same
 	return &this->a1 + p_iIndex * 4;
 }
 
 // ----------------------------------------------------------------------------------------
-inline bool aiMatrix4x4::operator== (const aiMatrix4x4 m) const
+template <typename TReal>
+inline bool aiMatrix4x4t<TReal>::operator== (const aiMatrix4x4t<TReal> m) const
 {
 	return (a1 == m.a1 && a2 == m.a2 && a3 == m.a3 && a4 == m.a4 &&
 			b1 == m.b1 && b2 == m.b2 && b3 == m.b3 && b4 == m.b4 &&
@@ -189,16 +235,18 @@ inline bool aiMatrix4x4::operator== (const aiMatrix4x4 m) const
 }
 
 // ----------------------------------------------------------------------------------------
-inline bool aiMatrix4x4::operator!= (const aiMatrix4x4 m) const
+template <typename TReal>
+inline bool aiMatrix4x4t<TReal>::operator!= (const aiMatrix4x4t<TReal> m) const
 {
 	return !(*this == m);
 }
 
 // ----------------------------------------------------------------------------------------
-inline void aiMatrix4x4::Decompose (aiVector3D& scaling, aiQuaternion& rotation,
-	aiVector3D& position) const
+template <typename TReal>
+inline void aiMatrix4x4t<TReal>::Decompose (aiVector3t<TReal>& scaling, aiQuaterniont<TReal>& rotation,
+	aiVector3t<TReal>& position) const
 {
-	const aiMatrix4x4& _this = *this;
+	const aiMatrix4x4t<TReal>& _this = *this;
 
 	// extract translation
 	position.x = _this[0][3];
@@ -206,10 +254,10 @@ inline void aiMatrix4x4::Decompose (aiVector3D& scaling, aiQuaternion& rotation,
 	position.z = _this[2][3];
 
 	// extract the rows of the matrix
-	aiVector3D vRows[3] = {
-		aiVector3D(_this[0][0],_this[1][0],_this[2][0]),
-		aiVector3D(_this[0][1],_this[1][1],_this[2][1]),
-		aiVector3D(_this[0][2],_this[1][2],_this[2][2])
+	aiVector3t<TReal> vRows[3] = {
+		aiVector3t<TReal>(_this[0][0],_this[1][0],_this[2][0]),
+		aiVector3t<TReal>(_this[0][1],_this[1][1],_this[2][1]),
+		aiVector3t<TReal>(_this[0][2],_this[1][2],_this[2][2])
 	};
 
 	// extract the scaling factors
@@ -239,19 +287,20 @@ inline void aiMatrix4x4::Decompose (aiVector3D& scaling, aiQuaternion& rotation,
 	}
 
 	// build a 3x3 rotation matrix
-	aiMatrix3x3 m(vRows[0].x,vRows[1].x,vRows[2].x,
+	aiMatrix3x3t<TReal> m(vRows[0].x,vRows[1].x,vRows[2].x,
 		vRows[0].y,vRows[1].y,vRows[2].y,
 		vRows[0].z,vRows[1].z,vRows[2].z);
 
 	// and generate the rotation quaternion from it
-	rotation = aiQuaternion(m);
+	rotation = aiQuaterniont<TReal>(m);
 }
 
 // ----------------------------------------------------------------------------------------
-inline void aiMatrix4x4::DecomposeNoScaling (aiQuaternion& rotation,
-	aiVector3D& position) const
+template <typename TReal>
+inline void aiMatrix4x4t<TReal>::DecomposeNoScaling (aiQuaterniont<TReal>& rotation,
+	aiVector3t<TReal>& position) const
 {
-	const aiMatrix4x4& _this = *this;
+	const aiMatrix4x4t<TReal>& _this = *this;
 
 	// extract translation
 	position.x = _this[0][3];
@@ -259,33 +308,35 @@ inline void aiMatrix4x4::DecomposeNoScaling (aiQuaternion& rotation,
 	position.z = _this[2][3];
 
 	// extract rotation
-	rotation = aiQuaternion((aiMatrix3x3)_this);
+	rotation = aiQuaterniont<TReal>((aiMatrix3x3t<TReal>)_this);
 }
 
 // ----------------------------------------------------------------------------------------
-inline aiMatrix4x4& aiMatrix4x4::FromEulerAnglesXYZ(const aiVector3D& blubb)
+template <typename TReal>
+inline aiMatrix4x4t<TReal>& aiMatrix4x4t<TReal>::FromEulerAnglesXYZ(const aiVector3t<TReal>& blubb)
 {
 	return FromEulerAnglesXYZ(blubb.x,blubb.y,blubb.z);
 }
 
 // ----------------------------------------------------------------------------------------
-inline aiMatrix4x4& aiMatrix4x4::FromEulerAnglesXYZ(float x, float y, float z)
+template <typename TReal>
+inline aiMatrix4x4t<TReal>& aiMatrix4x4t<TReal>::FromEulerAnglesXYZ(TReal x, TReal y, TReal z)
 {
-	aiMatrix4x4& _this = *this;
+	aiMatrix4x4t<TReal>& _this = *this;
 
-	float cr = cos( x );
-	float sr = sin( x );
-	float cp = cos( y );
-	float sp = sin( y );
-	float cy = cos( z );
-	float sy = sin( z );
+	TReal cr = cos( x );
+	TReal sr = sin( x );
+	TReal cp = cos( y );
+	TReal sp = sin( y );
+	TReal cy = cos( z );
+	TReal sy = sin( z );
 
 	_this.a1 = cp*cy ;
 	_this.a2 = cp*sy;
 	_this.a3 = -sp ;
 
-	float srsp = sr*sp;
-	float crsp = cr*sp;
+	TReal srsp = sr*sp;
+	TReal crsp = cr*sp;
 
 	_this.b1 = srsp*cy-cr*sy ;
 	_this.b2 = srsp*sy+cr*cy ;
@@ -299,10 +350,11 @@ inline aiMatrix4x4& aiMatrix4x4::FromEulerAnglesXYZ(float x, float y, float z)
 }
 
 // ----------------------------------------------------------------------------------------
-inline bool aiMatrix4x4::IsIdentity() const
+template <typename TReal>
+inline bool aiMatrix4x4t<TReal>::IsIdentity() const
 {
 	// Use a small epsilon to solve floating-point inaccuracies
-	const static float epsilon = 10e-3f;
+	const static TReal epsilon = 10e-3f;
 
 	return (a2 <= epsilon && a2 >= -epsilon &&
 			a3 <= epsilon && a3 >= -epsilon &&
@@ -323,21 +375,23 @@ inline bool aiMatrix4x4::IsIdentity() const
 }
 
 // ----------------------------------------------------------------------------------------
-inline aiMatrix4x4& aiMatrix4x4::RotationX(float a, aiMatrix4x4& out)
+template <typename TReal>
+inline aiMatrix4x4t<TReal>& aiMatrix4x4t<TReal>::RotationX(TReal a, aiMatrix4x4t<TReal>& out)
 {
 	/*
 	     |  1  0       0       0 |
      M = |  0  cos(A) -sin(A)  0 |
          |  0  sin(A)  cos(A)  0 |
          |  0  0       0       1 |	*/
-	out = aiMatrix4x4();
+	out = aiMatrix4x4t<TReal>();
 	out.b2 = out.c3 = cos(a);
 	out.b3 = -(out.c2 = sin(a));
 	return out;
 }
 
 // ----------------------------------------------------------------------------------------
-inline aiMatrix4x4& aiMatrix4x4::RotationY(float a, aiMatrix4x4& out)
+template <typename TReal>
+inline aiMatrix4x4t<TReal>& aiMatrix4x4t<TReal>::RotationY(TReal a, aiMatrix4x4t<TReal>& out)
 {
 	/*
 	     |  cos(A)  0   sin(A)  0 |
@@ -345,21 +399,22 @@ inline aiMatrix4x4& aiMatrix4x4::RotationY(float a, aiMatrix4x4& out)
          | -sin(A)  0   cos(A)  0 |
          |  0       0   0       1 |
 		*/
-	out = aiMatrix4x4();
+	out = aiMatrix4x4t<TReal>();
 	out.a1 = out.c3 = cos(a);
 	out.c1 = -(out.a3 = sin(a));
 	return out;
 }
 
 // ----------------------------------------------------------------------------------------
-inline aiMatrix4x4& aiMatrix4x4::RotationZ(float a, aiMatrix4x4& out)
+template <typename TReal>
+inline aiMatrix4x4t<TReal>& aiMatrix4x4t<TReal>::RotationZ(TReal a, aiMatrix4x4t<TReal>& out)
 {
 	/*
 	     |  cos(A)  -sin(A)   0   0 |
      M = |  sin(A)   cos(A)   0   0 |
          |  0        0        1   0 |
          |  0        0        0   1 |	*/
-	out = aiMatrix4x4();
+	out = aiMatrix4x4t<TReal>();
 	out.a1 = out.b2 = cos(a);
 	out.a2 = -(out.b1 = sin(a));
 	return out;
@@ -367,26 +422,28 @@ inline aiMatrix4x4& aiMatrix4x4::RotationZ(float a, aiMatrix4x4& out)
 
 // ----------------------------------------------------------------------------------------
 // Returns a rotation matrix for a rotation around an arbitrary axis.
-inline aiMatrix4x4& aiMatrix4x4::Rotation( float a, const aiVector3D& axis, aiMatrix4x4& out)
+template <typename TReal>
+inline aiMatrix4x4t<TReal>& aiMatrix4x4t<TReal>::Rotation( TReal a, const aiVector3t<TReal>& axis, aiMatrix4x4t<TReal>& out)
 {
-  float c = cos( a), s = sin( a), t = 1 - c;
-  float x = axis.x, y = axis.y, z = axis.z;
+  TReal c = cos( a), s = sin( a), t = 1 - c;
+  TReal 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;
+  out.a4 = out.b4 = out.c4 = static_cast<TReal>(0.0);
+  out.d1 = out.d2 = out.d3 = static_cast<TReal>(0.0);
+  out.d4 = static_cast<TReal>(1.0);
 
   return out;
 }
 
 // ----------------------------------------------------------------------------------------
-inline aiMatrix4x4& aiMatrix4x4::Translation( const aiVector3D& v, aiMatrix4x4& out)
+template <typename TReal>
+inline aiMatrix4x4t<TReal>& aiMatrix4x4t<TReal>::Translation( const aiVector3t<TReal>& v, aiMatrix4x4t<TReal>& out)
 {
-	out = aiMatrix4x4();
+	out = aiMatrix4x4t<TReal>();
 	out.a4 = v.x;
 	out.b4 = v.y;
 	out.c4 = v.z;
@@ -394,9 +451,10 @@ inline aiMatrix4x4& aiMatrix4x4::Translation( const aiVector3D& v, aiMatrix4x4&
 }
 
 // ----------------------------------------------------------------------------------------
-inline aiMatrix4x4& aiMatrix4x4::Scaling( const aiVector3D& v, aiMatrix4x4& out)
+template <typename TReal>
+inline aiMatrix4x4t<TReal>& aiMatrix4x4t<TReal>::Scaling( const aiVector3t<TReal>& v, aiMatrix4x4t<TReal>& out)
 {
-	out = aiMatrix4x4();
+	out = aiMatrix4x4t<TReal>();
 	out.a1 = v.x;
 	out.b2 = v.y;
 	out.c3 = v.z;
@@ -413,12 +471,13 @@ inline aiMatrix4x4& aiMatrix4x4::Scaling( const aiVector3D& v, aiMatrix4x4& out)
  *          Journal of Graphics Tools, 4(4):1-4, 1999
  */
 // ----------------------------------------------------------------------------------------
-inline aiMatrix4x4& aiMatrix4x4::FromToMatrix(const aiVector3D& from, 
-	const aiVector3D& to, aiMatrix4x4& mtx)
+template <typename TReal>
+inline aiMatrix4x4t<TReal>& aiMatrix4x4t<TReal>::FromToMatrix(const aiVector3t<TReal>& from, 
+	const aiVector3t<TReal>& to, aiMatrix4x4t<TReal>& mtx)
 {	
-	aiMatrix3x3 m3;
-	aiMatrix3x3::FromToMatrix(from,to,m3);
-	mtx = aiMatrix4x4(m3);
+	aiMatrix3x3t<TReal> m3;
+	aiMatrix3x3t<TReal>::FromToMatrix(from,to,m3);
+	mtx = aiMatrix4x4t<TReal>(m3);
 	return mtx;
 }
 

+ 34 - 222
include/aiQuaternion.h

@@ -44,54 +44,56 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef AI_QUATERNION_H_INC
 #define AI_QUATERNION_H_INC
 
-#include <math.h>
-#include "aiTypes.h"
-
 #ifdef __cplusplus
-extern "C" {
-#endif
+
+template <typename TReal> class aiVector3t;
+template <typename TReal> class aiMatrix3x3t;
 
 // ---------------------------------------------------------------------------
 /** Represents a quaternion in a 4D vector. */
-struct aiQuaternion
+template <typename TReal>
+class aiQuaterniont
 {
-#ifdef __cplusplus
-	aiQuaternion() : w(0.0f), x(0.0f), y(0.0f), z(0.0f) {}
-	aiQuaternion(float _w, float _x, float _y, float _z) : w(_w), x(_x), y(_y), z(_z) {}
+public:
+	aiQuaterniont() : w(), x(), y(), z() {}
+	aiQuaterniont(TReal w, TReal x, TReal y, TReal z) 
+		: w(w), x(x), y(y), z(z) {}
 
 	/** Construct from rotation matrix. Result is undefined if the matrix is not orthonormal. */
-	aiQuaternion( const aiMatrix3x3& pRotMatrix);
+	aiQuaterniont( const aiMatrix3x3t<TReal>& pRotMatrix);
 
 	/** Construct from euler angles */
-	aiQuaternion( float rotx, float roty, float rotz);
+	aiQuaterniont( TReal rotx, TReal roty, TReal rotz);
 
 	/** Construct from an axis-angle pair */
-	aiQuaternion( aiVector3D axis, float angle);
+	aiQuaterniont( aiVector3t<TReal> axis, TReal angle);
 
 	/** Construct from a normalized quaternion stored in a vec3 */
-	aiQuaternion( aiVector3D normalized);
+	aiQuaterniont( aiVector3t<TReal> normalized);
 
 	/** Returns a matrix representation of the quaternion */
-	aiMatrix3x3 GetMatrix() const;
+	aiMatrix3x3t<TReal> GetMatrix() const;
 
+public:
 
-	bool operator== (const aiQuaternion& o) const
-		{return x == o.x && y == o.y && z == o.z && w == o.w;}
+	bool operator== (const aiQuaterniont& o) const;
+	bool operator!= (const aiQuaterniont& o) const;
 
-	bool operator!= (const aiQuaternion& o) const
-		{return !(*this == o);}
+public:
 
 	/** Normalize the quaternion */
-	aiQuaternion& Normalize();
+	aiQuaterniont& Normalize();
 
 	/** Compute quaternion conjugate */
-	aiQuaternion& Conjugate ();
+	aiQuaterniont& Conjugate ();
 
 	/** Rotate a point by this quaternion */
-	aiVector3D Rotate (const aiVector3D& in);
+	aiVector3t<TReal> Rotate (const aiVector3t<TReal>& in);
 
 	/** Multiply two quaternions */
-	aiQuaternion operator* (const aiQuaternion& two) const;
+	aiQuaterniont operator* (const aiQuaterniont& two) const;
+
+public:
 
 	/** Performs a spherical interpolation between two quaternions and writes the result into the third.
 	 * @param pOut Target object to received the interpolated rotation.
@@ -99,214 +101,24 @@ struct aiQuaternion
 	 * @param pEnd End rotation, factor == 1.
 	 * @param pFactor Interpolation factor between 0 and 1. Values outside of this range yield undefined results.
 	 */
-	static void Interpolate( aiQuaternion& pOut, const aiQuaternion& pStart, const aiQuaternion& pEnd, float pFactor);
+	static void Interpolate( aiQuaterniont& pOut, const aiQuaterniont& pStart, 
+		const aiQuaterniont& pEnd, TReal pFactor);
 
-#endif // __cplusplus
+public:
 
 	//! w,x,y,z components of the quaternion
-	float w, x, y, z;	
+	TReal w, x, y, z;	
 } ;
 
+typedef aiQuaterniont<float> aiQuaternion;
 
-#ifdef __cplusplus
-
-// ---------------------------------------------------------------------------
-// Constructs a quaternion from a rotation matrix
-inline aiQuaternion::aiQuaternion( const aiMatrix3x3 &pRotMatrix)
-{
-	float t = 1 + pRotMatrix.a1 + pRotMatrix.b2 + pRotMatrix.c3;
-
-	// large enough
-	if( t > 0.001f)
-	{
-		float s = sqrt( t) * 2.0f;
-		x = (pRotMatrix.c2 - pRotMatrix.b3) / s;
-		y = (pRotMatrix.a3 - pRotMatrix.c1) / s;
-		z = (pRotMatrix.b1 - pRotMatrix.a2) / s;
-		w = 0.25f * s;
-	} // else we have to check several cases
-	else if( pRotMatrix.a1 > pRotMatrix.b2 && pRotMatrix.a1 > pRotMatrix.c3 )  
-	{	
-    // Column 0: 
-		float s = sqrt( 1.0f + pRotMatrix.a1 - pRotMatrix.b2 - pRotMatrix.c3) * 2.0f;
-		x = 0.25f * s;
-		y = (pRotMatrix.b1 + pRotMatrix.a2) / s;
-		z = (pRotMatrix.a3 + pRotMatrix.c1) / s;
-		w = (pRotMatrix.c2 - pRotMatrix.b3) / s;
-	} 
-	else if( pRotMatrix.b2 > pRotMatrix.c3) 
-	{ 
-    // Column 1: 
-		float s = sqrt( 1.0f + pRotMatrix.b2 - pRotMatrix.a1 - pRotMatrix.c3) * 2.0f;
-		x = (pRotMatrix.b1 + pRotMatrix.a2) / s;
-		y = 0.25f * s;
-		z = (pRotMatrix.c2 + pRotMatrix.b3) / s;
-		w = (pRotMatrix.a3 - pRotMatrix.c1) / s;
-	} else 
-	{ 
-    // Column 2:
-		float s = sqrt( 1.0f + pRotMatrix.c3 - pRotMatrix.a1 - pRotMatrix.b2) * 2.0f;
-		x = (pRotMatrix.a3 + pRotMatrix.c1) / s;
-		y = (pRotMatrix.c2 + pRotMatrix.b3) / s;
-		z = 0.25f * s;
-		w = (pRotMatrix.b1 - pRotMatrix.a2) / s;
-	}
-}
-
-// ---------------------------------------------------------------------------
-// Construction from euler angles
-inline aiQuaternion::aiQuaternion( float fPitch, float fYaw, float fRoll )
-{
-	const float fSinPitch(sin(fPitch*0.5F));
-	const float fCosPitch(cos(fPitch*0.5F));
-	const float fSinYaw(sin(fYaw*0.5F));
-	const float fCosYaw(cos(fYaw*0.5F));
-	const float fSinRoll(sin(fRoll*0.5F));
-	const float fCosRoll(cos(fRoll*0.5F));
-	const float fCosPitchCosYaw(fCosPitch*fCosYaw);
-	const float fSinPitchSinYaw(fSinPitch*fSinYaw);
-	x = fSinRoll * fCosPitchCosYaw     - fCosRoll * fSinPitchSinYaw;
-	y = fCosRoll * fSinPitch * fCosYaw + fSinRoll * fCosPitch * fSinYaw;
-	z = fCosRoll * fCosPitch * fSinYaw - fSinRoll * fSinPitch * fCosYaw;
-	w = fCosRoll * fCosPitchCosYaw     + fSinRoll * fSinPitchSinYaw;
-}
-
-// ---------------------------------------------------------------------------
-// Returns a matrix representation of the quaternion
-inline aiMatrix3x3 aiQuaternion::GetMatrix() const
-{
-	aiMatrix3x3 resMatrix;
-	resMatrix.a1 = 1.0f - 2.0f * (y * y + z * z);
-	resMatrix.a2 = 2.0f * (x * y - z * w);
-	resMatrix.a3 = 2.0f * (x * z + y * w);
-	resMatrix.b1 = 2.0f * (x * y + z * w);
-	resMatrix.b2 = 1.0f - 2.0f * (x * x + z * z);
-	resMatrix.b3 = 2.0f * (y * z - x * w);
-	resMatrix.c1 = 2.0f * (x * z - y * w);
-	resMatrix.c2 = 2.0f * (y * z + x * w);
-	resMatrix.c3 = 1.0f - 2.0f * (x * x + y * y);
-
-	return resMatrix;
-}
-
-// ---------------------------------------------------------------------------
-// Construction from an axis-angle pair
-inline aiQuaternion::aiQuaternion( aiVector3D axis, float angle)
-{
-	axis.Normalize();
-
-	const float sin_a = sin( angle / 2 );
-    const float cos_a = cos( angle / 2 );
-    x    = axis.x * sin_a;
-    y    = axis.y * sin_a;
-    z    = axis.z * sin_a;
-    w    = cos_a;
-}
-// ---------------------------------------------------------------------------
-// Construction from am existing, normalized quaternion
-inline aiQuaternion::aiQuaternion( aiVector3D normalized)
-{
-	x = normalized.x;
-	y = normalized.y;
-	z = normalized.z;
+#else
 
-	const float t = 1.0f - (x*x) - (y*y) - (z*z);
-
-	if (t < 0.0f)
-		w = 0.0f;
-	else w = sqrt (t);
-}
-
-// ---------------------------------------------------------------------------
-// Performs a spherical interpolation between two quaternions 
-// Implementation adopted from the gmtl project. All others I found on the net fail in some cases.
-// Congrats, gmtl!
-inline void aiQuaternion::Interpolate( aiQuaternion& pOut, const aiQuaternion& pStart, const aiQuaternion& pEnd, float pFactor)
-{
-  // calc cosine theta
-  float cosom = pStart.x * pEnd.x + pStart.y * pEnd.y + pStart.z * pEnd.z + pStart.w * pEnd.w;
-
-  // adjust signs (if necessary)
-  aiQuaternion end = pEnd;
-  if( cosom < 0.0f)
-  {
-    cosom = -cosom;
-    end.x = -end.x;   // Reverse all signs
-    end.y = -end.y;
-    end.z = -end.z;
-    end.w = -end.w;
-  } 
-
-  // Calculate coefficients
-  float sclp, sclq;
-  if( (1.0f - cosom) > 0.0001f) // 0.0001 -> some epsillon
-  {
-    // Standard case (slerp)
-    float omega, sinom;
-    omega = acos( cosom); // extract theta from dot product's cos theta
-    sinom = sin( omega);
-    sclp  = sin( (1.0f - pFactor) * omega) / sinom;
-    sclq  = sin( pFactor * omega) / sinom;
-  } else
-  {
-    // Very close, do linear interp (because it's faster)
-    sclp = 1.0f - pFactor;
-    sclq = pFactor;
-  }
-
-  pOut.x = sclp * pStart.x + sclq * end.x;
-  pOut.y = sclp * pStart.y + sclq * end.y;
-  pOut.z = sclp * pStart.z + sclq * end.z;
-  pOut.w = sclp * pStart.w + sclq * end.w;
-}
-
-// ---------------------------------------------------------------------------
-inline aiQuaternion& aiQuaternion::Normalize()
-{
-	// compute the magnitude and divide through it
-	const float mag = sqrt(x*x + y*y + z*z + w*w);
-	if (mag)
-	{
-		const float invMag = 1.0f/mag;
-		x *= invMag;
-		y *= invMag;
-		z *= invMag;
-		w *= invMag;
-	}
-	return *this;
-}
-
-// ---------------------------------------------------------------------------
-inline aiQuaternion aiQuaternion::operator* (const aiQuaternion& t) const
-{
-	return aiQuaternion(w*t.w - x*t.x - y*t.y - z*t.z,
-		w*t.x + x*t.w + y*t.z - z*t.y,
-		w*t.y + y*t.w + z*t.x - x*t.z,
-		w*t.z + z*t.w + x*t.y - y*t.x);
-}
-
-// ---------------------------------------------------------------------------
-inline aiQuaternion& aiQuaternion::Conjugate ()
-{
-	x = -x;
-	y = -y;
-	z = -z;
-	return *this;
-}
-
-// ---------------------------------------------------------------------------
-inline aiVector3D aiQuaternion::Rotate (const aiVector3D& v)
-{
-	aiQuaternion q2(0.f,v.x,v.y,v.z), q = *this, qinv = q;
-	q.Conjugate();
-
-	q = q*q2*qinv;
-	return aiVector3D(q.x,q.y,q.z);
-
-}
+struct aiQuaternion {
+	float w, x, y, z;	
+};
 
-} // end extern "C"
+#endif
 
-#endif // __cplusplus
 
 #endif // AI_QUATERNION_H_INC

+ 274 - 0
include/aiQuaternion.inl

@@ -0,0 +1,274 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2010, 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.
+---------------------------------------------------------------------------
+*/
+
+/** @file  aiQuaterniont.inl
+ *  @brief Inline implementation of aiQuaterniont<TReal> operators
+ */
+#ifndef AI_QUATERNION_INL_INC
+#define AI_QUATERNION_INL_INC
+
+#ifdef __cplusplus
+#include "aiQuaternion.h"
+
+// ---------------------------------------------------------------------------
+template<typename TReal>
+bool aiQuaterniont<TReal>::operator== (const aiQuaterniont& o) const
+{
+	return x == o.x && y == o.y && z == o.z && w == o.w;
+}
+
+// ---------------------------------------------------------------------------
+template<typename TReal>
+bool aiQuaterniont<TReal>::operator!= (const aiQuaterniont& o) const
+{
+	return !(*this == o);
+}
+
+
+
+// ---------------------------------------------------------------------------
+// Constructs a quaternion from a rotation matrix
+template<typename TReal>
+inline aiQuaterniont<TReal>::aiQuaterniont( const aiMatrix3x3t<TReal> &pRotMatrix)
+{
+	TReal t = 1 + pRotMatrix.a1 + pRotMatrix.b2 + pRotMatrix.c3;
+
+	// large enough
+	if( t > static_cast<TReal>(0.001))
+	{
+		TReal s = sqrt( t) * static_cast<TReal>(2.0);
+		x = (pRotMatrix.c2 - pRotMatrix.b3) / s;
+		y = (pRotMatrix.a3 - pRotMatrix.c1) / s;
+		z = (pRotMatrix.b1 - pRotMatrix.a2) / s;
+		w = static_cast<TReal>(0.25) * s;
+	} // else we have to check several cases
+	else if( pRotMatrix.a1 > pRotMatrix.b2 && pRotMatrix.a1 > pRotMatrix.c3 )  
+	{	
+		// Column 0: 
+		TReal s = sqrt( static_cast<TReal>(1.0) + pRotMatrix.a1 - pRotMatrix.b2 - pRotMatrix.c3) * static_cast<TReal>(2.0);
+		x = static_cast<TReal>(0.25) * s;
+		y = (pRotMatrix.b1 + pRotMatrix.a2) / s;
+		z = (pRotMatrix.a3 + pRotMatrix.c1) / s;
+		w = (pRotMatrix.c2 - pRotMatrix.b3) / s;
+	} 
+	else if( pRotMatrix.b2 > pRotMatrix.c3) 
+	{ 
+		// Column 1: 
+		TReal s = sqrt( static_cast<TReal>(1.0) + pRotMatrix.b2 - pRotMatrix.a1 - pRotMatrix.c3) * static_cast<TReal>(2.0);
+		x = (pRotMatrix.b1 + pRotMatrix.a2) / s;
+		y = static_cast<TReal>(0.25) * s;
+		z = (pRotMatrix.c2 + pRotMatrix.b3) / s;
+		w = (pRotMatrix.a3 - pRotMatrix.c1) / s;
+	} else 
+	{ 
+		// Column 2:
+		TReal s = sqrt( static_cast<TReal>(1.0) + pRotMatrix.c3 - pRotMatrix.a1 - pRotMatrix.b2) * static_cast<TReal>(2.0);
+		x = (pRotMatrix.a3 + pRotMatrix.c1) / s;
+		y = (pRotMatrix.c2 + pRotMatrix.b3) / s;
+		z = static_cast<TReal>(0.25) * s;
+		w = (pRotMatrix.b1 - pRotMatrix.a2) / s;
+	}
+}
+
+// ---------------------------------------------------------------------------
+// Construction from euler angles
+template<typename TReal>
+inline aiQuaterniont<TReal>::aiQuaterniont( TReal fPitch, TReal fYaw, TReal fRoll )
+{
+	const TReal fSinPitch(sin(fPitch*static_cast<TReal>(0.5)));
+	const TReal fCosPitch(cos(fPitch*static_cast<TReal>(0.5)));
+	const TReal fSinYaw(sin(fYaw*static_cast<TReal>(0.5)));
+	const TReal fCosYaw(cos(fYaw*static_cast<TReal>(0.5)));
+	const TReal fSinRoll(sin(fRoll*static_cast<TReal>(0.5)));
+	const TReal fCosRoll(cos(fRoll*static_cast<TReal>(0.5)));
+	const TReal fCosPitchCosYaw(fCosPitch*fCosYaw);
+	const TReal fSinPitchSinYaw(fSinPitch*fSinYaw);
+	x = fSinRoll * fCosPitchCosYaw     - fCosRoll * fSinPitchSinYaw;
+	y = fCosRoll * fSinPitch * fCosYaw + fSinRoll * fCosPitch * fSinYaw;
+	z = fCosRoll * fCosPitch * fSinYaw - fSinRoll * fSinPitch * fCosYaw;
+	w = fCosRoll * fCosPitchCosYaw     + fSinRoll * fSinPitchSinYaw;
+}
+
+// ---------------------------------------------------------------------------
+// Returns a matrix representation of the quaternion
+template<typename TReal>
+inline aiMatrix3x3t<TReal> aiQuaterniont<TReal>::GetMatrix() const
+{
+	aiMatrix3x3t<TReal> resMatrix;
+	resMatrix.a1 = static_cast<TReal>(1.0) - static_cast<TReal>(2.0) * (y * y + z * z);
+	resMatrix.a2 = static_cast<TReal>(2.0) * (x * y - z * w);
+	resMatrix.a3 = static_cast<TReal>(2.0) * (x * z + y * w);
+	resMatrix.b1 = static_cast<TReal>(2.0) * (x * y + z * w);
+	resMatrix.b2 = static_cast<TReal>(1.0) - static_cast<TReal>(2.0) * (x * x + z * z);
+	resMatrix.b3 = static_cast<TReal>(2.0) * (y * z - x * w);
+	resMatrix.c1 = static_cast<TReal>(2.0) * (x * z - y * w);
+	resMatrix.c2 = static_cast<TReal>(2.0) * (y * z + x * w);
+	resMatrix.c3 = static_cast<TReal>(1.0) - static_cast<TReal>(2.0) * (x * x + y * y);
+
+	return resMatrix;
+}
+
+// ---------------------------------------------------------------------------
+// Construction from an axis-angle pair
+template<typename TReal>
+inline aiQuaterniont<TReal>::aiQuaterniont( aiVector3t<TReal> axis, TReal angle)
+{
+	axis.Normalize();
+
+	const TReal sin_a = sin( angle / 2 );
+	const TReal cos_a = cos( angle / 2 );
+	x    = axis.x * sin_a;
+	y    = axis.y * sin_a;
+	z    = axis.z * sin_a;
+	w    = cos_a;
+}
+// ---------------------------------------------------------------------------
+// Construction from am existing, normalized quaternion
+template<typename TReal>
+inline aiQuaterniont<TReal>::aiQuaterniont( aiVector3t<TReal> normalized)
+{
+	x = normalized.x;
+	y = normalized.y;
+	z = normalized.z;
+
+	const TReal t = static_cast<TReal>(1.0) - (x*x) - (y*y) - (z*z);
+
+	if (t < static_cast<TReal>(0.0)) {
+		w = static_cast<TReal>(0.0);
+	}
+	else w = sqrt (t);
+}
+
+// ---------------------------------------------------------------------------
+// Performs a spherical interpolation between two quaternions 
+// Implementation adopted from the gmtl project. All others I found on the net fail in some cases.
+// Congrats, gmtl!
+template<typename TReal>
+inline void aiQuaterniont<TReal>::Interpolate( aiQuaterniont& pOut, const aiQuaterniont& pStart, const aiQuaterniont& pEnd, TReal pFactor)
+{
+	// calc cosine theta
+	TReal cosom = pStart.x * pEnd.x + pStart.y * pEnd.y + pStart.z * pEnd.z + pStart.w * pEnd.w;
+
+	// adjust signs (if necessary)
+	aiQuaterniont end = pEnd;
+	if( cosom < static_cast<TReal>(0.0))
+	{
+		cosom = -cosom;
+		end.x = -end.x;   // Reverse all signs
+		end.y = -end.y;
+		end.z = -end.z;
+		end.w = -end.w;
+	} 
+
+	// Calculate coefficients
+	TReal sclp, sclq;
+	if( (static_cast<TReal>(1.0) - cosom) > static_cast<TReal>(0.0001)) // 0.0001 -> some epsillon
+	{
+		// Standard case (slerp)
+		TReal omega, sinom;
+		omega = acos( cosom); // extract theta from dot product's cos theta
+		sinom = sin( omega);
+		sclp  = sin( (static_cast<TReal>(1.0) - pFactor) * omega) / sinom;
+		sclq  = sin( pFactor * omega) / sinom;
+	} else
+	{
+		// Very close, do linear interp (because it's faster)
+		sclp = static_cast<TReal>(1.0) - pFactor;
+		sclq = pFactor;
+	}
+
+	pOut.x = sclp * pStart.x + sclq * end.x;
+	pOut.y = sclp * pStart.y + sclq * end.y;
+	pOut.z = sclp * pStart.z + sclq * end.z;
+	pOut.w = sclp * pStart.w + sclq * end.w;
+}
+
+// ---------------------------------------------------------------------------
+template<typename TReal>
+inline aiQuaterniont<TReal>& aiQuaterniont<TReal>::Normalize()
+{
+	// compute the magnitude and divide through it
+	const TReal mag = sqrt(x*x + y*y + z*z + w*w);
+	if (mag)
+	{
+		const TReal invMag = static_cast<TReal>(1.0)/mag;
+		x *= invMag;
+		y *= invMag;
+		z *= invMag;
+		w *= invMag;
+	}
+	return *this;
+}
+
+// ---------------------------------------------------------------------------
+template<typename TReal>
+inline aiQuaterniont<TReal> aiQuaterniont<TReal>::operator* (const aiQuaterniont& t) const
+{
+	return aiQuaterniont(w*t.w - x*t.x - y*t.y - z*t.z,
+		w*t.x + x*t.w + y*t.z - z*t.y,
+		w*t.y + y*t.w + z*t.x - x*t.z,
+		w*t.z + z*t.w + x*t.y - y*t.x);
+}
+
+// ---------------------------------------------------------------------------
+template<typename TReal>
+inline aiQuaterniont<TReal>& aiQuaterniont<TReal>::Conjugate ()
+{
+	x = -x;
+	y = -y;
+	z = -z;
+	return *this;
+}
+
+// ---------------------------------------------------------------------------
+template<typename TReal>
+inline aiVector3t<TReal> aiQuaterniont<TReal>::Rotate (const aiVector3t<TReal>& v)
+{
+	aiQuaterniont q2(0.f,v.x,v.y,v.z), q = *this, qinv = q;
+	q.Conjugate();
+
+	q = q*q2*qinv;
+	return aiVector3t<TReal>(q.x,q.y,q.z);
+
+}
+
+#endif
+#endif

+ 0 - 1
include/aiTexture.h

@@ -168,7 +168,6 @@ struct aiTexture
 	//! @return true if the given string matches the format hint
 	bool CheckFormat(const char* s) const
 	{
-		ai_assert(s && !mHeight);
 		return (0 == ::strncmp(achFormatHint,s,3));
 	}
 

+ 3 - 1
include/aiTypes.h

@@ -489,9 +489,11 @@ struct aiMemoryInfo
 }
 #endif //!  __cplusplus
 
-// Include implementations
+// Include implementation files
+#include "aiVector2D.inl"
 #include "aiVector3D.inl"
 #include "aiColor4D.inl"
+#include "aiQuaternion.inl"
 #include "aiMatrix3x3.inl"
 #include "aiMatrix4x4.inl"
 #endif 

+ 39 - 119
include/aiVector2D.h

@@ -38,7 +38,7 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ---------------------------------------------------------------------------
 */
-/** @file aiVector2D.h
+/** @file aiVector2t.h
  *  @brief 2D vector structure, including operators when compiling in C++
  */
 #ifndef AI_VECTOR2D_H_INC
@@ -46,142 +46,62 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include <math.h>
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #include "./Compiler/pushpack1.h"
 
 // ----------------------------------------------------------------------------------
 /** Represents a two-dimensional vector. 
  */
-struct aiVector2D
-{
+
 #ifdef __cplusplus
-	aiVector2D () : x(0.0f), y(0.0f) {}
-	aiVector2D (float _x, float _y) : x(_x), y(_y) {}
-	aiVector2D (float _xyz) : x(_xyz), y(_xyz) {}
-	aiVector2D (const aiVector2D& o) : x(o.x), y(o.y) {}
-
-	void Set( float pX, float pY) { 
-		x = pX; y = pY;
-	}
-	
-	float SquareLength() const {
-		return x*x + y*y; 
-	}
-	
-	float Length() const {
-		return ::sqrt( SquareLength());
-	}
-
-	aiVector2D& Normalize() { 
-		*this /= Length(); return *this;
-	}
-
-	const aiVector2D& operator += (const aiVector2D& o) {
-		x += o.x; y += o.y;  return *this; 
-	}
-	const aiVector2D& operator -= (const aiVector2D& o) {
-		x -= o.x; y -= o.y;  return *this; 
-	}
-	const aiVector2D& operator *= (float f) { 
-		x *= f; y *= f;  return *this; 
-	}
-	const aiVector2D& operator /= (float f) {
-		x /= f; y /= f;  return *this; 
-	}
-
-	float operator[](unsigned int i) const {
-		return *(&x + i);
-	}
-
-	float& operator[](unsigned int i) {
-		return *(&x + i);
-	}
-
-	bool operator== (const aiVector2D& other) const {
-		return x == other.x && y == other.y;
-	}
-
-	bool operator!= (const aiVector2D& other) const {
-		return x != other.x || y != other.y;
-	}
-
-	aiVector2D& operator= (float f)	{
-		x = y = f;return *this;
-	}
-
-	const aiVector2D SymMul(const aiVector2D& o) {
-		return aiVector2D(x*o.x,y*o.y);
-	}
+template <typename TReal>
+class aiVector2t
+{
+public:
 
-#endif // __cplusplus
+	aiVector2t () : x(), y() {}
+	aiVector2t (TReal _x, TReal _y) : x(_x), y(_y) {}
+	explicit aiVector2t (TReal _xyz) : x(_xyz), y(_xyz) {}
+	aiVector2t (const aiVector2t& o) : x(o.x), y(o.y) {}
 
-	float x, y;	
-} PACK_STRUCT;
+public:
 
-#include "./Compiler/poppack1.h"
+	void Set( TReal pX, TReal pY);
+	TReal SquareLength() const ;
+	TReal Length() const ;
+	aiVector2t& Normalize();
 
-#ifdef __cplusplus
-} // end extern "C"
+public:
 
-// ----------------------------------------------------------------------------------
-// symmetric addition
-inline aiVector2D operator + (const aiVector2D& v1, const aiVector2D& v2)
-{
-	return aiVector2D( v1.x + v2.x, v1.y + v2.y);
-}
+	const aiVector2t& operator += (const aiVector2t& o);
+	const aiVector2t& operator -= (const aiVector2t& o);
+	const aiVector2t& operator *= (TReal f);
+	const aiVector2t& operator /= (TReal f);
 
-// ----------------------------------------------------------------------------------
-// symmetric subtraction
-inline aiVector2D operator - (const aiVector2D& v1, const aiVector2D& v2)
-{
-	return aiVector2D( v1.x - v2.x, v1.y - v2.y);
-}
+	TReal operator[](unsigned int i) const;
+	TReal& operator[](unsigned int i);
 
-// ----------------------------------------------------------------------------------
-// scalar product
-inline float operator * (const aiVector2D& v1, const aiVector2D& v2)
-{
-	return v1.x*v2.x + v1.y*v2.y;
-}
+	bool operator== (const aiVector2t& other) const;
+	bool operator!= (const aiVector2t& other) const;
 
-// ----------------------------------------------------------------------------------
-// scalar multiplication
-inline aiVector2D operator * ( float f, const aiVector2D& v)
-{
-	return aiVector2D( f*v.x, f*v.y);
-}
+	aiVector2t& operator= (TReal f);
+	const aiVector2t SymMul(const aiVector2t& o);
 
-// ----------------------------------------------------------------------------------
-// and the other way around
-inline aiVector2D operator * ( const aiVector2D& v, float f)
-{
-	return aiVector2D( f*v.x, f*v.y);
-}
+	template <typename TOther>
+	operator aiVector2t<TOther> () const;
 
-// ----------------------------------------------------------------------------------
-// scalar division
-inline aiVector2D operator / ( const aiVector2D& v, float f)
-{
-	
-	return v * (1/f);
-}
+	TReal x, y;	
+} PACK_STRUCT;
 
-// ----------------------------------------------------------------------------------
-// vector division
-inline aiVector2D operator / ( const aiVector2D& v, const aiVector2D& v2)
-{
-	return aiVector2D(v.x / v2.x,v.y / v2.y);
-}
+typedef aiVector2t<float> aiVector2D;
 
-// ----------------------------------------------------------------------------------
-// vector inversion
-inline aiVector2D operator - ( const aiVector2D& v)
-{
-	return aiVector2D( -v.x, -v.y);
-}
+#else
+
+struct aiVector2t {
+	TReal x,y;
+};
 
 #endif // __cplusplus
+
+#include "./Compiler/poppack1.h"
+
 #endif // AI_VECTOR2D_H_INC

+ 214 - 0
include/aiVector2D.inl

@@ -0,0 +1,214 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2010, 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.
+---------------------------------------------------------------------------
+*/
+
+/** @file  aiVector2D.inl
+ *  @brief Inline implementation of aiVector2t<TReal> operators
+ */
+#ifndef AI_VECTOR2D_INL_INC
+#define AI_VECTOR2D_INL_INC
+
+#ifdef __cplusplus
+#include "aiVector2D.h"
+
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+template <typename TOther>
+aiVector2t<TReal>::operator aiVector2t<TOther> () const {
+	return aiVector2t<TOther>(static_cast<TOther>(x),static_cast<TOther>(y));
+}
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+void aiVector2t<TReal>::Set( TReal pX, TReal pY) { 
+	x = pX; y = pY;
+}
+
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+TReal aiVector2t<TReal>::SquareLength() const {
+	return x*x + y*y; 
+}
+
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+TReal aiVector2t<TReal>::Length() const {
+	return ::sqrt( SquareLength());
+}
+
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+aiVector2t<TReal>& aiVector2t<TReal>::Normalize() { 
+	*this /= Length(); 
+	return *this;
+}
+
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+const aiVector2t<TReal>& aiVector2t<TReal>::operator += (const aiVector2t& o) {
+	x += o.x; y += o.y;  
+	return *this; 
+}
+
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+const aiVector2t<TReal>& aiVector2t<TReal>::operator -= (const aiVector2t& o) {
+	x -= o.x; y -= o.y;  
+	return *this; 
+}
+
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+const aiVector2t<TReal>& aiVector2t<TReal>::operator *= (TReal f) { 
+	x *= f; y *= f;  
+	return *this; 
+}
+
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+const aiVector2t<TReal>& aiVector2t<TReal>::operator /= (TReal f) {
+	x /= f; y /= f;  
+	return *this; 
+}
+
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+TReal aiVector2t<TReal>::operator[](unsigned int i) const {
+	return *(&x + i);
+}
+
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+TReal& aiVector2t<TReal>::operator[](unsigned int i) {
+	return *(&x + i);
+}
+
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+bool aiVector2t<TReal>::operator== (const aiVector2t& other) const {
+	return x == other.x && y == other.y;
+}
+
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+bool aiVector2t<TReal>::operator!= (const aiVector2t& other) const {
+	return x != other.x || y != other.y;
+}
+
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+aiVector2t<TReal>& aiVector2t<TReal>::operator= (TReal f)	{
+	x = y = f;
+	return *this;
+}
+
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+const aiVector2t<TReal> aiVector2t<TReal>::SymMul(const aiVector2t& o) {
+	return aiVector2t(x*o.x,y*o.y);
+}
+
+
+// ------------------------------------------------------------------------------------------------
+// symmetric addition
+template <typename TReal>
+inline aiVector2t<TReal> operator + (const aiVector2t<TReal>& v1, const aiVector2t<TReal>& v2)
+{
+	return aiVector2t<TReal>( v1.x + v2.x, v1.y + v2.y);
+}
+
+// ------------------------------------------------------------------------------------------------
+// symmetric subtraction
+template <typename TReal>
+inline aiVector2t<TReal> operator - (const aiVector2t<TReal>& v1, const aiVector2t<TReal>& v2)
+{
+	return aiVector2t<TReal>( v1.x - v2.x, v1.y - v2.y);
+}
+
+// ------------------------------------------------------------------------------------------------
+// scalar product
+template <typename TReal>
+inline TReal operator * (const aiVector2t<TReal>& v1, const aiVector2t<TReal>& v2)
+{
+	return v1.x*v2.x + v1.y*v2.y;
+}
+
+// ------------------------------------------------------------------------------------------------
+// scalar multiplication
+template <typename TReal>
+inline aiVector2t<TReal> operator * ( TReal f, const aiVector2t<TReal>& v)
+{
+	return aiVector2t<TReal>( f*v.x, f*v.y);
+}
+
+// ------------------------------------------------------------------------------------------------
+// and the other way around
+template <typename TReal>
+inline aiVector2t<TReal> operator * ( const aiVector2t<TReal>& v, TReal f)
+{
+	return aiVector2t<TReal>( f*v.x, f*v.y);
+}
+
+// ------------------------------------------------------------------------------------------------
+// scalar division
+template <typename TReal>
+inline aiVector2t<TReal> operator / ( const aiVector2t<TReal>& v, TReal f)
+{
+
+	return v * (1/f);
+}
+
+// ------------------------------------------------------------------------------------------------
+// vector division
+template <typename TReal>
+inline aiVector2t<TReal> operator / ( const aiVector2t<TReal>& v, const aiVector2t<TReal>& v2)
+{
+	return aiVector2t<TReal>(v.x / v2.x,v.y / v2.y);
+}
+
+// ------------------------------------------------------------------------------------------------
+// vector negation
+template <typename TReal>
+inline aiVector2t<TReal> operator - ( const aiVector2t<TReal>& v)
+{
+	return aiVector2t<TReal>( -v.x, -v.y);
+}
+
+#endif 
+#endif

+ 43 - 29
include/aiVector3D.h

@@ -46,44 +46,48 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include <math.h>
 
-#ifdef __cplusplus
-extern "C" {
-#endif
 
 #include "./Compiler/pushpack1.h"
 
-struct aiMatrix3x3;
-struct aiMatrix4x4;
+#ifdef __cplusplus
+
+template<typename TReal> class aiMatrix3x3t;
+template<typename TReal> class aiMatrix4x4t;
 
 // ---------------------------------------------------------------------------
 /** Represents a three-dimensional vector. */
-struct aiVector3D
+template <typename TReal>
+class aiVector3t 
 {
-#ifdef __cplusplus
-	aiVector3D () : x(0.0f), y(0.0f), z(0.0f) {}
-	aiVector3D (float _x, float _y, float _z) : x(_x), y(_y), z(_z) {}
-	aiVector3D (float _xyz) : x(_xyz), y(_xyz), z(_xyz) {}
-	aiVector3D (const aiVector3D& o) : x(o.x), y(o.y), z(o.z) {}
+public:
+
+	aiVector3t () : x(), y(), z() {}
+	aiVector3t (TReal _x, TReal _y, TReal _z) : x(_x), y(_y), z(_z) {}
+	explicit aiVector3t (TReal _xyz) : x(_xyz), y(_xyz), z(_xyz) {}
+	aiVector3t (const aiVector3t& o) : x(o.x), y(o.y), z(o.z) {}
 
 public:
 
 	// combined operators
-	const aiVector3D& operator += (const aiVector3D& o);
-	const aiVector3D& operator -= (const aiVector3D& o);
-	const aiVector3D& operator *= (float f);
-	const aiVector3D& operator /= (float f);
+	const aiVector3t& operator += (const aiVector3t& o);
+	const aiVector3t& operator -= (const aiVector3t& o);
+	const aiVector3t& operator *= (TReal f);
+	const aiVector3t& operator /= (TReal f);
 
 	// transform vector by matrix
-	aiVector3D& operator *= (const aiMatrix3x3& mat);
-	aiVector3D& operator *= (const aiMatrix4x4& mat);
+	aiVector3t& operator *= (const aiMatrix3x3t<TReal>& mat);
+	aiVector3t& operator *= (const aiMatrix4x4t<TReal>& mat);
 
 	// access a single element
-	float operator[](unsigned int i) const;
-	float& operator[](unsigned int i);
+	TReal operator[](unsigned int i) const;
+	TReal& operator[](unsigned int i);
 
 	// comparison
-	bool operator== (const aiVector3D& other) const;
-	bool operator!= (const aiVector3D& other) const;
+	bool operator== (const aiVector3t& other) const;
+	bool operator!= (const aiVector3t& other) const;
+
+	template <typename TOther>
+	operator aiVector3t<TOther> () const;
 
 public:
 
@@ -91,37 +95,47 @@ public:
 	 *  @param pX X component
 	 *  @param pY Y component
 	 *  @param pZ Z component  */
-	void Set( float pX, float pY, float pZ = 0.f);
+	void Set( TReal pX, TReal pY, TReal pZ);
 
 	/** @brief Get the squared length of the vector
 	 *  @return Square length */
-	float SquareLength() const;
+	TReal SquareLength() const;
 
 
 	/** @brief Get the length of the vector
 	 *  @return length */
-	float Length() const;
+	TReal Length() const;
 
 
 	/** @brief Normalize the vector */
-	aiVector3D& Normalize();
+	aiVector3t& Normalize();
 
 	
 	/** @brief Componentwise multiplication of two vectors
 	 *  
 	 *  Note that vec*vec yields the dot product.
 	 *  @param o Second factor */
-	const aiVector3D SymMul(const aiVector3D& o);
+	const aiVector3t SymMul(const aiVector3t& o);
 
-#endif // __cplusplus
+	TReal x, y, z;	
+} PACK_STRUCT;
+
+
+typedef aiVector3t<float> aiVector3D;
+
+#else
 
-	float x, y, z;	
+struct aiVector3D {
+
+	float x,y,y;
 } PACK_STRUCT;
 
+#endif // __cplusplus
+
 #include "./Compiler/poppack1.h"
 
 #ifdef __cplusplus
-} // end extern "C"
+
 
 
 #endif // __cplusplus

+ 71 - 39
include/aiVector3D.inl

@@ -40,19 +40,20 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 /** @file  aiVector3D.inl
- *  @brief Inline implementation of aiVector3D operators
+ *  @brief Inline implementation of aiVector3t<TReal> operators
  */
 #ifndef AI_VECTOR3D_INL_INC
 #define AI_VECTOR3D_INL_INC
 
-#include "aiVector3D.h"
 #ifdef __cplusplus
+#include "aiVector3D.h"
 
 // ------------------------------------------------------------------------------------------------
 /** Transformation of a vector by a 3x3 matrix */
-inline aiVector3D operator * (const aiMatrix3x3& pMatrix, const aiVector3D& pVector)
+template <typename TReal>
+inline aiVector3t<TReal> operator * (const aiMatrix3x3t<TReal>& pMatrix, const aiVector3t<TReal>& pVector)
 {
-	aiVector3D res;
+	aiVector3t<TReal> res;
 	res.x = pMatrix.a1 * pVector.x + pMatrix.a2 * pVector.y + pMatrix.a3 * pVector.z;
 	res.y = pMatrix.b1 * pVector.x + pMatrix.b2 * pVector.y + pMatrix.b3 * pVector.z;
 	res.z = pMatrix.c1 * pVector.x + pMatrix.c2 * pVector.y + pMatrix.c3 * pVector.z;
@@ -61,118 +62,149 @@ inline aiVector3D operator * (const aiMatrix3x3& pMatrix, const aiVector3D& pVec
 
 // ------------------------------------------------------------------------------------------------
 /** Transformation of a vector by a 4x4 matrix */
-inline aiVector3D operator * (const aiMatrix4x4& pMatrix, const aiVector3D& pVector)
+template <typename TReal>
+inline aiVector3t<TReal> operator * (const aiMatrix4x4t<TReal>& pMatrix, const aiVector3t<TReal>& pVector)
 {
-	aiVector3D res;
+	aiVector3t<TReal> res;
 	res.x = pMatrix.a1 * pVector.x + pMatrix.a2 * pVector.y + pMatrix.a3 * pVector.z + pMatrix.a4;
 	res.y = pMatrix.b1 * pVector.x + pMatrix.b2 * pVector.y + pMatrix.b3 * pVector.z + pMatrix.b4;
 	res.z = pMatrix.c1 * pVector.x + pMatrix.c2 * pVector.y + pMatrix.c3 * pVector.z + pMatrix.c4;
 	return res;
 }
 // ------------------------------------------------------------------------------------------------
-AI_FORCE_INLINE void aiVector3D::Set( float pX, float pY, float pZ) { 
+template <typename TReal>
+template <typename TOther>
+aiVector3t<TReal>::operator aiVector3t<TOther> () const {
+	return aiVector3t<TOther>(static_cast<TOther>(x),static_cast<TOther>(y),static_cast<TOther>(z));
+}
+// ------------------------------------------------------------------------------------------------
+template <typename TReal>
+AI_FORCE_INLINE void aiVector3t<TReal>::Set( TReal pX, TReal pY, TReal pZ) { 
 	x = pX; y = pY; z = pZ; 
 }
 // ------------------------------------------------------------------------------------------------
-AI_FORCE_INLINE float aiVector3D::SquareLength() const {
+template <typename TReal>
+AI_FORCE_INLINE TReal aiVector3t<TReal>::SquareLength() const {
 	return x*x + y*y + z*z; 
 }
 // ------------------------------------------------------------------------------------------------
-AI_FORCE_INLINE float aiVector3D::Length() const {
+template <typename TReal>
+AI_FORCE_INLINE TReal aiVector3t<TReal>::Length() const {
 	return sqrt( SquareLength()); 
 }
 // ------------------------------------------------------------------------------------------------
-AI_FORCE_INLINE aiVector3D& aiVector3D::Normalize() { 
+template <typename TReal>
+AI_FORCE_INLINE aiVector3t<TReal>& aiVector3t<TReal>::Normalize() { 
 	*this /= Length(); return *this;
 }
 // ------------------------------------------------------------------------------------------------
-AI_FORCE_INLINE const aiVector3D& aiVector3D::operator += (const aiVector3D& o) {
+template <typename TReal>
+AI_FORCE_INLINE const aiVector3t<TReal>& aiVector3t<TReal>::operator += (const aiVector3t<TReal>& o) {
 	x += o.x; y += o.y; z += o.z; return *this; 
 }
 // ------------------------------------------------------------------------------------------------
-AI_FORCE_INLINE const aiVector3D& aiVector3D::operator -= (const aiVector3D& o) {
+template <typename TReal>
+AI_FORCE_INLINE const aiVector3t<TReal>& aiVector3t<TReal>::operator -= (const aiVector3t<TReal>& o) {
 	x -= o.x; y -= o.y; z -= o.z; return *this;
 }
 // ------------------------------------------------------------------------------------------------
-AI_FORCE_INLINE const aiVector3D& aiVector3D::operator *= (float f) {
+template <typename TReal>
+AI_FORCE_INLINE const aiVector3t<TReal>& aiVector3t<TReal>::operator *= (TReal f) {
 	x *= f; y *= f; z *= f; return *this; 
 }
 // ------------------------------------------------------------------------------------------------
-AI_FORCE_INLINE const aiVector3D& aiVector3D::operator /= (float f) {
+template <typename TReal>
+AI_FORCE_INLINE const aiVector3t<TReal>& aiVector3t<TReal>::operator /= (TReal f) {
 	x /= f; y /= f; z /= f; return *this; 
 }
 // ------------------------------------------------------------------------------------------------
-AI_FORCE_INLINE aiVector3D& aiVector3D::operator *= (const aiMatrix3x3& mat){
+template <typename TReal>
+AI_FORCE_INLINE aiVector3t<TReal>& aiVector3t<TReal>::operator *= (const aiMatrix3x3t<TReal>& mat){
 	return(*this =  mat * (*this));
 }
 // ------------------------------------------------------------------------------------------------
-AI_FORCE_INLINE aiVector3D& aiVector3D::operator *= (const aiMatrix4x4& mat){
+template <typename TReal>
+AI_FORCE_INLINE aiVector3t<TReal>& aiVector3t<TReal>::operator *= (const aiMatrix4x4t<TReal>& mat){
 	return(*this = mat * (*this));
 }
 // ------------------------------------------------------------------------------------------------
-AI_FORCE_INLINE float aiVector3D::operator[](unsigned int i) const {
+template <typename TReal>
+AI_FORCE_INLINE TReal aiVector3t<TReal>::operator[](unsigned int i) const {
 	return *(&x + i);
 }
 // ------------------------------------------------------------------------------------------------
-AI_FORCE_INLINE float& aiVector3D::operator[](unsigned int i) {
+template <typename TReal>
+AI_FORCE_INLINE TReal& aiVector3t<TReal>::operator[](unsigned int i) {
 	return *(&x + i);
 }
 // ------------------------------------------------------------------------------------------------
-AI_FORCE_INLINE bool aiVector3D::operator== (const aiVector3D& other) const {
+template <typename TReal>
+AI_FORCE_INLINE bool aiVector3t<TReal>::operator== (const aiVector3t<TReal>& other) const {
 	return x == other.x && y == other.y && z == other.z;
 }
 // ------------------------------------------------------------------------------------------------
-AI_FORCE_INLINE bool aiVector3D::operator!= (const aiVector3D& other) const {
+template <typename TReal>
+AI_FORCE_INLINE bool aiVector3t<TReal>::operator!= (const aiVector3t<TReal>& other) const {
 	return x != other.x || y != other.y || z != other.z;
 }
 // ------------------------------------------------------------------------------------------------
-AI_FORCE_INLINE const aiVector3D aiVector3D::SymMul(const aiVector3D& o) {
-	return aiVector3D(x*o.x,y*o.y,z*o.z);
+template <typename TReal>
+AI_FORCE_INLINE const aiVector3t<TReal> aiVector3t<TReal>::SymMul(const aiVector3t<TReal>& o) {
+	return aiVector3t<TReal>(x*o.x,y*o.y,z*o.z);
 }
 // ------------------------------------------------------------------------------------------------
 // symmetric addition
-AI_FORCE_INLINE aiVector3D operator + (const aiVector3D& v1, const aiVector3D& v2)	{
-	return aiVector3D( v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
+template <typename TReal>
+AI_FORCE_INLINE aiVector3t<TReal> operator + (const aiVector3t<TReal>& v1, const aiVector3t<TReal>& v2)	{
+	return aiVector3t<TReal>( v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
 }
 // ------------------------------------------------------------------------------------------------
 // symmetric subtraction
-AI_FORCE_INLINE aiVector3D operator - (const aiVector3D& v1, const aiVector3D& v2)	{
-	return aiVector3D( v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
+template <typename TReal>
+AI_FORCE_INLINE aiVector3t<TReal> operator - (const aiVector3t<TReal>& v1, const aiVector3t<TReal>& v2)	{
+	return aiVector3t<TReal>( v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
 }
 // ------------------------------------------------------------------------------------------------
 // scalar product
-AI_FORCE_INLINE float operator * (const aiVector3D& v1, const aiVector3D& v2)	{
+template <typename TReal>
+AI_FORCE_INLINE TReal operator * (const aiVector3t<TReal>& v1, const aiVector3t<TReal>& v2)	{
 	return v1.x*v2.x + v1.y*v2.y + v1.z*v2.z;
 }
 // ------------------------------------------------------------------------------------------------
 // scalar multiplication
-AI_FORCE_INLINE aiVector3D operator * ( float f, const aiVector3D& v)	{
-	return aiVector3D( f*v.x, f*v.y, f*v.z);
+template <typename TReal>
+AI_FORCE_INLINE aiVector3t<TReal> operator * ( TReal f, const aiVector3t<TReal>& v)	{
+	return aiVector3t<TReal>( f*v.x, f*v.y, f*v.z);
 }
 // ------------------------------------------------------------------------------------------------
 // and the other way around
-AI_FORCE_INLINE  aiVector3D operator * ( const aiVector3D& v, float f)	{
-	return aiVector3D( f*v.x, f*v.y, f*v.z);
+template <typename TReal>
+AI_FORCE_INLINE  aiVector3t<TReal> operator * ( const aiVector3t<TReal>& v, TReal f)	{
+	return aiVector3t<TReal>( f*v.x, f*v.y, f*v.z);
 }
 // ------------------------------------------------------------------------------------------------
 // scalar division
-AI_FORCE_INLINE  aiVector3D operator / ( const aiVector3D& v, float f)	{
+template <typename TReal>
+AI_FORCE_INLINE  aiVector3t<TReal> operator / ( const aiVector3t<TReal>& v, TReal f)	{
 	return v * (1/f);
 }
 // ------------------------------------------------------------------------------------------------
 // vector division
-AI_FORCE_INLINE  aiVector3D operator / ( const aiVector3D& v, const aiVector3D& v2)	{
-	return aiVector3D(v.x / v2.x,v.y / v2.y,v.z / v2.z);
+template <typename TReal>
+AI_FORCE_INLINE  aiVector3t<TReal> operator / ( const aiVector3t<TReal>& v, const aiVector3t<TReal>& v2)	{
+	return aiVector3t<TReal>(v.x / v2.x,v.y / v2.y,v.z / v2.z);
 }
 // ------------------------------------------------------------------------------------------------
 // cross product
-AI_FORCE_INLINE  aiVector3D operator ^ ( const aiVector3D& v1, const aiVector3D& v2)	{
-	return aiVector3D( v1.y*v2.z - v1.z*v2.y, v1.z*v2.x - v1.x*v2.z, v1.x*v2.y - v1.y*v2.x);
+template <typename TReal>
+AI_FORCE_INLINE  aiVector3t<TReal> operator ^ ( const aiVector3t<TReal>& v1, const aiVector3t<TReal>& v2)	{
+	return aiVector3t<TReal>( v1.y*v2.z - v1.z*v2.y, v1.z*v2.x - v1.x*v2.z, v1.x*v2.y - v1.y*v2.x);
 }
 // ------------------------------------------------------------------------------------------------
-// vector inversion
-AI_FORCE_INLINE  aiVector3D operator - ( const aiVector3D& v)	{
-	return aiVector3D( -v.x, -v.y, -v.z);
+// vector negation
+template <typename TReal>
+AI_FORCE_INLINE  aiVector3t<TReal> operator - ( const aiVector3t<TReal>& v)	{
+	return aiVector3t<TReal>( -v.x, -v.y, -v.z);
 }
 
 

+ 8 - 0
workspaces/vc9/assimp.vcproj

@@ -1248,6 +1248,10 @@
 					RelativePath="..\..\include\aiQuaternion.h"
 					>
 				</File>
+				<File
+					RelativePath="..\..\include\aiQuaternion.inl"
+					>
+				</File>
 				<File
 					RelativePath="..\..\include\aiScene.h"
 					>
@@ -1264,6 +1268,10 @@
 					RelativePath="..\..\include\aiVector2D.h"
 					>
 				</File>
+				<File
+					RelativePath="..\..\include\aiVector2D.inl"
+					>
+				</File>
 				<File
 					RelativePath="..\..\include\aiVector3D.h"
 					>