4#include <glm/gtc/packing.hpp>
5#include <glm/gtc/type_ptr.hpp>
6#include <glm/gtc/epsilon.hpp>
9#include <glm/gtx/matrix_decompose.hpp>
10#include <glm/gtx/transform.hpp>
18 bool& isUniformScaleOut)
22 glm::mat4 LocalMatrix = glm::make_mat4(transform.
mat);
25 if (glm::epsilonEqual(LocalMatrix[3][3],
static_cast<T
>(0), glm::epsilon<T>()))
29 if (glm::epsilonNotEqual(LocalMatrix[0][3],
static_cast<T
>(0), glm::epsilon<T>()) ||
30 glm::epsilonNotEqual(LocalMatrix[1][3],
static_cast<T
>(0), glm::epsilon<T>()) ||
31 glm::epsilonNotEqual(LocalMatrix[2][3],
static_cast<T
>(0), glm::epsilon<T>()))
33 LocalMatrix[0][3] = LocalMatrix[1][3] = LocalMatrix[2][3] =
static_cast<T
>(0);
34 LocalMatrix[3][3] =
static_cast<T
>(1);
38 glm::vec3 translation(LocalMatrix[3]);
39 translationOut.
set(translation.x, translation.y, translation.z);
40 LocalMatrix[3] = glm::vec4(0, 0, 0, LocalMatrix[3].w);
45 for (glm::length_t i = 0; i < 3; ++i)
46 for (glm::length_t j = 0; j < 3; ++j)
47 Row[i][j] = LocalMatrix[i][j];
50 scaleOut.
x = length(Row[0]);
51 Row[0] = glm::detail::scale(Row[0],
static_cast<T
>(1));
53 scaleOut.
y = length(Row[1]);
54 Row[1] = glm::detail::scale(Row[1],
static_cast<T
>(1));
55 scaleOut.
z = length(Row[2]);
56 Row[2] = glm::detail::scale(Row[2],
static_cast<T
>(1));
59 rotationOut.y = asin(-Row[0][2]);
60 if (!
IS_ZERO(cos(rotationOut.y)))
62 rotationOut.x = atan2(Row[1][2], Row[2][2]);
63 rotationOut.z = atan2(Row[0][1], Row[0][0]);
67 rotationOut.x = atan2(-Row[2][0], Row[1][1]);
77 bool uniformScaleTemp =
false;
78 return decomposeMatrix(transform, translationOut, scaleOut, rotationOut, uniformScaleTemp);
86 glm::mat4 LocalMatrix = glm::make_mat4(transform.
mat);
89 if (glm::epsilonEqual(LocalMatrix[3][3],
static_cast<T
>(0), glm::epsilon<T>()))
93 if (glm::epsilonNotEqual(LocalMatrix[0][3],
static_cast<T
>(0), glm::epsilon<T>()) ||
94 glm::epsilonNotEqual(LocalMatrix[1][3],
static_cast<T
>(0), glm::epsilon<T>()) ||
95 glm::epsilonNotEqual(LocalMatrix[2][3],
static_cast<T
>(0), glm::epsilon<T>()))
97 LocalMatrix[0][3] = LocalMatrix[1][3] = LocalMatrix[2][3] =
static_cast<T
>(0);
98 LocalMatrix[3][3] =
static_cast<T
>(1);
102 glm::vec3 translation(LocalMatrix[3]);
103 translationOut.
set(translation.x, translation.y, translation.z);
104 LocalMatrix[3] = glm::vec4(0, 0, 0, LocalMatrix[3].w);
109 for (glm::length_t i = 0; i < 3; ++i)
110 for (glm::length_t j = 0; j < 3; ++j)
111 Row[i][j] = LocalMatrix[i][j];
114 scaleOut.
x = length(Row[0]);
115 Row[0] = glm::detail::scale(Row[0],
static_cast<T
>(1));
117 scaleOut.
y = length(Row[1]);
118 Row[1] = glm::detail::scale(Row[1],
static_cast<T
>(1));
119 scaleOut.
z = length(Row[2]);
120 Row[2] = glm::detail::scale(Row[2],
static_cast<T
>(1));
129 glm::mat4 LocalMatrix = glm::make_mat4(transform.
mat);
132 if (glm::epsilonEqual(LocalMatrix[3][3],
static_cast<T
>(0), glm::epsilon<T>()))
136 if (glm::epsilonNotEqual(LocalMatrix[0][3],
static_cast<T
>(0), glm::epsilon<T>()) ||
137 glm::epsilonNotEqual(LocalMatrix[1][3],
static_cast<T
>(0), glm::epsilon<T>()) ||
138 glm::epsilonNotEqual(LocalMatrix[2][3],
static_cast<T
>(0), glm::epsilon<T>()))
140 LocalMatrix[0][3] = LocalMatrix[1][3] = LocalMatrix[2][3] =
static_cast<T
>(0);
141 LocalMatrix[3][3] =
static_cast<T
>(1);
145 glm::vec3 translation(LocalMatrix[3]);
146 translationOut.
set(translation.x, translation.y, translation.z);
151 assert(pointsOut !=
nullptr);
153 const F32 x0 = cA.center[0];
154 const F32 y0 = cA.center[1];
155 const F32 r0 = cA.radius;
157 const F32 x1 = cB.center[0];
158 const F32 y1 = cB.center[1];
159 const F32 r1 = cB.radius;
164 const F32 dx = x1 - x0;
165 const F32 dy = y1 - y0;
169 const F32 d = hypot(dx, dy);
177 if (d < fabs(r0 - r1))
189 const F32 a = (r0*r0 - r1*r1 + d*d) / (2.0f * d);
192 const F32 x2 = x0 + dx * a / d;
193 const F32 y2 = y0 + dy * a / d;
198 const F32 h = sqrt(r0*r0 - a*a);
203 const F32 rx = -dy * (h / d);
204 const F32 ry = dx * (h / d);
208 pointsOut[0].x = x2 + rx;
209 pointsOut[1].x = x2 - rx;
211 pointsOut[0].y = y2 + ry;
212 pointsOut[1].y = y2 - ry;
244 colourOut.
set(uintColour.r / 255.0f,
245 uintColour.g / 255.0f,
246 uintColour.b / 255.0f,
247 uintColour.a / 255.0f);
251 colourOut.
set(uintColour.r / 255.0f,
252 uintColour.g / 255.0f,
253 uintColour.b / 255.0f);
293 return PACK_VEC3(value.x, value.y, value.z);
313 return to_U32(glm::packHalf2x16(glm::mediump_vec2(value.
x, value.
y)));
317 const glm::vec2 ret = glm::unpackHalf2x16(src);
318 value.
set(ret.x, ret.y);
328 return to_U16(glm::packHalf1x16(value));
332 value = glm::unpackHalf1x16(src);
342 return glm::uintBitsToFloat(src);
346 return glm::floatBitsToUint(src);
350 return glm::intBitsToFloat(src);
354 return glm::floatBitsToInt(src);
358 return to_U32(glm::packHalf2x16(glm::mediump_vec2(x, y)));
363 const glm::vec2 ret = glm::unpackHalf2x16(src);
394 return to_U32(glm::packUnorm4x8({ x, y, z, w }));
398 const glm::vec4 ret = glm::unpackUnorm4x8(src);
406 const glm::vec4 ret = glm::unpackUnorm4x8(src);
407 x = ret.x; y = ret.y; z = ret.z; w = ret.w;
435 assert(x >= 0.f && x <= 1.0f);
436 assert(y >= 0.f && y <= 1.0f);
437 assert(z >= 0.f && z <= 1.0f);
439 return glm::packF2x11_1x10(glm::vec3(x, y, z));
443 const glm::vec3 ret = glm::unpackF2x11_1x10(src);
449void Normalize(
vec3<F32>& inputRotation,
const bool degrees,
const bool normYaw,
const bool normPitch,
const bool normRoll)
noexcept {
454 yaw = fmod(yaw,
M_PI_f * 2.0f);
459 }
else if (yaw >
M_PI_f) {
460 yaw = fmod(yaw,
M_PI_f * 2.0f);
469 : inputRotation.pitch;
471 pitch = fmod(pitch,
M_PI_f * 2.0f);
476 }
else if (pitch >
M_PI_f) {
477 pitch = fmod(pitch,
M_PI_f * 2.0f);
481 inputRotation.pitch =
487 : inputRotation.roll;
489 roll = fmod(roll,
M_PI_f * 2.0f);
494 }
else if (roll >
M_PI_f) {
495 roll = fmod(roll,
M_PI_f * 2.0f);
void set(const T *v) noexcept
set the 2 components of the vector manually using a source pointer to a (large enough) array
bool isUniform(F32 tolerance=0.0001f) const noexcept
uniform vector: x = y = z
void set(const T *v) noexcept
set the 3 components of the vector manually using a source pointer to a (large enough) array
void set(const T *v) noexcept
set the 4 components of the vector manually using a source pointer to a (large enough) array
constexpr DEGREES< T > to_DEGREES(RADIANS< T > angle) noexcept
constexpr RADIANS< T > to_RADIANS(DEGREES< T > angle) noexcept
F32 INT_TO_FLOAT(I32 src)
void UNPACK_11_11_10(U32 src, vec3< F32_NORM > &res)
U32 PACK_11_11_10(const vec3< F32_NORM > &value)
bool decomposeMatrix(const mat4< F32 > &transform, vec3< F32 > &translationOut, vec3< F32 > &scaleOut, vec3< Angle::RADIANS< F32 > > &rotationOut, bool &isUniformScaleOut)
F32 PACK_VEC3(F32_SNORM x, F32_SNORM y, F32_SNORM z) noexcept
void Normalize(vec3< F32 > &inputRotation, bool degrees=false, bool normYaw=true, bool normPitch=true, bool normRoll=true) noexcept
Normalise the selected rotations to be within the +/-180 degree range.
UColour4 ToByteColour(const FColour4 &floatColour) noexcept
FColour4 ToFloatColour(const UColour4 &byteColour) noexcept
bool IntersectCircles(const Circle &cA, const Circle &cB, vec2< F32 > *pointsOut) noexcept
void UNPACK_VEC3(F32 src, F32_SNORM &x, F32_SNORM &y, F32_SNORM &z) noexcept
void UNPACK_HALF1x16(U16 src, F32 &value)
Only convert the range [-1024., 1024.] for accurate results.
U32 PACK_UNORM4x8(const vec4< F32_NORM > &value)
F32 UINT_TO_FLOAT(U32 src)
vec4< U8 > UNPACK_UNORM4x8_U8(U32 src)
U32 FLOAT_TO_UINT(F32 src)
U16 PACK_HALF1x16(F32 value)
Only convert the range [-1024., 1024.] for accurate results.
I32 FLOAT_TO_INT(F32 src)
vec4< F32_NORM > UNPACK_UNORM4x8_F32(U32 src)
U32 PACK_HALF2x16(vec2< F32 > value)
void UNPACK_HALF2x16(U32 src, vec2< F32 > &value)
void UNPACK_UNORM4x8(U32 src, vec4< F32_NORM > &value)
constexpr U8 FLOAT_TO_CHAR_UNORM(F32_NORM value) noexcept
Returns round(value * 255)
bool IS_ZERO(const T X) noexcept
constexpr U32 to_U32(const T value)
constexpr F32_NORM UNORM_CHAR_TO_FLOAT(U8 value) noexcept
Returns value / 255.f.
bool IS_IN_RANGE_INCLUSIVE(const T x, const U min, const U max) noexcept
constexpr U16 to_U16(const T value)