Path: blob/master/thirdparty/jolt_physics/Jolt/Math/Matrix.h
9913 views
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)1// SPDX-FileCopyrightText: 2021 Jorrit Rouwe2// SPDX-License-Identifier: MIT34#pragma once56#include <Jolt/Math/Vector.h>7#include <Jolt/Math/GaussianElimination.h>89JPH_NAMESPACE_BEGIN1011/// Templatized matrix class12template <uint Rows, uint Cols>13class [[nodiscard]] Matrix14{15public:16/// Constructor17inline Matrix() = default;18inline Matrix(const Matrix &inM2) { *this = inM2; }1920/// Dimensions21inline uint GetRows() const { return Rows; }22inline uint GetCols() const { return Cols; }2324/// Zero matrix25inline void SetZero()26{27for (uint c = 0; c < Cols; ++c)28mCol[c].SetZero();29}3031inline static Matrix sZero() { Matrix m; m.SetZero(); return m; }3233/// Check if this matrix consists of all zeros34inline bool IsZero() const35{36for (uint c = 0; c < Cols; ++c)37if (!mCol[c].IsZero())38return false;3940return true;41}4243/// Identity matrix44inline void SetIdentity()45{46// Clear matrix47SetZero();4849// Set diagonal to 150for (uint rc = 0, min_rc = min(Rows, Cols); rc < min_rc; ++rc)51mCol[rc].mF32[rc] = 1.0f;52}5354inline static Matrix sIdentity() { Matrix m; m.SetIdentity(); return m; }5556/// Check if this matrix is identity57bool IsIdentity() const { return *this == sIdentity(); }5859/// Diagonal matrix60inline void SetDiagonal(const Vector<Rows < Cols? Rows : Cols> &inV)61{62// Clear matrix63SetZero();6465// Set diagonal66for (uint rc = 0, min_rc = min(Rows, Cols); rc < min_rc; ++rc)67mCol[rc].mF32[rc] = inV[rc];68}6970inline static Matrix sDiagonal(const Vector<Rows < Cols? Rows : Cols> &inV)71{72Matrix m;73m.SetDiagonal(inV);74return m;75}7677/// Copy a (part) of another matrix into this matrix78template <class OtherMatrix>79void CopyPart(const OtherMatrix &inM, uint inSourceRow, uint inSourceCol, uint inNumRows, uint inNumCols, uint inDestRow, uint inDestCol)80{81for (uint c = 0; c < inNumCols; ++c)82for (uint r = 0; r < inNumRows; ++r)83mCol[inDestCol + c].mF32[inDestRow + r] = inM(inSourceRow + r, inSourceCol + c);84}8586/// Get float component by element index87inline float operator () (uint inRow, uint inColumn) const88{89JPH_ASSERT(inRow < Rows);90JPH_ASSERT(inColumn < Cols);91return mCol[inColumn].mF32[inRow];92}9394inline float & operator () (uint inRow, uint inColumn)95{96JPH_ASSERT(inRow < Rows);97JPH_ASSERT(inColumn < Cols);98return mCol[inColumn].mF32[inRow];99}100101/// Comparison102inline bool operator == (const Matrix &inM2) const103{104for (uint c = 0; c < Cols; ++c)105if (mCol[c] != inM2.mCol[c])106return false;107return true;108}109110inline bool operator != (const Matrix &inM2) const111{112for (uint c = 0; c < Cols; ++c)113if (mCol[c] != inM2.mCol[c])114return true;115return false;116}117118/// Assignment119inline Matrix & operator = (const Matrix &inM2)120{121for (uint c = 0; c < Cols; ++c)122mCol[c] = inM2.mCol[c];123return *this;124}125126/// Multiply matrix by matrix127template <uint OtherCols>128inline Matrix<Rows, OtherCols> operator * (const Matrix<Cols, OtherCols> &inM) const129{130Matrix<Rows, OtherCols> m;131for (uint c = 0; c < OtherCols; ++c)132for (uint r = 0; r < Rows; ++r)133{134float dot = 0.0f;135for (uint i = 0; i < Cols; ++i)136dot += mCol[i].mF32[r] * inM.mCol[c].mF32[i];137m.mCol[c].mF32[r] = dot;138}139return m;140}141142/// Multiply vector by matrix143inline Vector<Rows> operator * (const Vector<Cols> &inV) const144{145Vector<Rows> v;146for (uint r = 0; r < Rows; ++r)147{148float dot = 0.0f;149for (uint c = 0; c < Cols; ++c)150dot += mCol[c].mF32[r] * inV.mF32[c];151v.mF32[r] = dot;152}153return v;154}155156/// Multiply matrix with float157inline Matrix operator * (float inV) const158{159Matrix m;160for (uint c = 0; c < Cols; ++c)161m.mCol[c] = mCol[c] * inV;162return m;163}164165inline friend Matrix operator * (float inV, const Matrix &inM)166{167return inM * inV;168}169170/// Per element addition of matrix171inline Matrix operator + (const Matrix &inM) const172{173Matrix m;174for (uint c = 0; c < Cols; ++c)175m.mCol[c] = mCol[c] + inM.mCol[c];176return m;177}178179/// Per element subtraction of matrix180inline Matrix operator - (const Matrix &inM) const181{182Matrix m;183for (uint c = 0; c < Cols; ++c)184m.mCol[c] = mCol[c] - inM.mCol[c];185return m;186}187188/// Transpose matrix189inline Matrix<Cols, Rows> Transposed() const190{191Matrix<Cols, Rows> m;192for (uint r = 0; r < Rows; ++r)193for (uint c = 0; c < Cols; ++c)194m.mCol[r].mF32[c] = mCol[c].mF32[r];195return m;196}197198/// Inverse matrix199bool SetInversed(const Matrix &inM)200{201if constexpr (Rows != Cols) JPH_ASSERT(false);202Matrix copy(inM);203SetIdentity();204return GaussianElimination(copy, *this);205}206207inline Matrix Inversed() const208{209Matrix m;210m.SetInversed(*this);211return m;212}213214/// To String215friend ostream & operator << (ostream &inStream, const Matrix &inM)216{217for (uint i = 0; i < Cols - 1; ++i)218inStream << inM.mCol[i] << ", ";219inStream << inM.mCol[Cols - 1];220return inStream;221}222223/// Column access224const Vector<Rows> & GetColumn(int inIdx) const { return mCol[inIdx]; }225Vector<Rows> & GetColumn(int inIdx) { return mCol[inIdx]; }226227Vector<Rows> mCol[Cols]; ///< Column228};229230// The template specialization doesn't sit well with Doxygen231#ifndef JPH_PLATFORM_DOXYGEN232233/// Specialization of SetInversed for 2x2 matrix234template <>235inline bool Matrix<2, 2>::SetInversed(const Matrix<2, 2> &inM)236{237// Fetch elements238float a = inM.mCol[0].mF32[0];239float b = inM.mCol[1].mF32[0];240float c = inM.mCol[0].mF32[1];241float d = inM.mCol[1].mF32[1];242243// Calculate determinant244float det = a * d - b * c;245if (det == 0.0f)246return false;247248// Construct inverse249mCol[0].mF32[0] = d / det;250mCol[1].mF32[0] = -b / det;251mCol[0].mF32[1] = -c / det;252mCol[1].mF32[1] = a / det;253return true;254}255256#endif // !JPH_PLATFORM_DOXYGEN257258JPH_NAMESPACE_END259260261