Skip to content

Commit bec0c32

Browse files
committed
remade matrix classes to reduce dependencies and enable constexpr
1 parent 2d30935 commit bec0c32

22 files changed

+3231
-163
lines changed

engine/utils/math/Projection.h

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
//
2+
// Copyright (c) 2022 Jonathan Moallem (@J-Mo63) & Aryeh Zinn (@Raelr)
3+
//
4+
// This code is released under an unmodified zlib license.
5+
// For conditions of distribution and use, please see:
6+
// https://opensource.org/licenses/Zlib
7+
//
8+
9+
#ifndef SIEGE_ENGINE_UTILS_MATH_PROJECTION_H
10+
#define SIEGE_ENGINE_UTILS_MATH_PROJECTION_H
11+
12+
#include "../Logging.h"
13+
#include "mat/Mat4.h"
14+
#include "vec/Vec2.h"
15+
#include "vec/Vec3.h"
16+
17+
namespace Siege
18+
{
19+
/**
20+
* Creates a right-handed perspective matrix
21+
* @param fovy the vertical field of view of the perspective projection
22+
* @param aspect the aspect ratio of the perspective view
23+
* @param near the near plane
24+
* @param far the far plane
25+
* @return a new matrix with the provided perspective values
26+
*/
27+
inline constexpr Mat4 Perspective(float fovy, float aspect, float near, float far)
28+
{
29+
float const tanHalfFovy = tan(fovy / 2);
30+
31+
Mat4 result(0);
32+
result[0][0] = 1 / (aspect * tanHalfFovy);
33+
result[1][1] = -1 / tanHalfFovy;
34+
result[2][2] = far / (near - far);
35+
result[2][3] = -1;
36+
result[3][2] = -(far * near) / (far - near);
37+
return result;
38+
}
39+
40+
/**
41+
* Creates a right-handed orthographic projection
42+
* @param left the left side of the screen
43+
* @param right the right side (the far edge of the screen)
44+
* @param bottom the bottom of the screen
45+
* @param top the top of the screen
46+
* @param zNear the near clipping plane
47+
* @param zFar the far clipping plane
48+
* @return a new matrix with the orthographic projection
49+
*/
50+
inline constexpr Mat4 Orthographic(float left,
51+
float right,
52+
float bottom,
53+
float top,
54+
float zNear,
55+
float zFar)
56+
{
57+
Mat4 result(1);
58+
result[0][0] = 2.f / (right - left);
59+
result[1][1] = -2.f / (bottom - top);
60+
result[2][2] = -1.f / (zFar - zNear);
61+
result[3][0] = -(right + left) / (right - left);
62+
result[3][1] = -(bottom + top) / (bottom - top);
63+
result[3][2] = -zNear / (zFar - zNear);
64+
return result;
65+
}
66+
67+
/**
68+
* Un-projects a point from 2D view space to 3D world space
69+
* @param viewMatrix the view matrix to un-project from
70+
* @param projection the projection matrix used by the scene
71+
* @param ndc the normalised device coordinates (-1 to 1 on the x and y coordinates and 0 to 1 on
72+
* the z coordinates)
73+
* @return a 3D vector specifying the position in 3D space
74+
*/
75+
inline constexpr Vec3 UnProjectPoint3D(const Mat4& viewMatrix,
76+
const Mat4 projection,
77+
const Vec4& ndc)
78+
{
79+
Mat4 inv = Mat4::Inverse(projection * viewMatrix);
80+
81+
Vec4 unProjected = inv* Vec4 {ndc.XYZ(), 1.f};
82+
return unProjected.XYZ() / unProjected.w;
83+
}
84+
85+
/**
86+
* Converts a 3D coordinate to screen space
87+
* @param worldCoords the position in 3D space
88+
* @param viewProjection the combined view + projection matrix
89+
* @param width the width of the viewport
90+
* @param height the height of the viewport
91+
* @return a 2D vector specifying the position in screen space
92+
*/
93+
inline constexpr Vec2 WorldToScreen(const Vec3& worldCoords,
94+
const Mat4& viewProjection,
95+
float width,
96+
float height)
97+
{
98+
Siege::Vec4 clipCoords = viewProjection * Siege::Vec4 {worldCoords.XYZ(), 1.f};
99+
Siege::Vec3 coords = clipCoords.XYZ() / clipCoords.w;
100+
101+
float x = ((coords.x + 1.f) * 0.5f) * width;
102+
float y = ((coords.y + 1.f) * 0.5f) * height;
103+
104+
return {x, y};
105+
}
106+
} // namespace Siege
107+
108+
#endif // SIEGE_ENGINE_PROJECTION_H

