Plasma Engine  2.0
Loading...
Searching...
No Matches
Quat_inl.h
1#pragma once
2
3#include <Foundation/Math/Mat4.h>
4#include <Foundation/Math/Vec3.h>
5
6template <typename Type>
8{
9#if PL_ENABLED(PL_MATH_CHECK_FOR_NAN)
10 // Initialize all data to NaN in debug mode to find problems with uninitialized data easier.
11 const Type TypeNaN = plMath::NaN<Type>();
12 x = TypeNaN;
13 y = TypeNaN;
14 z = TypeNaN;
15 w = TypeNaN;
16#endif
17}
18
19template <typename Type>
20PL_ALWAYS_INLINE plQuatTemplate<Type>::plQuatTemplate(Type inX, Type inY, Type inZ, Type inW)
21 : x(inX)
22 , y(inY)
23 , z(inZ)
24 , w(inW)
25{
26}
27
28template <typename Type>
30{
31 return plQuatTemplate(0, 0, 0, 1);
32}
33
34template <typename Type>
35PL_ALWAYS_INLINE plQuatTemplate<Type> plQuatTemplate<Type>::MakeFromElements(Type inX, Type inY, Type inZ, Type inW)
36{
37 return plQuatTemplate<Type>(inX, inY, inZ, inW);
39
40template <typename Type>
41PL_ALWAYS_INLINE void plQuatTemplate<Type>::SetIdentity()
42{
43 x = (Type)0;
44 y = (Type)0;
45 z = (Type)0;
46 w = (Type)1;
47}
48
49template <typename Type>
51{
52 const plAngle halfAngle = angle * 0.5f;
53
54 plVec3 v = static_cast<Type>(plMath::Sin(halfAngle)) * vRotationAxis;
55 float w = plMath::Cos(halfAngle);
56
57 return plQuatTemplate<Type>(v.x, v.y, v.z, w);
58}
59
60template <typename Type>
62{
63 PL_NAN_ASSERT(this);
64
65 Type n = x * x + y * y + z * z + w * w;
68
69 x *= n;
70 y *= n;
71 z *= n;
72 w *= n;
73}
74
75template <typename Type>
76void plQuatTemplate<Type>::GetRotationAxisAndAngle(plVec3Template<Type>& out_vAxis, plAngle& out_angle, Type fEpsilon) const
78 PL_NAN_ASSERT(this);
79
80 out_angle = 2 * plMath::ACos(static_cast<float>(w));
81
82 const float s = plMath::Sqrt(1 - w * w);
83
84 if (s < fEpsilon)
85 {
86 out_vAxis.Set(1, 0, 0);
87 }
88 else
89 {
90 const float ds = 1.0f / s;
91 out_vAxis.x = x * ds;
92 out_vAxis.y = y * ds;
93 out_vAxis.z = z * ds;
94 }
95}
96
97template <typename Type>
98PL_FORCE_INLINE void plQuatTemplate<Type>::Invert()
100 PL_NAN_ASSERT(this);
101
102 *this = GetInverse();
103}
104
105template <typename Type>
107{
108 PL_NAN_ASSERT(this);
109
110 return (plQuatTemplate(-x, -y, -z, w));
112
113template <typename Type>
115{
116 PL_NAN_ASSERT(this);
117
118 return (plQuatTemplate(-x, -y, -z, -w));
119}
120
121template <typename Type>
122PL_FORCE_INLINE Type plQuatTemplate<Type>::Dot(const plQuatTemplate& rhs) const
123{
124 PL_NAN_ASSERT(this);
125 PL_NAN_ASSERT(&rhs);
127 return GetVectorPart().Dot(rhs.GetVectorPart()) + w * rhs.w;
128}
130template <typename Type>
133 return *this * v;
134}
136template <typename Type>
137PL_ALWAYS_INLINE const plVec3Template<Type> operator*(const plQuatTemplate<Type>& q, const plVec3Template<Type>& v)
139 plVec3Template<Type> t = q.GetVectorPart().CrossRH(v) * (Type)2;
140 return v + q.w * t + q.GetVectorPart().CrossRH(t);
141}
142
143template <typename Type>
144PL_ALWAYS_INLINE const plQuatTemplate<Type> operator*(const plQuatTemplate<Type>& q1, const plQuatTemplate<Type>& q2)
145{
147
148 q.w = q1.w * q2.w - (q1.x * q2.x + q1.y * q2.y + q1.z * q2.z);
149
150 const plVec3 v1 = q1.GetVectorPart();
151 const plVec3 v2 = q2.GetVectorPart();
152
153 const plVec3 vr = q1.w * v2 + q2.w * v1 + v1.CrossRH(v2);
154 q.x = vr.x;
155 q.y = vr.y;
156 q.z = vr.z;
157
158 return q;
159}
160
161template <typename Type>
162bool plQuatTemplate<Type>::IsValid(Type fEpsilon) const
163{
164 if (!GetVectorPart().IsValid())
165 return false;
166 if (!plMath::IsFinite(w))
167 return false;
168
169 Type n = x * x + y * y + z * z + w * w;
170
171 return plMath::IsEqual(n, (Type)1, fEpsilon);
172}
173
174template <typename Type>
176{
177 return plMath::IsNaN(x) || plMath::IsNaN(y) || plMath::IsNaN(z) || plMath::IsNaN(w);
178}
179
180template <typename Type>
181bool plQuatTemplate<Type>::IsEqualRotation(const plQuatTemplate<Type>& qOther, Type fEpsilon) const
182{
183 if (GetVectorPart().IsEqual(qOther.GetVectorPart(), (Type)0.00001) && plMath::IsEqual(w, qOther.w, (Type)0.00001))
184 {
185 return true;
186 }
187
188 plVec3Template<Type> vA1, vA2;
189 plAngle A1, A2;
190
191 GetRotationAxisAndAngle(vA1, A1);
192 qOther.GetRotationAxisAndAngle(vA2, A2);
193
194 if ((A1.IsEqualSimple(A2, plAngle::MakeFromDegree(static_cast<float>(fEpsilon)))) && (vA1.IsEqual(vA2, fEpsilon)))
195 return true;
196
197 if ((A1.IsEqualSimple(-A2, plAngle::MakeFromDegree(static_cast<float>(fEpsilon)))) && (vA1.IsEqual(-vA2, fEpsilon)))
198 return true;
199
200 return false;
201}
202
203template <typename Type>
205{
206 PL_NAN_ASSERT(this);
207
209
210 const Type fTx = x + x;
211 const Type fTy = y + y;
212 const Type fTz = z + z;
213 const Type fTwx = fTx * w;
214 const Type fTwy = fTy * w;
215 const Type fTwz = fTz * w;
216 const Type fTxx = fTx * x;
217 const Type fTxy = fTy * x;
218 const Type fTxz = fTz * x;
219 const Type fTyy = fTy * y;
220 const Type fTyz = fTz * y;
221 const Type fTzz = fTz * z;
222
223 m.Element(0, 0) = (Type)1 - (fTyy + fTzz);
224 m.Element(1, 0) = fTxy - fTwz;
225 m.Element(2, 0) = fTxz + fTwy;
226 m.Element(0, 1) = fTxy + fTwz;
227 m.Element(1, 1) = (Type)1 - (fTxx + fTzz);
228 m.Element(2, 1) = fTyz - fTwx;
229 m.Element(0, 2) = fTxz - fTwy;
230 m.Element(1, 2) = fTyz + fTwx;
231 m.Element(2, 2) = (Type)1 - (fTxx + fTyy);
232 return m;
233}
234
235template <typename Type>
237{
238 PL_NAN_ASSERT(this);
239
241
242 const Type fTx = x + x;
243 const Type fTy = y + y;
244 const Type fTz = z + z;
245 const Type fTwx = fTx * w;
246 const Type fTwy = fTy * w;
247 const Type fTwz = fTz * w;
248 const Type fTxx = fTx * x;
249 const Type fTxy = fTy * x;
250 const Type fTxz = fTz * x;
251 const Type fTyy = fTy * y;
252 const Type fTyz = fTz * y;
253 const Type fTzz = fTz * z;
254
255 m.Element(0, 0) = (Type)1 - (fTyy + fTzz);
256 m.Element(1, 0) = fTxy - fTwz;
257 m.Element(2, 0) = fTxz + fTwy;
258 m.Element(3, 0) = (Type)0;
259 m.Element(0, 1) = fTxy + fTwz;
260 m.Element(1, 1) = (Type)1 - (fTxx + fTzz);
261 m.Element(2, 1) = fTyz - fTwx;
262 m.Element(3, 1) = (Type)0;
263 m.Element(0, 2) = fTxz - fTwy;
264 m.Element(1, 2) = fTyz + fTwx;
265 m.Element(2, 2) = (Type)1 - (fTxx + fTyy);
266 m.Element(3, 2) = (Type)0;
267 m.Element(0, 3) = (Type)0;
268 m.Element(1, 3) = (Type)0;
269 m.Element(2, 3) = (Type)0;
270 m.Element(3, 3) = (Type)1;
271 return m;
272}
273
274template <typename Type>
276{
277 PL_NAN_ASSERT(&m);
278
279 const Type trace = m.Element(0, 0) + m.Element(1, 1) + m.Element(2, 2);
280 const Type half = (Type)0.5;
281
282 Type val[4];
283
284 if (trace > (Type)0)
285 {
286 Type s = plMath::Sqrt(trace + (Type)1);
287 Type t = half / s;
288
289 val[0] = (m.Element(1, 2) - m.Element(2, 1)) * t;
290 val[1] = (m.Element(2, 0) - m.Element(0, 2)) * t;
291 val[2] = (m.Element(0, 1) - m.Element(1, 0)) * t;
292
293 val[3] = half * s;
294 }
295 else
296 {
297 const plInt32 next[] = {1, 2, 0};
298 plInt32 i = 0;
299
300 if (m.Element(1, 1) > m.Element(0, 0))
301 i = 1;
302
303 if (m.Element(2, 2) > m.Element(i, i))
304 i = 2;
305
306 plInt32 j = next[i];
307 plInt32 k = next[j];
308
309 Type s = plMath::Sqrt(m.Element(i, i) - (m.Element(j, j) + m.Element(k, k)) + (Type)1);
310 Type t = half / s;
311
312 val[i] = half * s;
313 val[3] = (m.Element(j, k) - m.Element(k, j)) * t;
314 val[j] = (m.Element(i, j) + m.Element(j, i)) * t;
315 val[k] = (m.Element(i, k) + m.Element(k, i)) * t;
316 }
317
319 q.x = val[0];
320 q.y = val[1];
321 q.z = val[2];
322 q.w = val[3];
323 return q;
324}
325
326template <typename Type>
328{
329 const plVec3 x = (mMat * plVec3(1, 0, 0)).GetNormalized();
330 const plVec3 y = (mMat * plVec3(0, 1, 0)).GetNormalized();
331 const plVec3 z = x.CrossRH(y);
332
333 plMat3 m;
334 m.SetColumn(0, x);
335 m.SetColumn(1, y);
336 m.SetColumn(2, z);
337
338 *this = plQuat::MakeFromMat3(m);
339}
340
341template <typename Type>
343{
344 const plVec3 x = mMat.TransformDirection(plVec3(1, 0, 0)).GetNormalized();
345 const plVec3 y = mMat.TransformDirection(plVec3(0, 1, 0)).GetNormalized();
346 const plVec3 z = x.CrossRH(y);
347
348 plMat3 m;
349 m.SetColumn(0, x);
350 m.SetColumn(1, y);
351 m.SetColumn(2, z);
352
353 *this = plQuat::MakeFromMat3(m);
354}
355
362template <typename Type>
364{
365 const plVec3Template<Type> v0 = vDirFrom.GetNormalized();
366 const plVec3Template<Type> v1 = vDirTo.GetNormalized();
367
368 const Type fDot = v0.Dot(v1);
369
370 // if both vectors are identical -> no rotation needed
371 if (plMath::IsEqual(fDot, (Type)1, (Type)0.0000001))
372 {
373 return MakeIdentity();
374 }
375 else if (plMath::IsEqual(fDot, (Type)-1, (Type)0.0000001)) // if both vectors are opposing
376 {
377 // find an axis, that is not identical and not opposing, plVec3Template::Cross-product to find perpendicular vector, rotate around that
378 if (plMath::Abs(v0.Dot(plVec3Template<Type>(1, 0, 0))) < (Type)0.8)
379 return MakeFromAxisAndAngle(v0.CrossRH(plVec3Template<Type>(1, 0, 0)).GetNormalized(), plAngle::MakeFromRadian(plMath::Pi<float>()));
380 else
381 return MakeFromAxisAndAngle(v0.CrossRH(plVec3Template<Type>(0, 1, 0)).GetNormalized(), plAngle::MakeFromRadian(plMath::Pi<float>()));
382 }
383
384 const plVec3Template<Type> c = v0.CrossRH(v1);
385 const Type d = v0.Dot(v1);
386 const Type s = plMath::Sqrt(((Type)1 + d) * (Type)2);
387
388 PL_ASSERT_DEBUG(c.IsValid(), "SetShortestRotation failed.");
389
390 const Type fOneDivS = 1.0f / s;
391
393 q.x = c.x * fOneDivS;
394 q.y = c.y * fOneDivS;
395 q.z = c.z * fOneDivS;
396 q.w = s / (Type)2;
397 q.Normalize();
398
399 return q;
400}
401
402template <typename Type>
404{
405 PL_ASSERT_DEBUG((t >= (Type)0) && (t <= (Type)1), "Invalid lerp factor.");
406
407 const Type one = 1;
408 const Type qdelta = (Type)1 - (Type)0.001;
409
410 const Type fDot = (qFrom.x * qTo.x + qFrom.y * qTo.y + qFrom.z * qTo.z + qFrom.w * qTo.w);
411
412 Type cosTheta = fDot;
413
414 bool bFlipSign = false;
415 if (cosTheta < (Type)0)
416 {
417 bFlipSign = true;
418 cosTheta = -cosTheta;
419 }
420
421 Type t0, t1;
422
423 if (cosTheta < qdelta)
424 {
425 plAngle theta = plMath::ACos((float)cosTheta);
426
427 // use sqrtInv(1+c^2) instead of 1.0/sin(theta)
428 const Type iSinTheta = (Type)1 / plMath::Sqrt(one - (cosTheta * cosTheta));
429 const plAngle tTheta = static_cast<float>(t) * theta;
430
431 Type s0 = plMath::Sin(theta - tTheta);
432 Type s1 = plMath::Sin(tTheta);
433
434 t0 = s0 * iSinTheta;
435 t1 = s1 * iSinTheta;
436 }
437 else
438 {
439 // If q0 is nearly the same as q1 we just linearly interpolate
440 t0 = one - t;
441 t1 = t;
442 }
443
444 if (bFlipSign)
445 t1 = -t1;
446
448
449 q.x = t0 * qFrom.x;
450 q.y = t0 * qFrom.y;
451 q.z = t0 * qFrom.z;
452 q.w = t0 * qFrom.w;
453
454 q.x += t1 * qTo.x;
455 q.y += t1 * qTo.y;
456 q.z += t1 * qTo.z;
457 q.w += t1 * qTo.w;
458
459 q.Normalize();
460
461 return q;
462}
463
464template <typename Type>
465PL_ALWAYS_INLINE bool operator==(const plQuatTemplate<Type>& q1, const plQuatTemplate<Type>& q2)
466{
467 return q1.x == q2.x && q1.y == q2.y && q1.z == q2.z && q1.w == q2.w;
468}
469
470template <typename Type>
471PL_ALWAYS_INLINE bool operator!=(const plQuatTemplate<Type>& q1, const plQuatTemplate<Type>& q2)
472{
473 return !(q1 == q2);
474}
475
476template <typename Type>
478{
479 // Taken from https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles
480 // and http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/
481 // adapted to our convention (yaw->pitch->roll, ZYX order or 3-2-1 order)
482
483 auto& yaw = out_z;
484 auto& pitch = out_y;
485 auto& roll = out_x;
486
487 const double fSingularityTest = w * y - z * x;
488 const double fSingularityThreshold = 0.4999995;
489
490 if (fSingularityTest > fSingularityThreshold) // singularity at north pole
491 {
492 yaw = -2.0f * plMath::ATan2(x, w);
493 pitch = plAngle::MakeFromDegree(90.0f);
494 roll = plAngle::MakeFromDegree(0.0f);
495 }
496 else if (fSingularityTest < -fSingularityThreshold) // singularity at south pole
497 {
498 yaw = 2.0f * plMath::ATan2(x, w);
499 pitch = plAngle::MakeFromDegree(-90.0f);
500 roll = plAngle::MakeFromDegree(0.0f);
501 }
502 else
503 {
504 // yaw (z-axis rotation)
505 const double siny = 2.0 * (w * z + x * y);
506 const double cosy = 1.0 - 2.0 * (y * y + z * z);
507 yaw = plMath::ATan2((float)siny, (float)cosy);
508
509 // pitch (y-axis rotation)
510 pitch = plMath::ASin(2.0f * (float)fSingularityTest);
511
512 // roll (x-axis rotation)
513 const double sinr = 2.0 * (w * x + y * z);
514 const double cosr = 1.0 - 2.0 * (x * x + y * y);
515 roll = plMath::ATan2((float)sinr, (float)cosr);
516 }
517}
518
519template <typename Type>
521{
524 const auto& yaw = z;
525 const auto& pitch = y;
526 const auto& roll = x;
527 const double cy = plMath::Cos(yaw * 0.5);
528 const double sy = plMath::Sin(yaw * 0.5);
529 const double cp = plMath::Cos(pitch * 0.5);
530 const double sp = plMath::Sin(pitch * 0.5);
531 const double cr = plMath::Cos(roll * 0.5);
532 const double sr = plMath::Sin(roll * 0.5);
533
535 q.w = (float)(cy * cp * cr + sy * sp * sr);
536 q.x = (float)(cy * cp * sr - sy * sp * cr);
537 q.y = (float)(cy * sp * cr + sy * cp * sr);
538 q.z = (float)(sy * cp * cr - cy * sp * sr);
539 return q;
540}
Float wrapper struct for a safe usage and conversions of angles.
Definition Angle.h:10
bool IsEqualSimple(plAngle rhs, plAngle epsilon) const
Equality check with epsilon. Simple check without normalization. 360 degree will equal 0 degree,...
Definition Angle_inl.h:60
static constexpr plAngle MakeFromDegree(float fDegree)
Creates an instance of plAngle that was initialized from degree. (Performs a conversion)
Definition Angle_inl.h:33
static constexpr plAngle MakeFromRadian(float fRadian)
Creates an instance of plAngle that was initialized from radian. (No need for any conversion)
Definition Angle_inl.h:38
A 3x3 component matrix class.
Definition Mat3.h:9
void SetColumn(plUInt32 uiColumn, const plVec3Template< Type > &vColumn)
Sets all 3 components of the i-th column.
Definition Mat3_inl.h:218
A 4x4 component matrix class.
Definition Mat4.h:11
const plVec3Template< Type > TransformDirection(const plVec3Template< Type > &v) const
Matrix-vector multiplication, assuming the 4th component of the vector is zero. So,...
Definition Mat4_inl.h:374
Quaternions can be used to represent rotations in 3D space.
Definition Quat.h:19
void ReconstructFromMat4(const plMat4Template< Type > &m)
Reconstructs a rotation quaternion from a matrix that may contain scaling and mirroring.
Definition Quat_inl.h:342
void SetIdentity()
Sets the Quaternion to the identity.
Definition Quat_inl.h:41
plVec3Template< Type > GetVectorPart() const
Returns the x,y,z components as a vector.
Definition Quat.h:102
static plQuatTemplate< Type > MakeSlerp(const plQuatTemplate &qFrom, const plQuatTemplate &qTo, Type t)
Returns a quaternion that is the spherical linear interpolation of the other two.
Definition Quat_inl.h:403
static plQuatTemplate< Type > MakeFromMat3(const plMat3Template< Type > &m)
Creates a quaternion from the given matrix.
Definition Quat_inl.h:275
const plQuatTemplate< Type > GetInverse() const
Returns a quaternion that represents the negative / inverted rotation. E.g. the one that would rotate...
Definition Quat_inl.h:106
const plQuatTemplate< Type > GetNegated() const
Returns the Quaternion with all 4 components negated. This is not the same as the inverted rotation!
Definition Quat_inl.h:114
void Normalize()
Normalizes the quaternion to unit length. ALL rotation-quaternions should be normalized at all times ...
Definition Quat_inl.h:61
bool IsEqualRotation(const plQuatTemplate &qOther, Type fEpsilon) const
Determines whether this and qOther represent the same rotation. This is a rather slow operation.
Definition Quat_inl.h:181
static plQuatTemplate< Type > MakeFromElements(Type x, Type y, Type z, Type w)
Sets the individual elements of the quaternion directly. Note that x,y,z do NOT represent a rotation ...
Definition Quat_inl.h:35
void GetRotationAxisAndAngle(plVec3Template< Type > &out_vAxis, plAngle &out_angle, Type fEpsilon=plMath::DefaultEpsilon< Type >()) const
Returns the rotation-axis and angle, that this quaternion rotates around.
Definition Quat_inl.h:76
static plQuatTemplate< Type > MakeFromEulerAngles(const plAngle &x, const plAngle &y, const plAngle &z)
Sets the quaternion from Euler angles.
Definition Quat_inl.h:520
plVec3Template< Type > Rotate(const plVec3Template< Type > &v) const
Returns v rotated by the quaternion. Same as operator*.
Definition Quat_inl.h:131
bool IsNaN() const
Checks whether any component is NaN.
Definition Quat_inl.h:175
const plMat4Template< Type > GetAsMat4() const
Returns the Quaternion as a matrix.
Definition Quat_inl.h:236
static const plQuatTemplate< Type > MakeIdentity()
Static function that returns a quaternion that represents the identity rotation (none).
Definition Quat_inl.h:29
void ReconstructFromMat3(const plMat3Template< Type > &m)
Reconstructs a rotation quaternion from a matrix that may contain scaling and mirroring.
Definition Quat_inl.h:327
static plQuatTemplate< Type > MakeShortestRotation(const plVec3Template< Type > &vDirFrom, const plVec3Template< Type > &vDirTo)
Creates a quaternion, that rotates through the shortest arc from "vDirFrom" to "vDirTo".
Definition Quat_inl.h:363
const plMat3Template< Type > GetAsMat3() const
Returns the Quaternion as a matrix.
Definition Quat_inl.h:204
static plQuatTemplate< Type > MakeFromAxisAndAngle(const plVec3Template< Type > &vRotationAxis, plAngle angle)
Creates a quaternion from a rotation-axis and an angle.
Definition Quat_inl.h:50
Type Dot(const plQuatTemplate &rhs) const
Returns the dot-product of the two quaternions (commutative, order does not matter).
Definition Quat_inl.h:122
void GetAsEulerAngles(plAngle &out_x, plAngle &out_y, plAngle &out_z) const
Converts the quaternion to Euler angles.
Definition Quat_inl.h:477
bool IsValid(Type fEpsilon=plMath::DefaultEpsilon< Type >()) const
Checks whether all components are neither NaN nor infinite and that the quaternion is normalized.
Definition Quat_inl.h:162
void Invert()
Inverts the rotation, so instead of rotating N degrees around an axis, the quaternion will rotate -N ...
Definition Quat_inl.h:98
A 3-component vector class.
Definition Vec3.h:9
void Set(Type xyz)
Sets all 3 components to this value.
Definition Vec3_inl.h:32
const plVec3Template< Type > CrossRH(const plVec3Template< Type > &rhs) const
Returns the Cross-product of the two vectors (NOT commutative, order DOES matter)
Definition Vec3_inl.h:299
bool IsValid() const
Checks that all components are finite numbers.
Definition Vec3_inl.h:157
bool IsEqual(const plVec3Template< Type > &rhs, Type fEpsilon) const
Equality Check with epsilon.
Definition Vec3_inl.h:431
PL_DECLARE_IF_FLOAT_TYPE const plVec3Template< Type > GetNormalized() const
Returns a normalized version of this vector, leaves the vector itself unchanged.
Definition Vec3_inl.h:86
Type Dot(const plVec3Template< Type > &rhs) const
Returns the Dot-product of the two vectors (commutative, order does not matter)
Definition Vec3_inl.h:290
constexpr TYPE Pi()
Returns the natural constant Pi.
PL_ALWAYS_INLINE plAngle ASin(float f)
Returns the arcus sinus of f.
Definition MathFloat_inl.h:77
PL_ALWAYS_INLINE plAngle ACos(float f)
Returns the arcus cosinus of f.
Definition MathFloat_inl.h:82
PL_ALWAYS_INLINE float Sin(plAngle a)
***** Trigonometric Functions *****
Definition MathFloat_inl.h:62
PL_ALWAYS_INLINE plAngle ATan2(float y, float x)
Returns the atan2 of x and y.
Definition MathFloat_inl.h:92
constexpr Type Invert(Type f)
Returns 1 / f.
Definition Math_inl.h:63
constexpr TYPE NaN()
Returns the value for NaN as the template type. Returns zero, if the type does not support NaN.
Definition Constants_inl.h:58
PL_ALWAYS_INLINE double Sqrt(double f)
Returns the square root of f.
Definition MathDouble_inl.h:99
constexpr bool IsEqual(Type lhs, Type rhs, Type fEpsilon)
Checks, whether fValue is in the range [fDesired - fMaxImprecision; fDesired + fMaxImprecision].
Definition Math_inl.h:276
constexpr PL_ALWAYS_INLINE T Abs(T f)
Returns the absolute value of f.
Definition Math_inl.h:21
PL_ALWAYS_INLINE float Cos(plAngle a)
Takes an angle, returns its cosine.
Definition MathFloat_inl.h:67