Momentum Scripting v1
Loading...
Searching...
No Matches
Matrix3x3.h
1/*
2Copyright 2007-2025. Algoryx Simulation AB.
3
4All AGX source code, intellectual property, documentation, sample code,
5tutorials, scene files and technical white papers, are copyrighted, proprietary
6and confidential material of Algoryx Simulation AB. You may not download, read,
7store, distribute, publish, copy or otherwise disseminate, use or expose this
8material without having a written signed agreement with Algoryx Simulation AB.
9
10Algoryx Simulation AB disclaims all responsibilities for loss or damage caused
11from using this software, unless otherwise stated in written agreements with
12Algoryx Simulation AB.
13*/
14#ifndef MOMENTUM_MATRIX3X3_H
15#define MOMENTUM_MATRIX3X3_H
16
17#include "momentum_export.h"
18#include <momentum_namespace.h>
19
20#include "macros.h"
21#include <math.h>
22#include "Quat.h"
23#include "Vec3.h"
24#include "Vec4.h"
25
26#include <agx/Prefetch.h>
27
28#ifndef SWIG
29
30#include <agx/Matrix3x3.h>
31
32#endif
33
34namespace MOMENTUM_NAMESPACE
35{
36#define MOMENTUM_MATRIX3X3_SET_ROW(row, v1, v2, v3) \
37 m_data[(row)][0] = (v1); \
38 m_data[(row)][1] = (v2); \
39 m_data[(row)][2] = (v3);
40
41#define MOMENTUM_MATRIX3X3_INNER_PRODUCT(a,b,r,c) \
42 ((a).m_data[r][0] * (b).m_data[0][c]) \
43 +((a).m_data[r][1] * (b).m_data[1][c]) \
44 +((a).m_data[r][2] * (b).m_data[2][c])
45
46#define MOMENTUM_MATRIX3X3_DET2(a, b, c, d) ((a)*(d) - (b)*(c))
47
51 class MOMENTUM_EXPORT Matrix3x3
52 {
53 public:
54
55 /*=====================================================
56 Constructors
57 =======================================================*/
58
59#ifndef SWIG
61 operator agx::Matrix3x3() const
62 {
63 agx::Matrix3x3 mat;
64 mat.set(
65 this->m_data[0][0], this->m_data[0][1], this->m_data[0][2],
66 this->m_data[1][0], this->m_data[1][1], this->m_data[1][2],
67 this->m_data[2][0], this->m_data[2][1], this->m_data[2][2]
68 );
69 return mat;
70 }
72 Matrix3x3(agx::Matrix3x3 mat)
73 {
74 for (auto i = 0; i < 3; i++)
75 for (auto j = 0; j < 3; j++)
76 this->m_data[i][j] = mat(i, j);
77 }
78#endif
82 Matrix3x3();
83
85 Matrix3x3( const Matrix3x3& mat );
86
88 Matrix3x3( double const * const ptr );
89
90
92 Matrix3x3(const Quat& rotation);
93
94
96 Matrix3x3( double a00, double a01, double a02,
97 double a10, double a11, double a12,
98 double a20, double a21, double a22);
99
100
102 ~Matrix3x3();
103
104 /*=====================================================
105 Accessors
106 =======================================================*/
107
111 bool valid() const;
112
116 bool isNaN() const;
117
121 bool isFinite() const;
122
126 bool isIdentity() const;
127
131 bool isRigidTransformation() const;
132
137 Matrix3x3 inverse() const;
138
142 Matrix3x3 transpose() const;
143
144 /*=====================================================
145 Mutators
146 =======================================================*/
147
155 Matrix3x3 set(double const * const ptr );
156 Matrix3x3 set(double a00, double a01, double a02,
157 double a10, double a11, double a12,
158 double a20, double a21, double a22);
159
160
166 void setRow(size_t row, const Vec3& vec ) {
167 m_data[row][0] = vec[0];
168 m_data[row][1] = vec[1];
169 m_data[row][2] = vec[2];
170 }
171
172 void setCol(size_t col, const Vec3& vec ) {
173 m_data[0][col] = vec[0];
174 m_data[1][col] = vec[1];
175 m_data[2][col] = vec[2];
176 }
177
178 Vec3 getRow(size_t row) const
179 {
180 return Vec3(
181 m_data[row][0],
182 m_data[row][1],
183 m_data[row][2]
184 );
185 }
186
187 Vec3 getCol(size_t col) const
188 {
189 return Vec3(
190 m_data[0][col],
191 m_data[1][col],
192 m_data[2][col]
193 );
194 }
195
196 double at(size_t row, size_t col) const
197 {
198 return m_data[row][col];
199 }
200
201
202 Matrix3x3 setRotate(const Quat& q);
203 Matrix3x3 setRotate( const Vec3& from, const Vec3& to );
204 Matrix3x3 setRotate( double angle, const Vec3& axis );
205 Matrix3x3 setRotate( double angle, double x, double y, double z );
206 Matrix3x3 setRotate( double angle1, const Vec3& axis1,
207 double angle2, const Vec3& axis2,
208 double angle3, const Vec3& axis3 );
209
210 Matrix3x3 setIdentity();
211
212 /*=====================================================
213 Accessors
214 =======================================================*/
215
216 Quat getRotate() const;
217
222
223
224 /* Get the internal row-major buffer */
225 double *ptr();
226 const double *ptr() const;
227
228 /*=====================================================
229 Static methods
230 =======================================================*/
231
235 static Matrix3x3 crossMatrix(const Vec3& vec);
236 static Matrix3x3 rotate( const Vec3& from, const Vec3& to );
237 static Matrix3x3 rotate( double angle, double x, double y, double z );
238 static Matrix3x3 rotate( double angle, const Vec3& axis );
239 static Matrix3x3 rotate( double angle1, const Vec3& axis1,
240 double angle2, const Vec3& axis2,
241 double angle3, const Vec3& axis3 );
242
243 /*=====================================================
244 Operators
245 =======================================================*/
246 Vec3 operator* ( const Vec3& v ) const;
247
248 void operator*= ( const Matrix3x3& other );
249 Matrix3x3 operator* ( const Matrix3x3 &m ) const;
250 bool operator== ( const Matrix3x3& m ) const;
251 bool operator!= ( const Matrix3x3& m ) const;
252#ifndef SWIG
253 double& operator()(size_t row, size_t col);
254 Matrix3x3 operator= ( const Matrix3x3& rhs );
255#endif
256 double operator()(size_t row, size_t col) const;
257
258 Vec3 mult(const Vec3& v) const;
259
260 void mult( const Matrix3x3&, const Matrix3x3& );
261 void preMult( const Matrix3x3& );
262 void postMult( const Matrix3x3& );
263
268 std::string __str__() const;
269
270 protected:
271
272 bool invert( const Matrix3x3& rhs );
273
274 Matrix3x3 fastInverse(double det) const;
275 bool isDiagonal() const;
276 double determinant() const;
277
278
279 double m_data[3][3];
281
282 };
283}
284
285
286#ifndef SWIG
287/* ****************************************** */
288/* * IMPLEMENTATION ** */
289/* ****************************************** */
290
291namespace MOMENTUM_NAMESPACE
292{
293
294 /*=====================================================
295 Constructors
296 =======================================================*/
297
299 {
300 this->setIdentity();
301 }
302
303 inline Matrix3x3::Matrix3x3( const Matrix3x3& mat )
304 {
305 m_data[0][0] = mat(0, 0);
306 m_data[0][1] = mat(0, 1);
307 m_data[0][2] = mat(0, 2);
308
309 m_data[1][0] = mat(1, 0);
310 m_data[1][1] = mat(1, 1);
311 m_data[1][2] = mat(1, 2);
312
313 m_data[2][0] = mat(2, 0);
314 m_data[2][1] = mat(2, 1);
315 m_data[2][2] = mat(2, 2);
316 }
317
318 inline Matrix3x3::Matrix3x3( double a00, double a01, double a02,
319 double a10, double a11, double a12,
320 double a20, double a21, double a22)
321 {
322 m_data[0][0] = a00;
323 m_data[0][1] = a01;
324 m_data[0][2] = a02;
325
326 m_data[1][0] = a10;
327 m_data[1][1] = a11;
328 m_data[1][2] = a12;
329
330 m_data[2][0] = a20;
331 m_data[2][1] = a21;
332 m_data[2][2] = a22;
333
334 }
335
336 inline Matrix3x3::Matrix3x3( double const * const ptr )
337 {
338 set( ptr );
339 }
340
341
342 inline Matrix3x3::Matrix3x3(const Quat& quat)
343 {
344 this->setIdentity();
345 this->setRotate( quat );
346 }
347
349 {}
350
351
352 /*=====================================================
353 Queries
354 =======================================================*/
355
356 inline bool Matrix3x3::valid() const
357 {
358 return !isNaN();
359 }
360
361
362
363 inline bool Matrix3x3::isNaN() const
364 {
365 return std::isnan( m_data[0][0] ) || std::isnan( m_data[0][1] )
366 || std::isnan( m_data[0][2] )
367 || std::isnan( m_data[1][0] ) || std::isnan( m_data[1][1] )
368 || std::isnan( m_data[1][2] )
369 || std::isnan( m_data[2][0] ) || std::isnan( m_data[2][1] )
370 || std::isnan( m_data[2][2] );
371 }
372
373
374
375 inline bool Matrix3x3::isFinite() const
376 {
377 return std::isfinite( m_data[0][0] ) && std::isfinite( m_data[0][1] )
378 && std::isfinite( m_data[0][2] )
379 && std::isfinite( m_data[1][0] ) && std::isfinite( m_data[1][1] )
380 && std::isfinite( m_data[1][2] )
381 && std::isfinite( m_data[2][0] ) && std::isfinite( m_data[2][1] )
382 && std::isfinite( m_data[2][2] );
383 }
384
385
386 inline bool Matrix3x3::isIdentity() const
387 {
388 return *this == Matrix3x3();
389 }
390
391
393 {
394 bool isRigid = true;
395 // rows have norm 1
396 isRigid &= equivalent(m_data[0][0]*m_data[0][0] + m_data[0][1]*m_data[0][1] + m_data[0][2]*m_data[0][2], double(1), double(1.0e-3));
397 isRigid &= equivalent(m_data[1][0]*m_data[1][0] + m_data[1][1]*m_data[1][1] + m_data[1][2]*m_data[1][2], double(1), double(1.0e-3));
398 isRigid &= equivalent(m_data[2][0]*m_data[2][0] + m_data[2][1]*m_data[2][1] + m_data[2][2]*m_data[2][2], double(1), double(1.0e-3));
399 // columns have norm 1
400 isRigid &= equivalent(m_data[0][0]*m_data[0][0] + m_data[1][0]*m_data[1][0] + m_data[2][0]*m_data[2][0], double(1), double(1.0e-3));
401 isRigid &= equivalent(m_data[0][1]*m_data[0][1] + m_data[1][1]*m_data[1][1] + m_data[2][1]*m_data[2][1], double(1), double(1.0e-3));
402 isRigid &= equivalent(m_data[0][2]*m_data[0][2] + m_data[1][2]*m_data[1][2] + m_data[2][2]*m_data[2][2], double(1), double(1.0e-3));
403 // determinant 1
404 isRigid &= equivalent(m_data[0][0]*m_data[1][1]*m_data[2][2] + m_data[0][1]*m_data[1][2]*m_data[2][0] + m_data[0][2]*m_data[1][0]*m_data[2][1]
405 - m_data[2][0]*m_data[1][1]*m_data[0][2] - m_data[1][0]*m_data[0][1]*m_data[2][2] - m_data[0][0]*m_data[2][1]*m_data[1][2],
406 double(1), double(1.0e-1));
407 return isRigid;
408 }
409
410
411
412 /*=====================================================
413 Setters
414 =======================================================*/
415
416 inline Matrix3x3 Matrix3x3::set( double const * const ptr )
417 {
418 memcpy(m_data, ptr, sizeof(double)*9);
419 return *this;
420 }
421
422
423
424 inline Matrix3x3 Matrix3x3::set( double a00, double a01, double a02,
425 double a10, double a11, double a12,
426 double a20, double a21, double a22)
427 {
428 m_data[0][0] = a00;
429 m_data[0][1] = a01;
430 m_data[0][2] = a02;
431
432 m_data[1][0] = a10;
433 m_data[1][1] = a11;
434 m_data[1][2] = a12;
435
436 m_data[2][0] = a20;
437 m_data[2][1] = a21;
438 m_data[2][2] = a22;
439
440 return *this;
441 }
442
443
444 inline Matrix3x3 Matrix3x3::setRotate( const Vec3& from, const Vec3& to )
445 {
446 Quat quat;
447 quat.setRotate(from,to);
448 this->setRotate(quat);
449 return *this;
450 }
451
452
453 inline Matrix3x3 Matrix3x3::setRotate( double angle, const Vec3& axis )
454 {
455 Quat quat;
456 quat.setRotate( angle, axis);
457 this->setRotate(quat);
458 return *this;
459 }
460
461
462 inline Matrix3x3 Matrix3x3::setRotate( double angle, double x, double y, double z )
463 {
464 Quat quat;
465 quat.setRotate( angle, x, y, z);
466 this->setRotate(quat);
467 return *this;
468 }
469
470
471 inline Matrix3x3 Matrix3x3::setRotate( double angle1, const Vec3& axis1,
472 double angle2, const Vec3& axis2,
473 double angle3, const Vec3& axis3 )
474 {
475 Quat quat;
476 quat.setRotate(angle1, axis1,
477 angle2, axis2,
478 angle3, axis3);
479 this->setRotate(quat);
480 return *this;
481 }
482
483
485 {
486 Quat q(q_in);
487 double length2 = q.length2();
488 if (length2 != 1.0 && length2 != 0.0)
489 {
490 // normalize quat if required.
491 q /= agx::Quat::Type(std::sqrt(length2));
492 }
493
494 // Source: Gamasutra, Rotating Objects Using Quaternions
495 //
496 //http://www.gamasutra.com/features/programming/19980703/quaternions_01.htm
497
498 double wx, wy, wz, xx, yy, yz, xy, xz, zz, x2, y2, z2;
499
500 // calculate coefficients
501 x2 = q[0] + q[0];
502 y2 = q[1] + q[1];
503 z2 = q[2] + q[2];
504
505 xx = q[0] * x2;
506 xy = q[0] * y2;
507 xz = q[0] * z2;
508
509 yy = q[1] * y2;
510 yz = q[1] * z2;
511 zz = q[2] * z2;
512
513 wx = q[3] * x2;
514 wy = q[3] * y2;
515 wz = q[3] * z2;
516
517 // Note. Gamasutra gets the matrix assignments inverted, resulting
518 // in left-handed rotations, which is contrary to OpenGL and OSG's
519 // methodology. The matrix assignment has been altered in the next
520 // few lines of code to do the right thing.
521 // Don Burns - Oct 13, 2001
522 m_data[0][0] = (1.0 - (yy + zz));
523 m_data[1][0] = (xy - wz);
524 m_data[2][0] = (xz + wy);
525
526
527 m_data[0][1] = (xy + wz);
528 m_data[1][1] = (1.0 - (xx + zz));
529 m_data[2][1] = (yz - wx);
530
531
532 m_data[0][2] = (xz - wy);
533 m_data[1][2] = (yz + wx);
534 m_data[2][2] = (1.0 - (xx + yy));
535
536 return *this;
537 }
538
539
541 {
542 this->set(1,0,0, 0,1,0, 0,0,1);
543 return *this;
544 }
545
546 /*=====================================================
547 Getters
548 =======================================================*/
549
551 {
552 Quat q;
553 q = getAsQuat();
554 return q;
555 }
556
557 inline double *Matrix3x3::ptr()
558 {
559 return ( double* )m_data;
560 }
561
562
563 inline const double *Matrix3x3::ptr() const
564 {
565 return ( const double * )m_data;
566 }
567
568 /*=====================================================
569 Serialization methods
570 =======================================================*/
571
572 /*=====================================================
573 Static methods
574 =======================================================*/
575
576
578 {
579 return Matrix3x3( 0, -v.z(), v.y(),
580 v.z(), 0, -v.x(),
581 -v.y(), v.x(), 0);
582 }
583
584 inline Matrix3x3 Matrix3x3::rotate( const Vec3& from, const Vec3& to )
585 {
586 Matrix3x3 m;
587 m.setRotate(from, to);
588 return m;
589 }
590
591
592 inline Matrix3x3 Matrix3x3::rotate( double angle, double x, double y, double z )
593 {
594 Matrix3x3 m;
595 m.setRotate(angle, x, y, z);
596 return m;
597 }
598
599
600 inline Matrix3x3 Matrix3x3::rotate( double angle, const Vec3& axis )
601 {
602 Matrix3x3 m;
603 m.setRotate(angle, axis);
604 return m;
605 }
606
607
608 inline Matrix3x3 Matrix3x3::rotate( double angle1, const Vec3& axis1,
609 double angle2, const Vec3& axis2,
610 double angle3, const Vec3& axis3 )
611 {
612 Matrix3x3 m;
613 m.setRotate(angle1, axis1, angle2, axis2, angle3, axis3);
614 return m;
615 }
616
617
618 /*=====================================================
619 Operators
620 =======================================================*/
621
622
623 inline void Matrix3x3::mult( const Matrix3x3& lhs, const Matrix3x3& rhs )
624 {
625 agx::prefetch<agx::L1>( lhs.m_data );
626 agx::prefetch<agx::L1>( rhs.m_data );
627
628 if (&lhs==this)
629 {
630 postMult(rhs);
631 return;
632 }
633 if (&rhs==this)
634 {
635 preMult(lhs);
636 return;
637 }
638
639 m_data[0][0] = MOMENTUM_MATRIX3X3_INNER_PRODUCT(lhs, rhs, 0, 0);
640 m_data[0][1] = MOMENTUM_MATRIX3X3_INNER_PRODUCT(lhs, rhs, 0, 1);
641 m_data[0][2] = MOMENTUM_MATRIX3X3_INNER_PRODUCT(lhs, rhs, 0, 2);
642
643 m_data[1][0] = MOMENTUM_MATRIX3X3_INNER_PRODUCT(lhs, rhs, 1, 0);
644 m_data[1][1] = MOMENTUM_MATRIX3X3_INNER_PRODUCT(lhs, rhs, 1, 1);
645 m_data[1][2] = MOMENTUM_MATRIX3X3_INNER_PRODUCT(lhs, rhs, 1, 2);
646
647 m_data[2][0] = MOMENTUM_MATRIX3X3_INNER_PRODUCT(lhs, rhs, 2, 0);
648 m_data[2][1] = MOMENTUM_MATRIX3X3_INNER_PRODUCT(lhs, rhs, 2, 1);
649 m_data[2][2] = MOMENTUM_MATRIX3X3_INNER_PRODUCT(lhs, rhs, 2, 2);
650
651 }
652
653
654 inline void Matrix3x3::preMult( const Matrix3x3& other )
655 {
656
657 // more efficient method just use a T[3] for temporary storage.
658 double t[3];
659 for(size_t col=0; col<3; ++col) {
660 t[0] = MOMENTUM_MATRIX3X3_INNER_PRODUCT( other, *this, 0, col );
661 t[1] = MOMENTUM_MATRIX3X3_INNER_PRODUCT( other, *this, 1, col );
662 t[2] = MOMENTUM_MATRIX3X3_INNER_PRODUCT( other, *this, 2, col );
663 m_data[0][col] = t[0];
664 m_data[1][col] = t[1];
665 m_data[2][col] = t[2];
666 }
667 }
668
669
670 inline void Matrix3x3::postMult( const Matrix3x3& other )
671 {
672
673 // more efficient method just use a T[3] for temporary storage.
674 double t[3];
675 for(size_t row=0; row<3; ++row)
676 {
677 t[0] = MOMENTUM_MATRIX3X3_INNER_PRODUCT( *this, other, row, 0 );
678 t[1] = MOMENTUM_MATRIX3X3_INNER_PRODUCT( *this, other, row, 1 );
679 t[2] = MOMENTUM_MATRIX3X3_INNER_PRODUCT( *this, other, row, 2 );
680
681 MOMENTUM_MATRIX3X3_SET_ROW(row, t[0], t[1], t[2])
682 }
683 }
684
685 inline bool Matrix3x3::operator== ( const Matrix3x3& m ) const
686 {
687 const int bitCompare = memcmp(m_data, m.m_data, sizeof(m_data));
688 return (bitCompare == 0);
689 }
690
691
692 inline bool Matrix3x3::operator!= ( const Matrix3x3& m ) const
693 {
694 const int bitCompare = memcmp(m_data, m.m_data, sizeof(m_data));
695 return (bitCompare != 0);
696 }
697
698#ifndef SWIG
699
700 inline double& Matrix3x3::operator()( size_t row, size_t col )
701 {
702 return m_data[row][col];
703 }
704#endif
705
706
707 inline double Matrix3x3::operator()( size_t row, size_t col ) const
708 {
709 return m_data[row][col];
710 }
711
712
714 {
715 if ( this != &rhs )
716 this->set( rhs.ptr() );
717
718 return *this;
719 }
720
721
722 inline void Matrix3x3::operator*= ( const Matrix3x3& other )
723 {
724 if ( this == &other )
725 {
726 Matrix3x3 temp( other );
727 postMult( temp );
728 }
729 else postMult( other );
730 }
731
732
734 {
735 Matrix3x3 r;
736 r.mult( *this, m );
737 return r;
738 }
739
740
741 inline Vec3 Matrix3x3::operator* ( const Vec3& v ) const
742 {
743 return mult( v );
744 }
745
746 inline Vec3 operator* ( const Vec3& v, const Matrix3x3& m )
747 {
748 return m.mult( v );
749 }
750
751 std::ostream& operator<< (std::ostream& os, const Matrix3x3& m);
752
753 /*=====================================================
754 Internal
755 =======================================================*/
756
757 inline Vec3 Matrix3x3::mult( const Vec3& v ) const
758 {
759 return Vec3( ( m_data[0][0]*v.x() + m_data[0][1]*v.y() + m_data[0][2]*v.z() ) ,
760 ( m_data[1][0]*v.x() + m_data[1][1]*v.y() + m_data[1][2]*v.z() ) ,
761 ( m_data[2][0]*v.x() + m_data[2][1]*v.y() + m_data[2][2]*v.z() ) ) ;
762 }
763
764
765
767 {
768 return Matrix3x3( m_data[0][0], m_data[1][0], m_data[2][0],
769 m_data[0][1], m_data[1][1], m_data[2][1],
770 m_data[0][2], m_data[1][2], m_data[2][2]);
771 }
772
773 inline double Matrix3x3::determinant() const
774 {
775 return m_data[0][0] * m_data[1][1] * m_data[2][2] - m_data[0][0] * m_data[1][2] * m_data[2][1] -
776 m_data[0][1] * m_data[1][0] * m_data[2][2] + m_data[0][1] * m_data[1][2] * m_data[2][0] +
777 m_data[0][2] * m_data[1][0] * m_data[2][1] - m_data[0][2] * m_data[1][1] * m_data[2][0];
778 }
779
780 inline bool Matrix3x3::isDiagonal() const
781 {
782 return m_data[0][1] == 0.0 && m_data[0][2] == 0.0 &&
783 m_data[1][0] == 0.0 && m_data[1][2] == 0.0 &&
784 m_data[2][0] == 0.0 && m_data[2][1] == 0.0;
785 }
786
787 inline Matrix3x3 Matrix3x3::fastInverse(double det) const
788 {
789 Matrix3x3 dest;
790
791 double k = 1.0 / det;
792
793 dest(0, 0) = k * MOMENTUM_MATRIX3X3_DET2(m_data[1][1], m_data[1][2], m_data[2][1], m_data[2][2]);
794 dest(0, 1) = k * MOMENTUM_MATRIX3X3_DET2(m_data[0][2], m_data[0][1], m_data[2][2], m_data[2][1]);
795 dest(0, 2) = k * MOMENTUM_MATRIX3X3_DET2(m_data[0][1], m_data[0][2], m_data[1][1], m_data[1][2]);
796
797 dest(1, 0) = k * MOMENTUM_MATRIX3X3_DET2(m_data[1][2], m_data[1][0], m_data[2][2], m_data[2][0]);
798 dest(1, 1) = k * MOMENTUM_MATRIX3X3_DET2(m_data[0][0], m_data[0][2], m_data[2][0], m_data[2][2]);
799 dest(1, 2) = k * MOMENTUM_MATRIX3X3_DET2(m_data[0][2], m_data[0][0], m_data[1][2], m_data[1][0]);
800
801 dest(2, 0) = k * MOMENTUM_MATRIX3X3_DET2(m_data[1][0], m_data[1][1], m_data[2][0], m_data[2][1]);
802 dest(2, 1) = k * MOMENTUM_MATRIX3X3_DET2(m_data[0][1], m_data[0][0], m_data[2][1], m_data[2][0]);
803 dest(2, 2) = k * MOMENTUM_MATRIX3X3_DET2(m_data[0][0], m_data[0][1], m_data[1][0], m_data[1][1]);
804
805 return dest;
806 }
807
808 namespace {
809 inline void momentum_findMaxElement(const Matrix3x3& mat, bool skipFlags[3], int coord[2])
810 {
811 double max = 0;
812 // Will return {the first non-skipped row},0 in case of an all-NaN or all-inf matrix.
813 coord[0] = (skipFlags[0] ? (skipFlags[1] ? 2 : 1) : 0);
814 coord[1] = 1;
815
816 for (int i = 0; i < 3; i++)
817 {
818 if (skipFlags[i])
819 continue;
820
821 for (int j = 0; j < 3; j++)
822 {
823 if (std::abs(mat(i, j)) > max)
824 {
825 coord[0] = i;
826 coord[1] = j;
827 max = std::abs(mat(i, j));
828 }
829 }
830 }
831
832 agxAssert(coord[0] >= 0 && coord[1] >= 0);
833 }
834 }
835
837 {
838 /* Check if diagonal matrix */
839 if (this->isDiagonal())
840 return Matrix3x3(1.0 / m_data[0][0], 0, 0, 0, 1.0 / m_data[1][1], 0, 0, 0, 1.0 / m_data[2][2]);
841
842 /* Check if determinant is large enough to do fast inverse */
843 double determinant = this->determinant();
844
845 if (determinant > agx::RealEpsilon)
846 return this->fastInverse(determinant);
847
848 /* Else do robust, but slow inversion */
849 const int next[3] = { 1, 2, 0 };
850 Matrix3x3 result;
851 Matrix3x3 tmp(*this);
852
853 bool done[3] = { false, false, false };
854 int pivotColumns[3] = { -1, -1, -1 };
855
856 for (int i = 0; i < 3; i++)
857 {
858 // Select pivot row
859 int coord[2];
860 momentum_findMaxElement(tmp, done, coord);
861 pivotColumns[(int)coord[0]] = (int)coord[1];
862
863 // Gauss-Jordan pivoting
864 double *row = &tmp(coord[0], 0);
865 double *resultRow = &result(coord[0], 0);
866
867 // Scale target row
868 double scale = 1.0 / row[coord[1]];
869 for (int j = 0; j < 3; j++)
870 {
871 row[j] *= scale;
872 resultRow[j] *= scale;
873 }
874
875
876 // Column operations on other rows
877 for (int r = next[coord[0]]; r != coord[0]; r = next[r])
878 {
879 double *ra = &tmp(r, 0);
880 double *rb = &result(r, 0);
881 double f = ra[coord[1]];
882
883 for (int j = 0; j < 3; j++)
884 {
885 ra[j] -= f*row[j];
886 rb[j] -= f*resultRow[j];
887 }
888 }
889
890 done[coord[0]] = true;
891 }
892
893 // Do final row permutations
894 for (int i = 0; i < 3; i++)
895 {
896 double *ra = &tmp(pivotColumns[i], 0);
897 double *rb = &result(i, 0);
898 memcpy(ra, rb, sizeof(double) * 3);
899 }
900
901 return tmp;
902 }
903
904
905 inline bool equivalent( const Matrix3x3& a, const Matrix3x3& b, double epsilon = 1e-6 )
906 {
907 return
908 agx::equivalent(a(0, 0), b(0, 0), epsilon) &&
909 agx::equivalent(a(0, 1), b(0, 1), epsilon) &&
910 agx::equivalent(a(0, 2), b(0, 2), epsilon) &&
911 agx::equivalent(a(1, 0), b(1, 0), epsilon) &&
912 agx::equivalent(a(1, 1), b(1, 1), epsilon) &&
913 agx::equivalent(a(1, 2), b(1, 2), epsilon) &&
914 agx::equivalent(a(2, 0), b(2, 0), epsilon) &&
915 agx::equivalent(a(2, 1), b(2, 1), epsilon) &&
916 agx::equivalent(a(2, 2), b(2, 2), epsilon);
917 }
918
919}
920
921#endif //"#ifndef SWIG"
922
923#endif
Matrix class for inertia.
Definition: Matrix3x3.h:52
Matrix3x3()
Creates a new matrix, initialized to be an identity matrix.
Definition: Matrix3x3.h:298
double & operator()(size_t row, size_t col)
Definition: Matrix3x3.h:700
Matrix3x3 operator=(const Matrix3x3 &rhs)
Definition: Matrix3x3.h:713
void postMult(const Matrix3x3 &)
Definition: Matrix3x3.h:670
Matrix3x3 setIdentity()
Definition: Matrix3x3.h:540
Matrix3x3 set(double const *const ptr)
Definition: Matrix3x3.h:416
Matrix3x3(agx::Matrix3x3 mat)
Definition: Matrix3x3.h:72
Vec3 getRow(size_t row) const
Definition: Matrix3x3.h:178
bool valid() const
Definition: Matrix3x3.h:356
void preMult(const Matrix3x3 &)
Definition: Matrix3x3.h:654
bool isIdentity() const
Definition: Matrix3x3.h:386
Quat getRotate() const
Definition: Matrix3x3.h:550
void setCol(size_t col, const Vec3 &vec)
Definition: Matrix3x3.h:172
bool operator!=(const Matrix3x3 &m) const
Definition: Matrix3x3.h:692
static Matrix3x3 rotate(const Vec3 &from, const Vec3 &to)
Definition: Matrix3x3.h:584
bool isRigidTransformation() const
Definition: Matrix3x3.h:392
Vec3 getCol(size_t col) const
Definition: Matrix3x3.h:187
Matrix3x3 inverse() const
Matrix inverse.
Definition: Matrix3x3.h:836
Vec3 operator*(const Vec3 &v) const
Definition: Matrix3x3.h:741
bool isNaN() const
Definition: Matrix3x3.h:363
void operator*=(const Matrix3x3 &other)
Definition: Matrix3x3.h:722
bool operator==(const Matrix3x3 &m) const
Definition: Matrix3x3.h:685
bool isFinite() const
Definition: Matrix3x3.h:375
~Matrix3x3()
Destructor.
Definition: Matrix3x3.h:348
double at(size_t row, size_t col) const
Definition: Matrix3x3.h:196
Vec3 mult(const Vec3 &v) const
Definition: Matrix3x3.h:757
void setRow(size_t row, const Vec3 &vec)
Set the row of the matrix,.
Definition: Matrix3x3.h:166
static Matrix3x3 crossMatrix(const Vec3 &vec)
Generates a new matrix of a specific type.
Definition: Matrix3x3.h:577
Matrix3x3 transpose() const
Definition: Matrix3x3.h:766
double * ptr()
Definition: Matrix3x3.h:557
Matrix3x3 setRotate(const Quat &q)
Definition: Matrix3x3.h:484
The object holding quaternions and providing operations on these.
Definition: Quat.h:55
void setRotate(double angle, double x, double y, double z)
Set the rotation of the Quaternion as a rotation angle radians around the vector (x,...
double length2() const
Definition: Quat.h:656
A 3 dimensional vector which can be used to define a point or a vector and contains basic arithmetic.
Definition: Vec3.h:40
double y() const
Definition: Vec3.h:497
double z() const
Definition: Vec3.h:503
double x() const
Definition: Vec3.h:491
Namespace for Momentum Scripting API.
Definition: AffineMatrix4x4.h:29
std::ostream & operator<<(std::ostream &os, const EulerAngles &e)
Definition: EulerAngles.h:358
Vec3 max(const Vec3 &lhs, const Vec3 &rhs)
Definition: Vec3.h:804
Vec3 operator*(const Vec3 &v, const Matrix3x3 &m)
Definition: Matrix3x3.h:746
bool equivalent(const Matrix3x3 &a, const Matrix3x3 &b, double epsilon=1e-6)
Definition: Matrix3x3.h:905