19template <
typename T,
size_t Rows,
size_t Cols>
24 if constexpr (Rows == Cols) {
26 for (
size_t i = 0; i < Rows; ++i) {
27 for (
size_t j = 0; j < Cols; ++j) {
29 (i == j) ?
static_cast<T
>(1) :
static_cast<T
>(0);
34 std::memset(data, 0,
sizeof(data));
39 Matrix(std::initializer_list<std::initializer_list<T>> list) {
40 if (list.size() != Rows) {
41 throw std::invalid_argument(
42 "Number of rows does not match matrix dimension");
46 for (
const auto& row : list) {
47 if (row.size() != Cols) {
48 throw std::invalid_argument(
49 "Number of columns does not match matrix dimension");
53 for (
const auto& val : row) {
62 if (row >= Rows || col >= Cols) {
63 throw std::out_of_range(
"Matrix indices out of range");
65 return data[row][col];
69 if (row >= Rows || col >= Cols) {
70 throw std::out_of_range(
"Matrix indices out of range");
72 return data[row][col];
78 for (
size_t i = 0; i < Rows; ++i) {
79 for (
size_t j = 0; j < Cols; ++j) {
80 result(i, j) = data[i][j] + other(i, j);
89 for (
size_t i = 0; i < Rows; ++i) {
90 for (
size_t j = 0; j < Cols; ++j) {
91 result(i, j) = data[i][j] - other(i, j);
98 template <
size_t OtherCols>
105 for (
size_t i = 0; i < Rows; ++i) {
106 for (
size_t j = 0; j < OtherCols; ++j) {
107 T sum =
static_cast<T
>(0);
108 for (
size_t k = 0; k < Cols; ++k) {
109 sum += data[i][k] * other(k, j);
114 if (std::abs(sum) > std::numeric_limits<T>::epsilon()) {
126 for (
size_t i = 0; i < Rows; ++i) {
127 for (
size_t j = 0; j < Cols; ++j) {
128 result(j, i) = data[i][j];
136 static_assert(Rows == Cols,
137 "Determinant is only defined for square matrices");
139 if constexpr (Rows == 1)
return data[0][0];
140 if constexpr (Rows == 2) {
141 return data[0][0] * data[1][1] - data[0][1] * data[1][0];
143 if constexpr (Rows == 3) {
145 (data[1][1] * data[2][2] - data[1][2] * data[2][1]) -
147 (data[1][0] * data[2][2] - data[1][2] * data[2][0]) +
149 (data[1][0] * data[2][1] - data[1][1] * data[2][0]);
152 throw std::runtime_error(
153 "Determinant not implemented for matrices larger than 3x3");
158 static_assert(Rows == Cols,
159 "Inverse is only defined for square matrices");
162 if (std::abs(det) < std::numeric_limits<T>::epsilon()) {
163 throw std::runtime_error(
164 "Matrix is singular (determinant is near zero)");
167 if constexpr (Rows == 2) {
169 result(0, 0) = data[1][1] / det;
170 result(0, 1) = -data[0][1] / det;
171 result(1, 0) = -data[1][0] / det;
172 result(1, 1) = data[0][0] / det;
176 throw std::runtime_error(
177 "Inverse not implemented for matrices larger than 2x2");
182 std::ostringstream ss;
184 for (
size_t i = 0; i < Rows; ++i) {
186 for (
size_t j = 0; j < Cols; ++j) {
187 ss << std::setw(10) << std::fixed << std::setprecision(4)
188 << data[i][j] <<
" ";
204 static_assert(Rows == Cols,
205 "Identity matrix is only defined for square matrices");
213 static_assert(Rows == 4 && Cols == 4,
"Perspective matrix must be 4x4");
214 T tanHalfFovY = tan(fovY / 2.0f);
218 result(0, 0) = 1.0f / (aspectRatio * tanHalfFovY);
219 result(1, 1) = 1.0f / tanHalfFovY;
220 result(2, 2) = farPlane / (farPlane - nearPlane);
222 result(3, 2) = (-nearPlane * farPlane) / (farPlane - nearPlane);
232 static_assert(Rows == 4 && Cols == 4,
"Orthographic matrix must be 4x4");
237 result(0, 0) = 2.0f / (right - left);
238 result(1, 1) = 2.0f / (top - bottom);
239 result(2, 2) = -2.0f / (farPlane - nearPlane);
242 result(0, 3) = -(right + left) / (right - left);
243 result(1, 3) = -(top + bottom) / (top - bottom);
244 result(2, 3) = -(farPlane + nearPlane) / (farPlane - nearPlane);
253 static_assert(Rows == 4 && Cols == 4,
"View matrix must be 4x4");
262 result(0, 0) = xAxis[0];
263 result(1, 0) = xAxis[1];
264 result(2, 0) = xAxis[2];
265 result(3, 0) = -xAxis.
Dot(eye);
267 result(0, 1) = yAxis[0];
268 result(1, 1) = yAxis[1];
269 result(2, 1) = yAxis[2];
270 result(3, 1) = -yAxis.
Dot(eye);
272 result(0, 2) = +zAxis[0];
273 result(1, 2) = +zAxis[1];
274 result(2, 2) = +zAxis[2];
275 result(3, 2) = -zAxis.
Dot(eye);
296 result(0, 0) = xAxis[0];
297 result(1, 0) = xAxis[1];
298 result(2, 0) = xAxis[2];
300 result(0, 1) = yAxis[0];
301 result(1, 1) = yAxis[1];
302 result(2, 1) = yAxis[2];
304 result(0, 2) = -zAxis[0];
305 result(1, 2) = -zAxis[1];
306 result(2, 2) = -zAxis[2];
308 result(3, 0) = -xAxis.
Dot(eye);
309 result(3, 1) = -yAxis.
Dot(eye);
310 result(3, 2) = zAxis.
Dot(eye);
323 result(0, 0) = xAxis[0];
324 result(1, 0) = xAxis[1];
325 result(2, 0) = xAxis[2];
327 result(0, 1) = yAxis[0];
328 result(1, 1) = yAxis[1];
329 result(2, 1) = yAxis[2];
331 result(0, 2) = zAxis[0];
332 result(1, 2) = zAxis[1];
333 result(2, 2) = zAxis[2];
335 result(3, 0) = -xAxis.
Dot(eye);
336 result(3, 1) = -yAxis.
Dot(eye);
337 result(3, 2) = -zAxis.
Dot(eye);
346 forward[0] = cos(yaw) * cos(pitch);
347 forward[1] = sin(pitch);
348 forward[2] = sin(yaw) * cos(pitch);
350 return LookToLH(position, forward,
Vector<T, 3>{0, 1, 0});
358 sin(phi) * cos(theta),
360 sin(phi) * sin(theta)
371 result(3, 0) = translation.
GetX();
372 result(3, 1) = translation.
GetY();
373 result(3, 2) = translation.
GetZ();
388 result(0, 0) = scale.
GetX();
389 result(1, 1) = scale.
GetY();
390 result(2, 2) = scale.
GetZ();
399 scaling(0, 0) = scale.
GetX();
400 scaling(1, 1) = scale.
GetY();
401 scaling(2, 2) = scale.
GetZ();
405 return translateBack * scaling * translateToOrigin;
417#include <DirectXMath.h>
422 DirectX::XMMATRIX worldMatrix;
424 DirectX::XMMATRIX normalMatrix = XMMatrixTranspose(XMMatrixInverse(
nullptr, worldMatrix));
427 DirectX::XMFLOAT4X4 floatMat;
428 DirectX::XMStoreFloat4x4(&floatMat, mat);
431 for (
int row = 0; row < 4; ++row) {
432 for (
int col = 0; col < 4; ++col) {
433 matr(row, col) = floatMat.m[row][col];
static Matrix< T, 4, 4 > Scale(const Vector3D &scale, const Vector3D ¢er)
Builds a matrix that scales about an arbitrary center point.
static Matrix< T, Rows, Rows > Identity()
Matrix< T, Rows, Cols > Inverse() const
static Matrix< T, 4, 4 > FreeLook(const Vector< T, 3 > &position, T yaw, T pitch)
View matrix for a yaw/pitch-driven free camera at position.
static Matrix< T, 4, 4 > Perspective(T fovY, T aspectRatio, T nearPlane, T farPlane)
Builds a left-handed perspective projection (reversed-Z: near maps to depth 1).
static Matrix< T, 4, 4 > Orthographic(T left, T right, T bottom, T top, T nearPlane, T farPlane)
Builds an orthographic projection over the given box.
static Matrix< T, 4, 4 > LookTo(const Vector< T, 3 > &eye, const Vector< T, 3 > &direction, const Vector< T, 3 > &up)
Left-handed view matrix looking from eye along a direction (rather than at a point).
T & operator()(size_t row, size_t col)
Matrix(std::initializer_list< std::initializer_list< T > > list)
Matrix< T, Cols, Rows > Transpose() const
Returns the transposed matrix; does not modify this one.
const T & operator()(size_t row, size_t col) const
static Matrix< T, 4, 4 > Rotate(const Quaternion &rotation)
Builds a rotation matrix from a quaternion.
static Matrix< T, 4, 4 > Scale(const Vector3D &scale)
Builds a matrix that scales about the origin.
friend std::ostream & operator<<(std::ostream &os, const Matrix< T, Rows, Cols > &matrix)
static Matrix< T, 4, 4 > Translate(const Vector3D &translation)
Builds a translation matrix.
static Matrix< T, 4, 4 > OrbitView(const Vector< T, 3 > &target, T distance, T theta, T phi)
View matrix for a camera orbiting target at the given distance and angles.
Matrix< T, Rows, OtherCols > operator*(const Matrix< T, Cols, OtherCols > &other) const
static Matrix< T, 4, 4 > LookAt(const Vector< T, 3 > &eye, const Vector< T, 3 > ¢er, const Vector< T, 3 > &up)
Left-handed view matrix looking from eye toward center.
Matrix< T, Rows, Cols > operator-(const Matrix< T, Rows, Cols > &other) const
Matrix< T, Rows, Cols > operator+(const Matrix< T, Rows, Cols > &other) const
static Matrix< T, 4, 4 > LookAtRH(const Vector< T, 3 > &eye, const Vector< T, 3 > ¢er, const Vector< T, 3 > &up)
Right-handed view matrix looking from eye toward center.
constexpr Matrix() noexcept
std::string ToString() const
Represents a quaternion for 3D rotations.
Matrix< float, 4, 4 > toRotationMatrix() const
T Dot(const Vector< T, N > &other) const
std::enable_if< M==3, Vector< T, N > >::type Cross(const Vector< T, N > &other) const
Vector< T, N > Normalized() const
Vectors, matrices, quaternions, colors, AABBs, and random helpers.
Matrix< float, 4, 4 > Matrix4
Root namespace for everything the engine exposes.