LkEngine 0.1.2
 
Loading...
Searching...
No Matches
Math.h
Go to the documentation of this file.
1
5#pragma once
6
11#include <random>
12#include <time.h>
13
14#include <glm/glm.hpp>
15#include <glm/ext/matrix_common.hpp>
16#include <glm/gtc/matrix_transform.hpp>
17#include <glm/gtx/quaternion.hpp>
18#include <glm/gtc/type_ptr.hpp>
19#include <glm/gtx/rotate_vector.hpp>
20#include <glm/gtx/vector_angle.hpp>
21#include <glm/gtx/norm.hpp>
22
23#include "LkEngine/Core/Core.h"
24
26#include "LkEngine/Core/Math/Rotator.h"
27#include "LkEngine/Core/Math/Quaternion.h"
28
29namespace LkEngine
30{
31 struct LTransformComponent;
32
33 static std::string ToString(const LVector2& Vector, const uint8_t F = 2)
34 {
35 return Vector.ToString();
36 }
37
38 static std::string ToString(const LVector& Vector, const uint8_t F = 2)
39 {
40 return Vector.ToString();
41 }
42
43 static std::string ToString(const LVector4& Vector, const uint8_t F = 2)
44 {
45 return Vector.ToString();
46 }
47
48 static std::string ToString(const glm::vec3& Vector, const uint8_t F = 2)
49 {
50 return LK_FMT_LIB::format("({:.2f}, {:.2f}, {:.2f})", Vector.x, Vector.y, Vector.z);
51 }
52}
53
54struct b2Vec2;
55struct b2Vec3;
56
57namespace LkEngine::Math {
58
72 enum class Shape
73 {
74 None = 0,
75 Rectangle,
76 Circle,
77 Triangle,
78 Hexagon,
79 };
80
84 FORCEINLINE glm::vec3 Scale(glm::vec3& Vector, const float ScaleFactor)
85 {
86 return (Vector * ScaleFactor) / glm::length(Vector);
87 }
88
92 FORCEINLINE bool DecomposeTransform(const glm::mat4& Transform, glm::vec3& Translation, glm::quat& Rotation, glm::vec3& Scale)
93 {
94 using T = float;
95
96 glm::mat4 LocalMatrix(Transform);
97
98 if (glm::epsilonEqual(LocalMatrix[3][3], static_cast<T>(0), glm::epsilon<T>()))
99 {
100 return false;
101 }
102
103 Translation = glm::vec3(LocalMatrix[3]);
104 LocalMatrix[3] = glm::vec4(0, 0, 0, LocalMatrix[3].w);
105
106 glm::vec3 Row[3] = {};
107 /* Scale and shear. */
108 for (glm::length_t i = 0; i < 3; ++i)
109 {
110 for (glm::length_t j = 0; j < 3; ++j)
111 {
112 Row[i][j] = LocalMatrix[i][j];
113 }
114 }
115
116 /* Compute the X-scale and normalize the first row. */
117 Scale.x = glm::length(Row[0]);
118 Row[0] = LkEngine::Math::Scale(Row[0], static_cast<T>(1));
119
120 /* Compute the Y-scale and normalize the second row. */
121 Scale.y = glm::length(Row[1]);
122 Row[1] = LkEngine::Math::Scale(Row[1], static_cast<T>(1));
123
124 /* Get the Z-scale and normalize the third row. */
125 Scale.z = glm::length(Row[2]);
126 Row[2] = LkEngine::Math::Scale(Row[2], static_cast<T>(1));
127
128 /* Get the rotation as a quaternion. */
129 int i, j, k = 0;
130 T SquareRoot, Trace = Row[0].x + Row[1].y + Row[2].z;
131 if (Trace > static_cast<T>(0))
132 {
133 SquareRoot = sqrt(Trace + static_cast<T>(1));
134 Rotation.w = static_cast<T>(0.5) * SquareRoot;
135 SquareRoot = static_cast<T>(0.5) / SquareRoot;
136
137 Rotation.x = SquareRoot * (Row[1].z - Row[2].y);
138 Rotation.y = SquareRoot * (Row[2].x - Row[0].z);
139 Rotation.z = SquareRoot * (Row[0].y - Row[1].x);
140 }
141 else
142 {
143 static int Next[3] = { 1, 2, 0 };
144 i = 0;
145 if (Row[1].y > Row[0].x)
146 {
147 i = 1;
148 }
149 if (Row[2].z > Row[i][i])
150 {
151 i = 2;
152 }
153
154 j = Next[i];
155 k = Next[j];
156
157 SquareRoot = sqrt(Row[i][i] - Row[j][j] - Row[k][k] + static_cast<T>(1.0));
158
159 Rotation[i] = static_cast<T>(0.5) * SquareRoot;
160 SquareRoot = static_cast<T>(0.5) / SquareRoot;
161 Rotation[j] = SquareRoot * (Row[i][j] + Row[j][i]);
162 Rotation[k] = SquareRoot * (Row[i][k] + Row[k][i]);
163 Rotation.w = SquareRoot * (Row[j][k] - Row[k][j]);
164 }
165
166 return true;
167 }
168
172 FORCEINLINE glm::mat4 TransformMatrix(glm::vec3& Translation, glm::quat& Rotation, glm::vec3& Scale)
173 {
174 return glm::translate(glm::mat4(1.0f), Translation)
175 * glm::toMat4(Rotation)
176 * glm::scale(glm::mat4(1.0f), Scale);
177 }
178
179 glm::mat4 TransformMatrix2D(const glm::vec3& translation, float rot, const glm::vec3& scale);
180
184 template<typename T = float>
185 glm::vec2 ConvertToWorldCoordinates(glm::vec2 NdcCoordinates, T WindowWidth, T WindowHeight)
186 {
187 static_assert(std::is_floating_point_v<T> || std::is_integral_v<T>);
188 using F = std::conditional_t<std::is_floating_point_v<T>, T, float>;
189
190 glm::vec4 ConvertedCoordinates = glm::vec4(
191 (static_cast<F>(NdcCoordinates.x) / static_cast<F>(WindowWidth) - 0.5f) * 2.0f,
192 (static_cast<F>(NdcCoordinates.y) / static_cast<F>(WindowHeight) - 0.5f) * 2.0f,
193 -1.0,
194 1.0f
195 );
196
197 return glm::vec2(ConvertedCoordinates.x, ConvertedCoordinates.y);
198 }
199
205 template<typename TVector>
206 FORCEINLINE TVector ScreenToWorldCoordinates2D(const TVector& ScreenCoordinates,
207 const glm::mat4& InverseProjectionMatrix,
208 const glm::mat4& InverseViewMatrix,
209 const glm::vec4& Viewport)
210 {
211 static_assert(std::disjunction_v<
212 std::is_same<TVector, glm::vec2>,
213 std::is_same<TVector, LVector2>>, "TVector must valid vector type");
214
215 const int WindowWidth = Viewport.z;
216 const int WindowHeight = Viewport.w;
217
218 glm::vec4 ClipCoordinates = glm::vec4(
219 ((2.0f * ScreenCoordinates.x) / (WindowWidth - 1.0f)),
220 (1.0f - 2.0f * ScreenCoordinates.y) / WindowHeight,
221 0.0f,
222 1.0f
223 );
224
225 /* Multiply by the inverse projection. */
226 glm::vec4 EyeCoordinates = InverseProjectionMatrix * ClipCoordinates;
227 EyeCoordinates.z = -1.0f; // Point into the scene.
228 EyeCoordinates.w = 0.0f;
229
230 glm::vec4 WorldCoordinates = InverseViewMatrix * EyeCoordinates;
231
232 return TVector(WorldCoordinates.x, WorldCoordinates.y);
233 }
234
238 template<typename TVector = glm::vec3, typename TVec2>
239 FORCEINLINE TVector ConvertScreenToWorldCoordinates(const TVec2& ScreenCoordinates,
240 const float Depth,
241 const glm::mat4& ViewMatrix,
242 const glm::mat4& ProjectionMatrix,
243 const glm::vec4& Viewport)
244 {
245 static_assert(std::conjunction_v<
246 std::disjunction<
247 std::is_same<TVector, glm::vec3>,
248 std::is_same<TVector, LVector>
249 >,
250 std::disjunction<
251 std::is_same<TVec2, glm::vec2>,
252 std::is_same<TVec2, LVector2>
253 >>, "TVector and TVec2 must valid vector types");
254 LK_CORE_ASSERT((Depth >= 0.0f && Depth <= 1.0f), "Depth not in range of 0.0 to 1.0");
255 LK_CORE_DEBUG_TAG("MathLibrary" "ConvertScreenToWorldCoordinates Type='{}'", Core::TypeName<TVector>());
256
257 glm::vec3 ScreenCoordinatesWithDepth{};
258
259 if constexpr (std::is_same_v<TVec2, glm::vec2>)
260 {
261 ScreenCoordinatesWithDepth = { ScreenCoordinates.x, ScreenCoordinates.y, Depth };
262 }
263 else if constexpr (std::is_same_v<TVec2, LVector2>)
264 {
265 ScreenCoordinatesWithDepth = { ScreenCoordinates.X, ScreenCoordinates.Y, Depth };
266 }
267 else
268 {
269 LK_CORE_ASSERT(false, "ConvertScreenToWorldCoordinates failed");
270 }
271
272 return TVector(glm::unProject(ScreenCoordinatesWithDepth, ViewMatrix, ProjectionMatrix, Viewport));
273 }
274
275 glm::vec2 ScreenToWorld2D(const glm::vec2& ndc, const glm::mat4& inv_proj, const LTransformComponent& Transform);
276 float Get2DRotationFromQuaternion(const glm::quat& quat);
277
282 template<typename TVector>
283 FORCEINLINE TVector GetForwardVector(const glm::mat4& TransformMatrix)
284 {
285 static_assert(std::disjunction_v<
286 std::is_same<TVector, glm::vec3>,
287 std::is_same<TVector, LVector>>,
288 "TVector must valid vector type");
289 return TVector(glm::normalize(glm::vec3(-TransformMatrix[2][0], -TransformMatrix[2][1], -TransformMatrix[2][2])));
290 }
291
296 template<typename TVector>
297 FORCEINLINE TVector GetRightVector(const glm::mat4& TransformMatrix)
298 {
299 static_assert(std::disjunction_v<
300 std::is_same<TVector, glm::vec3>,
301 std::is_same<TVector, LVector>>,
302 "TVector must valid vector type");
303 return glm::normalize(glm::vec3(TransformMatrix[0][0], TransformMatrix[0][1], TransformMatrix[0][2]));
304 }
305
306 template<typename TVector>
307 FORCEINLINE TVector Normalize(const TVector& InVector)
308 {
309 static_assert(std::disjunction_v<
310 std::is_same<TVector, LVector>,
311 std::is_same<TVector, LVector2>,
312 std::is_same<TVector, glm::vec3>,
313 std::is_same<TVector, glm::vec2>>,
314 "TVector must valid vector type");
315 return TVector(glm::normalize(InVector));
316 }
317
320}
321
Core header.
FORCEINLINE TVector GetRightVector(const glm::mat4 &TransformMatrix)
Calculate the right vector from a transform matrix.
Definition Math.h:297
FORCEINLINE TVector ScreenToWorldCoordinates2D(const TVector &ScreenCoordinates, const glm::mat4 &InverseProjectionMatrix, const glm::mat4 &InverseViewMatrix, const glm::vec4 &Viewport)
Convert screen coordinates to its world counterpart in 2D.
Definition Math.h:206
FORCEINLINE TVector GetForwardVector(const glm::mat4 &TransformMatrix)
Calculate the forward vector from a transform matrix.
Definition Math.h:283
glm::vec2 ConvertToWorldCoordinates(glm::vec2 NdcCoordinates, T WindowWidth, T WindowHeight)
Calculate world coordinates.
Definition Math.h:185
FORCEINLINE TVector ConvertScreenToWorldCoordinates(const TVec2 &ScreenCoordinates, const float Depth, const glm::mat4 &ViewMatrix, const glm::mat4 &ProjectionMatrix, const glm::vec4 &Viewport)
Convert screen coordinates to its world counterpart.
Definition Math.h:239
FORCEINLINE glm::mat4 TransformMatrix(glm::vec3 &Translation, glm::quat &Rotation, glm::vec3 &Scale)
Calculate a transform matrix.
Definition Math.h:172
FORCEINLINE glm::vec3 Scale(glm::vec3 &Vector, const float ScaleFactor)
Scale a vector.
Definition Math.h:84
FORCEINLINE bool DecomposeTransform(const glm::mat4 &Transform, glm::vec3 &Translation, glm::quat &Rotation, glm::vec3 &Scale)
Decompose a transform.
Definition Math.h:92
Mathematical vectors.
TVector4< float > LVector4
Definition Vector.h:60
LVector3 LVector
Definition Vector.h:68
TVector2< float > LVector2
Definition Vector.h:48
Definition Asset.h:11
Definition Components.h:69