Răsfoiți Sursa

[+] Added few functions for conveniance. Decompose overload.

Alexandr Arutjunov 9 ani în urmă
părinte
comite
70614ce205
2 a modificat fișierele cu 140 adăugiri și 41 ștergeri
  1. 27 0
      include/assimp/matrix4x4.h
  2. 113 41
      include/assimp/matrix4x4.inl

+ 27 - 0
include/assimp/matrix4x4.h

@@ -93,7 +93,15 @@ public:
 public:
 public:
 
 
     // array access operators
     // array access operators
+	/** @fn TReal* operator[] (unsigned int p_iIndex)
+	 *  @param [in] p_iIndex - index of the row.
+	 *  @return pointer to pointed row.
+	 */
     TReal* operator[]       (unsigned int p_iIndex);
     TReal* operator[]       (unsigned int p_iIndex);
+
+	/** @fn const TReal* operator[] (unsigned int p_iIndex) const
+	 *  @overload TReal* operator[] (unsigned int p_iIndex)
+	 */
     const TReal* operator[] (unsigned int p_iIndex) const;
     const TReal* operator[] (unsigned int p_iIndex) const;
 
 
     // comparison operators
     // comparison operators
@@ -140,6 +148,25 @@ public:
     void Decompose (aiVector3t<TReal>& scaling, aiQuaterniont<TReal>& rotation,
     void Decompose (aiVector3t<TReal>& scaling, aiQuaterniont<TReal>& rotation,
         aiVector3t<TReal>& position) const;
         aiVector3t<TReal>& position) const;
 
 
