#pragma once #include #include 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, am_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: 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; Matrix4x4() {} Matrix4x4(float val); Matrix4x4(const Matrix3x3&); 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); Matrix4x4(const Vector4& r1, const Vector4& r2, const Vector4& r3, const Vector4& r4); explicit Matrix4x4(const Quaternion& orientation); Vector3 GetTranslatePart() const; Matrix3x3 GetRotatePart() const { return Matrix3x3 { At(0, 0), At(0, 1), At(0, 2), At(1, 0), At(1, 1), At(1, 2), At(2, 0), At(2, 1), At(2, 2) }; } void SetTranslatePart(float translateX, float translateY, float translateZ); void SetTranslatePart(const Vector3& offset); void SetRotatePart(const Quaternion& q); 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); Matrix4x4(const Quaternion& orientation, const Vector3& translation); Vector4 GetRow(int index) const; Vector4 GetColumn(int index) const; float At(int x, int y) const { return elems[x][y]; } Vector4 Diagonal() const; Vector4 WorldX() const; Vector4 WorldY() const; Vector4 WorldZ() const; /// Computes the determinant of this matrix. // If the determinant is nonzero, this matrix is invertible. float Determinant() const; Matrix4x4 Inverse() const { } Matrix4x4 Transpose() const; Vector2 Transform(const Vector2& rhs) const; Vector3 Transform(const Vector3& rhs) const; Vector4 Transform(const Vector4& rhs) const; 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); Vector3 GetTranslationComponent() const; Matrix3x3 GetRotationComponent() const; Vector4 GetRow() const; Vector4 GetColumn() const; Vector4 operator[](int row) { return Vector4{elems[row][0], elems[row][1], elems[row][2], elems[row][3]}; } protected: float elems[4][4]; void SetMatrixRotatePart(Matrix4x4 &m, const Quaternion &q); }; }