7#include "structure/math/spk_quaternion.hpp"
8#include "structure/math/spk_safe_comparand.hpp"
9#include "structure/math/spk_vector2.hpp"
10#include "structure/math/spk_vector3.hpp"
11#include "structure/math/spk_vector4.hpp"
13#include "utils/spk_math_utils.hpp"
15#include "spk_constants.hpp"
31 template <
size_t SizeX,
size_t SizeY>
48 std::array<float, SizeY> _rows;
60 throw std::invalid_argument(
61 "Can't access the row " + std::to_string(p_index) +
" on a matrix " + std::to_string(SizeX) +
"x" + std::to_string(SizeY));
63 return (_rows[p_index]);
74 throw std::invalid_argument(
75 "Can't access the row " + std::to_string(p_index) +
" on a matrix " + std::to_string(SizeX) +
"x" + std::to_string(SizeY));
77 return (_rows[p_index]);
82 std::array<Column, SizeX> _cols;
90 for (
size_t i = 0; i < SizeX; i++)
92 for (
size_t j = 0; j < SizeY; j++)
94 (*this)[i][j] = (i == j ? 1.0f : 0.0f);
105 for (
size_t i = 0; i < SizeX; i++)
107 for (
size_t j = 0; j < SizeY; j++)
109 (*this)[i][j] = p_values[i * SizeY + j];
118 IMatrix(std::initializer_list<float> p_values)
120 if (p_values.size() != SizeX * SizeY)
122 throw std::invalid_argument(
"Initializer list size does not match the matrix dimensions.");
125 auto it = p_values.begin();
126 for (
size_t j = 0; j < SizeY; j++)
128 for (
size_t i = 0; i < SizeX; i++)
130 (*this)[i][j] = *it++;
151 if (p_index >= SizeX)
153 throw std::invalid_argument(
154 "Can't access the column " + std::to_string(p_index) +
" on a matrix " + std::to_string(SizeX) +
"x" + std::to_string(SizeY));
156 return (_cols[p_index]);
166 if (p_index >= SizeX)
168 throw std::invalid_argument(
169 "Can't access the column " + std::to_string(p_index) +
" on a matrix " + std::to_string(SizeX) +
"x" + std::to_string(SizeY));
171 return (_cols[p_index]);
179 template <
size_t X = SizeX,
size_t Y = SizeY,
typename std::enable_if_t<(X == 3 && Y == 3),
int> = 0>
183 result.
x = (*this)[0][0] * p_vec.
x + (*this)[1][0] * p_vec.
y + (*this)[2][0] * 1;
184 result.
y = (*this)[0][1] * p_vec.
x + (*this)[1][1] * p_vec.
y + (*this)[2][1] * 1;
185 result.
z = (*this)[0][2] * p_vec.
x + (*this)[1][2] * p_vec.
y + (*this)[2][2] * 1;
194 template <
size_t X = SizeX,
size_t Y = SizeY,
typename std::enable_if_t<(X == 4 && Y == 4),
int> = 0>
197 Vector4 temp(p_vec.
x, p_vec.
y, p_vec.
z, 1.0f);
198 Vector4 transformed = (*this) * temp;
199 return Vector3(transformed.
x / transformed.
w, transformed.
y / transformed.
w, transformed.
z / transformed.
w);
209 template <
size_t X = SizeX,
size_t Y = SizeY,
typename std::enable_if_t<(X == 3 && Y == 3),
int> = 0>
213 result.
x = (*this)[0][0] * p_vec.
x + (*this)[1][0] * p_vec.
y + (*this)[2][0] * 1;
214 result.
y = (*this)[0][1] * p_vec.
x + (*this)[1][1] * p_vec.
y + (*this)[2][1] * 1;
224 template <
size_t X = SizeX,
size_t Y = SizeY,
typename std::enable_if_t<(X == 4 && Y == 4),
int> = 0>
228 result.
x = (*this)[0][0] * p_vec.
x + (*this)[1][0] * p_vec.
y + (*this)[2][0] * p_vec.
z + (*this)[3][0] * p_vec.
w;
229 result.
y = (*this)[0][1] * p_vec.
x + (*this)[1][1] * p_vec.
y + (*this)[2][1] * p_vec.
z + (*this)[3][1] * p_vec.
w;
230 result.
z = (*this)[0][2] * p_vec.
x + (*this)[1][2] * p_vec.
y + (*this)[2][2] * p_vec.
z + (*this)[3][2] * p_vec.
w;
231 result.
w = (*this)[0][3] * p_vec.
x + (*this)[1][3] * p_vec.
y + (*this)[2][3] * p_vec.
z + (*this)[3][3] * p_vec.
w;
244 for (
size_t i = 0; i < SizeX; ++i)
246 for (
size_t j = 0; j < SizeY; ++j)
249 for (
size_t k = 0; k < SizeX; ++k)
251 result[i][j] += (*this)[i][k] * p_other[k][j];
266 for (
size_t i = 0; i < SizeX; ++i)
268 for (
size_t j = 0; j < SizeY; ++j)
287 return !(*
this == p_other);
302 float cosX = std::cos(spk::MathUtils::degreeToRadian(p_angleX));
303 float sinX = std::sin(spk::MathUtils::degreeToRadian(p_angleX));
305 float cosY = std::cos(spk::MathUtils::degreeToRadian(p_angleY));
306 float sinY = std::sin(spk::MathUtils::degreeToRadian(p_angleY));
308 float cosZ = std::cos(spk::MathUtils::degreeToRadian(p_angleZ));
309 float sinZ = std::sin(spk::MathUtils::degreeToRadian(p_angleZ));
311 IMatrix<4, 4> rotationX = {1, 0, 0, 0, 0, cosX, -sinX, 0, 0, sinX, cosX, 0, 0, 0, 0, 1};
313 IMatrix<4, 4> rotationY = {cosY, 0, sinY, 0, 0, 1, 0, 0, -sinY, 0, cosY, 0, 0, 0, 0, 1};
315 IMatrix<4, 4> rotationZ = {cosZ, -sinZ, 0, 0, sinZ, cosZ, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
330 return (
rotation(p_angle.
x, p_angle.
y, p_angle.
z));
333 template <
size_t X = SizeX,
size_t Y = SizeY,
typename std::enable_if_t<(X == 4 && Y == 4),
int> = 0>
344 float xx = p_q.
x * p_q.
x;
345 float yy = p_q.
y * p_q.
y;
346 float zz = p_q.
z * p_q.
z;
347 float xy = p_q.
x * p_q.
y;
348 float xz = p_q.
x * p_q.
z;
349 float yz = p_q.
y * p_q.
z;
350 float wx = p_q.
w * p_q.
x;
351 float wy = p_q.
w * p_q.
y;
352 float wz = p_q.
w * p_q.
z;
355 rotationMatrix[0][0] = 1.0f - 2.0f * (yy + zz);
356 rotationMatrix[0][1] = 2.0f * (xy + wz);
357 rotationMatrix[0][2] = 2.0f * (xz - wy);
358 rotationMatrix[0][3] = 0.0f;
360 rotationMatrix[1][0] = 2.0f * (xy - wz);
361 rotationMatrix[1][1] = 1.0f - 2.0f * (xx + zz);
362 rotationMatrix[1][2] = 2.0f * (yz + wx);
363 rotationMatrix[1][3] = 0.0f;
365 rotationMatrix[2][0] = 2.0f * (xz + wy);
366 rotationMatrix[2][1] = 2.0f * (yz - wx);
367 rotationMatrix[2][2] = 1.0f - 2.0f * (xx + yy);
368 rotationMatrix[2][3] = 0.0f;
370 rotationMatrix[3][0] = 0.0f;
371 rotationMatrix[3][1] = 0.0f;
372 rotationMatrix[3][2] = 0.0f;
373 rotationMatrix[3][3] = 1.0f;
375 return rotationMatrix;
388 return IMatrix<4, 4>{1, 0, 0, p_translateX, 0, 1, 0, p_translateY, 0, 0, 1, p_translateZ, 0, 0, 0, 1};
399 return (
translation(p_translation.
x, p_translation.
y, p_translation.
z));
413 return IMatrix<4, 4>{p_scaleX, 0, 0, 0, 0, p_scaleY, 0, 0, 0, 0, p_scaleZ, 0, 0, 0, 0, 1};
424 return (
scale(p_scale.
x, p_scale.
y, p_scale.
z));
435 for (
size_t j = 0; j < SizeY; ++j)
443 for (
size_t i = 0; i < SizeX; ++i)
464 for (
size_t j = 0; j < SizeY; ++j)
472 for (
size_t i = 0; i < SizeX; ++i)
491 std::wstringstream wss;
502 std::stringstream ss;
507 template <
size_t X = SizeX,
size_t Y = SizeY,
typename std::enable_if_t<(X == 4 && Y == 4),
int> = 0>
517 static IMatrix lookAt(
const spk::Vector3 &p_from,
const spk::Vector3 &p_to,
const spk::Vector3 &p_up)
519 const spk::Vector3 forward = ((p_to - p_from).normalize());
520 const spk::Vector3 right = (forward != p_up && forward != p_up.
inverse() ? forward.
cross(p_up).
normalize() : spk::Vector3(1, 0, 0));
521 const spk::Vector3 up = right.
cross(forward);
525 result[0][0] = right.
x;
526 result[0][1] = right.
y;
527 result[0][2] = right.
z;
531 result[2][0] = -forward.
x;
532 result[2][1] = -forward.
y;
533 result[2][2] = -forward.
z;
534 result[3][0] = -right.
dot(p_from);
535 result[3][1] = -up.
dot(p_from);
536 result[3][2] = forward.
dot(p_from);
541 template <
size_t X = SizeX,
size_t Y = SizeY,
typename std::enable_if_t<(X == 4 && Y == 4),
int> = 0>
554 const float rad = spk::MathUtils::degreeToRadian(p_rotationAngle);
561 result[0][0] = c + v.
x * v.
x * (1 - c);
562 result[0][1] = v.
x * v.
y * (1 - c) - v.
z * s;
563 result[0][2] = v.
x * v.
z * (1 - c) + v.
y * s;
565 result[1][0] = v.
y * v.
x * (1 - c) + v.
z * s;
566 result[1][1] = c + v.
y * v.
y * (1 - c);
567 result[1][2] = v.
y * v.
z * (1 - c) - v.
x * s;
569 result[2][0] = v.
z * v.
x * (1 - c) - v.
y * s;
570 result[2][1] = v.
z * v.
y * (1 - c) + v.
x * s;
571 result[2][2] = c + v.
z * v.
z * (1 - c);
581 template <
size_t X = SizeX,
size_t Y = SizeY,
typename std::enable_if_t<(X == 4 && Y == 4),
int> = 0>
596 const float rad = spk::MathUtils::degreeToRadian(p_fov);
597 const float tanHalfFov = tan(rad / 2.0f);
599 result[0][0] = 1.0f / (tanHalfFov * p_aspectRatio);
600 result[1][1] = 1.0f / tanHalfFov;
601 result[2][2] = -(p_farPlane + p_nearPlane) / (p_farPlane - p_nearPlane);
602 result[2][3] = -1.0f;
603 result[3][2] = -(2.0f * p_farPlane * p_nearPlane) / (p_farPlane - p_nearPlane);
609 template <
size_t X = SizeX,
size_t Y = SizeY,
typename std::enable_if_t<(X == 4 && Y == 4),
int> = 0>
622 static IMatrix ortho(
float p_left,
float p_right,
float p_bottom,
float p_top,
float p_nearPlane,
float p_farPlane)
626 result[0][0] = 2.0f / (p_right - p_left);
627 result[1][1] = 2.0f / (p_top - p_bottom);
628 result[2][2] = -2.0f / (p_farPlane - p_nearPlane);
629 result[3][0] = -(p_right + p_left) / (p_right - p_left);
630 result[3][1] = -(p_top + p_bottom) / (p_top - p_bottom);
631 result[3][2] = -(p_farPlane + p_nearPlane) / (p_farPlane - p_nearPlane);
636 template <
size_t X = SizeX,
size_t Y = SizeY,
typename std::enable_if_t<(X == Y),
int> = 0>
643 const size_t N = SizeX;
648 for (
size_t i = 0; i < N; ++i)
651 float maxElem = std::fabs(A[i][i]);
652 for (
size_t r = i + 1; r < N; ++r)
654 float v = std::fabs(A[i][r]);
669 for (
size_t c = 0; c < N; ++c)
671 std::swap(A[c][i], A[c][pivotRow]);
676 for (
size_t r = i + 1; r < N; ++r)
678 float factor = A[i][r] / A[i][i];
679 for (
size_t c = i; c < N; ++c)
681 A[c][r] -= factor * A[c][i];
688 return det *
static_cast<float>(sign);
691 template <
size_t X = SizeX,
size_t Y = SizeY,
typename std::enable_if_t<(X == Y),
int> = 0>
701 template <
size_t X = SizeX,
size_t Y = SizeY,
typename std::enable_if_t<(X == Y),
int> = 0>
711 throw std::runtime_error(
"Matrix inversion requires a square matrix.");
714 const size_t N = SizeX;
718 for (
size_t i = 0; i < N; i++)
720 float maxElem = std::fabs(A[i][i]);
722 for (
size_t k = i + 1; k < N; k++)
724 float val = std::fabs(A[i][k]);
734 for (
size_t col = 0; col < N; col++)
736 std::swap(A[col][i], A[col][pivotRow]);
737 std::swap(B[col][i], B[col][pivotRow]);
741 float pivotVal = A[i][i];
744 throw std::runtime_error(
"Matrix is not invertible (singular pivot encountered).");
747 for (
size_t col = 0; col < N; col++)
749 A[col][i] /= pivotVal;
750 B[col][i] /= pivotVal;
753 for (
size_t row = 0; row < N; row++)
757 float factor = A[i][row];
758 for (
size_t col = 0; col < N; col++)
760 A[col][row] -= factor * A[col][i];
761 B[col][row] -= factor * B[col][i];
776 template <
size_t X = SizeX,
size_t Y = SizeY,
typename std::enable_if_t<(X == 3 && Y == 3),
int> = 0>
786 m[2][0] = p_translateX;
787 m[2][1] = p_translateY;
797 template <
size_t X = SizeX,
size_t Y = SizeY,
typename std::enable_if_t<(X == 3 && Y == 3),
int> = 0>
809 template <
size_t X = SizeX,
size_t Y = SizeY,
typename std::enable_if_t<(X == 3 && Y == 3),
int> = 0>
830 template <
size_t X = SizeX,
size_t Y = SizeY,
typename std::enable_if_t<(X == 3 && Y == 3),
int> = 0>
833 return scale(p_scale.
x, p_scale.
y);
841 template <
size_t X = SizeX,
size_t Y = SizeY,
typename std::enable_if_t<(X == 3 && Y == 3),
int> = 0>
844 const float rad = spk::MathUtils::degreeToRadian(p_angleDegrees);
845 const float c = std::cos(rad);
846 const float s = std::sin(rad);
862 using Matrix2x2 = IMatrix<2, 2>;
863 using Matrix3x3 = IMatrix<3, 3>;
864 using Matrix4x4 = IMatrix<4, 4>;
View of the values belonging to a single matrix column.
Definition spk_matrix.hpp:46
float & operator[](size_t p_index)
Mutable row access within the column.
Definition spk_matrix.hpp:56
const float & operator[](size_t p_index) const
Read-only row access within the column.
Definition spk_matrix.hpp:70
Column-major matrix with basic arithmetic, transforms, and helpers.
Definition spk_matrix.hpp:33
static IMatrix lookAt(const spk::Vector3 &p_from, const spk::Vector3 &p_to, const spk::Vector3 &p_up)
Builds a view matrix looking from one point to another.
Definition spk_matrix.hpp:517
static IMatrix< 3, 3 > rotationZ(float p_angleDegrees)
Definition spk_matrix.hpp:842
const Column & operator[](size_t p_index) const
Accesses a column.
Definition spk_matrix.hpp:164
static IMatrix< 4, 4 > translation(spk::Vector3 p_translation)
Builds a translation matrix from a vector.
Definition spk_matrix.hpp:397
static IMatrix< 4, 4 > rotation(const spk::Quaternion &p_q)
Converts a quaternion to a 4x4 rotation matrix.
Definition spk_matrix.hpp:342
static IMatrix< 4, 4 > scale(float p_scaleX, float p_scaleY, float p_scaleZ)
Builds a scale matrix.
Definition spk_matrix.hpp:411
Vector3 operator*(const Vector3 &p_vec) const
Transforms a 3D vector with a 3x3 matrix (homogeneous w=1).
Definition spk_matrix.hpp:180
Vector2 operator*(const Vector2 &p_vec) const
Transforms a 2D vector with a 3x3 matrix (homogeneous).
Definition spk_matrix.hpp:210
bool operator==(const IMatrix &p_other) const
Compares two matrices with tolerant float comparison.
Definition spk_matrix.hpp:264
Column & operator[](size_t p_index)
Accesses a column.
Definition spk_matrix.hpp:149
IMatrix(std::initializer_list< float > p_values)
Builds from a flat initializer list (column-major).
Definition spk_matrix.hpp:118
std::string toString() const
Converts the matrix to a string representation.
Definition spk_matrix.hpp:500
static IMatrix rotateAroundAxis(const spk::Vector3 &p_axis, const float &p_rotationAngle)
Builds a rotation matrix around an arbitrary axis.
Definition spk_matrix.hpp:550
IMatrix()
Builds an identity matrix.
Definition spk_matrix.hpp:88
IMatrix< SizeX, SizeY > inverse() const
Returns the inverse of a square matrix.
Definition spk_matrix.hpp:707
static IMatrix< 4, 4 > scale(spk::Vector3 p_scale)
Builds a scale matrix from a vector.
Definition spk_matrix.hpp:422
static IMatrix< 3, 3 > translation(const spk::Vector2 &p_translation)
Creates a 2D translation matrix from a vector.
Definition spk_matrix.hpp:798
static spk::IMatrix< SizeX, SizeY > identity()
Returns an identity matrix of the same dimension.
Definition spk_matrix.hpp:139
float determinant() const
Computes determinant for square matrices.
Definition spk_matrix.hpp:641
friend std::wostream & operator<<(std::wostream &p_os, const IMatrix &p_mat)
Streams the matrix to a wide output stream.
Definition spk_matrix.hpp:433
bool isInvertible() const
Checks if the matrix is invertible (determinant non-zero).
Definition spk_matrix.hpp:696
static IMatrix< 3, 3 > scale(float p_scaleX, float p_scaleY)
Creates a 2D scale matrix.
Definition spk_matrix.hpp:810
static IMatrix< 4, 4 > rotation(float p_angleX, float p_angleY, float p_angleZ)
Builds a 4x4 rotation matrix from Euler angles in degrees.
Definition spk_matrix.hpp:298
static IMatrix ortho(float p_left, float p_right, float p_bottom, float p_top, float p_nearPlane, float p_farPlane)
Builds an orthographic projection matrix.
Definition spk_matrix.hpp:622
static IMatrix< 3, 3 > translation(float p_translateX, float p_translateY)
Creates a 2D translation matrix.
Definition spk_matrix.hpp:777
static IMatrix< 4, 4 > translation(float p_translateX, float p_translateY, float p_translateZ)
Builds a translation matrix.
Definition spk_matrix.hpp:386
std::wstring toWstring() const
Converts the matrix to a wide string representation.
Definition spk_matrix.hpp:489
IMatrix< SizeX, SizeY > operator*(const IMatrix< SizeX, SizeY > &p_other) const
Multiplies two matrices of the same dimensions.
Definition spk_matrix.hpp:240
static IMatrix perspective(float p_fov, float p_aspectRatio, float p_nearPlane, float p_farPlane)
Builds a perspective projection matrix.
Definition spk_matrix.hpp:592
Vector4 operator*(const Vector4 &p_vec) const
Transforms a 4D vector with a 4x4 matrix.
Definition spk_matrix.hpp:225
bool operator!=(const IMatrix &p_other) const
Inequality helper.
Definition spk_matrix.hpp:285
IMatrix(float *p_values)
Builds a matrix from a contiguous column-major array.
Definition spk_matrix.hpp:103
static IMatrix< 4, 4 > rotation(spk::Vector3 p_angle)
Builds a 4x4 rotation matrix from Euler components in degrees.
Definition spk_matrix.hpp:328
static IMatrix< 3, 3 > scale(const spk::Vector2 &p_scale)
Creates a 2D scale matrix from a vector.
Definition spk_matrix.hpp:831
friend std::ostream & operator<<(std::ostream &p_os, const IMatrix &p_mat)
Streams the matrix to a narrow output stream.
Definition spk_matrix.hpp:462
Represents a rotation using (x, y, z, w) and offers common conversions.
Definition spk_quaternion.hpp:19
float x
X component of the quaternion vector part.
Definition spk_quaternion.hpp:22
float w
W component representing the scalar part.
Definition spk_quaternion.hpp:28
float z
Z component of the quaternion vector part.
Definition spk_quaternion.hpp:26
float y
Y component of the quaternion vector part.
Definition spk_quaternion.hpp:24
TType x
X component.
Definition spk_vector2.hpp:44
TType y
Y component.
Definition spk_vector2.hpp:48
TType x
X component.
Definition spk_vector3.hpp:43
IVector3< float > normalize() const
Return the vector once normalized by its length.
Definition spk_vector3.hpp:521
float dot(const IVector3 &p_other) const
Computes dot product with another vector.
Definition spk_vector3.hpp:560
TType z
Z component.
Definition spk_vector3.hpp:51
TType y
Y component.
Definition spk_vector3.hpp:47
IVector3 inverse() const
Return the inverse vector.
Definition spk_vector3.hpp:344
IVector3 cross(const IVector3 &p_other) const
Computes 3D cross product.
Definition spk_vector3.hpp:576
TType z
Z component.
Definition spk_vector4.hpp:51
TType w
W component.
Definition spk_vector4.hpp:55
TType y
Y component.
Definition spk_vector4.hpp:47
TType x
X component.
Definition spk_vector4.hpp:43
Wraps arithmetic values to compare with tolerance for floating-point inputs.
Definition spk_safe_comparand.hpp:17