+	// -------------------------------------------------------------------
+	/** @fn void Decompose(aiVector3t<TReal>& pScaling, aiVector3t<TReal>& pRotation, aiVector3t<TReal>& pPosition) const
+     *  @brief Decompose a trafo matrix into its original components
+     *  @param [out] pScaling - Receives the output scaling for the x,y,z axes.
+     *  @param [out] pRotation - Receives the output rotation as a Euler angles.
+     *  @param [out] pPosition - Receives the output position for the x,y,z axes.
+     */
+    void Decompose(aiVector3t<TReal>& pScaling, aiVector3t<TReal>& pRotation, aiVector3t<TReal>& pPosition) const;
+
+	// -------------------------------------------------------------------
+	/** @fn void Decompose(aiVector3t<TReal>& pScaling, aiVector3t<TReal>& pRotationAxis, TReal& pRotationAngle, aiVector3t<TReal>& pPosition) const
+     *  @brief Decompose a trafo matrix into its original components
+     *  @param [out] pScaling - Receives the output scaling for the x,y,z axes.
+     *  @param [out] pRotationAxis - Receives the output rotation axis.
+	 *  @param [out] pRotationAngle - Receives the output rotation angle for @ref pRotationAxis.
+     *  @param [out] pPosition - Receives the output position for the x,y,z axes.
+     */
+    void Decompose(aiVector3t<TReal>& pScaling, aiVector3t<TReal>& pRotationAxis, TReal& pRotationAngle, aiVector3t<TReal>& pPosition) const;
+
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     /** @brief Decompose a trafo matrix with no scaling into its
     /** @brief Decompose a trafo matrix with no scaling into its
      *    original components
      *    original components

+ 113 - 41
include/assimp/matrix4x4.inl

@@ -299,49 +299,45 @@ inline bool aiMatrix4x4t<TReal>::Equal(const aiMatrix4x4t<TReal>& m, TReal epsil
 }
 }
 
 
 // ----------------------------------------------------------------------------------------
 // ----------------------------------------------------------------------------------------
-template <typename TReal>
-inline void aiMatrix4x4t<TReal>::Decompose (aiVector3t<TReal>& scaling, aiQuaterniont<TReal>& rotation,
-    aiVector3t<TReal>& position) const
-{
-    const aiMatrix4x4t<TReal>& _this = *this;
 
 
-    // extract translation
-    position.x = _this[0][3];
-    position.y = _this[1][3];
-    position.z = _this[2][3];
+#define ASSIMP_MATRIX4_4_DECOMPOSE_PART		\
+	const aiMatrix4x4t<TReal>& _this = *this;/* Create alias for conveniance. */ \
+	\
+	/* extract translation */ \
+	pPosition.x = _this[0][3]; \
+	pPosition.y = _this[1][3]; \
+	pPosition.z = _this[2][3]; \
+	\
+	/* extract the rows of the matrix. */ \
+	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 */ \
+	pScaling.x = vRows[0].Length(); \
+	pScaling.y = vRows[1].Length(); \
+	pScaling.z = vRows[2].Length(); \
+	\
+	/* and the sign of the scaling */ \
+	if (Determinant() < 0) pScaling = -pScaling; \
+	\
+	/* and remove all scaling from the matrix */ \
+	if(pScaling.x) vRows[0] /= pScaling.x; \
+	if(pScaling.y) vRows[1] /= pScaling.y; \
+	if(pScaling.z) vRows[2] /= pScaling.z; \
+	\
+	do {} while(false)
 
 
-    // extract the rows of the matrix
-    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
-    scaling.x = vRows[0].Length();
-    scaling.y = vRows[1].Length();
-    scaling.z = vRows[2].Length();
-
-    // and the sign of the scaling
-    if (Determinant() < 0) {
-        scaling.x = -scaling.x;
-        scaling.y = -scaling.y;
-        scaling.z = -scaling.z;
-    }
 
 
-    // and remove all scaling from the matrix
-    if(scaling.x)
-    {
-        vRows[0] /= scaling.x;
-    }
-    if(scaling.y)
-    {
-        vRows[1] /= scaling.y;
-    }
-    if(scaling.z)
-    {
-        vRows[2] /= scaling.z;
-    }
+
+
+template <typename TReal>
+inline void aiMatrix4x4t<TReal>::Decompose (aiVector3t<TReal>& pScaling, aiQuaterniont<TReal>& pRotation,
+    aiVector3t<TReal>& pPosition) const
+{
+	ASSIMP_MATRIX4_4_DECOMPOSE_PART;
 
 
     // build a 3x3 rotation matrix
     // build a 3x3 rotation matrix
     aiMatrix3x3t<TReal> m(vRows[0].x,vRows[1].x,vRows[2].x,
     aiMatrix3x3t<TReal> m(vRows[0].x,vRows[1].x,vRows[2].x,
@@ -349,7 +345,83 @@ inline void aiMatrix4x4t<TReal>::Decompose (aiVector3t<TReal>& scaling, aiQuater
         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 = aiQuaterniont<TReal>(m);
+    pRotation = aiQuaterniont<TReal>(m);
+}
+
+template <typename TReal>
+inline void aiMatrix4x4t<TReal>::Decompose(aiVector3t<TReal>& pScaling, aiVector3t<TReal>& pRotation, aiVector3t<TReal>& pPosition) const
+{
+	ASSIMP_MATRIX4_4_DECOMPOSE_PART;
+
+	/*
+	    |  CE      -CF      -D   0 |
+	M = | -BDE+AF   BDF+AE  -BC  0 |
+	    |  ADE+BF  -ADF+BE   AC  0 |
+	    |  0        0        0   1 |
+
+	A = cos(angle_x);
+	B = sin(angle_x);
+	C = cos(angle_y);
+	D = sin(angle_y);
+	E = cos(angle_z);
+	F = sin(angle_z);
+	*/
+
+	// Use a small epsilon to solve floating-point inaccuracies
+    constexpr TReal epsilon = 10e-3f;
+
+	pRotation.y  = -asin(_this[0][2]);// Angle around oY.
+
+	TReal C = cos(pRotation.y);
+
+	if(fabs(C) > epsilon)
+	{
+		// Finding angle around oX.
+		TReal tan_x =  _this[2][2] / C;
+		TReal tan_y = -_this[1][2] / C;
+
+		pRotation.x = atan2(tan_y, tan_x);
+		// Finding angle around oZ.
+		tan_x =  _this[0][0] / C;
+		tan_y = -_this[0][1] / C;
+		pRotation.z = atan2(tan_y, tan_x);
+	}
+	else
+	{
+		pRotation.x = 0;// Set angle around oX to 0.
+
+		// And finding angle around oZ.
+		TReal tan_x = _this[1][1];
+		TReal tan_y = _this[1][0];
+
+		pRotation.z = atan2(tan_y, tan_x);
+	}
+}
+
+#undef ASSIMP_MATRIX4_4_DECOMPOSE_PART
+
+template <typename TReal>
+inline void aiMatrix4x4t<TReal>::Decompose(aiVector3t<TReal>& pScaling, aiVector3t<TReal>& pRotationAxis, TReal& pRotationAngle,
+											aiVector3t<TReal>& pPosition) const
+{
+aiQuaterniont<TReal> pRotation;
+
+	Decompose(pScaling, pRotation, pPosition);
+	pRotation.Normalize();
+
+	TReal angle_cos = pRotation.w;
+	TReal angle_sin = sqrt(1.0f - angle_cos * angle_cos);
+
+	pRotationAngle = acos(angle_cos) * 2;
+
+	// Use a small epsilon to solve floating-point inaccuracies
+    constexpr TReal epsilon = 10e-3f;
+
+	if(fabs(angle_sin) < epsilon) angle_sin = 1;
+
+	pRotationAxis.x = pRotation.x / angle_sin;
+	pRotationAxis.y = pRotation.y / angle_sin;
+	pRotationAxis.z = pRotation.z / angle_sin;
 }
 }
 
 
 // ----------------------------------------------------------------------------------------
 // ----------------------------------------------------------------------------------------