226 lines
12 KiB
C++
226 lines
12 KiB
C++
#pragma once
|
|
|
|
#include <J3ML/LinearAlgebra.h>
|
|
#include <J3ML/LinearAlgebra/Quaternion.h>
|
|
|
|
namespace LinearAlgebra {
|
|
|
|
/// 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:
|
|
// TODO: Implement assertions to ensure matrix bounds are not violated!
|
|
enum { Rows = 4 };
|
|
enum { Cols = 4 };
|
|
|
|
/// A constant matrix that has zeroes in all its entries
|
|
static const Matrix4x4 Zero;
|
|
/// A constant matrix that is the identity.
|
|
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.
|
|
/// Never compare a matrix to this value. Due to how IEEE floats work, "nan == nan" returns false!
|
|
static const Matrix4x4 NaN;
|
|
|
|
/// Creates a new float4x4 with uninitialized member values.
|
|
Matrix4x4() {}
|
|
Matrix4x4(float val);
|
|
/// Constructs this float4x4 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&);
|
|
/// 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);
|
|
|
|
|
|
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 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]). */
|
|
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).
|
|
Matrix3x3 GetRotatePart() const;
|
|
void SetTranslatePart(float translateX, float translateY, float translateZ);
|
|
void SetTranslatePart(const Vector3& offset);
|
|
void SetRotatePart(const Quaternion& q);
|
|
void Set3x3Part(const Matrix3x3& r);
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
Vector4 GetRow(int index) const;
|
|
Vector4 GetColumn(int index) const;
|
|
Vector3 GetRow3(int index) const;
|
|
|
|
Vector3 GetColumn3(int index) const;
|
|
float &At(int row, int col);
|
|
float At(int x, int y) const;
|
|
|
|
/// 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 has an inverse.
|
|
/** @return Returns true if this matrix can be inverted, up to the given epsilon. */
|
|
bool IsInvertible(float epsilon = 1e-3f) const;
|
|
|
|
Vector4 Diagonal() const;
|
|
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.
|
|
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.
|
|
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.
|
|
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]; }
|
|
const float *ptr() const { return &elems[0][0]; }
|
|
|
|
float Determinant3x3() const;
|
|
/// Computes the determinant of this matrix.
|
|
// If the determinant is nonzero, this matrix is invertible.
|
|
float Determinant() 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;
|
|
|
|
|
|
Matrix4x4 Translate(const Vector3& rhs) const;
|
|
static Matrix4x4 FromTranslation(const Vector3& rhs);
|
|
|
|
|
|
static Matrix4x4 D3DOrthoProjLH(float nearPlane, float farPlane, float hViewportSize, float vViewportSize);
|
|
static Matrix4x4 D3DOrthoProjRH(float nearPlane, float farPlane, float hViewportSize, float vViewportSize);
|
|
static Matrix4x4 D3DPerspProjLH(float nearPlane, float farPlane, float hViewportSize, float vViewportSize);
|
|
static Matrix4x4 D3DPerspProjRH(float nearPlane, float farPlane, float hViewportSize, float vViewportSize);
|
|
|
|
static Matrix4x4 OpenGLOrthoProjLH(float nearPlane, float farPlane, float hViewportSize, float vViewportSize);
|
|
static Matrix4x4 OpenGLOrthoProjRH(float nearPlane, float farPlane, float hViewportSize, float vViewportSize);
|
|
static Matrix4x4 OpenGLPerspProjLH(float nearPlane, float farPlane, float hViewportSize, float vViewportSize);
|
|
static Matrix4x4 OpenGLPerspProjRH(float nearPlane, float farPlane, float hViewportSize, float vViewportSize);
|
|
|
|
Vector4 GetRow() const;
|
|
Vector4 GetColumn() const;
|
|
|
|
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;
|
|
|
|
|
|
|
|
Vector2 operator * (const Vector2& rhs) const;
|
|
Vector3 operator * (const Vector3& rhs) const;
|
|
Vector4 operator * (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;
|
|
|
|
protected:
|
|
float elems[4][4];
|
|
|
|
|
|
};
|
|
} |