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>
26#include "LkEngine/Core/Math/Rotator.h"
27#include "LkEngine/Core/Math/Quaternion.h"
31 struct LTransformComponent;
33 static std::string ToString(
const LVector2& Vector,
const uint8_t F = 2)
35 return Vector.ToString();
38 static std::string ToString(
const LVector& Vector,
const uint8_t F = 2)
40 return Vector.ToString();
43 static std::string ToString(
const LVector4& Vector,
const uint8_t F = 2)
45 return Vector.ToString();
48 static std::string ToString(
const glm::vec3& Vector,
const uint8_t F = 2)
50 return LK_FMT_LIB::format(
"({:.2f}, {:.2f}, {:.2f})", Vector.x, Vector.y, Vector.z);
57namespace LkEngine::Math {
84 FORCEINLINE glm::vec3
Scale(glm::vec3& Vector,
const float ScaleFactor)
86 return (Vector * ScaleFactor) / glm::length(Vector);
92 FORCEINLINE
bool DecomposeTransform(
const glm::mat4& Transform, glm::vec3& Translation, glm::quat& Rotation, glm::vec3& Scale)
96 glm::mat4 LocalMatrix(Transform);
98 if (glm::epsilonEqual(LocalMatrix[3][3],
static_cast<T
>(0), glm::epsilon<T>()))
103 Translation = glm::vec3(LocalMatrix[3]);
104 LocalMatrix[3] = glm::vec4(0, 0, 0, LocalMatrix[3].w);
106 glm::vec3 Row[3] = {};
108 for (glm::length_t i = 0; i < 3; ++i)
110 for (glm::length_t j = 0; j < 3; ++j)
112 Row[i][j] = LocalMatrix[i][j];
117 Scale.x = glm::length(Row[0]);
121 Scale.y = glm::length(Row[1]);
125 Scale.z = glm::length(Row[2]);
130 T SquareRoot, Trace = Row[0].x + Row[1].y + Row[2].z;
131 if (Trace >
static_cast<T
>(0))
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;
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);
143 static int Next[3] = { 1, 2, 0 };
145 if (Row[1].y > Row[0].x)
149 if (Row[2].z > Row[i][i])
157 SquareRoot = sqrt(Row[i][i] - Row[j][j] - Row[k][k] +
static_cast<T
>(1.0));
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]);
172 FORCEINLINE glm::mat4
TransformMatrix(glm::vec3& Translation, glm::quat& Rotation, glm::vec3& Scale)
174 return glm::translate(glm::mat4(1.0f), Translation)
175 * glm::toMat4(Rotation)
176 * glm::scale(glm::mat4(1.0f),
Scale);
179 glm::mat4 TransformMatrix2D(
const glm::vec3& translation,
float rot,
const glm::vec3& scale);
184 template<
typename T =
float>
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>;
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,
197 return glm::vec2(ConvertedCoordinates.x, ConvertedCoordinates.y);
205 template<
typename TVector>
207 const glm::mat4& InverseProjectionMatrix,
208 const glm::mat4& InverseViewMatrix,
209 const glm::vec4& Viewport)
211 static_assert(std::disjunction_v<
212 std::is_same<TVector, glm::vec2>,
213 std::is_same<TVector, LVector2>>,
"TVector must valid vector type");
215 const int WindowWidth = Viewport.z;
216 const int WindowHeight = Viewport.w;
218 glm::vec4 ClipCoordinates = glm::vec4(
219 ((2.0f * ScreenCoordinates.x) / (WindowWidth - 1.0f)),
220 (1.0f - 2.0f * ScreenCoordinates.y) / WindowHeight,
226 glm::vec4 EyeCoordinates = InverseProjectionMatrix * ClipCoordinates;
227 EyeCoordinates.z = -1.0f;
228 EyeCoordinates.w = 0.0f;
230 glm::vec4 WorldCoordinates = InverseViewMatrix * EyeCoordinates;
232 return TVector(WorldCoordinates.x, WorldCoordinates.y);
238 template<
typename TVector = glm::vec3,
typename TVec2>
241 const glm::mat4& ViewMatrix,
242 const glm::mat4& ProjectionMatrix,
243 const glm::vec4& Viewport)
245 static_assert(std::conjunction_v<
247 std::is_same<TVector, glm::vec3>,
248 std::is_same<TVector, LVector>
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>());
257 glm::vec3 ScreenCoordinatesWithDepth{};
259 if constexpr (std::is_same_v<TVec2, glm::vec2>)
261 ScreenCoordinatesWithDepth = { ScreenCoordinates.x, ScreenCoordinates.y, Depth };
263 else if constexpr (std::is_same_v<TVec2, LVector2>)
265 ScreenCoordinatesWithDepth = { ScreenCoordinates.X, ScreenCoordinates.Y, Depth };
269 LK_CORE_ASSERT(
false,
"ConvertScreenToWorldCoordinates failed");
272 return TVector(glm::unProject(ScreenCoordinatesWithDepth, ViewMatrix, ProjectionMatrix, Viewport));
275 glm::vec2 ScreenToWorld2D(
const glm::vec2& ndc,
const glm::mat4& inv_proj,
const LTransformComponent& Transform);
276 float Get2DRotationFromQuaternion(
const glm::quat& quat);
282 template<
typename TVector>
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");
296 template<
typename TVector>
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");
306 template<
typename TVector>
307 FORCEINLINE TVector Normalize(
const TVector& InVector)
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));
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
TVector4< float > LVector4
Definition Vector.h:60
LVector3 LVector
Definition Vector.h:68
TVector2< float > LVector2
Definition Vector.h:48