Quellcode durchsuchen

- 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 vor 13 Jahren
Ursprung
Commit
ea3f655c57

+ 2 - 0
code/CMakeLists.txt

@@ -36,10 +36,12 @@ SET( PUBLIC_HEADERS
 	${HEADER_PATH}/aiMesh.h
 	${HEADER_PATH}/aiMesh.h
 	${HEADER_PATH}/aiPostProcess.h
 	${HEADER_PATH}/aiPostProcess.h
 	${HEADER_PATH}/aiQuaternion.h
 	${HEADER_PATH}/aiQuaternion.h
+	${HEADER_PATH}/aiQuaternion.inl
 	${HEADER_PATH}/aiScene.h
 	${HEADER_PATH}/aiScene.h
 	${HEADER_PATH}/aiTexture.h
 	${HEADER_PATH}/aiTexture.h
 	${HEADER_PATH}/aiTypes.h
 	${HEADER_PATH}/aiTypes.h
 	${HEADER_PATH}/aiVector2D.h
 	${HEADER_PATH}/aiVector2D.h
+	${HEADER_PATH}/aiVector2D.inl
 	${HEADER_PATH}/aiVector3D.h
 	${HEADER_PATH}/aiVector3D.h
 	${HEADER_PATH}/aiVector3D.inl
 	${HEADER_PATH}/aiVector3D.inl
 	${HEADER_PATH}/aiVersion.h
 	${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];
 				register unsigned int idx = face.mIndices[i];
 				vertexDone  [idx] = true;
 				vertexDone  [idx] = true;
-				meshTang    [idx] = qnan;
-				meshBitang  [idx] = qnan;
+				meshTang    [idx] = aiVector3D(qnan);
+				meshBitang  [idx] = aiVector3D(qnan);
 			}
 			}
 
 
 			continue;
 			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)	{
 		for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)	{
 			const aiVector3D& pos = mesh->mVertices[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)	{
 	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)	{
 		for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)	{
 			const aiVector3D& pos = mesh->mVertices[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)	{
 	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)	{
 		for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)	{
 			const aiVector3D& pos = mesh->mVertices[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
 	// 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
 		// again the same, except we're applying a transformation now
 		for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)	{
 		for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)	{
 			const aiVector3D pos = mTrafo * mesh->mVertices[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)	{
 		if (face.mNumIndices < 3)	{
 			// either a point or a line -> no well-defined normal vector
 			// either a point or a line -> no well-defined normal vector
 			for (unsigned int i = 0;i < face.mNumIndices;++i) {
 			for (unsigned int i = 0;i < face.mNumIndices;++i) {
-				pMesh->mNormals[face.mIndices[i]] = qnan;
+				pMesh->mNormals[face.mIndices[i]] = aiVector3D(qnan);
 			}
 			}
 			continue;
 			continue;
 		}
 		}
@@ -128,7 +128,7 @@ bool GenFaceNormalsProcess::GenMeshFaceNormals (aiMesh* pMesh)
 		const aiVector3D* pV1 = &pMesh->mVertices[face.mIndices[0]];
 		const aiVector3D* pV1 = &pMesh->mVertices[face.mIndices[0]];
 		const aiVector3D* pV2 = &pMesh->mVertices[face.mIndices[1]];
 		const aiVector3D* pV2 = &pMesh->mVertices[face.mIndices[1]];
 		const aiVector3D* pV3 = &pMesh->mVertices[face.mIndices[face.mNumIndices-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) {
 		for (unsigned int i = 0;i < face.mNumIndices;++i) {
 			pMesh->mNormals[face.mIndices[i]] = vNor;
 			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)
 		if (face.mNumIndices < 3)
 		{
 		{
 			// either a point or a line -> no normal vector
 			// 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;
 			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;
 			pMesh->mNormals[face.mIndices[i]] = vNor;
+		}
 	}
 	}
 
 
 	// Set up a SpatialSort to quickly find all vertices close to a given position
 	// 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 ...
 		// to optimize the whole algorithm a little bit ...
 		std::vector<bool> abHad(pMesh->mNumVertices,false);
 		std::vector<bool> abHad(pMesh->mNumVertices,false);
 		for (unsigned int i = 0; i < pMesh->mNumVertices;++i)	{
 		for (unsigned int i = 0; i < pMesh->mNumVertices;++i)	{
-			if (abHad[i])continue;
+			if (abHad[i]) {
+				continue;
+			}
 
 
 			// Get all vertices that share this one ...
 			// Get all vertices that share this one ...
 			vertexFinder->FindPositions( pMesh->mVertices[i], posEpsilon, verticesFound);
 			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
 #ifndef AI_COLOR4D_H_INC
 #define AI_COLOR4D_H_INC
 #define AI_COLOR4D_H_INC
 
 
+#include "./Compiler/pushpack1.h"
+
 #ifdef __cplusplus
 #ifdef __cplusplus
-extern "C" {
-#endif
 
 
-#include "./Compiler/pushpack1.h"
 // ----------------------------------------------------------------------------------
 // ----------------------------------------------------------------------------------
 /** Represents a color in Red-Green-Blue space including an 
 /** Represents a color in Red-Green-Blue space including an 
 *   alpha component. Color values range from 0 to 1. */
 *   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) {}
 		: 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) {}
 		: r(o.r), g(o.g), b(o.b), a(o.a) {}
 
 
+public:
 	// combined operators
 	// 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
 	// 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
 	// 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 */
 	/** check whether a color is (close to) black */
 	inline bool IsBlack() const;
 	inline bool IsBlack() const;
 
 
-#endif // !__cplusplus
+public:
 
 
 	// Red, green, blue and alpha color values 
 	// Red, green, blue and alpha color values 
-	float r, g, b, a;
+	TReal r, g, b, a;
 } PACK_STRUCT;  // !struct aiColor4D
 } 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
 #endif // __cplusplus
+
+#include "./Compiler/poppack1.h"
+
 #endif // AI_VECTOR3D_H_INC
 #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
 /** @file  aiColor4D.inl
- *  @brief Inline implementation of aiColor4D operators
+ *  @brief Inline implementation of aiColor4t<TReal> operators
  */
  */
 #ifndef AI_COLOR4D_INL_INC
 #ifndef AI_COLOR4D_INL_INC
 #define AI_COLOR4D_INL_INC
 #define AI_COLOR4D_INL_INC
 
 
-#include "aiColor4D.h"
 #ifdef __cplusplus
 #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);
 	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);
 	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;
 	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;
 	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);
 	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.
 	// 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;
 	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
 #ifndef AI_MATRIX3x3_H_INC
 #define AI_MATRIX3x3_H_INC
 #define AI_MATRIX3x3_H_INC
 
 
+#include "./Compiler/pushpack1.h"
+
 #ifdef __cplusplus
 #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
 /** @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), 
 		a1(_a1), a2(_a2), a3(_a3), 
 		b1(_b1), b2(_b2), b3(_b3), 
 		b1(_b1), b2(_b2), b3(_b3), 
 		c1(_c1), c2(_c2), c3(_c3)
 		c1(_c1), c2(_c2), c3(_c3)
@@ -78,17 +81,20 @@ struct aiMatrix3x3
 
 
 public:
 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
 	// 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
 	// 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:
 public:
 
 
@@ -96,20 +102,20 @@ public:
 	/** @brief Construction from a 4x4 matrix. The remaining parts 
 	/** @brief Construction from a 4x4 matrix. The remaining parts 
 	 *  of the matrix are ignored.
 	 *  of the matrix are ignored.
 	 */
 	 */
-	explicit aiMatrix3x3( const aiMatrix4x4& pMatrix);
+	explicit aiMatrix3x3t( const aiMatrix4x4t<TReal>& pMatrix);
 
 
 	// -------------------------------------------------------------------
 	// -------------------------------------------------------------------
 	/** @brief Transpose the matrix
 	/** @brief Transpose the matrix
 	 */
 	 */
-	aiMatrix3x3& Transpose();
+	aiMatrix3x3t& Transpose();
 
 
 	// -------------------------------------------------------------------
 	// -------------------------------------------------------------------
 	/** @brief Invert the matrix.
 	/** @brief Invert the matrix.
 	 *  If the matrix is not invertible all elements are set to qnan.
 	 *  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:
 public:
 	// -------------------------------------------------------------------
 	// -------------------------------------------------------------------
@@ -118,7 +124,7 @@ public:
 	 *  @param out Receives the output matrix
 	 *  @param out Receives the output matrix
 	 *  @return Reference to 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
 	/** @brief Returns a rotation matrix for a rotation around
@@ -128,8 +134,8 @@ public:
 	 *  @param axis Axis to rotate around
 	 *  @param axis Axis to rotate around
 	 *  @param out To be filled
 	 *  @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 
 	/** @brief Returns a translation matrix 
@@ -137,7 +143,7 @@ public:
 	 *  @param out Receives the output matrix
 	 *  @param out Receives the output matrix
 	 *  @return Reference to 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
 	/** @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"
 	 *          "Efficiently Building a Matrix to Rotate One Vector to Another"
 	 *          Journal of Graphics Tools, 4(4):1-4, 1999
 	 *          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 a1, a2, a3;
 	float b1, b2, b3;
 	float b1, b2, b3;
 	float c1, c2, c3;
 	float c1, c2, c3;
-};
+} PACK_STRUCT;
 
 
-#ifdef __cplusplus
-} // end of extern C
 #endif
 #endif
 
 
+#include "./Compiler/poppack1.h"
+
 #endif // AI_MATRIX3x3_H_INC
 #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
 /** @file aiMatrix3x3.inl
  *  @brief Inline implementation of the 3x3 matrix operators
  *  @brief Inline implementation of the 3x3 matrix operators
  */
  */
 #ifndef AI_MATRIX3x3_INL_INC
 #ifndef AI_MATRIX3x3_INL_INC
 #define AI_MATRIX3x3_INL_INC
 #define AI_MATRIX3x3_INL_INC
 
 
+#ifdef __cplusplus
 #include "aiMatrix3x3.h"
 #include "aiMatrix3x3.h"
 
 
-#ifdef __cplusplus
 #include "aiMatrix4x4.h"
 #include "aiMatrix4x4.h"
 #include <algorithm>
 #include <algorithm>
 #include <limits>
 #include <limits>
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Construction from a 4x4 matrix. The remaining parts of the matrix are ignored.
 // 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;
 	a1 = pMatrix.a1; a2 = pMatrix.a2; a3 = pMatrix.a3;
 	b1 = pMatrix.b1; b2 = pMatrix.b2; b3 = pMatrix.b3;
 	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.a2 * a1 + m.b2 * a2 + m.c2 * a3,
 		m.a3 * a1 + m.b3 * a2 + m.c3 * a3,
 		m.a3 * a1 + m.b3 * a2 + m.c3 * a3,
 		m.a1 * b1 + m.b1 * b2 + m.c1 * b3,
 		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;
 	temp *= m;
 	return temp;
 	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;
 	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;
 	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 &&
 	return a1 == m.a1 && a2 == m.a2 && a3 == m.a3 &&
 		   b1 == m.b1 && b2 == m.b2 && b3 == m.b3 &&
 		   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);
 	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;
 	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;
 	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
 	// 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
 		// 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;
 		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.a1 = invdet  * (b2 * c3 - b3 * c2);
 	res.a2 = -invdet * (a2 * c3 - a3 * c2);
 	res.a2 = -invdet * (a2 * c3 - a3 * c2);
 	res.a3 = invdet  * (a2 * b3 - a3 * b2);
 	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.a1 = out.b2 = ::cos(a);
 	out.b1 = ::sin(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.
 // 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
   // 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.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.a3 = v.x;
 	out.b3 = v.y;
 	out.b3 = v.y;
 	return out;
 	return out;
@@ -165,13 +230,14 @@ inline aiMatrix3x3& aiMatrix3x3::Translation( const aiVector2D& v, aiMatrix3x3&
  *          Journal of Graphics Tools, 4(4):1-4, 1999
  *          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 u,v;     /* temporary storage vectors */
 		aiVector3D x;       /* vector most nearly orthogonal to "from" */
 		aiVector3D x;       /* vector most nearly orthogonal to "from" */
@@ -184,31 +250,31 @@ inline aiMatrix3x3& aiMatrix3x3::FromToMatrix(const aiVector3D& from,
 		{
 		{
 			if (x.x < x.z)
 			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
 			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
 		else
 		{
 		{
 			if (x.y < x.z)
 			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
 			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;
 		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;
 		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++) 
 		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]
 				mtx[i][j] =  - c1 * u[i] * u[j] - c2 * v[i] * v[j]
 					+ c3 * v[i] * u[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" */
 	else  /* the most common case, unless "from"="to", or "from"=-"to" */
 	{
 	{
 		const aiVector3D v = from ^ to;
 		const aiVector3D v = from ^ to;
 		/* ... use this hand optimized version (9 mults less) */
 		/* ... 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][0] = e + hvx * v.x;
 		mtx[0][1] = hvxy - v.z;
 		mtx[0][1] = hvxy - v.z;
 		mtx[0][2] = hvxz + v.y;
 		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
 #ifndef AI_MATRIX4X4_H_INC
 #define 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
 /** @brief Represents a row-major 4x4 matrix, use this for homogeneous
  *   coordinates.
  *   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:
 public:
 
 
 	// array access operators
 	// 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
 	// 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:
 public:
 
 
 	// -------------------------------------------------------------------
 	// -------------------------------------------------------------------
-	/** @brief Transpose the matrix
-	 */
-	aiMatrix4x4& Transpose();
+	/** @brief Transpose the matrix */
+	aiMatrix4x4t& Transpose();
 
 
 	// -------------------------------------------------------------------
 	// -------------------------------------------------------------------
 	/** @brief Invert the matrix.
 	/** @brief Invert the matrix.
 	 *  If the matrix is not invertible all elements are set to qnan.
 	 *  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 
 	 *   quaternion 
 	 *  @param position Receives the output position for the x,y,z axes
 	 *  @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 
 	/** @brief Decompose a trafo matrix with no scaling into its 
@@ -144,8 +134,8 @@ public:
 	 *    quaternion 
 	 *    quaternion 
 	 *  @param position Receives the output position for the x,y,z axes
 	 *  @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 y Rotation angle for the y-axis, in radians
 	 *  @param z Rotation angle for the z-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:
 public:
 	// -------------------------------------------------------------------
 	// -------------------------------------------------------------------
@@ -164,7 +154,7 @@ public:
 	 *  @param out Receives the output matrix
 	 *  @param out Receives the output matrix
 	 *  @return Reference to 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
 	/** @brief Returns a rotation matrix for a rotation around the y axis
@@ -172,7 +162,7 @@ public:
 	 *  @param out Receives the output matrix
 	 *  @param out Receives the output matrix
 	 *  @return Reference to 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
 	/** @brief Returns a rotation matrix for a rotation around the z axis
@@ -180,7 +170,7 @@ public:
 	 *  @param out Receives the output matrix
 	 *  @param out Receives the output matrix
 	 *  @return Reference to 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.
 	/** Returns a rotation matrix for a rotation around an arbitrary axis.
@@ -189,8 +179,8 @@ public:
 	 *  @param out Receives the output matrix
 	 *  @param out Receives the output matrix
 	 *  @return Reference to 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 
 	/** @brief Returns a translation matrix 
@@ -198,7 +188,7 @@ public:
 	 *  @param out Receives the output matrix
 	 *  @param out Receives the output matrix
 	 *  @return Reference to 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 
 	/** @brief Returns a scaling matrix 
@@ -206,7 +196,7 @@ public:
 	 *  @param out Receives the output matrix
 	 *  @param out Receives the output matrix
 	 *  @return Reference to 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
 	/** @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"
 	 *          "Efficiently Building a Matrix to Rotate One Vector to Another"
 	 *          Journal of Graphics Tools, 4(4):1-4, 1999
 	 *          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 a1, a2, a3, a4;
 	float b1, b2, b3, b4;
 	float b1, b2, b3, b4;
 	float c1, c2, c3, c4;
 	float c1, c2, c3, c4;
 	float d1, d2, d3, d4;
 	float d1, d2, d3, d4;
+};
 
 
-} PACK_STRUCT; // !class aiMatrix4x4
 
 
+#endif // __cplusplus
 
 
 #include "./Compiler/poppack1.h"
 #include "./Compiler/poppack1.h"
 
 
-#ifdef __cplusplus
-} // end extern "C"
-
-
-#endif // __cplusplus
 #endif // AI_MATRIX4X4_H_INC
 #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
  *  @brief Inline implementation of the 4x4 matrix operators
  */
  */
 #ifndef AI_MATRIX4x4_INL_INC
 #ifndef AI_MATRIX4x4_INL_INC
 #define AI_MATRIX4x4_INL_INC
 #define AI_MATRIX4x4_INL_INC
 
 
-#include "aiMatrix4x4.h"
-
 #ifdef __cplusplus
 #ifdef __cplusplus
+
+#include "aiMatrix4x4.h"
 #include "aiMatrix3x3.h"
 #include "aiMatrix3x3.h"
+#include "aiQuaternion.h"
 
 
 #include <algorithm>
 #include <algorithm>
 #include <limits>
 #include <limits>
 #include <math.h>
 #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.a1 * a1 + m.b1 * a2 + m.c1 * a3 + m.d1 * a4,
 		m.a2 * a1 + m.b2 * a2 + m.c2 * a3 + m.d2 * 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,
 		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;
 	temp *= m;
 	return temp;
 	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;
 	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 
 	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 
 		+ 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
 	// 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
 		// Matrix not invertible. Setting all elements to nan is not really
 		// correct in a mathematical sense but it is easy to debug for the
 		// correct in a mathematical sense but it is easy to debug for the
 		// programmer.
 		// 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,
 			nan,nan,nan,nan,
 			nan,nan,nan,nan,
 			nan,nan,nan,nan,
@@ -143,9 +184,9 @@ inline aiMatrix4x4& aiMatrix4x4::Inverse()
 		return *this;
 		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.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.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));
 	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;
 	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;
 	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 &&
 	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 &&
 			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);
 	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
 	// extract translation
 	position.x = _this[0][3];
 	position.x = _this[0][3];
@@ -206,10 +254,10 @@ inline void aiMatrix4x4::Decompose (aiVector3D& scaling, aiQuaternion& rotation,
 	position.z = _this[2][3];
 	position.z = _this[2][3];
 
 
 	// extract the rows of the matrix
 	// 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
 	// extract the scaling factors
@@ -239,19 +287,20 @@ inline void aiMatrix4x4::Decompose (aiVector3D& scaling, aiQuaternion& rotation,
 	}
 	}
 
 
 	// build a 3x3 rotation matrix
 	// 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].y,vRows[1].y,vRows[2].y,
 		vRows[0].z,vRows[1].z,vRows[2].z);
 		vRows[0].z,vRows[1].z,vRows[2].z);
 
 
 	// and generate the rotation quaternion from it
 	// 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
 	// extract translation
 	position.x = _this[0][3];
 	position.x = _this[0][3];
@@ -259,33 +308,35 @@ inline void aiMatrix4x4::DecomposeNoScaling (aiQuaternion& rotation,
 	position.z = _this[2][3];
 	position.z = _this[2][3];
 
 
 	// extract rotation
 	// 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);
 	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.a1 = cp*cy ;
 	_this.a2 = cp*sy;
 	_this.a2 = cp*sy;
 	_this.a3 = -sp ;
 	_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.b1 = srsp*cy-cr*sy ;
 	_this.b2 = srsp*sy+cr*cy ;
 	_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
 	// 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 &&
 	return (a2 <= epsilon && a2 >= -epsilon &&
 			a3 <= epsilon && a3 >= -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 |
 	     |  1  0       0       0 |
      M = |  0  cos(A) -sin(A)  0 |
      M = |  0  cos(A) -sin(A)  0 |
          |  0  sin(A)  cos(A)  0 |
          |  0  sin(A)  cos(A)  0 |
          |  0  0       0       1 |	*/
          |  0  0       0       1 |	*/
-	out = aiMatrix4x4();
+	out = aiMatrix4x4t<TReal>();
 	out.b2 = out.c3 = cos(a);
 	out.b2 = out.c3 = cos(a);
 	out.b3 = -(out.c2 = sin(a));
 	out.b3 = -(out.c2 = sin(a));
 	return out;
 	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 |
 	     |  cos(A)  0   sin(A)  0 |
@@ -345,21 +399,22 @@ inline aiMatrix4x4& aiMatrix4x4::RotationY(float a, aiMatrix4x4& out)
          | -sin(A)  0   cos(A)  0 |
          | -sin(A)  0   cos(A)  0 |
          |  0       0   0       1 |
          |  0       0   0       1 |
 		*/
 		*/
-	out = aiMatrix4x4();
+	out = aiMatrix4x4t<TReal>();
 	out.a1 = out.c3 = cos(a);
 	out.a1 = out.c3 = cos(a);
 	out.c1 = -(out.a3 = sin(a));
 	out.c1 = -(out.a3 = sin(a));
 	return out;
 	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 |
 	     |  cos(A)  -sin(A)   0   0 |
      M = |  sin(A)   cos(A)   0   0 |
      M = |  sin(A)   cos(A)   0   0 |
          |  0        0        1   0 |
          |  0        0        1   0 |
          |  0        0        0   1 |	*/
          |  0        0        0   1 |	*/
-	out = aiMatrix4x4();
+	out = aiMatrix4x4t<TReal>();
 	out.a1 = out.b2 = cos(a);
 	out.a1 = out.b2 = cos(a);
 	out.a2 = -(out.b1 = sin(a));
 	out.a2 = -(out.b1 = sin(a));
 	return out;
 	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.
 // 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
   // 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.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.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.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;
   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.a4 = v.x;
 	out.b4 = v.y;
 	out.b4 = v.y;
 	out.c4 = v.z;
 	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.a1 = v.x;
 	out.b2 = v.y;
 	out.b2 = v.y;
 	out.c3 = v.z;
 	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
  *          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;
 	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
 #ifndef AI_QUATERNION_H_INC
 #define AI_QUATERNION_H_INC
 #define AI_QUATERNION_H_INC
 
 
-#include <math.h>
-#include "aiTypes.h"
-
 #ifdef __cplusplus
 #ifdef __cplusplus
-extern "C" {
-#endif
+
+template <typename TReal> class aiVector3t;
+template <typename TReal> class aiMatrix3x3t;
 
 
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
 /** Represents a quaternion in a 4D vector. */
 /** 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. */
 	/** 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 */
 	/** Construct from euler angles */
-	aiQuaternion( float rotx, float roty, float rotz);
+	aiQuaterniont( TReal rotx, TReal roty, TReal rotz);
 
 
 	/** Construct from an axis-angle pair */
 	/** 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 */
 	/** Construct from a normalized quaternion stored in a vec3 */
-	aiQuaternion( aiVector3D normalized);
+	aiQuaterniont( aiVector3t<TReal> normalized);
 
 
 	/** Returns a matrix representation of the quaternion */
 	/** 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 */
 	/** Normalize the quaternion */
-	aiQuaternion& Normalize();
+	aiQuaterniont& Normalize();
 
 
 	/** Compute quaternion conjugate */
 	/** Compute quaternion conjugate */
-	aiQuaternion& Conjugate ();
+	aiQuaterniont& Conjugate ();
 
 
 	/** Rotate a point by this quaternion */
 	/** Rotate a point by this quaternion */
-	aiVector3D Rotate (const aiVector3D& in);
+	aiVector3t<TReal> Rotate (const aiVector3t<TReal>& in);
 
 
 	/** Multiply two quaternions */
 	/** 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.
 	/** Performs a spherical interpolation between two quaternions and writes the result into the third.
 	 * @param pOut Target object to received the interpolated rotation.
 	 * @param pOut Target object to received the interpolated rotation.
@@ -99,214 +101,24 @@ struct aiQuaternion
 	 * @param pEnd End rotation, factor == 1.
 	 * @param pEnd End rotation, factor == 1.
 	 * @param pFactor Interpolation factor between 0 and 1. Values outside of this range yield undefined results.
 	 * @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
 	//! 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
 #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
 	//! @return true if the given string matches the format hint
 	bool CheckFormat(const char* s) const
 	bool CheckFormat(const char* s) const
 	{
 	{
-		ai_assert(s && !mHeight);
 		return (0 == ::strncmp(achFormatHint,s,3));
 		return (0 == ::strncmp(achFormatHint,s,3));
 	}
 	}
 
 

+ 3 - 1
include/aiTypes.h

@@ -489,9 +489,11 @@ struct aiMemoryInfo
 }
 }
 #endif //!  __cplusplus
 #endif //!  __cplusplus
 
 
-// Include implementations
+// Include implementation files
+#include "aiVector2D.inl"
 #include "aiVector3D.inl"
 #include "aiVector3D.inl"
 #include "aiColor4D.inl"
 #include "aiColor4D.inl"
+#include "aiQuaternion.inl"
 #include "aiMatrix3x3.inl"
 #include "aiMatrix3x3.inl"
 #include "aiMatrix4x4.inl"
 #include "aiMatrix4x4.inl"
 #endif 
 #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.
 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++
  *  @brief 2D vector structure, including operators when compiling in C++
  */
  */
 #ifndef AI_VECTOR2D_H_INC
 #ifndef AI_VECTOR2D_H_INC
@@ -46,142 +46,62 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 #include <math.h>
 #include <math.h>
 
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #include "./Compiler/pushpack1.h"
 #include "./Compiler/pushpack1.h"
 
 
 // ----------------------------------------------------------------------------------
 // ----------------------------------------------------------------------------------
 /** Represents a two-dimensional vector. 
 /** Represents a two-dimensional vector. 
  */
  */
-struct aiVector2D
-{
+
 #ifdef __cplusplus
 #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
 #endif // __cplusplus
+
+#include "./Compiler/poppack1.h"
+
 #endif // AI_VECTOR2D_H_INC
 #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>
 #include <math.h>
 
 
-#ifdef __cplusplus
-extern "C" {
-#endif
 
 
 #include "./Compiler/pushpack1.h"
 #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. */
 /** 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:
 public:
 
 
 	// combined operators
 	// 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
 	// 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
 	// 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
 	// 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:
 public:
 
 
@@ -91,37 +95,47 @@ public:
 	 *  @param pX X component
 	 *  @param pX X component
 	 *  @param pY Y component
 	 *  @param pY Y component
 	 *  @param pZ Z 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
 	/** @brief Get the squared length of the vector
 	 *  @return Square length */
 	 *  @return Square length */
-	float SquareLength() const;
+	TReal SquareLength() const;
 
 
 
 
 	/** @brief Get the length of the vector
 	/** @brief Get the length of the vector
 	 *  @return length */
 	 *  @return length */
-	float Length() const;
+	TReal Length() const;
 
 
 
 
 	/** @brief Normalize the vector */
 	/** @brief Normalize the vector */
-	aiVector3D& Normalize();
+	aiVector3t& Normalize();
 
 
 	
 	
 	/** @brief Componentwise multiplication of two vectors
 	/** @brief Componentwise multiplication of two vectors
 	 *  
 	 *  
 	 *  Note that vec*vec yields the dot product.
 	 *  Note that vec*vec yields the dot product.
 	 *  @param o Second factor */
 	 *  @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;
 } PACK_STRUCT;
 
 
+#endif // __cplusplus
+
 #include "./Compiler/poppack1.h"
 #include "./Compiler/poppack1.h"
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus
-} // end extern "C"
+
 
 
 
 
 #endif // __cplusplus
 #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
 /** @file  aiVector3D.inl
- *  @brief Inline implementation of aiVector3D operators
+ *  @brief Inline implementation of aiVector3t<TReal> operators
  */
  */
 #ifndef AI_VECTOR3D_INL_INC
 #ifndef AI_VECTOR3D_INL_INC
 #define AI_VECTOR3D_INL_INC
 #define AI_VECTOR3D_INL_INC
 
 
-#include "aiVector3D.h"
 #ifdef __cplusplus
 #ifdef __cplusplus
+#include "aiVector3D.h"
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 /** Transformation of a vector by a 3x3 matrix */
 /** 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.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.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;
 	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 */
 /** 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.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.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;
 	res.z = pMatrix.c1 * pVector.x + pMatrix.c2 * pVector.y + pMatrix.c3 * pVector.z + pMatrix.c4;
 	return res;
 	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; 
 	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; 
 	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()); 
 	return sqrt( SquareLength()); 
 }
 }
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-AI_FORCE_INLINE aiVector3D& aiVector3D::Normalize() { 
+template <typename TReal>
+AI_FORCE_INLINE aiVector3t<TReal>& aiVector3t<TReal>::Normalize() { 
 	*this /= Length(); return *this;
 	*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; 
 	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;
 	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; 
 	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; 
 	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));
 	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));
 	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);
 	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);
 	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;
 	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;
 	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
 // 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
 // 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
 // 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;
 	return v1.x*v2.x + v1.y*v2.y + v1.z*v2.z;
 }
 }
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // scalar multiplication
 // 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
 // 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
 // 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);
 	return v * (1/f);
 }
 }
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // vector division
 // 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
 // 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"
 					RelativePath="..\..\include\aiQuaternion.h"
 					>
 					>
 				</File>
 				</File>
+				<File
+					RelativePath="..\..\include\aiQuaternion.inl"
+					>
+				</File>
 				<File
 				<File
 					RelativePath="..\..\include\aiScene.h"
 					RelativePath="..\..\include\aiScene.h"
 					>
 					>
@@ -1264,6 +1268,10 @@
 					RelativePath="..\..\include\aiVector2D.h"
 					RelativePath="..\..\include\aiVector2D.h"
 					>
 					>
 				</File>
 				</File>
+				<File
+					RelativePath="..\..\include\aiVector2D.inl"
+					>
+				</File>
 				<File
 				<File
 					RelativePath="..\..\include\aiVector3D.h"
 					RelativePath="..\..\include\aiVector3D.h"
 					>
 					>