engine/utils/math/Transform.h

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
//
2+
// Copyright (c) 2022 Jonathan Moallem (@J-Mo63) & Aryeh Zinn (@Raelr)
3+
//
4+
// This code is released under an unmodified zlib license.
5+
// For conditions of distribution and use, please see:
6+
// https://opensource.org/licenses/Zlib
7+
//
8+
9+
#ifndef SIEGE_ENGINE_UTILS_MATH_TRANSFORM_H
10+
#define SIEGE_ENGINE_UTILS_MATH_TRANSFORM_H
11+
12+
#include <cmath>
13+
14+
#include "mat/Mat4.h"
15+
#include "vec/Vec2.h"
16+
#include "vec/Vec3.h"
17+
18+
namespace Siege
19+
{
20+
/**
21+
* Creates a view matrix which is pointing at a specific location in 3D space
22+
* @param eye the position of the camera
23+
* @param center the location the camera is pointing at
24+
* @param up the global up direction in world space (defaults to -1 on the y axis)
25+
* @return a new 4x4 matrix with the view matrix values
26+
*/
27+
inline constexpr Mat4 LookAt(const Vec3& eye, const Vec3& center, const Vec3& up = Vec3::Up())
28+
{
29+
Vec3 const f(Vec3::Normalise(center - eye));
30+
Vec3 const s(Vec3::Normalise(Vec3::Cross(f, up)));
31+
Vec3 const u(Vec3::Cross(s, f));
32+
33+
Mat4 result {1};
34+
result[0][0] = s.x;
35+
result[1][0] = s.y;
36+
result[2][0] = s.z;
37+
result[0][1] = u.x;
38+
result[1][1] = u.y;
39+
result[2][1] = u.z;
40+
result[0][2] = -f.x;
41+
result[1][2] = -f.y;
42+
result[2][2] = -f.z;
43+
result[3][0] = -Vec3::Dot(s, eye);
44+
result[3][1] = -Vec3::Dot(u, eye);
45+
result[3][2] = Vec3::Dot(f, eye);
46+
return result;
47+
}
48+
49+
/**
50+
* Creates a translation matrix. A translation matrix specifies a movement in space
51+
* @param matrix the 4x4 matrix to translate
52+
* @param position the position to move the matrix to
53+
* @return a new matrix with the provided translation
54+
*/
55+
inline constexpr Mat4 Translate(const Mat4& matrix, const Vec3& position)
56+
{
57+
Mat4 result = matrix;
58+
result[3] =
59+
matrix[0] * position[0] + matrix[1] * position[1] + matrix[2] * position[2] + matrix[3];
60+
return result;
61+
}
62+
63+
/**
64+
* Creates a rotation matrix
65+
* @param matrix the matrix to rotate
66+
* @param angle the angle of rotation
67+
* @param rotation the axis to rotate the matrix on (specified by using 1 for the axis)
68+
* @return a new matrix specifying the rotation
69+
*/
70+
inline constexpr Mat4 Rotate(const Mat4& matrix, float angle, const Vec3& rotation)
71+
{
72+
float const a = angle;
73+
float const c = cos(a);
74+
float const s = sin(a);
75+
76+
Vec3 axis(Vec3::Normalise(rotation));
77+
Vec3 temp((1 - c) * axis);
78+
79+
Mat4 rotate;
80+
rotate[0][0] = c + temp[0] * axis[0];
81+
rotate[0][1] = temp[0] * axis[1] + s * axis[2];
82+
rotate[0][2] = temp[0] * axis[2] - s * axis[1];
83+
84+
rotate[1][0] = temp[1] * axis[0] - s * axis[2];
85+
rotate[1][1] = c + temp[1] * axis[1];
86+
rotate[1][2] = temp[1] * axis[2] + s * axis[0];
87+
88+
rotate[2][0] = temp[2] * axis[0] + s * axis[1];
89+
rotate[2][1] = temp[2] * axis[1] - s * axis[0];
90+
rotate[2][2] = c + temp[2] * axis[2];
91+
92+
Mat4 result;
93+
result[0] = matrix[0] * rotate[0][0] + matrix[1] * rotate[0][1] + matrix[2] * rotate[0][2];
94+
result[1] = matrix[0] * rotate[1][0] + matrix[1] * rotate[1][1] + matrix[2] * rotate[1][2];
95+
result[2] = matrix[0] * rotate[2][0] + matrix[1] * rotate[2][1] + matrix[2] * rotate[2][2];
96+
result[3] = matrix[3];
97+
return result;
98+
}
99+
100+
/**
101+
* Creates a scale matrix
102+
* @param matrix the matrix to scale
103+
* @param scale the dimensions to scale the matrix by
104+
* @return a matrix with the new scaling factors
105+
*/
106+
inline constexpr Mat4 Scale(const Mat4& matrix, const Vec3 scale)
107+
{
108+
Mat4 result;
109+
result[0] = matrix[0] * scale.x;
110+
result[1] = matrix[1] * scale.y;
111+
result[2] = matrix[2] * scale.z;
112+
result[3] = matrix[3];
113+
return result;
114+
}
115+
116+
/**
117+
* Creates a transform matrix in 3D space
118+
* @param position the position in 3D space
119+
* @param rotation the rotation in 3D space
120+
* @param scale the scale in 3D space
121+
* @return a new 4x4 matrix specifying the 3D transform
122+
*/
123+
inline constexpr Mat4 Transform3D(const Vec3& position, const Vec3& rotation, const Vec3& scale)
124+
{
125+
const float cosR = Float::Cos(rotation.z);
126+
const float sinR = Float::Sin(rotation.z);
127+
const float cosP = Float::Cos(rotation.x);
128+
const float sinP = Float::Sin(rotation.x);
129+
const float cosY = Float::Cos(rotation.y);
130+
const float sinY = Float::Sin(rotation.y);
131+
132+
return {{scale.x * (cosY * cosR + sinY * sinP * sinR),
133+
scale.x * (cosP * sinR),
134+
scale.x * (cosY * sinP * sinR - cosR * sinY)},
135+
{scale.y * (cosR * sinY * sinP - cosY * sinR),
136+
scale.y * (cosP * cosR),
137+
scale.y * (cosY * cosR * sinP + sinY * sinR)},
138+
{scale.z * (cosP * sinY), scale.z * (-sinP), scale.z * (cosY * cosP)},
139+
{position.XYZ(), 1.0f}};
140+
}
141+
142+
/**
143+
* Calculates the normal matrix for a 3D object
144+
* @param rotation the rotation of the object
145+
* @param scale the scale of the object
146+
* @return a 4x4 matrix specifying the object normals
147+
*/
148+
inline constexpr Mat4 Normal(const Vec3& rotation, const Vec3& scale)
149+
{
150+
const float cosR = Float::Cos(rotation.z);
151+
const float sinR = Float::Sin(rotation.z);
152+
const float cosP = Float::Cos(rotation.x);
153+
const float sinP = Float::Sin(rotation.x);
154+
const float cosY = Float::Cos(rotation.y);
155+
const float SinY = Float::Sin(rotation.y);
156+
157+
Siege::Vec3 inverseScale = 1.0f / scale;
158+
159+
return {{
160+
inverseScale.x * (cosY * cosR + SinY * sinP * sinR),
161+
inverseScale.x * (cosP * sinR),
162+
inverseScale.x * (cosY * sinP * sinR - cosR * SinY),
163+
},
164+
{
165+
inverseScale.y * (cosR * SinY * sinP - cosY * sinR),
166+
inverseScale.y * (cosP * cosR),
167+
inverseScale.y * (cosY * cosR * sinP + SinY * sinR),
168+
},
169+
{
170+
inverseScale.z * (cosP * SinY),
171+
inverseScale.z * (-sinP),
172+
inverseScale.z * (cosY * cosP),
173+
}};
174+
}
175+
} // namespace Siege
176+
177+
#endif // SIEGE_ENGINE_UTILS_MATH_TRANSFORM_H

