Plasma Engine  2.0
Loading...
Searching...
No Matches
Vec3_inl.h
1#pragma once
2
3template <typename Type>
5{
6#if PL_ENABLED(PL_MATH_CHECK_FOR_NAN)
7 // Initialize all data to NaN in debug mode to find problems with uninitialized data easier.
8 const Type TypeNaN = plMath::NaN<Type>();
9 x = TypeNaN;
10 y = TypeNaN;
11 z = TypeNaN;
12#endif
13}
14
15template <typename Type>
16PL_ALWAYS_INLINE plVec3Template<Type>::plVec3Template(Type x, Type y, Type z)
17 : x(x)
18 , y(y)
19 , z(z)
20{
21}
22
23template <typename Type>
25 : x(v)
26 , y(v)
27 , z(v)
28{
29}
30
31template <typename Type>
32PL_ALWAYS_INLINE void plVec3Template<Type>::Set(Type xyz)
33{
34 x = xyz;
35 y = xyz;
36 z = xyz;
37}
38
39template <typename Type>
40PL_ALWAYS_INLINE void plVec3Template<Type>::Set(Type inX, Type inY, Type inZ)
41{
42 x = inX;
43 y = inY;
44 z = inZ;
45}
46
47template <typename Type>
48PL_ALWAYS_INLINE void plVec3Template<Type>::SetZero()
49{
50 x = y = z = 0;
51}
52
53template <typename Type>
54PL_IMPLEMENT_IF_FLOAT_TYPE PL_ALWAYS_INLINE Type plVec3Template<Type>::GetLength() const
55{
56 return (plMath::Sqrt(GetLengthSquared()));
57}
58
59template <typename Type>
60PL_IMPLEMENT_IF_FLOAT_TYPE plResult plVec3Template<Type>::SetLength(Type fNewLength, Type fEpsilon /* = plMath::DefaultEpsilon<Type>() */)
61{
62 if (NormalizeIfNotZero(plVec3Template<Type>::MakeZero(), fEpsilon) == PL_FAILURE)
63 return PL_FAILURE;
64
65 *this *= fNewLength;
66 return PL_SUCCESS;
67}
68
69template <typename Type>
70PL_FORCE_INLINE Type plVec3Template<Type>::GetLengthSquared() const
71{
72 PL_NAN_ASSERT(this);
73
74 return (x * x + y * y + z * z);
75}
76
77template <typename Type>
78PL_IMPLEMENT_IF_FLOAT_TYPE PL_FORCE_INLINE Type plVec3Template<Type>::GetLengthAndNormalize()
79{
80 const Type fLength = GetLength();
81 *this /= fLength;
82 return fLength;
84
85template <typename Type>
86PL_IMPLEMENT_IF_FLOAT_TYPE PL_FORCE_INLINE const plVec3Template<Type> plVec3Template<Type>::GetNormalized() const
87{
88 const Type fLen = GetLength();
90 const Type fLengthInv = plMath::Invert(fLen);
91 return plVec3Template<Type>(x * fLengthInv, y * fLengthInv, z * fLengthInv);
92}
93
94template <typename Type>
95PL_IMPLEMENT_IF_FLOAT_TYPE PL_ALWAYS_INLINE void plVec3Template<Type>::Normalize()
96{
97 *this /= GetLength();
98}
99
100template <typename Type>
101PL_IMPLEMENT_IF_FLOAT_TYPE plResult plVec3Template<Type>::NormalizeIfNotZero(const plVec3Template<Type>& vFallback, Type fEpsilon)
102{
103 PL_NAN_ASSERT(&vFallback);
105 const Type fLength = GetLength();
106
107 if (!plMath::IsFinite(fLength) || plMath::IsZero(fLength, fEpsilon))
108 {
109 *this = vFallback;
110 return PL_FAILURE;
111 }
112
113 *this /= fLength;
114 return PL_SUCCESS;
115}
116
120template <typename Type>
121PL_IMPLEMENT_IF_FLOAT_TYPE PL_FORCE_INLINE bool plVec3Template<Type>::IsNormalized(Type fEpsilon /* = plMath::HugeEpsilon<Type>() */) const
123 const Type t = GetLengthSquared();
124 return plMath::IsEqual(t, (Type)1, fEpsilon);
126
127template <typename Type>
128PL_FORCE_INLINE bool plVec3Template<Type>::IsZero() const
129{
130 PL_NAN_ASSERT(this);
131
132 return ((x == 0.0f) && (y == 0.0f) && (z == 0.0f));
133}
134
135template <typename Type>
136bool plVec3Template<Type>::IsZero(Type fEpsilon) const
137{
138 PL_NAN_ASSERT(this);
139
140 return (plMath::IsZero(x, fEpsilon) && plMath::IsZero(y, fEpsilon) && plMath::IsZero(z, fEpsilon));
141}
142
143template <typename Type>
145{
146 if (plMath::IsNaN(x))
147 return true;
148 if (plMath::IsNaN(y))
149 return true;
150 if (plMath::IsNaN(z))
151 return true;
152
153 return false;
154}
155
156template <typename Type>
158{
159 if (!plMath::IsFinite(x))
160 return false;
161 if (!plMath::IsFinite(y))
162 return false;
163 if (!plMath::IsFinite(z))
164 return false;
166 return true;
167}
169template <typename Type>
171{
172 PL_NAN_ASSERT(this);
173
174 return plVec3Template<Type>(-x, -y, -z);
176
177template <typename Type>
179{
180 x += rhs.x;
181 y += rhs.y;
182 z += rhs.z;
184 PL_NAN_ASSERT(this);
185}
187template <typename Type>
190 x -= rhs.x;
191 y -= rhs.y;
192 z -= rhs.z;
193
194 PL_NAN_ASSERT(this);
196
197template <typename Type>
198PL_FORCE_INLINE void plVec3Template<Type>::operator*=(const plVec3Template& rhs)
199{
202 x *= rhs.x;
203 y *= rhs.y;
204 z *= rhs.z;
205
206 PL_NAN_ASSERT(this);
207}
209template <typename Type>
210PL_FORCE_INLINE void plVec3Template<Type>::operator/=(const plVec3Template& rhs)
211{
213
214 x /= rhs.x;
215 y /= rhs.y;
216 z /= rhs.z;
217
218 PL_NAN_ASSERT(this);
220
221template <typename Type>
222PL_FORCE_INLINE void plVec3Template<Type>::operator*=(Type f)
224 x *= f;
225 y *= f;
226 z *= f;
228 PL_NAN_ASSERT(this);
229}
230
231template <typename Type>
232PL_FORCE_INLINE void plVec3Template<Type>::operator/=(Type f)
233{
234 if constexpr (std::is_floating_point_v<Type>)
235 {
236 const Type f_inv = plMath::Invert(f);
237 x *= f_inv;
238 y *= f_inv;
239 z *= f_inv;
240 }
241 else
242 {
243 x /= f;
244 y /= f;
245 z /= f;
246 }
247
248 // if this assert fires, you might have tried to normalize a zero-length vector
249 PL_NAN_ASSERT(this);
250}
251
252template <typename Type>
254{
255 *this = (v3 - v2).CrossRH(v1 - v2);
256 return NormalizeIfNotZero();
257}
258
259template <typename Type>
260PL_IMPLEMENT_IF_FLOAT_TYPE void plVec3Template<Type>::MakeOrthogonalTo(const plVec3Template<Type>& vNormal)
261{
262 PL_ASSERT_DEBUG(
263 vNormal.IsNormalized(), "The vector to make this vector orthogonal to, must be normalized. It's length is {0}", plArgF(vNormal.GetLength(), 3));
264
265 plVec3Template<Type> vOrtho = vNormal.CrossRH(*this);
266 *this = vOrtho.CrossRH(vNormal);
267}
268
269template <typename Type>
271{
272 PL_ASSERT_DEBUG(!IsZero(plMath::SmallEpsilon<Type>()), "The vector must not be zero to be able to compute an orthogonal vector.");
273
274 Type fDot = plMath::Abs(this->Dot(plVec3Template<Type>(0, 1, 0)));
275 if (fDot < 0.999f)
276 return this->CrossRH(plVec3Template<Type>(0, 1, 0));
277
278 return this->CrossRH(plVec3Template<Type>(1, 0, 0));
279}
280
281template <typename Type>
282PL_IMPLEMENT_IF_FLOAT_TYPE const plVec3Template<Type> plVec3Template<Type>::GetReflectedVector(const plVec3Template<Type>& vNormal) const
283{
284 PL_ASSERT_DEBUG(vNormal.IsNormalized(), "vNormal must be normalized.");
285
286 return ((*this) - ((Type)2 * this->Dot(vNormal) * vNormal));
287}
288
289template <typename Type>
290PL_FORCE_INLINE Type plVec3Template<Type>::Dot(const plVec3Template<Type>& rhs) const
291{
292 PL_NAN_ASSERT(this);
293 PL_NAN_ASSERT(&rhs);
294
295 return ((x * rhs.x) + (y * rhs.y) + (z * rhs.z));
296}
297
298template <typename Type>
300{
301 PL_NAN_ASSERT(this);
302 PL_NAN_ASSERT(&rhs);
303
304 return plVec3Template<Type>(y * rhs.z - z * rhs.y, z * rhs.x - x * rhs.z, x * rhs.y - y * rhs.x);
305}
306
307template <typename Type>
309{
310 PL_ASSERT_DEBUG(this->IsNormalized(), "This vector must be normalized.");
311 PL_ASSERT_DEBUG(rhs.IsNormalized(), "The other vector must be normalized.");
312
313 return plMath::ACos(static_cast<float>(plMath::Clamp(this->Dot(rhs), (Type)-1, (Type)1)));
314}
315
316template <typename Type>
318{
319 PL_NAN_ASSERT(this);
320 PL_NAN_ASSERT(&rhs);
321
322 return plVec3Template<Type>(plMath::Min(x, rhs.x), plMath::Min(y, rhs.y), plMath::Min(z, rhs.z));
323}
324
325template <typename Type>
327{
328 PL_NAN_ASSERT(this);
329 PL_NAN_ASSERT(&rhs);
330
331 return plVec3Template<Type>(plMath::Max(x, rhs.x), plMath::Max(y, rhs.y), plMath::Max(z, rhs.z));
332}
333
334template <typename Type>
335PL_FORCE_INLINE const plVec3Template<Type> plVec3Template<Type>::CompClamp(const plVec3Template& vLow, const plVec3Template& vHigh) const
336{
337 PL_NAN_ASSERT(this);
338 PL_NAN_ASSERT(&vLow);
339 PL_NAN_ASSERT(&vHigh);
340
341 return plVec3Template<Type>(plMath::Clamp(x, vLow.x, vHigh.x), plMath::Clamp(y, vLow.y, vHigh.y), plMath::Clamp(z, vLow.z, vHigh.z));
342}
343
344template <typename Type>
346{
347 PL_NAN_ASSERT(this);
348 PL_NAN_ASSERT(&rhs);
349
350 return plVec3Template<Type>(x * rhs.x, y * rhs.y, z * rhs.z);
351}
352
353template <typename Type>
355{
356 PL_NAN_ASSERT(this);
357 PL_NAN_ASSERT(&rhs);
358
359 return plVec3Template<Type>(x / rhs.x, y / rhs.y, z / rhs.z);
360}
361
362template <typename Type>
364{
365 PL_NAN_ASSERT(this);
366
368}
369
370template <typename Type>
371PL_FORCE_INLINE const plVec3Template<Type> operator+(const plVec3Template<Type>& v1, const plVec3Template<Type>& v2)
372{
373 PL_NAN_ASSERT(&v1);
374 PL_NAN_ASSERT(&v2);
375
376 return plVec3Template<Type>(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
377}
378
379template <typename Type>
380PL_FORCE_INLINE const plVec3Template<Type> operator-(const plVec3Template<Type>& v1, const plVec3Template<Type>& v2)
381{
382 PL_NAN_ASSERT(&v1);
383 PL_NAN_ASSERT(&v2);
384
385 return plVec3Template<Type>(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
386}
387
388template <typename Type>
389PL_FORCE_INLINE const plVec3Template<Type> operator*(Type f, const plVec3Template<Type>& v)
390{
391 PL_NAN_ASSERT(&v);
392
393 return plVec3Template<Type>(v.x * f, v.y * f, v.z * f);
394}
395
396template <typename Type>
397PL_FORCE_INLINE const plVec3Template<Type> operator*(const plVec3Template<Type>& v, Type f)
398{
399 PL_NAN_ASSERT(&v);
400
401 return plVec3Template<Type>(v.x * f, v.y * f, v.z * f);
402}
403
404template <typename Type>
405PL_FORCE_INLINE const plVec3Template<Type> operator/(const plVec3Template<Type>& v, Type f)
406{
407 PL_NAN_ASSERT(&v);
408
409 if constexpr (std::is_floating_point_v<Type>)
410 {
411 // multiplication is much faster than division
412 const Type f_inv = plMath::Invert(f);
413 return plVec3Template<Type>(v.x * f_inv, v.y * f_inv, v.z * f_inv);
414 }
415 else
416 {
417 return plVec3Template<Type>(v.x / f, v.y / f, v.z / f);
418 }
419}
420
421template <typename Type>
423{
424 PL_NAN_ASSERT(this);
425 PL_NAN_ASSERT(&rhs);
426
427 return ((x == rhs.x) && (y == rhs.y) && (z == rhs.z));
428}
429
430template <typename Type>
431bool plVec3Template<Type>::IsEqual(const plVec3Template<Type>& rhs, Type fEpsilon) const
432{
433 PL_NAN_ASSERT(this);
434 PL_NAN_ASSERT(&rhs);
435
436 return (plMath::IsEqual(x, rhs.x, fEpsilon) && plMath::IsEqual(y, rhs.y, fEpsilon) && plMath::IsEqual(z, rhs.z, fEpsilon));
437}
438
439template <typename Type>
440PL_ALWAYS_INLINE bool operator==(const plVec3Template<Type>& v1, const plVec3Template<Type>& v2)
441{
442 return v1.IsIdentical(v2);
443}
444
445template <typename Type>
446PL_ALWAYS_INLINE bool operator!=(const plVec3Template<Type>& v1, const plVec3Template<Type>& v2)
447{
448 return !v1.IsIdentical(v2);
449}
450
451template <typename Type>
452PL_FORCE_INLINE bool operator<(const plVec3Template<Type>& v1, const plVec3Template<Type>& v2)
453{
454 PL_NAN_ASSERT(&v1);
455 PL_NAN_ASSERT(&v2);
456
457 if (v1.x < v2.x)
458 return true;
459 if (v1.x > v2.x)
460 return false;
461 if (v1.y < v2.y)
462 return true;
463 if (v1.y > v2.y)
464 return false;
465
466 return (v1.z < v2.z);
467}
468
469template <typename Type>
470PL_IMPLEMENT_IF_FLOAT_TYPE const plVec3Template<Type> plVec3Template<Type>::GetRefractedVector(const plVec3Template<Type>& vNormal, Type fRefIndex1, Type fRefIndex2) const
471{
472 PL_ASSERT_DEBUG(vNormal.IsNormalized(), "vNormal must be normalized.");
473
474 const Type n = fRefIndex1 / fRefIndex2;
475 const Type cosI = this->Dot(vNormal);
476 const Type sinT2 = n * n * (1.0f - (cosI * cosI));
477
478 // invalid refraction
479 if (sinT2 > 1.0f)
480 return (*this);
481
482 return ((n * (*this)) - (n + plMath::Sqrt(1.0f - sinT2)) * vNormal);
483}
Float wrapper struct for a safe usage and conversions of angles.
Definition Angle.h:10
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
PL_DECLARE_IF_FLOAT_TYPE Type GetLength() const
Returns the length of the vector.
Definition Vec3_inl.h:54
const plVec3Template< Type > CompClamp(const plVec3Template< Type > &vLow, const plVec3Template< Type > &vHigh) const
Returns the component-wise clamped value of *this between low and high.
Definition Vec3_inl.h:335
bool IsNaN() const
Returns true, if any of x, y or z is NaN.
Definition Vec3_inl.h:144
const plVec3Template< Type > CompDiv(const plVec3Template< Type > &rhs) const
Returns the component-wise division of *this and rhs.
Definition Vec3_inl.h:354
const plVec3Template< Type > CompMin(const plVec3Template< Type > &rhs) const
Returns the component-wise minimum of *this and rhs.
Definition Vec3_inl.h:317
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 IsIdentical(const plVec3Template< Type > &rhs) const
Equality Check (bitwise)
Definition Vec3_inl.h:422
void operator+=(const plVec3Template< Type > &rhs)
Adds rhs component-wise to this vector.
Definition Vec3_inl.h:178
const plVec3Template< Type > Abs() const
brief Returns the component-wise absolute of *this.
Definition Vec3_inl.h:363
bool IsValid() const
Checks that all components are finite numbers.
Definition Vec3_inl.h:157
PL_DECLARE_IF_FLOAT_TYPE bool IsNormalized(Type fEpsilon=plMath::HugeEpsilon< Type >()) const
Returns, whether the squared length of this vector is between 0.999f and 1.001f.
Definition Vec3_inl.h:121
void operator*=(const plVec3Template< Type > &rhs)
Multiplies rhs component-wise to this vector.
Definition Vec3_inl.h:198
Type GetLengthSquared() const
Returns the squared length. Faster, since no square-root is taken. Useful, if one only wants to compa...
Definition Vec3_inl.h:70
PL_DECLARE_IF_FLOAT_TYPE const plVec3Template< Type > GetReflectedVector(const plVec3Template< Type > &vNormal) const
Returns this vector reflected at vNormal.
Definition Vec3_inl.h:282
bool IsEqual(const plVec3Template< Type > &rhs, Type fEpsilon) const
Equality Check with epsilon.
Definition Vec3_inl.h:431
const plVec3Template< Type > CompMax(const plVec3Template< Type > &rhs) const
Returns the component-wise maximum of *this and rhs.
Definition Vec3_inl.h:326
PL_DECLARE_IF_FLOAT_TYPE Type GetLengthAndNormalize()
Normalizes this vector and returns its previous length in one operation. More efficient than calling ...
Definition Vec3_inl.h:78
PL_DECLARE_IF_FLOAT_TYPE void Normalize()
Normalizes this vector.
Definition Vec3_inl.h:95
void SetZero()
Sets the vector to all zero.
Definition Vec3_inl.h:48
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
PL_DECLARE_IF_FLOAT_TYPE plResult NormalizeIfNotZero(const plVec3Template< Type > &vFallback=plVec3Template< Type >(1, 0, 0), Type fEpsilon=plMath::SmallEpsilon< Type >())
Tries to normalize this vector. If the vector is too close to zero, PL_FAILURE is returned and the ve...
Definition Vec3_inl.h:101
void operator/=(const plVec3Template< Type > &rhs)
Divides this vector component-wise by rhs.
Definition Vec3_inl.h:210
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
void operator-=(const plVec3Template< Type > &rhs)
Subtracts rhs component-wise from this vector.
Definition Vec3_inl.h:188
const plVec3Template< Type > CompMul(const plVec3Template< Type > &rhs) const
Returns the component-wise multiplication of *this and rhs.
Definition Vec3_inl.h:345
bool IsZero() const
Returns, whether this vector is (0, 0, 0).
Definition Vec3_inl.h:128
plVec3Template()
default-constructed vector is uninitialized (for speed)
Definition Vec3_inl.h:4
PL_DECLARE_IF_FLOAT_TYPE const plVec3Template< Type > GetOrthogonalVector() const
Returns some arbitrary vector orthogonal to this one. The vector is NOT normalized.
Definition Vec3_inl.h:270
PL_DECLARE_IF_FLOAT_TYPE const plVec3Template< Type > GetRefractedVector(const plVec3Template< Type > &vNormal, Type fRefIndex1, Type fRefIndex2) const
Returns this vector, refracted at vNormal, using the refraction index of the current medium and the m...
Definition Vec3_inl.h:470
PL_DECLARE_IF_FLOAT_TYPE void MakeOrthogonalTo(const plVec3Template< Type > &vNormal)
Modifies this direction vector to be orthogonal to the given (normalized) direction vector....
Definition Vec3_inl.h:260
const plVec3Template< Type > operator-() const
Returns the negation of this vector.
Definition Vec3_inl.h:170
PL_DECLARE_IF_FLOAT_TYPE plResult CalculateNormal(const plVec3Template< Type > &v1, const plVec3Template< Type > &v2, const plVec3Template< Type > &v3)
Calculates the normal of the triangle defined by the three vertices. Vertices are assumed to be order...
Definition Vec3_inl.h:253
plAngle GetAngleBetween(const plVec3Template< Type > &rhs) const
Returns the positive angle between *this and rhs. Both this and rhs must be normalized.
Definition Vec3_inl.h:308
PL_DECLARE_IF_FLOAT_TYPE plResult SetLength(Type fNewLength, Type fEpsilon=plMath::DefaultEpsilon< Type >())
Tries to rescale the vector to the given length. If the vector is too close to zero,...
Definition Vec3_inl.h:60
constexpr PL_ALWAYS_INLINE T Min(T f1, T f2)
Returns the smaller value, f1 or f2.
Definition Math_inl.h:27
PL_ALWAYS_INLINE plAngle ACos(float f)
Returns the arcus cosinus of f.
Definition MathFloat_inl.h:82
constexpr Type Invert(Type f)
Returns 1 / f.
Definition Math_inl.h:63
constexpr PL_ALWAYS_INLINE T Clamp(T value, T min_val, T max_val)
Clamps "value" to the range [min; max]. Returns "value", if it is inside the range already.
Definition Math_inl.h:51
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
bool IsZero(Type f, Type fEpsilon)
Checks whether the given number is close to zero.
Definition Math_inl.h:288
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
constexpr PL_ALWAYS_INLINE T Max(T f1, T f2)
Returns the greater value, f1 or f2.
Definition Math_inl.h:39
Definition FormatStringArgs.h:48
Default enum for returning failure or success, instead of using a bool.
Definition Types.h:54