586 lines
36 KiB
C++
586 lines
36 KiB
C++
#pragma once
|
|
|
|
|
|
#include <J3ML/LinearAlgebra/Forward.hpp>
|
|
#include <J3ML/Algorithm/RNG.hpp>
|
|
|
|
#include <algorithm>
|
|
#include <iostream>
|
|
#include <bits/ostream.tcc>
|
|
|
|
using namespace J3ML::Algorithm;
|
|
|
|
namespace J3ML::LinearAlgebra {
|
|
|
|
/// @brief A 4-by-4 matrix for affine transformations and perspective projections of 3D geometry.
|
|
/// This matrix can represent the most generic form of transformations for 3D objects,
|
|
/// including perspective projections, which a 4-by-3 cannot store, and translations, which a 3-by-3 cannot represent.
|
|
/* The elements of this matrix are
|
|
* m_00, m_01, m_02, m_03
|
|
* m_10, m_11, m_12, m_13
|
|
* m_20, m_21, m_22, m_23,
|
|
* m_30, m_31, m_32, m_33
|
|
*
|
|
* The element m_yx is the value on the row y and column x.
|
|
* You can access m_yx using the double-bracket notation m[y][x]
|
|
*/
|
|
class Matrix4x4 {
|
|
public: /// Constant Values
|
|
enum { Rows = 4 };
|
|
enum { Cols = 4 };
|
|
public: /// Constant Members
|
|
/// A constant matrix that has zeroes in all its entries
|
|
static const Matrix4x4 Zero;
|
|
/// A constant matrix that is the identity.
|
|
/** The identity matrix looks like the following:
|
|
1 0 0 0
|
|
0 1 0 0
|
|
0 0 1 0
|
|
0 0 0 1
|
|
Transforming a vector by the identity matrix is like multiplying a number by one, i.e. the vector is not changed */
|
|
static const Matrix4x4 Identity;
|
|
/// A compile-time constant float4x4 which has NaN in each element.
|
|
/// For this constant, each element has the value of quet NaN, or Not-A-Number.
|
|
/// @note Never compare a matrix to this value. Due to how IEEE floats work, "nan == nan" returns false!
|
|
static const Matrix4x4 NaN;
|
|
public: /// Constructors
|
|
/// Creates a new Matrix4x4 with uninitialized member values.
|
|
Matrix4x4() {}
|
|
Matrix4x4(const Matrix4x4 &rhs) = default; // {Set(rhs);}
|
|
Matrix4x4(float val);
|
|
/// Constructs this Matrix4x4 to represent the same transformation as the given float3x3.
|
|
/** This function expands the last row and column of this matrix with the elements from the identity matrix. */
|
|
Matrix4x4(const Matrix3x3& m);
|
|
explicit Matrix4x4(const float* data);
|
|
|
|
/// Constructs a new float4x4 by explicitly specifying all the matrix elements.
|
|
/// The elements are specified in row-major format, i.e. the first row first followed by the second and third row.
|
|
/// E.g. The element _10 denotes the scalar at second (index 1) row, first (index 0) column.
|
|
Matrix4x4(float m00, float m01, float m02, float m03,
|
|
float m10, float m11, float m12, float m13,
|
|
float m20, float m21, float m22, float m23,
|
|
float m30, float m31, float m32, float m33);
|
|
/// Constructs the matrix by explicitly specifying the four column vectors.
|
|
/** @param col0 The first column. If this matrix represents a change-of-basis transformation, this parameter is the world-space
|
|
direction of the local X axis.
|
|
@param col1 The second column. If this matrix represents a change-of-basis transformation, this parameter is the world-space
|
|
direction of the local Y axis.
|
|
@param col2 The third column. If this matrix represents a change-of-basis transformation, this parameter is the world-space
|
|
direction of the local Z axis.
|
|
@param col3 The fourth column. If this matrix represents a change-of-basis transformation, this parameter is the world-space
|
|
position of the local space pivot. */
|
|
Matrix4x4(const Vector4& r1, const Vector4& r2, const Vector4& r3, const Vector4& r4);
|
|
|
|
/// Constructs this Matrix4x4 from the given quaternion.
|
|
explicit Matrix4x4(const Quaternion& orientation);
|
|
|
|
|
|
/// Constructs this float4x4 from the given quaternion and translation.
|
|
/// Logically, the translation occurs after the rotation has been performed.
|
|
Matrix4x4(const Quaternion& orientation, const Vector3 &translation);
|
|
|
|
/// Creates a LookAt matrix from a look-at direction vector.
|
|
/** A LookAt matrix is a rotation matrix that orients an object to face towards a specified target direction.
|
|
@param localForward Specifies the forward direction in the local space of the object. This is the direction
|
|
the model is facing at in its own local/object space, often +X (1,0,0), +Y (0,1,0) or +Z (0,0,1). The
|
|
vector to pass in here depends on the conventions you or your modeling software is using, and it is best
|
|
pick one convention for all your objects, and be consistent.
|
|
This input parameter must be a normalized vector.
|
|
@param targetDirection Specifies the desired world space direction the object should look at. This function
|
|
will compute a rotation matrix which will rotate the localForward vector to orient towards this targetDirection
|
|
vector. This input parameter must be a normalized vector.
|
|
@param localUp Specifies the up direction in the local space of the object. This is the up direction the model
|
|
was authored in, often +Y (0,1,0) or +Z (0,0,1). The vector to pass in here depends on the conventions you
|
|
or your modeling software is using, and it is best to pick one convention for all your objects, and be
|
|
consistent. This input parameter must be a normalized vector. This vector must be perpendicular to the
|
|
vector localForward, i.e. localForward.Dot(localUp) == 0.
|
|
@param worldUp Specifies the global up direction of the scene in world space. Simply rotating one vector to
|
|
coincide with another (localForward->targetDirection) would cause the up direction of the resulting
|
|
orientation to drift (e.g. the model could be looking at its target its head slanted sideways). To keep
|
|
the up direction straight, this function orients the localUp direction of the model to point towards the
|
|
specified worldUp direction (as closely as possible). The worldUp and targetDirection vectors cannot be
|
|
collinear, but they do not need to be perpendicular either.
|
|
@return A matrix that maps the given local space forward direction vector to point towards the given target
|
|
direction, and the given local up direction towards the given target world up direction. The returned
|
|
matrix M is orthonormal with a determinant of +1. For the matrix M it holds that
|
|
M * localForward = targetDirection, and M * localUp lies in the plane spanned by the vectors targetDirection
|
|
and worldUp.
|
|
@note The position of (the translation performed by) the resulting matrix will be set to (0,0,0), i.e. the object
|
|
will be placed to origin. Call SetTranslatePart() on the resulting matrix to set the position of the model.
|
|
@see RotateFromTo(). */
|
|
static Matrix4x4 LookAt(const Vector3& localFwd, const Vector3& targetDir, const Vector3& localUp, const Vector3& worldUp);
|
|
|
|
/// Returns a random 4x4 matrix with each entry randomized between the range [minElem, maxElem]
|
|
/** Warning: The matrices returned by this function do not represent well-formed 3D transformations.
|
|
This function is mostly used for testing and debugging purposes only. */
|
|
static Matrix4x4 RandomGeneral(RNG& rng, float minElem, float maxElem);
|
|
|
|
/// Creates a new Matrix4x4 that rotates about one of the principal axes.
|
|
/** Calling RotateX, RotateY, or RotateZ is slightly faster than calling the more generic RotateAxisAngle function.
|
|
@param radians The angle to rotate by, in radians. For example, Pi/4.f equals 45 degrees.
|
|
@param pointOnAxis If specified, the rotation is performed about an axis that passes through this point,
|
|
and not through the origin. The returned matrix will not be a pure rotation matrix, but will also contain translation. */
|
|
static Matrix4x4 RotateX(float radians, const Vector3 &pointOnAxis);
|
|
/// [similarOverload: RotateX] [hideIndex]
|
|
static Matrix4x4 RotateX(float radians);
|
|
/// [similarOverload: RotateX] [hideIndex]
|
|
static Matrix4x4 RotateY(float radians, const Vector3 &pointOnAxis);
|
|
/// [similarOverload: RotateX] [hideIndex]
|
|
static Matrix4x4 RotateY(float radians);
|
|
/// [similarOverload: RotateX] [hideIndex]
|
|
static Matrix4x4 RotateZ(float radians, const Vector3 &pointOnAxis);
|
|
/// [similarOverload: RotateX] [hideIndex]
|
|
static Matrix4x4 RotateZ(float radians);
|
|
|
|
/// Creates a new Matrix4x4 that rotates about the given axis.
|
|
/** @param axisDirection The axis to rotate about. This vector must be normalized.
|
|
@param angleRadians The angle to rotate by, in radians.
|
|
@param pointOnAxis If specified, the rotation is performed about an axis that passes through this point,
|
|
and not through the origin. The returned matrix will not be a pure rotation matrix, but will also contain translation. */
|
|
static Matrix4x4 RotateAxisAngle(const Vector3 &axisDirection, float angleRadians, const Vector3& pointOnAxis);
|
|
static Matrix4x4 RotateAxisAngle(const Vector3 &axisDirection, float angleRadians);
|
|
|
|
/// Creates a new Matrix4x4 that rotates sourceDirection vector to coincide with the targetDirection vector.
|
|
/** @note There are infinite such rotations - this function returns the rotation that has the shortest angle
|
|
(when decomposed to axis-angle notation)
|
|
@param sourceDirection The 'from' direction vector. This vector must be normalized.
|
|
@param targetDirection The 'to' direction vector. This vector must be normalized.
|
|
@param centerPoint If specified, rotation is performed using this point as the coordinate space origin.
|
|
If omitted, the rotation is performed about the coordinate system origin (0,0,0).
|
|
@return A new rotation matrix R for which R*sourceDirection == targetDirection */
|
|
static Matrix4x4 RotateFromTo(const Vector3 &sourceDirection, const Vector3 &targetDirection, const Vector3 ¢erPoint);
|
|
static Matrix4x4 RotateFromTo(const Vector3 &sourceDirection, const Vector3 &targetDirection);
|
|
static Matrix4x4 RotateFromTo(const Vector4 &sourceDirection, const Vector4 &targetDirection);
|
|
|
|
/// Creates a new Matrix4x4 that rotates one coordinate system to coincide with another.
|
|
/** This function rotates the sourceDirection vector to coincide with the targetDirection vector, and then
|
|
rotates sourceDirection2 (which was transformed by 1.) to targetDirection2, but keeping the constraint that
|
|
sourceDirection must look at targetDirection. */
|
|
/** @param sourceDirection The first 'from' direction. This vector must be normalized.
|
|
@param targetDirection The first 'to' direction. This vector must be normalized.
|
|
@param sourceDirection2 The second 'from' direction. This vector must be normalized.
|
|
@param targetDirection2 The second 'to' direction. This vector must be normalized.
|
|
@param centerPoint If specified, rotation is performed using this point as the coordinate space origin.
|
|
@return The returned matrix maps sourceDirection to targetDirection. Additionally, the returned matrix
|
|
rotates sourceDirection2 to point towards targetDirection2 as closely as possible, under the previous constriant.
|
|
The returned matrix is a rotation matrix, i.e. it is orthonormal with a determinant of +1, and optionally
|
|
has a translation component if the rotation is not performed w.r.t. the coordinate system origin */
|
|
static Matrix4x4 RotateFromTo(const Vector3& sourceDirection, const Vector3 &targetDirection,
|
|
const Vector3 &sourceDirection2, const Vector3 &targetDirection2,
|
|
const Vector3 ¢erPoint);
|
|
static Matrix4x4 RotateFromTo(const Vector3& sourceDirection, const Vector3 &targetDirection,
|
|
const Vector3 &sourceDirection2, const Vector3 &targetDirection2);
|
|
|
|
/// Produces a matrix that shears along a principal axis.
|
|
/** The shear matrix offsets the two other axes according to the
|
|
position of the point along the shear axis. */
|
|
static Matrix4x4 ShearX(float yFactor, float zFactor);
|
|
static Matrix4x4 ShearY(float xFactor, float zFactor);
|
|
static Matrix4x4 ShearZ(float xFactor, float yFactor);
|
|
|
|
/// Identical to D3DXMatrixOrthoLH, except transposed to account for Matrix * vector convention used in J3ML.
|
|
/// See http://msdn.microsoft.com/en-us/library/windows/desktop/bb205346(v=vs.85).aspx
|
|
/// @note Use the M*v multiplication order to project points with this matrix.
|
|
static Matrix4x4 D3DOrthoProjLH(float nearPlane, float farPlane, float hViewportSize, float vViewportSize);
|
|
/// Identical to D3DXMatrixOrthoRH, except transposed to account for Matrix * vector convention used in J3ML.
|
|
/// See http://msdn.microsoft.com/en-us/library/windows/desktop/bb205349(v=vs.85).aspx
|
|
/// @note Use the M*v multiplication order to project points with this matrix.
|
|
static Matrix4x4 D3DOrthoProjRH(float nearPlane, float farPlane, float hViewportSize, float vViewportSize);
|
|
|
|
/// Identical to D3DXMatrixPerspectiveLH, except transposed to account for Matrix * vector convention used in J3ML.
|
|
/// See http://msdn.microsoft.com/en-us/library/windows/desktop/bb205352(v=vs.85).aspx
|
|
/// @note Use the M*v multiplication order to project points with this matrix.
|
|
static Matrix4x4 D3DPerspProjLH(float nearPlane, float farPlane, float hViewportSize, float vViewportSize);
|
|
/// Identical to D3DXMatrixPerspectiveRH, except transposed to account for Matrix * vector convention used in J3ML.
|
|
/// See http://msdn.microsoft.com/en-us/library/windows/desktop/bb205355(v=vs.85).aspx
|
|
/// @note Use the M*v multiplication order to project points with this matrix.
|
|
static Matrix4x4 D3DPerspProjRH(float nearPlane, float farPlane, float hViewportSize, float vViewportSize);
|
|
|
|
/// Computes a left-handled orthographic projection matrix for OpenGL.
|
|
/// @note Use the M*v multiplication order to project points with this matrix.
|
|
static Matrix4x4 OpenGLOrthoProjLH(float nearPlane, float farPlane, float hViewportSize, float vViewportSize);
|
|
/// Computes a right-handled orthographic projection matrix for OpenGL.
|
|
/// @note Use the M*v multiplication order to project points with this matrix.
|
|
static Matrix4x4 OpenGLOrthoProjRH(float nearPlane, float farPlane, float hViewportSize, float vViewportSize);
|
|
|
|
/// Computes a left-handed perspective projection matrix for OpenGL.
|
|
/// @note Use the M*v multiplication order to project points with this matrix.
|
|
/// @param n Near-plane
|
|
/// @param f Far-plane
|
|
/// @param h Horizontal FOV
|
|
/// @param v Vertical FOV
|
|
static Matrix4x4 OpenGLPerspProjLH(float n, float f, float h, float v);
|
|
/// Identical to http://www.opengl.org/sdk/docs/man/xhtml/gluPerspective.xml , except uses viewport sizes instead of FOV to set up the
|
|
/// projection matrix.
|
|
/// @note Use the M*v multiplication order to project points with this matrix.
|
|
// @param n Near-plane
|
|
/// @param f Far-plane
|
|
/// @param h Horizontal FOV
|
|
/// @param v Vertical FOV
|
|
static Matrix4x4 OpenGLPerspProjRH(float n, float f, float h, float v);
|
|
|
|
/// Creates a new transformation matrix that translates by the given offset.
|
|
static Matrix4x4 Translate(const Vector3& translation);
|
|
/// Creates a new transformation matrix that scales by the given factors.
|
|
static Matrix4x4 Scale(const Vector3& scale);
|
|
|
|
/// Creates a new Matrix4x4 as a combination of translation, rotation, and scale.
|
|
/** This function creates a new Matrix4x4 M of the form M = T * R * S, where T is a translation matrix, R is a
|
|
rotation matrix, and S a scale matrix. Transforming a vector v using this matrix computes the vector
|
|
v' = M * v = T*R*S*v = (T * (R * (S * v))), which means that the scale operation is applied to the
|
|
vector first, followed by rotation, and finally translation. */
|
|
static Matrix4x4 FromTRS(const Vector3& translate, const Quaternion& rotate, const Vector3& scale);
|
|
static Matrix4x4 FromTRS(const Vector3& translate, const Matrix3x3& rotate, const Vector3& scale);
|
|
static Matrix4x4 FromTRS(const Vector3& translate, const Matrix4x4& rotate, const Vector3& scale);
|
|
|
|
void SetCol3(int col, const Vector3 &xyz);
|
|
|
|
bool HasNegativeScale() const;
|
|
|
|
public:
|
|
/// Returns the translation part.
|
|
/** The translation part is stored in the fourth column of this matrix.
|
|
This is equivalent to decomposing this matrix in the form M = T * M', i.e. this translation is applied last,
|
|
after applying rotation and scale. If this matrix represents a local->world space transformation for an object,
|
|
then this gives the world space position of the object.
|
|
@note This function assumes that this matrix does not contain projection (the fourth row of this matrix is [0 0 0 1]). */
|
|
[[nodiscard]] Vector3 GetTranslatePart() const;
|
|
/// Returns the top-left 3x3 part of this matrix. This stores the rotation part of this matrix (if this matrix represents a rotation).
|
|
[[nodiscard]] Matrix3x3 GetRotatePart() const;
|
|
|
|
/// Sets the translation part of this matrix.
|
|
/** This function sets the translation part of this matrix. These are the first three elements of the fourth column. All other entries are left untouched. */
|
|
void SetTranslatePart(float translateX, float translateY, float translateZ);
|
|
void SetTranslatePart(const Vector3& offset);
|
|
/// Sets the 3-by-3 part of this matrix to perform rotation about the given axis and angle (in radians). Leaves all other
|
|
/// entries of this matrix untouched.
|
|
void SetRotatePart(const Quaternion& q);
|
|
void SetRotatePart(const Vector3& axisDirection, float angleRadians);
|
|
|
|
/// Sets the 3-by-3 part of this matrix.
|
|
/// @note This is a convenience function which calls Set3x3Part.
|
|
/// @note This function erases the previous top-left 3x3 part of this matrix (any previous rotation, scaling and shearing, etc.) Translation is unaffecte.d
|
|
void SetRotatePart(const Matrix3x3& rotation) { Set3x3Part(rotation); }
|
|
/// Sets the 3-by-3 part of this matrix to perform rotation about the positive X axis which passes through the origin.
|
|
/// Leaves all other entries of this matrix untouched.
|
|
void SetRotatePartX(float angleRadians);
|
|
/// Sets the 3-by-3 part of this matrix to perform the rotation about the positive Y axis.
|
|
/// Leaves all other entries of the matrix untouched.
|
|
void SetRotatePartY(float angleRadians);
|
|
/// Sets the 3-by-3 part of this matrix to perform the rotation about the positive Z axis.
|
|
/// Leaves all other entries of the matrix untouched.
|
|
void SetRotatePartZ(float angleRadians);
|
|
void Set3x3Part(const Matrix3x3& r);
|
|
|
|
/// Sets the value of a given row.
|
|
/// @param row The index of the row to a set, in the range [0-3].
|
|
/// @param data A pointer to an array of 4 floats that contain the new x,y,z,w values for the row.
|
|
void SetRow(int row, const float* data);
|
|
void SetRow(int row, const Vector3& rowVector, float m_r3);
|
|
void SetRow(int row, const Vector4& rowVector);
|
|
void SetRow(int row, float m_r0, float m_r1, float m_r2, float m_r3);
|
|
|
|
/// Sets the value of a given column.
|
|
/// @param column The index of the column to set, in the range [0-3].
|
|
/// @param data A pointer to an array of 3 floats that contain the new x,y,z,w values for the column.
|
|
void SetCol(int col, const float *data);
|
|
void SetCol(int col, const Vector3& colVector, float m_c3);
|
|
void SetCol(int col, const Vector4& colVector);
|
|
void SetCol(int col, float m_c0, float m_c1, float m_c2, float m_c3);
|
|
|
|
void SetCol3(int col, float x, float y, float z);
|
|
|
|
/// Returns the given row.
|
|
/** @param The zero-based index [0, 3] of the row to get */
|
|
[[nodiscard]] Vector4 GetRow(int row) const;
|
|
[[nodiscard]] Vector4 Row(int row) const;
|
|
Vector4& Row(int row);
|
|
|
|
/// Returns only the first-three elements of the given row.
|
|
[[nodiscard]] Vector3 GetRow3(int index) const;
|
|
[[nodiscard]] Vector3 Row3(int i) const;
|
|
/// This method also allows assignment to the retrieved row.
|
|
Vector3& Row3(int row);
|
|
|
|
/// Returns the given column.
|
|
/** @param col The zero-based index [0, 3] of the column to get. */
|
|
[[nodiscard]] Vector4 GetColumn(int index) const;
|
|
[[nodiscard]] Vector4 Column(int index) const;
|
|
[[nodiscard]] Vector4 Col(int i) const;
|
|
|
|
/// Returns only the first three elements of the given column.
|
|
[[nodiscard]] Vector3 GetColumn3(int index) const;
|
|
[[nodiscard]] Vector3 Column3(int index) const;
|
|
|
|
[[nodiscard]] Vector3 Col3(int i) const;
|
|
|
|
/// Returns the scaling performed by this matrix. This function assumes taht the last row is [0 0 0 1].
|
|
/// GetScale().x specifies the amount of scaling applied to the local x direction vector when it is transformed by this matrix.
|
|
/// i.e. GetScale()[i] equals Col[i].Length();
|
|
[[nodiscard]] Vector3 GetScale() const;
|
|
|
|
|
|
float &At(int row, int col);
|
|
[[nodiscard]] float At(int x, int y) const;
|
|
|
|
|
|
void SwapColumns(int col1, int col2);
|
|
|
|
/// Swaps two rows.
|
|
void SwapRows(int row1, int row2);
|
|
/// Swapsthe xyz-parts of two rows element-by-element
|
|
void SwapRows3(int row1, int row2);
|
|
|
|
void ScaleRow(int row, float scalar);
|
|
void ScaleRow3(int row, float scalar);
|
|
void ScaleColumn(int col, float scalar);
|
|
void ScaleColumn3(int col, float scalar);
|
|
/// Reduces this matrix to its row-echelon form.
|
|
void Pivot();
|
|
|
|
/// Tests if this matrix does not contain any NaNs or infs.
|
|
/** @return Returns true if the entries of this float4x4 are all finite, and do not contain NaN or infs. */
|
|
bool IsFinite() const;
|
|
|
|
|
|
/// Tests if this matrix is the identity matrix.
|
|
bool IsIdentity(float epsilon = 1e-3f) const;
|
|
|
|
/// Tests if this matrix has an inverse.
|
|
/** @return Returns true if this matrix can be inverted, up to the given epsilon. */
|
|
bool IsInvertible(float epsilon = 1e-3f) const;
|
|
|
|
[[nodiscard]] Vector4 Diagonal() const;
|
|
[[nodiscard]] Vector3 Diagonal3() const;
|
|
/// Returns the local +X axis in world space.
|
|
/// This is the same as transforming the vector (1,0,0) by this matrix.
|
|
[[nodiscard]] Vector3 WorldX() const;
|
|
/// Returns the local +Y axis in world space.
|
|
/// This is the same as transforming the vector (0,1,0) by this matrix.
|
|
[[nodiscard]] Vector3 WorldY() const;
|
|
/// Returns the local +Z axis in world space.
|
|
/// This is the same as transforming the vector (0,0,1) by this matrix.
|
|
[[nodiscard]] Vector3 WorldZ() const;
|
|
|
|
/// Accesses this structure as a float array.
|
|
/// @return A pointer to the upper-left element. The data is contiguous in memory.
|
|
/// ptr[0] gives the element [0][0], ptr[1] is [0][1], ptr[2] is [0][2].
|
|
/// ptr[4] == [1][0], ptr[5] == [1][1], ..., and finally, ptr[15] == [3][3].
|
|
float *ptr() { return &elems[0][0]; }
|
|
[[nodiscard]] const float *ptr() const { return &elems[0][0]; }
|
|
|
|
/// Computes the determinant of the upper-left 3x3 submatrix of this matrix.
|
|
[[nodiscard]] float Determinant3x3() const;
|
|
/// Computes the determinant of this matrix.
|
|
// If the determinant is nonzero, this matrix is invertible.
|
|
[[nodiscard]] float Determinant() const;
|
|
|
|
/// Computes the determinant of this matrix.
|
|
/** If the determinant is nonzero, this matrix is invertible.
|
|
If the determinant is negative, this matrix performs reflection about some axis.
|
|
From http://msdn.microsoft.com/en-us/library/bb204853(VS.85).aspx :
|
|
"If the determinant is positive, the basis is said to be "positively" oriented (or right-handed).
|
|
If the determinant is negative, the basis is said to be "negatively" oriented (or left-handed)." */
|
|
float Determinant4() const;
|
|
|
|
#define SKIPNUM(val, skip) (val >= skip ? (val+1) : val)
|
|
|
|
float Minor(int i, int j) const;
|
|
|
|
Matrix4x4 Inverse() const;
|
|
|
|
Matrix4x4 Transpose() const;
|
|
|
|
Vector2 Transform(float tx, float ty) const;
|
|
Vector2 Transform(const Vector2& rhs) const;
|
|
|
|
|
|
Vector3 Transform(float tx, float ty, float tz) const;
|
|
Vector3 Transform(const Vector3& rhs) const;
|
|
|
|
Vector4 Transform(float tx, float ty, float tz, float tw) const;
|
|
Vector4 Transform(const Vector4& rhs) const;
|
|
|
|
static Matrix4x4 FromTranslation(const Vector3& rhs);
|
|
|
|
|
|
Vector4 operator[](int row);
|
|
|
|
Matrix4x4 operator-() const;
|
|
Matrix4x4 operator +(const Matrix4x4& rhs) const;
|
|
Matrix4x4 operator - (const Matrix4x4& rhs) const;
|
|
|
|
Matrix4x4 operator *(float scalar) const;
|
|
Matrix4x4 operator /(float scalar) const;
|
|
|
|
Vector4 operator[](int row) const;
|
|
|
|
Vector2 operator * (const Vector2& rhs) const;
|
|
Vector3 operator * (const Vector3& rhs) const;
|
|
Vector4 operator * (const Vector4& rhs) const;
|
|
|
|
Vector2 Mul(const Vector2& rhs) const;
|
|
Vector3 Mul(const Vector3& rhs) const;
|
|
Vector4 Mul(const Vector4& rhs) const;
|
|
|
|
Matrix4x4 operator * (const Matrix3x3 &rhs) const;
|
|
|
|
Matrix4x4 operator +() const;
|
|
|
|
Matrix4x4 operator * (const Matrix4x4& rhs) const;
|
|
|
|
Matrix4x4 &operator = (const Matrix3x3& rhs);
|
|
Matrix4x4 &operator = (const Quaternion& rhs);
|
|
Matrix4x4 &operator = (const Matrix4x4& rhs) = default;
|
|
|
|
/// Returns the scale component of this matrix.
|
|
/** This function decomposes this matrix M into a form M = M' * S, where M' has the unitary column vectors and S is a diagonal matrix.
|
|
@return ExtractScale returns the diagonal entries of S, i.e. the scale of the columns of this matrix. If this matrix
|
|
represents a local->world space transformation for an object, then this scale represents a 'local scale', i.e.
|
|
scaling that is performed before translating and rotating the object from its local coordinate system to its world
|
|
position.
|
|
@note This function assumes that this matrix does not contain projection (the fourth row of this matrix is [0 0 0 1]). */
|
|
Vector3 ExtractScale() const;
|
|
|
|
/// Removes the scaling performed by this matrix. That is, decomposes this matrix M into a form M = M' * S, where
|
|
/// M' has unitary column vectors and S is a diagonal matrix. Then replaces this matrix with M'.
|
|
/// @note This function assumes that this matrix does not contain projection (the fourth row of this matrix is [0 0 0 1]).
|
|
/// @note This function assumes that this matrix has orthogonal basis vectors (row and column vector sets are orthogonal).
|
|
/// @note This function does not remove reflection (-1 scale along some axis).
|
|
void RemoveScale();
|
|
|
|
|
|
/// Decomposes this matrix to translate, rotate, and scale parts.
|
|
/** This function decomposes this matrix M to a form M = T * R * S, where T is a translation matrix, R is a rotation matrix, and S is a scale matrix
|
|
@note Remember that in the convention of this class, transforms are applied in the order M * v, so scale is
|
|
applied first, then rotation, and finally the translation last.
|
|
@note This function assumes that this matrix does not contain projection (The fourth row of this matrix is [0 0 0 1]).
|
|
@param translate [out] This vector receives the translation component this matrix performs. The translation is applied last
|
|
after rotation and scaling.
|
|
@param rotate [out] This object receives the rotation part of this transform.
|
|
@param scale [out] This vector receives the scaling along the local (before transformation by R) X, Y, and Z axes performed by this matrix. */
|
|
void Decompose(Vector3& translate, Quaternion& rotate, Vector3& scale) const;
|
|
void Decompose(Vector3& translate, Matrix3x3& rotate, Vector3& scale) const;
|
|
void Decompose(Vector3& translate, Matrix4x4& rotate, Vector3& scale) const;
|
|
|
|
/// Returns true if this matrix only contains uniform scaling, compared to the given epsilon.
|
|
/// @note If the matrix does not really do any scaling, this function returns true (scaling uniformly by a factor of 1).
|
|
/// @note This function only examines the upper 3-by-3 part of this matrix.
|
|
/// @note This function assumes that this matrix does not contain projection (the fourth row of this matrix is [0 0 0 1]).
|
|
bool HasUniformScale(float epsilon = 1e-3f) const;
|
|
|
|
/// Returns true if the row vectors of 3x3-top-left submatrix are all perpendicular to each other.
|
|
bool IsColOrthogonal3(float epsilon = 1e-3f) const;
|
|
/// Returns true if the column vector of 3x3-top-left submatrix are all perpendicular to each other.
|
|
bool IsRowOrthogonal3(float epsilon = 1e-3f) const;
|
|
|
|
bool IsColOrthogonal(float epsilon = 1e-3f) const;
|
|
bool IsRowOrthogonal(float epsilon = 1e-3f) const;
|
|
/// Returns true if this matrix is seen to contain a "projective" part,
|
|
/// i.e. whether the last row of this matrix differs from [0 0 0 1]
|
|
bool ContainsProjection(float epsilon = 1e-3f) const;
|
|
|
|
|
|
/// Sets all values of this matrix.
|
|
void Set(float _00, float _01, float _02, float _03,
|
|
float _10, float _11, float _12, float _13,
|
|
float _20, float _21, float _22, float _23,
|
|
float _30, float _31, float _32, float _33);
|
|
|
|
/// Sets this to be a copy of the matrix rhs.
|
|
void Set(const Matrix4x4 &rhs);
|
|
|
|
/// Sets all values of this matrix.
|
|
/** @param values The values in this array will be copied over to this matrix. The source must contain 16 floats in row-major order
|
|
(the same order as the Set() ufnction above has its input parameters in. */
|
|
void Set(const float *p);
|
|
|
|
/// Sets this matrix to equal the identity.
|
|
void SetIdentity();
|
|
/// Returns the adjugate of this matrix.
|
|
Matrix4x4 Adjugate() const;
|
|
|
|
/// Computes the Cholesky decomposition of this matrix.
|
|
/// The returned matrix L satisfies L * transpose(L) = this;
|
|
/// Returns true on success.
|
|
bool CholeskyDecompose(Matrix4x4 &outL) const;
|
|
|
|
/// Computes the LU decomposition of this matrix.
|
|
/// This decomposition has the form 'this = L * U'
|
|
/// Returns true on success.
|
|
bool LUDecompose(Matrix4x4& outLower, Matrix4x4& outUpper) const;
|
|
|
|
/// Inverts this matrix using the generic Gauss's method.
|
|
/// @return Returns true on success, false otherwise.
|
|
bool Inverse(float epsilon = 1e-6f);
|
|
|
|
/// Returns an inverted copy of this matrix.
|
|
/// If this matrix does not have an inverse, returns the matrix that was the result of running
|
|
/// Gauss's method on the matrix.
|
|
Matrix4x4 Inverted() const;
|
|
|
|
/// Inverts a column-orthogonal matrix.
|
|
/// If a matrix is of form M=T*R*S, where T is an affine translation matrix
|
|
/// R is a rotation matrix and S is a diagonal matrix with non-zero but pote ntially non-uniform scaling
|
|
/// factors (possibly mirroring), then the matrix M is column-orthogonal and this function can be used to compute the inverse.
|
|
/// Calling this function is faster than the calling the generic matrix Inverted() function.
|
|
/// Returns true on success. On failure, the matrix is not modified. This function fails if any of the
|
|
/// elements of this vector are not finite, or if the matrix contains a zero scaling factor on X, Y, or Z.
|
|
/// This function may not be called if this matrix contains any projection (last row differs from (0 0 0 1)).
|
|
/// @note The returned matrix will be row-orthogonal, but not column-orthogonal in general.
|
|
/// The returned matrix will be column-orthogonal if the original matrix M was row-orthogonal as well.
|
|
/// (in which case S had uniform scale, InverseOrthogonalUniformScale() could have been used instead).
|
|
bool InverseColOrthogonal();
|
|
|
|
|
|
/// Inverts a matrix that is a concatenation of only translate, rotate, and uniform scale operations.
|
|
/// If a matrix is of form M = T*R*S, where T is an affine translation matrix,
|
|
/// R is a rotation matrix and S is a diagonal matrix with non-zero and uniform scaling factors (possibly mirroring),
|
|
/// then the matrix M is both column- and row-orthogonal and this function can be used to compute this inverse.
|
|
/// This function is faster than calling InverseColOrthogonal() or the generic Inverted().
|
|
/// Returns true on success. On failure, the matrix is not modified. This function fails if any of the
|
|
/// elements of this vector are not finite, or if the matrix contains a zero scaling factor on X, Y, or Z.
|
|
/// This function may not be called if this matrix contains any shearing or nonuniform scaling.
|
|
/// This function may not be called if this matrix contains any projection (last row differs from (0 0 0 1)).
|
|
bool InverseOrthogonalUniformScale();
|
|
|
|
/// Inverts a matrix that is a concatenation of only translate and rotate operations.
|
|
/// If a matrix is of form M = T*R*S, where T is an affine translation matrix, R is a rotation
|
|
/// matrix and S is either identity or a mirroring matrix, then the matrix M is orthonormal and this function can be used to compute the inverse.
|
|
/// This function is faster than calling InverseOrthogonalUniformScale(), InverseColOrthogonal(), or the generic Inverted().
|
|
/// This function may not be called if this matrix contains any scaling or shearing, but it may contain mirroring.
|
|
/// This function may not be called if this matrix contains any projection (last row differs from (0 0 0 1)).
|
|
void InverseOrthonormal();
|
|
|
|
/// Transposes this matrix.
|
|
/// This operation swaps all elements with respect to the diagonal.
|
|
void Transpose();
|
|
/// Returns a transposed copy of this matrix.
|
|
Matrix4x4 Transposed() const;
|
|
/// Computes the inverse transpose of this matrix in-place.
|
|
/// Use the inverse transpose to transform covariant vectors (normal vectors).
|
|
bool InverseTranspose();
|
|
/// Returns the inverse transpose of this matrix.
|
|
/// Use that matrix to transform covariant vectors (normal vectors).
|
|
Matrix4x4 InverseTransposed() const;
|
|
/// Returns the sum of the diagonal elements of this matrix.
|
|
float Trace() const;
|
|
|
|
[[nodiscard]] Quaternion ToQuat() const;
|
|
|
|
/// Returns true if this Matrix4x4 is equal to the given Matrix4x4, up to given per-element epsilon.
|
|
bool Equals(const Matrix4x4& other, float epsilon = 1e-3f) const;
|
|
|
|
|
|
[[nodiscard]] std::string ToString() const;
|
|
|
|
protected:
|
|
float elems[4][4];
|
|
|
|
|
|
Vector3 TransformDir(float tx, float ty, float tz) const;
|
|
};
|
|
|
|
std::ostream& operator << (std::ostream& out, const Matrix4x4& rhs);
|
|
}
|