engine/utils/math/mat/Equality.h

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
//
2+
// Copyright (c) 2022 Jonathan Moallem (@J-Mo63) & Aryeh Zinn (@Raelr)
3+
//
4+
// This code is released under an unmodified zlib license.
5+
// For conditions of distribution and use, please see:
6+
// https://opensource.org/licenses/Zlib
7+
//
8+
9+
#ifndef SIEGE_ENGINE_UTILS_MATH_MAT_EQUALITY_H
10+
#define SIEGE_ENGINE_UTILS_MATH_MAT_EQUALITY_H
11+
12+
#include "Mat.h"
13+
#include <cmath>
14+
15+
namespace Siege
16+
{
17+
/**
18+
* A fuzzy equals comparison function. Checks if two 4x4 matrices are equal within a given tolerance
19+
* level
20+
* @tparam T the type of numerical value stored by the matrix
21+
* @param lhs the matrix on the left hand side of the operation
22+
* @param rhs the matrix on the right hand side of the operation
23+
* @return a boolean specifying if they are equal within the given tolerance
24+
*/
25+
template<typename T>
26+
inline constexpr bool FEquals(const Mat<T, 4, 4>& lhs, const Mat<T, 4, 4>& rhs)
27+
{
28+
T epsilon = std::numeric_limits<T>::epsilon();
29+
30+
return (lhs[0][0] - rhs[0][0] <= epsilon) && (lhs[0][1] - rhs[0][1] <= epsilon) &&
31+
(lhs[0][2] - rhs[0][2] <= epsilon) && (lhs[0][3] - rhs[0][3] <= epsilon) &&
32+
(lhs[1][0] - rhs[1][0] <= epsilon) && (lhs[1][1] - rhs[1][1] <= epsilon) &&
33+
(lhs[1][2] - rhs[1][2] <= epsilon) && (lhs[1][3] - rhs[1][3] <= epsilon) &&
34+
(lhs[2][0] - rhs[2][0] <= epsilon) && (lhs[2][1] - rhs[2][1] <= epsilon) &&
35+
(lhs[2][2] - rhs[2][2] <= epsilon) && (lhs[2][3] - rhs[2][3] <= epsilon) &&
36+
(lhs[3][0] - rhs[3][0] <= epsilon) && (lhs[3][1] - rhs[3][1] <= epsilon) &&
37+
(lhs[3][2] - rhs[3][2] <= epsilon) && (lhs[3][3] - rhs[3][3] <= epsilon);
38+
}
39+
40+
/**
41+
* A fuzzy equals comparison function. Checks if two 3x3 matrices are equal within a given tolerance
42+
* level
43+
* @tparam T the type of numerical value stored by the matrix
44+
* @param lhs the matrix on the left hand side of the operation
45+
* @param rhs the matrix on the right hand side of the operation
46+
* @return a boolean specifying if they are equal within the given tolerance
47+
*/
48+
template<typename T>
49+
inline constexpr bool FEquals(const Mat<T, 3, 3>& lhs, const Mat<T, 3, 3>& rhs)
50+
{
51+
T epsilon = std::numeric_limits<T>::epsilon();
52+
53+
return (lhs[0][0] - rhs[0][0] <= epsilon) && (lhs[0][1] - rhs[0][1] <= epsilon) &&
54+
(lhs[0][2] - rhs[0][2] <= epsilon) && (lhs[1][0] - rhs[1][0] <= epsilon) &&
55+
(lhs[1][1] - rhs[1][1] <= epsilon) && (lhs[1][2] - rhs[1][2] <= epsilon) &&
56+
(lhs[2][0] - rhs[2][0] <= epsilon) && (lhs[2][1] - rhs[2][1] <= epsilon) &&
57+
(lhs[2][2] - rhs[2][2] <= epsilon);
58+
}
59+
60+
/**
61+
* A fuzzy equals comparison function. Checks if two 2x2 matrices are equal within a given tolerance
62+
* level
63+
* @tparam T the type of numerical value stored by the matrix
64+
* @param lhs the matrix on the left hand side of the operation
65+
* @param rhs the matrix on the right hand side of the operation
66+
* @return a boolean specifying if they are equal within the given tolerance
67+
*/
68+
template<typename T>
69+
inline constexpr bool FEquals(const Mat<T, 2, 2>& lhs, const Mat<T, 2, 2>& rhs)
70+
{
71+
T epsilon = std::numeric_limits<T>::epsilon();
72+
return (lhs[0][0] - rhs[0][0] <= epsilon) && (lhs[0][1] - rhs[0][1] <= epsilon) &&
73+
(lhs[1][0] - rhs[1][0] <= epsilon) && (lhs[1][1] - rhs[1][1] <= epsilon);
74+
}
75+
} // namespace Siege
76+
77+
#endif // SIEGE_ENGINE_UTILS_MATH_MAT_EQUALITY_H

0 commit comments

Comments
 (0)