Plasma Engine  2.0
Loading...
Searching...
No Matches
Mat4_inl.h
1#pragma once
2
3#include <Foundation/Math/Mat3.h>
4
5template <typename Type>
7{
8#if PL_ENABLED(PL_MATH_CHECK_FOR_NAN)
9 // Initialize all data to NaN in debug mode to find problems with uninitialized data easier.
10 const Type TypeNaN = plMath::NaN<Type>();
11 for (plUInt32 i = 0; i < 16; ++i)
12 m_fElementsCM[i] = TypeNaN;
13#endif
14}
15
16template <typename Type>
18{
19 if (layout == plMatrixLayout::ColumnMajor)
20 {
21 plMemoryUtils::Copy(m_fElementsCM, pData, 16);
22 }
23 else
24 {
25 for (int i = 0; i < 4; ++i)
26 {
27 Element(0, i) = pData[i * 4 + 0];
28 Element(1, i) = pData[i * 4 + 1];
29 Element(2, i) = pData[i * 4 + 2];
30 Element(3, i) = pData[i * 4 + 3];
31 }
32 }
33}
34
35template <typename Type>
36plMat4Template<Type>::plMat4Template(Type c1r1, Type c2r1, Type c3r1, Type c4r1, Type c1r2, Type c2r2, Type c3r2, Type c4r2, Type c1r3, Type c2r3,
37 Type c3r3, Type c4r3, Type c1r4, Type c2r4, Type c3r4, Type c4r4)
38{
39 Element(0, 0) = c1r1;
40 Element(1, 0) = c2r1;
41 Element(2, 0) = c3r1;
42 Element(3, 0) = c4r1;
43 Element(0, 1) = c1r2;
44 Element(1, 1) = c2r2;
45 Element(2, 1) = c3r2;
46 Element(3, 1) = c4r2;
47 Element(0, 2) = c1r3;
48 Element(1, 2) = c2r3;
49 Element(2, 2) = c3r3;
50 Element(3, 2) = c4r3;
51 Element(0, 3) = c1r4;
52 Element(1, 3) = c2r4;
53 Element(2, 3) = c3r4;
54 Element(3, 3) = c4r4;
55}
56
57template <typename Type>
60 SetTransformationMatrix(mRotation, vTranslation);
61}
63template <typename Type>
67
68 for (plUInt32 i = 0; i < PL_ARRAY_SIZE(res.m_fElementsCM); ++i)
69 res.m_fElementsCM[i] = 0.0f;
70
71 return res;
72}
73
74template <typename Type>
76{
78 res.m_fElementsCM[0] = 1.0f;
79 res.m_fElementsCM[1] = 0.0f;
80 res.m_fElementsCM[2] = 0.0f;
81 res.m_fElementsCM[3] = 0.0f;
82 res.m_fElementsCM[4] = 0.0f;
83 res.m_fElementsCM[5] = 1.0f;
84 res.m_fElementsCM[6] = 0.0f;
85 res.m_fElementsCM[7] = 0.0f;
86 res.m_fElementsCM[8] = 0.0f;
87 res.m_fElementsCM[9] = 0.0f;
88 res.m_fElementsCM[10] = 1.0f;
89 res.m_fElementsCM[11] = 0.0f;
90 res.m_fElementsCM[12] = 0.0f;
91 res.m_fElementsCM[13] = 0.0f;
92 res.m_fElementsCM[14] = 0.0f;
93 res.m_fElementsCM[15] = 1.0f;
94 return res;
95}
97template <typename Type>
101 for (int i = 0; i < 4; ++i)
102 {
103 res.Element(0, i) = pData[i * 4 + 0];
104 res.Element(1, i) = pData[i * 4 + 1];
105 res.Element(2, i) = pData[i * 4 + 2];
106 res.Element(3, i) = pData[i * 4 + 3];
108 return res;
109}
110
111template <typename Type>
113{
116 return res;
117}
118
119template <typename Type>
120plMat4Template<Type> plMat4Template<Type>::MakeFromValues(Type c1r1, Type c2r1, Type c3r1, Type c4r1, Type c1r2, Type c2r2, Type c3r2, Type c4r2, Type c1r3, Type c2r3, Type c3r3, Type c4r3, Type c1r4, Type c2r4, Type c3r4, Type c4r4)
123 res.Element(0, 0) = c1r1;
124 res.Element(1, 0) = c2r1;
125 res.Element(2, 0) = c3r1;
126 res.Element(3, 0) = c4r1;
127 res.Element(0, 1) = c1r2;
128 res.Element(1, 1) = c2r2;
129 res.Element(2, 1) = c3r2;
130 res.Element(3, 1) = c4r2;
131 res.Element(0, 2) = c1r3;
132 res.Element(1, 2) = c2r3;
133 res.Element(2, 2) = c3r3;
134 res.Element(3, 2) = c4r3;
135 res.Element(0, 3) = c1r4;
136 res.Element(1, 3) = c2r4;
137 res.Element(2, 3) = c3r4;
138 res.Element(3, 3) = c4r4;
139 return res;
141
142template <typename Type>
144{
145 return plMat4Template<Type>::MakeFromValues(1, 0, 0, vTranslation.x, 0, 1, 0, vTranslation.y, 0, 0, 1, vTranslation.z, 0, 0, 0, 1);
147
148
149template <typename Type>
151{
153 res.SetTransformationMatrix(mRotation, vTranslation);
154 return res;
156
157template <typename Type>
159{
161 res.Element(0, 0) = vScale.x;
162 res.Element(1, 0) = 0;
163 res.Element(2, 0) = 0;
164 res.Element(3, 0) = 0;
165 res.Element(0, 1) = 0;
166 res.Element(1, 1) = vScale.y;
167 res.Element(2, 1) = 0;
168 res.Element(3, 1) = 0;
169 res.Element(0, 2) = 0;
170 res.Element(1, 2) = 0;
171 res.Element(2, 2) = vScale.z;
172 res.Element(3, 2) = 0;
173 res.Element(0, 3) = 0;
174 res.Element(1, 3) = 0;
175 res.Element(2, 3) = 0;
176 res.Element(3, 3) = 1;
177 return res;
178}
180template <typename Type>
183 const Type fSin = plMath::Sin(angle);
184 const Type fCos = plMath::Cos(angle);
185
186 return plMat4Template<Type>::MakeFromValues(1.0f, 0.0f, 0.0f, 0.0f, 0.0f, fCos, -fSin, 0.0f, 0.0f, fSin, fCos, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f);
187}
188
189template <typename Type>
191{
192 const Type fSin = plMath::Sin(angle);
193 const Type fCos = plMath::Cos(angle);
194
195 return plMat4Template<Type>::MakeFromValues(fCos, 0.0f, fSin, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, -fSin, 0.0f, fCos, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f);
197
198template <typename Type>
200{
201 const Type fSin = plMath::Sin(angle);
202 const Type fCos = plMath::Cos(angle);
203
204 return plMat4Template<Type>::MakeFromValues(fCos, -fSin, 0.0f, 0.0f, fSin, fCos, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f);
206
207template <typename Type>
209{
210 SetRotationalPart(mRotation);
211 SetTranslationVector(vTranslation);
212 SetRow(3, plVec4Template<Type>(0, 0, 0, 1));
213}
214
215template <typename Type>
217{
218 PL_NAN_ASSERT(this);
219
220 if (layout == plMatrixLayout::ColumnMajor)
221 {
222 plMemoryUtils::Copy(out_pData, m_fElementsCM, 16);
223 }
224 else
225 {
226 for (int i = 0; i < 4; ++i)
227 {
228 out_pData[i * 4 + 0] = Element(0, i);
229 out_pData[i * 4 + 1] = Element(1, i);
230 out_pData[i * 4 + 2] = Element(2, i);
231 out_pData[i * 4 + 3] = Element(3, i);
232 }
233 }
234}
235
236template <typename Type>
238{
239 *this = MakeZero();
240}
241
242template <typename Type>
244{
245 *this = MakeIdentity();
246}
247
248template <typename Type>
250{
251 plMath::Swap(Element(0, 1), Element(1, 0));
252 plMath::Swap(Element(0, 2), Element(2, 0));
253 plMath::Swap(Element(0, 3), Element(3, 0));
254 plMath::Swap(Element(1, 2), Element(2, 1));
255 plMath::Swap(Element(1, 3), Element(3, 1));
256 plMath::Swap(Element(2, 3), Element(3, 2));
257}
258
259template <typename Type>
261{
262 PL_NAN_ASSERT(this);
263
264 return plMat4Template::MakeFromRowMajorArray(m_fElementsCM);
265}
266
267template <typename Type>
269{
270 plMat4Template<Type> Inverse = *this;
271 plResult res = Inverse.Invert(fEpsilon);
272 PL_ASSERT_DEBUG(res.Succeeded(), "Could not invert the given Mat4.");
273 PL_IGNORE_UNUSED(res);
274 return Inverse;
275}
276
277template <typename Type>
279{
280 PL_NAN_ASSERT(this);
281 PL_ASSERT_DEBUG(uiRow <= 3, "Invalid Row Index {0}", uiRow);
282
284 r.x = Element(0, uiRow);
285 r.y = Element(1, uiRow);
286 r.z = Element(2, uiRow);
287 r.w = Element(3, uiRow);
288
289 return r;
290}
291
292template <typename Type>
293void plMat4Template<Type>::SetRow(plUInt32 uiRow, const plVec4Template<Type>& vRow)
294{
295 PL_ASSERT_DEBUG(uiRow <= 3, "Invalid Row Index {0}", uiRow);
296
297 Element(0, uiRow) = vRow.x;
298 Element(1, uiRow) = vRow.y;
299 Element(2, uiRow) = vRow.z;
300 Element(3, uiRow) = vRow.w;
301}
302
303template <typename Type>
305{
306 PL_NAN_ASSERT(this);
307 PL_ASSERT_DEBUG(uiColumn <= 3, "Invalid Column Index {0}", uiColumn);
308
310 r.x = Element(uiColumn, 0);
311 r.y = Element(uiColumn, 1);
312 r.z = Element(uiColumn, 2);
313 r.w = Element(uiColumn, 3);
314
315 return r;
316}
317
318template <typename Type>
319void plMat4Template<Type>::SetColumn(plUInt32 uiColumn, const plVec4Template<Type>& vColumn)
320{
321 PL_ASSERT_DEBUG(uiColumn <= 3, "Invalid Column Index {0}", uiColumn);
322
323 Element(uiColumn, 0) = vColumn.x;
324 Element(uiColumn, 1) = vColumn.y;
325 Element(uiColumn, 2) = vColumn.z;
326 Element(uiColumn, 3) = vColumn.w;
327}
328
329template <typename Type>
331{
332 PL_NAN_ASSERT(this);
333
334 return plVec4Template<Type>(Element(0, 0), Element(1, 1), Element(2, 2), Element(3, 3));
335}
336
337template <typename Type>
339{
340 Element(0, 0) = vDiag.x;
341 Element(1, 1) = vDiag.y;
342 Element(2, 2) = vDiag.z;
343 Element(3, 3) = vDiag.w;
344}
345
346template <typename Type>
348{
350 r.x = Element(0, 0) * v.x + Element(1, 0) * v.y + Element(2, 0) * v.z + Element(3, 0);
351 r.y = Element(0, 1) * v.x + Element(1, 1) * v.y + Element(2, 1) * v.z + Element(3, 1);
352 r.z = Element(0, 2) * v.x + Element(1, 2) * v.y + Element(2, 2) * v.z + Element(3, 2);
353
354 PL_NAN_ASSERT(&r);
355 return r;
356}
357
358template <typename Type>
359void plMat4Template<Type>::TransformPosition(plVec3Template<Type>* pV, plUInt32 uiNumVectors, plUInt32 uiStride /* = sizeof(plVec3Template) */) const
360{
361 PL_ASSERT_DEBUG(pV != nullptr, "Array must not be nullptr.");
362 PL_ASSERT_DEBUG(uiStride >= sizeof(plVec3Template<Type>), "Data must not overlap.");
363
364 plVec3Template<Type>* pCur = pV;
365
366 for (plUInt32 i = 0; i < uiNumVectors; ++i)
367 {
368 *pCur = TransformPosition(*pCur);
369 pCur = plMemoryUtils::AddByteOffset(pCur, uiStride);
370 }
371}
372
373template <typename Type>
375{
377 r.x = Element(0, 0) * v.x + Element(1, 0) * v.y + Element(2, 0) * v.z;
378 r.y = Element(0, 1) * v.x + Element(1, 1) * v.y + Element(2, 1) * v.z;
379 r.z = Element(0, 2) * v.x + Element(1, 2) * v.y + Element(2, 2) * v.z;
380
381 PL_NAN_ASSERT(&r);
382 return r;
383}
384
385template <typename Type>
387 plVec3Template<Type>* pV, plUInt32 uiNumVectors, plUInt32 uiStride /* = sizeof(plVec3Template<Type>) */) const
388{
389 PL_ASSERT_DEBUG(pV != nullptr, "Array must not be nullptr.");
390 PL_ASSERT_DEBUG(uiStride >= sizeof(plVec3Template<Type>), "Data must not overlap.");
391
392 plVec3Template<Type>* pCur = pV;
393
394 for (plUInt32 i = 0; i < uiNumVectors; ++i)
395 {
396 *pCur = TransformDirection(*pCur);
397 pCur = plMemoryUtils::AddByteOffset(pCur, uiStride);
398 }
399}
400
401template <typename Type>
403{
405 r.x = Element(0, 0) * v.x + Element(1, 0) * v.y + Element(2, 0) * v.z + Element(3, 0) * v.w;
406 r.y = Element(0, 1) * v.x + Element(1, 1) * v.y + Element(2, 1) * v.z + Element(3, 1) * v.w;
407 r.z = Element(0, 2) * v.x + Element(1, 2) * v.y + Element(2, 2) * v.z + Element(3, 2) * v.w;
408 r.w = Element(0, 3) * v.x + Element(1, 3) * v.y + Element(2, 3) * v.z + Element(3, 3) * v.w;
409
410 PL_NAN_ASSERT(&r);
411 return r;
412}
413
414template <typename Type>
415void plMat4Template<Type>::Transform(plVec4Template<Type>* pV, plUInt32 uiNumVectors, plUInt32 uiStride /* = sizeof(plVec4Template) */) const
416{
417 PL_ASSERT_DEBUG(pV != nullptr, "Array must not be nullptr.");
418 PL_ASSERT_DEBUG(uiStride >= sizeof(plVec4Template<Type>), "Data must not overlap.");
419
420 plVec4Template<Type>* pCur = pV;
421
422 for (plUInt32 i = 0; i < uiNumVectors; ++i)
423 {
424 *pCur = Transform(*pCur);
425 pCur = plMemoryUtils::AddByteOffset(pCur, uiStride);
426 }
427}
428
429template <typename Type>
431{
432 PL_NAN_ASSERT(this);
433
434 return plVec3Template<Type>(Element(3, 0), Element(3, 1), Element(3, 2));
435}
436
437template <typename Type>
439{
440 Element(3, 0) = v.x;
441 Element(3, 1) = v.y;
442 Element(3, 2) = v.z;
443}
444
445template <typename Type>
447{
448 for (plUInt32 col = 0; col < 3; ++col)
449 {
450 for (plUInt32 row = 0; row < 3; ++row)
451 {
452 Element(col, row) = mRotation.Element(col, row);
453 }
454 }
455}
456
457template <typename Type>
459{
461
462 for (plUInt32 col = 0; col < 3; ++col)
463 {
464 for (plUInt32 row = 0; row < 3; ++row)
465 {
466 r.Element(col, row) = Element(col, row);
467 }
468 }
469
470 PL_NAN_ASSERT(&r);
471 return r;
472}
473
474template <typename Type>
476{
477 for (plInt32 i = 0; i < 16; ++i)
478 m_fElementsCM[i] *= f;
479
480 PL_NAN_ASSERT(this);
481}
482
483template <typename Type>
485{
486 const Type fInv = plMath::Invert(f);
487
488 operator*=(fInv);
489}
490
491template <typename Type>
492const plMat4Template<Type> operator*(const plMat4Template<Type>& m1, const plMat4Template<Type>& m2)
493{
495 for (plInt32 i = 0; i < 4; ++i)
496 {
497 r.Element(0, i) = m1.Element(0, i) * m2.Element(0, 0) + m1.Element(1, i) * m2.Element(0, 1) + m1.Element(2, i) * m2.Element(0, 2) +
498 m1.Element(3, i) * m2.Element(0, 3);
499 r.Element(1, i) = m1.Element(0, i) * m2.Element(1, 0) + m1.Element(1, i) * m2.Element(1, 1) + m1.Element(2, i) * m2.Element(1, 2) +
500 m1.Element(3, i) * m2.Element(1, 3);
501 r.Element(2, i) = m1.Element(0, i) * m2.Element(2, 0) + m1.Element(1, i) * m2.Element(2, 1) + m1.Element(2, i) * m2.Element(2, 2) +
502 m1.Element(3, i) * m2.Element(2, 3);
503 r.Element(3, i) = m1.Element(0, i) * m2.Element(3, 0) + m1.Element(1, i) * m2.Element(3, 1) + m1.Element(2, i) * m2.Element(3, 2) +
504 m1.Element(3, i) * m2.Element(3, 3);
505 }
506
507 PL_NAN_ASSERT(&r);
508 return r;
509}
510
511template <typename Type>
512PL_ALWAYS_INLINE const plVec3Template<Type> operator*(const plMat4Template<Type>& m, const plVec3Template<Type>& v)
513{
514 return m.TransformPosition(v);
515}
516
517template <typename Type>
518PL_ALWAYS_INLINE const plVec4Template<Type> operator*(const plMat4Template<Type>& m, const plVec4Template<Type>& v)
519{
520 return m.Transform(v);
521}
522
523
524
525// *** Stuff needed for matrix inversion ***
526
527template <typename Type>
528PL_FORCE_INLINE Type GetDeterminantOf3x3SubMatrix(const plMat4Template<Type>& m, plInt32 i, plInt32 j)
529{
530 const plInt32 si0 = 0 + ((i <= 0) ? 1 : 0);
531 const plInt32 si1 = 1 + ((i <= 1) ? 1 : 0);
532 const plInt32 si2 = 2 + ((i <= 2) ? 1 : 0);
533
534 const plInt32 sj0 = 0 + ((j <= 0) ? 1 : 0);
535 const plInt32 sj1 = 1 + ((j <= 1) ? 1 : 0);
536 const plInt32 sj2 = 2 + ((j <= 2) ? 1 : 0);
537
538 Type fDet2 = ((m.Element(sj0, si0) * m.Element(sj1, si1) * m.Element(sj2, si2) + m.Element(sj1, si0) * m.Element(sj2, si1) * m.Element(sj0, si2) +
539 m.Element(sj2, si0) * m.Element(sj0, si1) * m.Element(sj1, si2)) -
540 (m.Element(sj0, si2) * m.Element(sj1, si1) * m.Element(sj2, si0) + m.Element(sj1, si2) * m.Element(sj2, si1) * m.Element(sj0, si0) +
541 m.Element(sj2, si2) * m.Element(sj0, si1) * m.Element(sj1, si0)));
542
543 return fDet2;
544}
545
546template <typename Type>
547PL_FORCE_INLINE Type GetDeterminantOf4x4Matrix(const plMat4Template<Type>& m)
548{
549 Type det = 0.0;
550
551 det += m.Element(0, 0) * GetDeterminantOf3x3SubMatrix(m, 0, 0);
552 det += -m.Element(1, 0) * GetDeterminantOf3x3SubMatrix(m, 0, 1);
553 det += m.Element(2, 0) * GetDeterminantOf3x3SubMatrix(m, 0, 2);
554 det += -m.Element(3, 0) * GetDeterminantOf3x3SubMatrix(m, 0, 3);
555
556 return det;
557}
558
559
560// *** free functions ***
561
562template <typename Type>
563PL_ALWAYS_INLINE const plMat4Template<Type> operator*(Type f, const plMat4Template<Type>& m1)
564{
565 return operator*(m1, f);
566}
567
568template <typename Type>
569const plMat4Template<Type> operator*(const plMat4Template<Type>& m1, Type f)
570{
572
573 for (plUInt32 i = 0; i < 16; ++i)
574 r.m_fElementsCM[i] = m1.m_fElementsCM[i] * f;
575
576 PL_NAN_ASSERT(&r);
577 return r;
578}
579
580template <typename Type>
581const plMat4Template<Type> operator/(const plMat4Template<Type>& m1, Type f)
582{
583 return operator*(m1, plMath::Invert(f));
584}
585
586template <typename Type>
587const plMat4Template<Type> operator+(const plMat4Template<Type>& m1, const plMat4Template<Type>& m2)
588{
590
591 for (plUInt32 i = 0; i < 16; ++i)
592 r.m_fElementsCM[i] = m1.m_fElementsCM[i] + m2.m_fElementsCM[i];
593
594 PL_NAN_ASSERT(&r);
595 return r;
596}
597
598template <typename Type>
599const plMat4Template<Type> operator-(const plMat4Template<Type>& m1, const plMat4Template<Type>& m2)
600{
602
603 for (plUInt32 i = 0; i < 16; ++i)
604 r.m_fElementsCM[i] = m1.m_fElementsCM[i] - m2.m_fElementsCM[i];
605
606 PL_NAN_ASSERT(&r);
607 return r;
608}
609
610template <typename Type>
612{
613 PL_NAN_ASSERT(this);
614 PL_NAN_ASSERT(&rhs);
615
616 for (plUInt32 i = 0; i < 16; ++i)
617 {
618 if (m_fElementsCM[i] != rhs.m_fElementsCM[i])
619 return false;
620 }
621
622 return true;
623}
624
625template <typename Type>
626bool plMat4Template<Type>::IsEqual(const plMat4Template<Type>& rhs, Type fEpsilon) const
627{
628 PL_NAN_ASSERT(this);
629 PL_NAN_ASSERT(&rhs);
630
631 PL_ASSERT_DEBUG(fEpsilon >= 0.0f, "Epsilon may not be negative.");
632
633 for (plUInt32 i = 0; i < 16; ++i)
634 {
635 if (!plMath::IsEqual(m_fElementsCM[i], rhs.m_fElementsCM[i], fEpsilon))
636 return false;
637 }
638
639 return true;
640}
641
642template <typename Type>
643PL_ALWAYS_INLINE bool operator==(const plMat4Template<Type>& lhs, const plMat4Template<Type>& rhs)
644{
645 return lhs.IsIdentical(rhs);
646}
647
648template <typename Type>
649PL_ALWAYS_INLINE bool operator!=(const plMat4Template<Type>& lhs, const plMat4Template<Type>& rhs)
650{
651 return !lhs.IsIdentical(rhs);
652}
653
654template <typename Type>
655bool plMat4Template<Type>::IsZero(Type fEpsilon) const
656{
657 PL_NAN_ASSERT(this);
658
659 for (plUInt32 i = 0; i < 16; ++i)
660 {
661 if (!plMath::IsZero(m_fElementsCM[i], fEpsilon))
662 return false;
663 }
664
665 return true;
666}
667
668template <typename Type>
669bool plMat4Template<Type>::IsIdentity(Type fEpsilon) const
670{
671 PL_NAN_ASSERT(this);
672
673 if (!plMath::IsEqual(Element(0, 0), (Type)1, fEpsilon))
674 return false;
675 if (!plMath::IsEqual(Element(0, 1), (Type)0, fEpsilon))
676 return false;
677 if (!plMath::IsEqual(Element(0, 2), (Type)0, fEpsilon))
678 return false;
679 if (!plMath::IsEqual(Element(0, 3), (Type)0, fEpsilon))
680 return false;
681
682 if (!plMath::IsEqual(Element(1, 0), (Type)0, fEpsilon))
683 return false;
684 if (!plMath::IsEqual(Element(1, 1), (Type)1, fEpsilon))
685 return false;
686 if (!plMath::IsEqual(Element(1, 2), (Type)0, fEpsilon))
687 return false;
688 if (!plMath::IsEqual(Element(1, 3), (Type)0, fEpsilon))
689 return false;
690
691 if (!plMath::IsEqual(Element(2, 0), (Type)0, fEpsilon))
692 return false;
693 if (!plMath::IsEqual(Element(2, 1), (Type)0, fEpsilon))
694 return false;
695 if (!plMath::IsEqual(Element(2, 2), (Type)1, fEpsilon))
696 return false;
697 if (!plMath::IsEqual(Element(2, 3), (Type)0, fEpsilon))
698 return false;
699
700 if (!plMath::IsEqual(Element(3, 0), (Type)0, fEpsilon))
701 return false;
702 if (!plMath::IsEqual(Element(3, 1), (Type)0, fEpsilon))
703 return false;
704 if (!plMath::IsEqual(Element(3, 2), (Type)0, fEpsilon))
705 return false;
706 if (!plMath::IsEqual(Element(3, 3), (Type)1, fEpsilon))
707 return false;
708
709 return true;
710}
711
712template <typename Type>
714{
715 for (plUInt32 i = 0; i < 16; ++i)
716 {
717 if (!plMath::IsFinite(m_fElementsCM[i]))
718 return false;
719 }
720
721 return true;
722}
723
724template <typename Type>
726{
727 for (plUInt32 i = 0; i < 16; ++i)
728 {
729 if (plMath::IsNaN(m_fElementsCM[i]))
730 return true;
731 }
732
733 return false;
734}
735
736template <typename Type>
738{
740
741 v.x = plVec3Template<Type>(Element(0, 0), Element(0, 1), Element(0, 2)).GetLength();
742 v.y = plVec3Template<Type>(Element(1, 0), Element(1, 1), Element(1, 2)).GetLength();
743 v.z = plVec3Template<Type>(Element(2, 0), Element(2, 1), Element(2, 2)).GetLength();
744
745 PL_NAN_ASSERT(&v);
746 return v;
747}
748
749template <typename Type>
750plResult plMat4Template<Type>::SetScalingFactors(const plVec3Template<Type>& vXYZ, Type fEpsilon /* = plMath::DefaultEpsilon<Type>() */)
751{
752 plVec3Template<Type> tx(Element(0, 0), Element(0, 1), Element(0, 2));
753 plVec3Template<Type> ty(Element(1, 0), Element(1, 1), Element(1, 2));
754 plVec3Template<Type> tz(Element(2, 0), Element(2, 1), Element(2, 2));
755
756 if (tx.SetLength(vXYZ.x, fEpsilon) == PL_FAILURE)
757 return PL_FAILURE;
758 if (ty.SetLength(vXYZ.y, fEpsilon) == PL_FAILURE)
759 return PL_FAILURE;
760 if (tz.SetLength(vXYZ.z, fEpsilon) == PL_FAILURE)
761 return PL_FAILURE;
762
763
764 Element(0, 0) = tx.x;
765 Element(0, 1) = tx.y;
766 Element(0, 2) = tx.z;
767 Element(1, 0) = ty.x;
768 Element(1, 1) = ty.y;
769 Element(1, 2) = ty.z;
770 Element(2, 0) = tz.x;
771 Element(2, 1) = tz.y;
772 Element(2, 2) = tz.z;
773
774 return PL_SUCCESS;
775}
776
777#include <Foundation/Math/Implementation/AllClasses_inl.h>
Float wrapper struct for a safe usage and conversions of angles.
Definition Angle.h:10
A 3x3 component matrix class.
Definition Mat3.h:9
A 4x4 component matrix class.
Definition Mat4.h:11
plMat4Template()
Default Constructor DOES NOT INITIALIZE the matrix, at all.
Definition Mat4_inl.h:6
void SetIdentity()
Sets all elements to zero, except the diagonal, which is set to one.
Definition Mat4_inl.h:243
const plVec3Template< Type > GetTranslationVector() const
Returns the first 3 components of the last column.
Definition Mat4_inl.h:430
static plMat4Template< Type > MakeIdentity()
Returns an identity matrix.
Definition Mat4_inl.h:75
static plMat4Template< Type > MakeScaling(const plVec3Template< Type > &vScale)
Creates a matrix with all zero values, except along the diagonal, which is set to x,...
Definition Mat4_inl.h:158
plVec4Template< Type > GetColumn(plUInt32 uiColumn) const
Returns all 4 components of the i-th column.
Definition Mat4_inl.h:304
static plMat4Template< Type > MakeTransformation(const plMat3Template< Type > &mRotation, const plVec3Template< Type > &vTranslation)
Creates a transformation matrix from a rotation and a translation.
Definition Mat4_inl.h:150
const plMat3Template< Type > GetRotationalPart() const
Returns the 3x3 rotational and scaling part of the matrix.
Definition Mat4_inl.h:458
static plMat4Template< Type > MakeFromValues(Type c1r1, Type c2r1, Type c3r1, Type c4r1, Type c1r2, Type c2r2, Type c3r2, Type c4r2, Type c1r3, Type c2r3, Type c3r3, Type c4r3, Type c1r4, Type c2r4, Type c3r4, Type c4r4)
Creates a matrix from 16 values. Naming is "column-n row-m".
Definition Mat4_inl.h:120
static plMat4Template< Type > MakeFromRowMajorArray(const Type *const pData)
Creates a matrix from 16 values that are in row-major layout.
Definition Mat4_inl.h:98
bool IsValid() const
Checks whether all components are finite numbers.
Definition Mat4_inl.h:713
static plMat4Template< Type > MakeRotationY(plAngle angle)
Creates a matrix that is a rotation matrix around the Y-axis.
Definition Mat4_inl.h:190
static plMat4Template< Type > MakeRotationX(plAngle angle)
Creates a matrix that is a rotation matrix around the X-axis.
Definition Mat4_inl.h:181
void SetTranslationVector(const plVec3Template< Type > &v)
Sets the first 3 components of the last column.
Definition Mat4_inl.h:438
Type m_fElementsCM[16]
The matrix as a 16-element Type array (column-major)
Definition Mat4.h:24
plVec4Template< Type > GetDiagonal() const
Returns all 4 components on the diagonal of the matrix.
Definition Mat4_inl.h:330
const plVec3Template< Type > TransformPosition(const plVec3Template< Type > &v) const
Matrix-vector multiplication, assuming the 4th component of the vector is one (default behavior).
Definition Mat4_inl.h:347
const plMat4Template< Type > GetTranspose() const
Returns the transpose of this matrix.
Definition Mat4_inl.h:260
const plVec4Template< Type > Transform(const plVec4Template< Type > &v) const
Matrix-vector multiplication.
Definition Mat4_inl.h:402
plResult SetScalingFactors(const plVec3Template< Type > &vXYZ, Type fEpsilon=plMath::DefaultEpsilon< Type >())
Tries to set the three scaling factors in the matrix. Returns PL_FAILURE if the matrix columns cannot...
Definition Mat4_inl.h:750
static plMat4Template< Type > MakeRotationZ(plAngle angle)
Creates a matrix that is a rotation matrix around the Z-axis.
Definition Mat4_inl.h:199
void SetDiagonal(const plVec4Template< Type > &vDiag)
Sets all 4 components on the diagonal of the matrix.
Definition Mat4_inl.h:338
void Transpose()
Transposes this matrix.
Definition Mat4_inl.h:249
static plMat4Template< Type > MakeTranslation(const plVec3Template< Type > &vTranslation)
Creates a matrix with all zero values, except the last column, which is set to x, y,...
Definition Mat4_inl.h:143
static plMat4Template< Type > MakeZero()
Returns a zero matrix.
Definition Mat4_inl.h:64
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
bool IsZero(Type fEpsilon=plMath::DefaultEpsilon< Type >()) const
Checks whether all elements are zero.
Definition Mat4_inl.h:655
void SetTransformationMatrix(const plMat3Template< Type > &mRotation, const plVec3Template< Type > &vTranslation)
Sets a transformation matrix from a rotation and a translation.
Definition Mat4_inl.h:208
bool IsIdentity(Type fEpsilon=plMath::DefaultEpsilon< Type >()) const
Checks whether this is an identity matrix.
Definition Mat4_inl.h:669
void SetRotationalPart(const plMat3Template< Type > &mRotation)
Sets the 3x3 rotational part of the matrix.
Definition Mat4_inl.h:446
bool IsIdentical(const plMat4Template< Type > &rhs) const
Equality Check.
Definition Mat4_inl.h:611
bool IsNaN() const
Checks whether any component is NaN.
Definition Mat4_inl.h:725
void SetColumn(plUInt32 uiColumn, const plVec4Template< Type > &vColumn)
Sets all 4 components of the i-th column.
Definition Mat4_inl.h:319
plVec4Template< Type > GetRow(plUInt32 uiRow) const
Returns all 4 components of the i-th row.
Definition Mat4_inl.h:278
const plVec3Template< Type > GetScalingFactors() const
Returns the 3 scaling factors that are encoded in the matrix.
Definition Mat4_inl.h:737
void GetAsArray(Type *out_pData, plMatrixLayout::Enum layout) const
Copies the 16 values of this matrix into the given array. 'layout' defines whether the data should en...
Definition Mat4_inl.h:216
const plMat4Template< Type > GetInverse(Type fEpsilon=plMath::SmallEpsilon< Type >()) const
Returns the inverse of this matrix.
Definition Mat4_inl.h:268
void operator*=(Type f)
Component-wise multiplication (commutative)
Definition Mat4_inl.h:475
void operator/=(Type f)
Component-wise division.
Definition Mat4_inl.h:484
bool IsEqual(const plMat4Template< Type > &rhs, Type fEpsilon) const
Equality Check with epsilon.
Definition Mat4_inl.h:626
plResult Invert(Type fEpsilon=plMath::SmallEpsilon< Type >())
Inverts this matrix. Return value indicates whether the matrix could be inverted.
Definition AllClasses_inl.h:310
void SetRow(plUInt32 uiRow, const plVec4Template< Type > &vRow)
Sets all 4 components of the i-th row.
Definition Mat4_inl.h:293
static plMat4Template< Type > MakeFromColumnMajorArray(const Type *const pData)
Creates a matrix from 16 values that are in column-major layout.
Definition Mat4_inl.h:112
void SetZero()
Sets all elements to zero.
Definition Mat4_inl.h:237
static T * AddByteOffset(T *pPtr, std::ptrdiff_t offset)
Returns the address stored in ptr plus the given byte offset iOffset, cast to type T.
static void Copy(T *pDestination, const T *pSource, size_t uiCount=1)
Copies objects of type T from pSource to pDestination.
A 3-component vector class.
Definition Vec3.h:9
PL_DECLARE_IF_FLOAT_TYPE Type GetLength() const
Returns the length of the vector.
Definition Vec3_inl.h:54
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
A 4-component vector class.
Definition Vec4.h:9
PL_ALWAYS_INLINE float Sin(plAngle a)
***** Trigonometric Functions *****
Definition MathFloat_inl.h:62
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
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
PL_ALWAYS_INLINE void Swap(T &ref_f1, T &ref_f2)
Swaps the values in the two variables f1 and f2.
Definition Math_inl.h:224
PL_ALWAYS_INLINE float Cos(plAngle a)
Takes an angle, returns its cosine.
Definition MathFloat_inl.h:67
Enum
Definition Declarations.h:65
@ ColumnMajor
The matrix is stored in column-major format.
Definition Declarations.h:67
Default enum for returning failure or success, instead of using a bool.
Definition Types.h:54