|
|
@@ -11,9 +11,12 @@ namespace bs
|
|
|
* @{
|
|
|
*/
|
|
|
|
|
|
- /** A 3x3 matrix. Can be used for non-homogenous transformations of three dimensional vectors and points. */
|
|
|
- class BS_UTILITY_EXPORT Matrix3
|
|
|
- {
|
|
|
+ /**
|
|
|
+ * A 3x3 matrix. Can be used for non-homogenous transformations of three dimensional vectors and points. In row major
|
|
|
+ * format.
|
|
|
+ */
|
|
|
+ class BS_UTILITY_EXPORT Matrix3
|
|
|
+ {
|
|
|
private:
|
|
|
struct EulerAngleOrderData
|
|
|
{
|
|
|
@@ -21,7 +24,7 @@ namespace bs
|
|
|
float sign;
|
|
|
};
|
|
|
|
|
|
- public:
|
|
|
+ public:
|
|
|
Matrix3() {}
|
|
|
|
|
|
Matrix3(BS_ZERO zero)
|
|
|
@@ -32,14 +35,14 @@ namespace bs
|
|
|
:Matrix3(Matrix3::IDENTITY)
|
|
|
{ }
|
|
|
|
|
|
- Matrix3(const Matrix3& mat)
|
|
|
+ Matrix3(const Matrix3& mat)
|
|
|
{
|
|
|
memcpy(m, mat.m, 9*sizeof(float));
|
|
|
}
|
|
|
|
|
|
- Matrix3(float m00, float m01, float m02,
|
|
|
- float m10, float m11, float m12,
|
|
|
- float m20, float m21, float m22)
|
|
|
+ Matrix3(float m00, float m01, float m02,
|
|
|
+ float m10, float m11, float m12,
|
|
|
+ float m20, float m21, float m22)
|
|
|
{
|
|
|
m[0][0] = m00;
|
|
|
m[0][1] = m01;
|
|
|
@@ -53,50 +56,50 @@ namespace bs
|
|
|
}
|
|
|
|
|
|
/** Construct a matrix from a quaternion. */
|
|
|
- explicit Matrix3(const Quaternion& rotation)
|
|
|
- {
|
|
|
- fromQuaternion(rotation);
|
|
|
- }
|
|
|
+ explicit Matrix3(const Quaternion& rotation)
|
|
|
+ {
|
|
|
+ fromQuaternion(rotation);
|
|
|
+ }
|
|
|
|
|
|
/** Construct a matrix that performs rotation and scale. */
|
|
|
- explicit Matrix3(const Quaternion& rotation, const Vector3& scale)
|
|
|
- {
|
|
|
- fromQuaternion(rotation);
|
|
|
+ explicit Matrix3(const Quaternion& rotation, const Vector3& scale)
|
|
|
+ {
|
|
|
+ fromQuaternion(rotation);
|
|
|
|
|
|
for (int row = 0; row < 3; row++)
|
|
|
{
|
|
|
for (int col = 0; col < 3; col++)
|
|
|
m[row][col] = scale[row]*m[row][col];
|
|
|
}
|
|
|
- }
|
|
|
+ }
|
|
|
|
|
|
/** Construct a matrix from an angle/axis pair. */
|
|
|
- explicit Matrix3(const Vector3& axis, const Radian& angle)
|
|
|
- {
|
|
|
- fromAxisAngle(axis, angle);
|
|
|
- }
|
|
|
-
|
|
|
- /** Construct a matrix from 3 orthonormal local axes. */
|
|
|
- explicit Matrix3(const Vector3& xaxis, const Vector3& yaxis, const Vector3& zaxis)
|
|
|
- {
|
|
|
- fromAxes(xaxis, yaxis, zaxis);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
+ explicit Matrix3(const Vector3& axis, const Radian& angle)
|
|
|
+ {
|
|
|
+ fromAxisAngle(axis, angle);
|
|
|
+ }
|
|
|
+
|
|
|
+ /** Construct a matrix from 3 orthonormal local axes. */
|
|
|
+ explicit Matrix3(const Vector3& xaxis, const Vector3& yaxis, const Vector3& zaxis)
|
|
|
+ {
|
|
|
+ fromAxes(xaxis, yaxis, zaxis);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
* Construct a matrix from euler angles, YXZ ordering.
|
|
|
- *
|
|
|
+ *
|
|
|
* @see Matrix3::fromEulerAngles
|
|
|
- */
|
|
|
+ */
|
|
|
explicit Matrix3(const Radian& xAngle, const Radian& yAngle, const Radian& zAngle)
|
|
|
{
|
|
|
fromEulerAngles(xAngle, yAngle, zAngle);
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * Construct a matrix from euler angles, custom ordering.
|
|
|
- *
|
|
|
+ /**
|
|
|
+ * Construct a matrix from euler angles, custom ordering.
|
|
|
+ *
|
|
|
* @see Matrix3::fromEulerAngles
|
|
|
- */
|
|
|
+ */
|
|
|
explicit Matrix3(const Radian& xAngle, const Radian& yAngle, const Radian& zAngle, EulerAngleOrder order)
|
|
|
{
|
|
|
fromEulerAngles(xAngle, yAngle, zAngle, order);
|
|
|
@@ -116,29 +119,29 @@ namespace bs
|
|
|
std::swap(m[2][2], other.m[2][2]);
|
|
|
}
|
|
|
|
|
|
- /** Returns a row of the matrix. */
|
|
|
- float* operator[] (UINT32 row) const
|
|
|
+ /** Returns a row of the matrix. */
|
|
|
+ float* operator[] (UINT32 row) const
|
|
|
{
|
|
|
assert(row < 3);
|
|
|
|
|
|
return (float*)m[row];
|
|
|
}
|
|
|
|
|
|
- Vector3 getColumn(UINT32 col) const;
|
|
|
- void setColumn(UINT32 col, const Vector3& vec);
|
|
|
+ Vector3 getColumn(UINT32 col) const;
|
|
|
+ void setColumn(UINT32 col, const Vector3& vec);
|
|
|
|
|
|
- Matrix3& operator= (const Matrix3& rhs)
|
|
|
+ Matrix3& operator= (const Matrix3& rhs)
|
|
|
{
|
|
|
memcpy(m, rhs.m, 9*sizeof(float));
|
|
|
return *this;
|
|
|
}
|
|
|
- bool operator== (const Matrix3& rhs) const;
|
|
|
- bool operator!= (const Matrix3& rhs) const;
|
|
|
+ bool operator== (const Matrix3& rhs) const;
|
|
|
+ bool operator!= (const Matrix3& rhs) const;
|
|
|
|
|
|
- Matrix3 operator+ (const Matrix3& rhs) const;
|
|
|
- Matrix3 operator- (const Matrix3& rhs) const;
|
|
|
- Matrix3 operator* (const Matrix3& rhs) const;
|
|
|
- Matrix3 operator- () const;
|
|
|
+ Matrix3 operator+ (const Matrix3& rhs) const;
|
|
|
+ Matrix3 operator- (const Matrix3& rhs) const;
|
|
|
+ Matrix3 operator* (const Matrix3& rhs) const;
|
|
|
+ Matrix3 operator- () const;
|
|
|
Matrix3 operator* (float rhs) const;
|
|
|
|
|
|
friend Matrix3 operator* (float lhs, const Matrix3& rhs);
|
|
|
@@ -146,158 +149,158 @@ namespace bs
|
|
|
/** Transforms the given vector by this matrix and returns the newly transformed vector. */
|
|
|
Vector3 transform(const Vector3& vec) const;
|
|
|
|
|
|
- /** Returns a transpose of the matrix (switched columns and rows). */
|
|
|
- Matrix3 transpose () const;
|
|
|
-
|
|
|
- /**
|
|
|
- * Calculates an inverse of the matrix if it exists.
|
|
|
- *
|
|
|
- * @param[out] mat Resulting matrix inverse.
|
|
|
- * @param[in] fTolerance (optional) Tolerance to use when checking if determinant is zero (or near zero in this case).
|
|
|
- * Zero determinant means inverse doesn't exist.
|
|
|
- * @return True if inverse exists, false otherwise.
|
|
|
- */
|
|
|
- bool inverse(Matrix3& mat, float fTolerance = 1e-06f) const;
|
|
|
-
|
|
|
- /**
|
|
|
- * Calculates an inverse of the matrix if it exists.
|
|
|
- *
|
|
|
+ /** Returns a transpose of the matrix (switched columns and rows). */
|
|
|
+ Matrix3 transpose () const;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Calculates an inverse of the matrix if it exists.
|
|
|
+ *
|
|
|
+ * @param[out] mat Resulting matrix inverse.
|
|
|
* @param[in] fTolerance (optional) Tolerance to use when checking if determinant is zero (or near zero in this case).
|
|
|
* Zero determinant means inverse doesn't exist.
|
|
|
- *
|
|
|
- * @return Resulting matrix inverse if it exists, otherwise a zero matrix.
|
|
|
- */
|
|
|
- Matrix3 inverse(float fTolerance = 1e-06f) const;
|
|
|
-
|
|
|
- /** Calculates the matrix determinant. */
|
|
|
- float determinant() const;
|
|
|
-
|
|
|
- /**
|
|
|
- * Decompose a Matrix3 to rotation and scale.
|
|
|
- *
|
|
|
- * @note
|
|
|
+ * @return True if inverse exists, false otherwise.
|
|
|
+ */
|
|
|
+ bool inverse(Matrix3& mat, float fTolerance = 1e-06f) const;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Calculates an inverse of the matrix if it exists.
|
|
|
+ *
|
|
|
+ * @param[in] fTolerance (optional) Tolerance to use when checking if determinant is zero (or near zero in this case).
|
|
|
+ * Zero determinant means inverse doesn't exist.
|
|
|
+ *
|
|
|
+ * @return Resulting matrix inverse if it exists, otherwise a zero matrix.
|
|
|
+ */
|
|
|
+ Matrix3 inverse(float fTolerance = 1e-06f) const;
|
|
|
+
|
|
|
+ /** Calculates the matrix determinant. */
|
|
|
+ float determinant() const;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Decompose a Matrix3 to rotation and scale.
|
|
|
+ *
|
|
|
+ * @note
|
|
|
* Matrix must consist only of rotation and uniform scale transformations, otherwise accurate results are not
|
|
|
* guaranteed. Applying non-uniform scale guarantees rotation portion will not be accurate.
|
|
|
- */
|
|
|
- void decomposition(Quaternion& rotation, Vector3& scale) const;
|
|
|
-
|
|
|
- /**
|
|
|
- * Decomposes the matrix into various useful values.
|
|
|
- *
|
|
|
- * @param[out] matL Unitary matrix. Columns form orthonormal bases. If your matrix is affine and
|
|
|
- * doesn't use non-uniform scaling this matrix will be a conjugate transpose of the rotation part of the matrix.
|
|
|
- * @param[out] matS Singular values of the matrix. If your matrix is affine these will be scaling factors of the matrix.
|
|
|
+ */
|
|
|
+ void decomposition(Quaternion& rotation, Vector3& scale) const;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Decomposes the matrix into various useful values.
|
|
|
+ *
|
|
|
+ * @param[out] matL Unitary matrix. Columns form orthonormal bases. If your matrix is affine and
|
|
|
+ * doesn't use non-uniform scaling this matrix will be a conjugate transpose of the rotation part of the matrix.
|
|
|
+ * @param[out] matS Singular values of the matrix. If your matrix is affine these will be scaling factors of the matrix.
|
|
|
* @param[out] matR Unitary matrix. Columns form orthonormal bases. If your matrix is affine and
|
|
|
* doesn't use non-uniform scaling this matrix will be the rotation part of the matrix.
|
|
|
- */
|
|
|
- void singularValueDecomposition(Matrix3& matL, Vector3& matS, Matrix3& matR) const;
|
|
|
-
|
|
|
- /**
|
|
|
- * Decomposes the matrix into a set of values.
|
|
|
- *
|
|
|
- * @param[out] matQ Columns form orthonormal bases. If your matrix is affine and
|
|
|
- * doesn't use non-uniform scaling this matrix will be the rotation part of the matrix.
|
|
|
- * @param[out] vecD If the matrix is affine these will be scaling factors of the matrix.
|
|
|
+ */
|
|
|
+ void singularValueDecomposition(Matrix3& matL, Vector3& matS, Matrix3& matR) const;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Decomposes the matrix into a set of values.
|
|
|
+ *
|
|
|
+ * @param[out] matQ Columns form orthonormal bases. If your matrix is affine and
|
|
|
+ * doesn't use non-uniform scaling this matrix will be the rotation part of the matrix.
|
|
|
+ * @param[out] vecD If the matrix is affine these will be scaling factors of the matrix.
|
|
|
* @param[out] vecU If the matrix is affine these will be shear factors of the matrix.
|
|
|
- */
|
|
|
+ */
|
|
|
void QDUDecomposition(Matrix3& matQ, Vector3& vecD, Vector3& vecU) const;
|
|
|
|
|
|
- /** Gram-Schmidt orthonormalization (applied to columns of rotation matrix) */
|
|
|
- void orthonormalize();
|
|
|
+ /** Gram-Schmidt orthonormalization (applied to columns of rotation matrix) */
|
|
|
+ void orthonormalize();
|
|
|
|
|
|
- /**
|
|
|
- * Converts an orthonormal matrix to axis angle representation.
|
|
|
- *
|
|
|
- * @note Matrix must be orthonormal.
|
|
|
- */
|
|
|
- void toAxisAngle(Vector3& axis, Radian& angle) const;
|
|
|
+ /**
|
|
|
+ * Converts an orthonormal matrix to axis angle representation.
|
|
|
+ *
|
|
|
+ * @note Matrix must be orthonormal.
|
|
|
+ */
|
|
|
+ void toAxisAngle(Vector3& axis, Radian& angle) const;
|
|
|
|
|
|
- /** Creates a rotation matrix from an axis angle representation. */
|
|
|
- void fromAxisAngle(const Vector3& axis, const Radian& angle);
|
|
|
+ /** Creates a rotation matrix from an axis angle representation. */
|
|
|
+ void fromAxisAngle(const Vector3& axis, const Radian& angle);
|
|
|
|
|
|
- /**
|
|
|
- * Converts an orthonormal matrix to quaternion representation.
|
|
|
- *
|
|
|
- * @note Matrix must be orthonormal.
|
|
|
- */
|
|
|
- void toQuaternion(Quaternion& quat) const;
|
|
|
+ /**
|
|
|
+ * Converts an orthonormal matrix to quaternion representation.
|
|
|
+ *
|
|
|
+ * @note Matrix must be orthonormal.
|
|
|
+ */
|
|
|
+ void toQuaternion(Quaternion& quat) const;
|
|
|
|
|
|
- /** Creates a rotation matrix from a quaternion representation. */
|
|
|
- void fromQuaternion(const Quaternion& quat);
|
|
|
+ /** Creates a rotation matrix from a quaternion representation. */
|
|
|
+ void fromQuaternion(const Quaternion& quat);
|
|
|
|
|
|
- /** Creates a matrix from a three axes. */
|
|
|
+ /** Creates a matrix from a three axes. */
|
|
|
void fromAxes(const Vector3& xAxis, const Vector3& yAxis, const Vector3& zAxis);
|
|
|
|
|
|
- /**
|
|
|
- * Converts an orthonormal matrix to euler angle (pitch/yaw/roll) representation.
|
|
|
- *
|
|
|
- * @param[in,out] xAngle Rotation about x axis. (AKA Pitch)
|
|
|
- * @param[in,out] yAngle Rotation about y axis. (AKA Yaw)
|
|
|
- * @param[in,out] zAngle Rotation about z axis. (AKA Roll)
|
|
|
- * @return True if unique solution was found, false otherwise.
|
|
|
- *
|
|
|
+ /**
|
|
|
+ * Converts an orthonormal matrix to euler angle (pitch/yaw/roll) representation.
|
|
|
+ *
|
|
|
+ * @param[in,out] xAngle Rotation about x axis. (AKA Pitch)
|
|
|
+ * @param[in,out] yAngle Rotation about y axis. (AKA Yaw)
|
|
|
+ * @param[in,out] zAngle Rotation about z axis. (AKA Roll)
|
|
|
+ * @return True if unique solution was found, false otherwise.
|
|
|
+ *
|
|
|
* @note Matrix must be orthonormal.
|
|
|
- */
|
|
|
- bool toEulerAngles(Radian& xAngle, Radian& yAngle, Radian& zAngle) const;
|
|
|
+ */
|
|
|
+ bool toEulerAngles(Radian& xAngle, Radian& yAngle, Radian& zAngle) const;
|
|
|
|
|
|
- /**
|
|
|
- * Creates a rotation matrix from the provided Pitch/Yaw/Roll angles.
|
|
|
- *
|
|
|
+ /**
|
|
|
+ * Creates a rotation matrix from the provided Pitch/Yaw/Roll angles.
|
|
|
+ *
|
|
|
* @param[in] xAngle Rotation about x axis. (AKA Pitch)
|
|
|
* @param[in] yAngle Rotation about y axis. (AKA Yaw)
|
|
|
* @param[in] zAngle Rotation about z axis. (AKA Roll)
|
|
|
- *
|
|
|
- * @note Matrix must be orthonormal.
|
|
|
+ *
|
|
|
+ * @note Matrix must be orthonormal.
|
|
|
* Since different values will be produced depending in which order are the rotations applied, this method assumes
|
|
|
* they are applied in YXZ order. If you need a specific order, use the overloaded "fromEulerAngles" method instead.
|
|
|
- */
|
|
|
- void fromEulerAngles(const Radian& xAngle, const Radian& yAngle, const Radian& zAngle);
|
|
|
+ */
|
|
|
+ void fromEulerAngles(const Radian& xAngle, const Radian& yAngle, const Radian& zAngle);
|
|
|
|
|
|
- /**
|
|
|
- * Creates a rotation matrix from the provided Pitch/Yaw/Roll angles.
|
|
|
- *
|
|
|
+ /**
|
|
|
+ * Creates a rotation matrix from the provided Pitch/Yaw/Roll angles.
|
|
|
+ *
|
|
|
* @param[in] xAngle Rotation about x axis. (AKA Pitch)
|
|
|
* @param[in] yAngle Rotation about y axis. (AKA Yaw)
|
|
|
* @param[in] zAngle Rotation about z axis. (AKA Roll)
|
|
|
* @param[in] order The order in which rotations will be applied.
|
|
|
* Different rotations can be created depending on the order.
|
|
|
- *
|
|
|
- * @note Matrix must be orthonormal.
|
|
|
- */
|
|
|
- void fromEulerAngles(const Radian& xAngle, const Radian& yAngle, const Radian& zAngle, EulerAngleOrder order);
|
|
|
+ *
|
|
|
+ * @note Matrix must be orthonormal.
|
|
|
+ */
|
|
|
+ void fromEulerAngles(const Radian& xAngle, const Radian& yAngle, const Radian& zAngle, EulerAngleOrder order);
|
|
|
|
|
|
- /**
|
|
|
- * Eigensolver, matrix must be symmetric.
|
|
|
+ /**
|
|
|
+ * Eigensolver, matrix must be symmetric.
|
|
|
*
|
|
|
* @note
|
|
|
* Eigenvectors are vectors which when transformed by the matrix, only change in magnitude, but not in direction.
|
|
|
* Eigenvalue is that magnitude. In other words you will get the same result whether you multiply the vector by the
|
|
|
* matrix or by its eigenvalue.
|
|
|
- */
|
|
|
- void eigenSolveSymmetric(float eigenValues[3], Vector3 eigenVectors[3]) const;
|
|
|
+ */
|
|
|
+ void eigenSolveSymmetric(float eigenValues[3], Vector3 eigenVectors[3]) const;
|
|
|
|
|
|
- static const float EPSILON;
|
|
|
- static const Matrix3 ZERO;
|
|
|
- static const Matrix3 IDENTITY;
|
|
|
+ static const float EPSILON;
|
|
|
+ static const Matrix3 ZERO;
|
|
|
+ static const Matrix3 IDENTITY;
|
|
|
|
|
|
- protected:
|
|
|
+ protected:
|
|
|
friend class Matrix4;
|
|
|
|
|
|
- // Support for eigensolver
|
|
|
- void tridiagonal (float diag[3], float subDiag[3]);
|
|
|
- bool QLAlgorithm (float diag[3], float subDiag[3]);
|
|
|
+ // Support for eigensolver
|
|
|
+ void tridiagonal (float diag[3], float subDiag[3]);
|
|
|
+ bool QLAlgorithm (float diag[3], float subDiag[3]);
|
|
|
|
|
|
- // Support for singular value decomposition
|
|
|
- static const float SVD_EPSILON;
|
|
|
- static const unsigned int SVD_MAX_ITERS;
|
|
|
- static void bidiagonalize (Matrix3& matA, Matrix3& matL, Matrix3& matR);
|
|
|
- static void golubKahanStep (Matrix3& matA, Matrix3& matL, Matrix3& matR);
|
|
|
+ // Support for singular value decomposition
|
|
|
+ static const float SVD_EPSILON;
|
|
|
+ static const unsigned int SVD_MAX_ITERS;
|
|
|
+ static void bidiagonalize (Matrix3& matA, Matrix3& matL, Matrix3& matR);
|
|
|
+ static void golubKahanStep (Matrix3& matA, Matrix3& matL, Matrix3& matR);
|
|
|
|
|
|
// Euler angle conversions
|
|
|
static const EulerAngleOrderData EA_LOOKUP[6];
|
|
|
|
|
|
- float m[3][3];
|
|
|
- };
|
|
|
+ float m[3][3];
|
|
|
+ };
|
|
|
|
|
|
/** @} */
|
|
|
|