framework2
1590 строк · 44.6 Кб
1
2
3
4
5#include "ofMatrix4x4.h"
6
7#include <limits>
8#include <stdlib.h>
9#include <iomanip>
10
11#if (_MSC_VER)
12#undef min
13// see: http://stackoverflow.com/questions/1904635/warning-c4003-and-errors-c2589-and-c2059-on-x-stdnumericlimitsintmax
14#endif
15
16// FIXME: why not using std::numeric_limits<double>::epsilon()
17inline bool equivalent(double lhs,double rhs,double epsilon=1e-6)
18{ double delta = rhs-lhs; return delta<0.0?delta>=-epsilon:delta<=epsilon; }
19template<typename T>
20inline T square(T v) { return v*v; }
21
22#define SET_ROW(row, v1, v2, v3, v4 ) \
23_mat[(row)][0] = (v1); \
24_mat[(row)][1] = (v2); \
25_mat[(row)][2] = (v3); \
26_mat[(row)][3] = (v4);
27
28#define INNER_PRODUCT(a,b,r,c) \
29((a)._mat[r][0] * (b)._mat[0][c]) \
30+((a)._mat[r][1] * (b)._mat[1][c]) \
31+((a)._mat[r][2] * (b)._mat[2][c]) \
32+((a)._mat[r][3] * (b)._mat[3][c])
33
34ofMatrix4x4::ofMatrix4x4( float a00, float a01, float a02, float a03,
35float a10, float a11, float a12, float a13,
36float a20, float a21, float a22, float a23,
37float a30, float a31, float a32, float a33)
38{
39SET_ROW(0, a00, a01, a02, a03 )
40SET_ROW(1, a10, a11, a12, a13 )
41SET_ROW(2, a20, a21, a22, a23 )
42SET_ROW(3, a30, a31, a32, a33 )
43}
44
45void ofMatrix4x4::set( float a00, float a01, float a02, float a03,
46float a10, float a11, float a12, float a13,
47float a20, float a21, float a22, float a23,
48float a30, float a31, float a32, float a33)
49{
50SET_ROW(0, a00, a01, a02, a03 )
51SET_ROW(1, a10, a11, a12, a13 )
52SET_ROW(2, a20, a21, a22, a23 )
53SET_ROW(3, a30, a31, a32, a33 )
54}
55
56#define QX q._v[0]
57#define QY q._v[1]
58#define QZ q._v[2]
59#define QW q._v[3]
60
61void ofMatrix4x4::setRotate(const ofQuaternion& q)
62{
63double length2 = q.length2();
64if (fabs(length2) <= std::numeric_limits<double>::min())
65{
66_mat[0][0] = 1.0; _mat[1][0] = 0.0; _mat[2][0] = 0.0;
67_mat[0][1] = 0.0; _mat[1][1] = 1.0; _mat[2][1] = 0.0;
68_mat[0][2] = 0.0; _mat[1][2] = 0.0; _mat[2][2] = 1.0;
69}
70else
71{
72double rlength2;
73// normalize quat if required.
74// We can avoid the expensive sqrt in this case since all 'coefficients' below are products of two q components.
75// That is a square of a square root, so it is possible to avoid that
76if (length2 != 1.0)
77{
78rlength2 = 2.0/length2;
79}
80else
81{
82rlength2 = 2.0;
83}
84
85// Source: Gamasutra, Rotating Objects Using Quaternions
86//
87//http://www.gamasutra.com/features/19980703/quaternions_01.htm
88
89double wx, wy, wz, xx, yy, yz, xy, xz, zz, x2, y2, z2;
90
91// calculate coefficients
92x2 = rlength2*QX;
93y2 = rlength2*QY;
94z2 = rlength2*QZ;
95
96xx = QX * x2;
97xy = QX * y2;
98xz = QX * z2;
99
100yy = QY * y2;
101yz = QY * z2;
102zz = QZ * z2;
103
104wx = QW * x2;
105wy = QW * y2;
106wz = QW * z2;
107
108// Note. Gamasutra gets the matrix assignments inverted, resulting
109// in left-handed rotations, which is contrary to OpenGL and OSG's
110// methodology. The matrix assignment has been altered in the next
111// few lines of code to do the right thing.
112// Don Burns - Oct 13, 2001
113_mat[0][0] = 1.0 - (yy + zz);
114_mat[1][0] = xy - wz;
115_mat[2][0] = xz + wy;
116
117
118_mat[0][1] = xy + wz;
119_mat[1][1] = 1.0 - (xx + zz);
120_mat[2][1] = yz - wx;
121
122_mat[0][2] = xz - wy;
123_mat[1][2] = yz + wx;
124_mat[2][2] = 1.0 - (xx + yy);
125}
126
127#if 0
128_mat[0][3] = 0.0;
129_mat[1][3] = 0.0;
130_mat[2][3] = 0.0;
131
132_mat[3][0] = 0.0;
133_mat[3][1] = 0.0;
134_mat[3][2] = 0.0;
135_mat[3][3] = 1.0;
136#endif
137}
138//
139//ofQuaternion ofMatrix4x4::getRotate() const {
140// ofVec4f q;
141// float trace = _mat[0][0] + _mat[1][1] + _mat[2][2]; // I removed + 1.0f; see discussion with Ethan
142// if( trace > 0 ) {// I changed M_EPSILON to 0
143// float s = 0.5f / sqrtf(trace+ 1.0f);
144// q.w = 0.25f / s;
145// q.x = ( _mat[2][1] - _mat[1][2] ) * s;
146// q.y = ( _mat[0][2] - _mat[2][0] ) * s;
147// q.z = ( _mat[1][0] - _mat[0][1] ) * s;
148// } else {
149// if ( _mat[0][0] > _mat[1][1] && _mat[0][0] > _mat[2][2] ) {
150// float s = 2.0f * sqrtf( 1.0f + _mat[0][0] - _mat[1][1] - _mat[2][2]);
151// q.w = (_mat[2][1] - _mat[1][2] ) / s;
152// q.x = 0.25f * s;
153// q.y = (_mat[0][1] + _mat[1][0] ) / s;
154// q.z = (_mat[0][2] + _mat[2][0] ) / s;
155// } else if (_mat[1][1] > _mat[2][2]) {
156// float s = 2.0f * sqrtf( 1.0f + _mat[1][1] - _mat[0][0] - _mat[2][2]);
157// q.w = (_mat[0][2] - _mat[2][0] ) / s;
158// q.x = (_mat[0][1] + _mat[1][0] ) / s;
159// q.y = 0.25f * s;
160// q.z = (_mat[1][2] + _mat[2][1] ) / s;
161// } else {
162// float s = 2.0f * sqrtf( 1.0f + _mat[2][2] - _mat[0][0] - _mat[1][1] );
163// q.w = (_mat[1][0] - _mat[0][1] ) / s;
164// q.x = (_mat[0][2] + _mat[2][0] ) / s;
165// q.y = (_mat[1][2] + _mat[2][1] ) / s;
166// q.z = 0.25f * s;
167// }
168// }
169// return ofQuaternion(q.x, q.y, q.z, q.w);
170//}
171
172//#define COMPILE_getRotate_David_Spillings_Mk1
173//#define COMPILE_getRotate_David_Spillings_Mk2
174#define COMPILE_getRotate_Original
175
176#ifdef COMPILE_getRotate_David_Spillings_Mk1
177// David Spillings implementation Mk 1
178ofQuaternion ofMatrix4x4::getRotate() const
179{
180ofQuaternion q;
181
182float s;
183float tq[4];
184int i, j;
185
186// Use tq to store the largest trace
187tq[0] = 1 + _mat[0][0]+_mat[1][1]+_mat[2][2];
188tq[1] = 1 + _mat[0][0]-_mat[1][1]-_mat[2][2];
189tq[2] = 1 - _mat[0][0]+_mat[1][1]-_mat[2][2];
190tq[3] = 1 - _mat[0][0]-_mat[1][1]+_mat[2][2];
191
192// Find the maximum (could also use stacked if's later)
193j = 0;
194for(i=1;i<4;i++) j = (tq[i]>tq[j])? i : j;
195
196// check the diagonal
197if (j==0)
198{
199/* perform instant calculation */
200QW = tq[0];
201QX = _mat[1][2]-_mat[2][1];
202QY = _mat[2][0]-_mat[0][2];
203QZ = _mat[0][1]-_mat[1][0];
204}
205else if (j==1)
206{
207QW = _mat[1][2]-_mat[2][1];
208QX = tq[1];
209QY = _mat[0][1]+_mat[1][0];
210QZ = _mat[2][0]+_mat[0][2];
211}
212else if (j==2)
213{
214QW = _mat[2][0]-_mat[0][2];
215QX = _mat[0][1]+_mat[1][0];
216QY = tq[2];
217QZ = _mat[1][2]+_mat[2][1];
218}
219else /* if (j==3) */
220{
221QW = _mat[0][1]-_mat[1][0];
222QX = _mat[2][0]+_mat[0][2];
223QY = _mat[1][2]+_mat[2][1];
224QZ = tq[3];
225}
226
227s = sqrt(0.25/tq[j]);
228QW *= s;
229QX *= s;
230QY *= s;
231QZ *= s;
232
233return q;
234
235}
236#endif
237
238
239#ifdef COMPILE_getRotate_David_Spillings_Mk2
240// David Spillings implementation Mk 2
241ofQuaternion ofMatrix4x4::getRotate() const
242{
243ofQuaternion q;
244
245// From http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
246QW = 0.5 * sqrt( osg::maximum( 0.0, 1.0 + _mat[0][0] + _mat[1][1] + _mat[2][2] ) );
247QX = 0.5 * sqrt( osg::maximum( 0.0, 1.0 + _mat[0][0] - _mat[1][1] - _mat[2][2] ) );
248QY = 0.5 * sqrt( osg::maximum( 0.0, 1.0 - _mat[0][0] + _mat[1][1] - _mat[2][2] ) );
249QZ = 0.5 * sqrt( osg::maximum( 0.0, 1.0 - _mat[0][0] - _mat[1][1] + _mat[2][2] ) );
250
251#if 0
252// Robert Osfield, June 7th 2007, arggg this new implementation produces many many errors, so have to revert to sign(..) orignal below.
253QX = QX * osg::signOrZero( _mat[1][2] - _mat[2][1]) ;
254QY = QY * osg::signOrZero( _mat[2][0] - _mat[0][2]) ;
255QZ = QZ * osg::signOrZero( _mat[0][1] - _mat[1][0]) ;
256#else
257QX = QX * osg::sign( _mat[1][2] - _mat[2][1]) ;
258QY = QY * osg::sign( _mat[2][0] - _mat[0][2]) ;
259QZ = QZ * osg::sign( _mat[0][1] - _mat[1][0]) ;
260#endif
261
262return q;
263}
264#endif
265
266#ifdef COMPILE_getRotate_Original
267// Original implementation
268ofQuaternion ofMatrix4x4::getRotate() const
269{
270ofQuaternion q;
271
272ofMatrix4x4 mat = *this;
273ofVec3f vs = mat.getScale();
274mat.scale(1./vs.x,1./vs.y,1./vs.z);
275
276ofVec4f* m = mat._mat;
277
278// Source: Gamasutra, Rotating Objects Using Quaternions
279//
280//http://www.gamasutra.com/features/programming/19980703/quaternions_01.htm
281
282float tr, s;
283float tq[4];
284int i, j, k;
285
286int nxt[3] = {1, 2, 0};
287
288tr = m[0][0] + m[1][1] + m[2][2]+1.0;
289
290// check the diagonal
291if (tr > 0.0)
292{
293s = (float)sqrt (tr);
294QW = s / 2.0;
295s = 0.5 / s;
296QX = (m[1][2] - m[2][1]) * s;
297QY = (m[2][0] - m[0][2]) * s;
298QZ = (m[0][1] - m[1][0]) * s;
299}
300else
301{
302// diagonal is negative
303i = 0;
304if (m[1][1] > m[0][0])
305i = 1;
306if (m[2][2] > m[i][i])
307i = 2;
308j = nxt[i];
309k = nxt[j];
310
311s = (float)sqrt ((m[i][i] - (m[j][j] + m[k][k])) + 1.0);
312
313tq[i] = s * 0.5;
314
315if (s != 0.0)
316s = 0.5 / s;
317
318tq[3] = (m[j][k] - m[k][j]) * s;
319tq[j] = (m[i][j] + m[j][i]) * s;
320tq[k] = (m[i][k] + m[k][i]) * s;
321
322QX = tq[0];
323QY = tq[1];
324QZ = tq[2];
325QW = tq[3];
326}
327
328return q;
329}
330#endif
331
332
333//int ofMatrix4x4::compare(const ofMatrix4x4& m) const
334//{
335// const ofMatrix4x4::float* lhs = reinterpret_cast<const ofMatrix4x4::float*>(_mat);
336// const ofMatrix4x4::float* end_lhs = lhs+16;
337// const ofMatrix4x4::float* rhs = reinterpret_cast<const ofMatrix4x4::float*>(m._mat);
338// for(;lhs!=end_lhs;++lhs,++rhs)
339// {
340// if (*lhs < *rhs) return -1;
341// if (*rhs < *lhs) return 1;
342// }
343// return 0;
344//}
345
346void ofMatrix4x4::setTranslation( float tx, float ty, float tz )
347{
348_mat[3][0] = tx;
349_mat[3][1] = ty;
350_mat[3][2] = tz;
351}
352
353
354void ofMatrix4x4::setTranslation( const ofVec3f& v )
355{
356_mat[3][0] = v.getPtr()[0];
357_mat[3][1] = v.getPtr()[1];
358_mat[3][2] = v.getPtr()[2];
359}
360
361void ofMatrix4x4::makeIdentityMatrix()
362{
363SET_ROW(0, 1, 0, 0, 0 )
364SET_ROW(1, 0, 1, 0, 0 )
365SET_ROW(2, 0, 0, 1, 0 )
366SET_ROW(3, 0, 0, 0, 1 )
367}
368
369void ofMatrix4x4::makeScaleMatrix( const ofVec3f& v )
370{
371makeScaleMatrix(v.getPtr()[0], v.getPtr()[1], v.getPtr()[2] );
372}
373
374void ofMatrix4x4::makeScaleMatrix( float x, float y, float z )
375{
376SET_ROW(0, x, 0, 0, 0 )
377SET_ROW(1, 0, y, 0, 0 )
378SET_ROW(2, 0, 0, z, 0 )
379SET_ROW(3, 0, 0, 0, 1 )
380}
381
382void ofMatrix4x4::makeTranslationMatrix( const ofVec3f& v )
383{
384makeTranslationMatrix( v.getPtr()[0], v.getPtr()[1], v.getPtr()[2] );
385}
386void ofMatrix4x4::makeTranslationMatrix( float x, float y, float z )
387{
388SET_ROW(0, 1, 0, 0, 0 )
389SET_ROW(1, 0, 1, 0, 0 )
390SET_ROW(2, 0, 0, 1, 0 )
391SET_ROW(3, x, y, z, 1 )
392}
393
394void ofMatrix4x4::makeRotationMatrix( const ofVec3f& from, const ofVec3f& to )
395{
396makeIdentityMatrix();
397
398ofQuaternion quat;
399quat.makeRotate(from,to);
400setRotate(quat);
401}
402void ofMatrix4x4::makeRotationMatrix( float angle, const ofVec3f& axis )
403{
404makeIdentityMatrix();
405
406ofQuaternion quat;
407quat.makeRotate( angle, axis);
408setRotate(quat);
409}
410
411void ofMatrix4x4::makeRotationMatrix( float angle, float x, float y, float z )
412{
413makeIdentityMatrix();
414
415ofQuaternion quat;
416quat.makeRotate( angle, x, y, z);
417setRotate(quat);
418}
419
420void ofMatrix4x4::makeRotationMatrix( const ofQuaternion& quat )
421{
422makeIdentityMatrix();
423
424setRotate(quat);
425}
426
427void ofMatrix4x4::makeRotationMatrix( float angle1, const ofVec3f& axis1,
428float angle2, const ofVec3f& axis2,
429float angle3, const ofVec3f& axis3)
430{
431makeIdentityMatrix();
432
433ofQuaternion quat;
434quat.makeRotate(angle1, axis1,
435angle2, axis2,
436angle3, axis3);
437setRotate(quat);
438}
439
440void ofMatrix4x4::makeFromMultiplicationOf( const ofMatrix4x4& lhs, const ofMatrix4x4& rhs )
441{
442if (&lhs==this)
443{
444postMult(rhs);
445return;
446}
447if (&rhs==this)
448{
449preMult(lhs);
450return;
451}
452
453// PRECONDITION: We assume neither &lhs nor &rhs == this
454// if it did, use preMult or postMult instead
455_mat[0][0] = INNER_PRODUCT(lhs, rhs, 0, 0);
456_mat[0][1] = INNER_PRODUCT(lhs, rhs, 0, 1);
457_mat[0][2] = INNER_PRODUCT(lhs, rhs, 0, 2);
458_mat[0][3] = INNER_PRODUCT(lhs, rhs, 0, 3);
459_mat[1][0] = INNER_PRODUCT(lhs, rhs, 1, 0);
460_mat[1][1] = INNER_PRODUCT(lhs, rhs, 1, 1);
461_mat[1][2] = INNER_PRODUCT(lhs, rhs, 1, 2);
462_mat[1][3] = INNER_PRODUCT(lhs, rhs, 1, 3);
463_mat[2][0] = INNER_PRODUCT(lhs, rhs, 2, 0);
464_mat[2][1] = INNER_PRODUCT(lhs, rhs, 2, 1);
465_mat[2][2] = INNER_PRODUCT(lhs, rhs, 2, 2);
466_mat[2][3] = INNER_PRODUCT(lhs, rhs, 2, 3);
467_mat[3][0] = INNER_PRODUCT(lhs, rhs, 3, 0);
468_mat[3][1] = INNER_PRODUCT(lhs, rhs, 3, 1);
469_mat[3][2] = INNER_PRODUCT(lhs, rhs, 3, 2);
470_mat[3][3] = INNER_PRODUCT(lhs, rhs, 3, 3);
471}
472
473void ofMatrix4x4::preMult( const ofMatrix4x4& other )
474{
475// brute force method requiring a copy
476//ofMatrix4x4 tmp(other* *this);
477// *this = tmp;
478
479// more efficient method just use a float[4] for temporary storage.
480float t[4];
481for(int col=0; col<4; ++col) {
482t[0] = INNER_PRODUCT( other, *this, 0, col );
483t[1] = INNER_PRODUCT( other, *this, 1, col );
484t[2] = INNER_PRODUCT( other, *this, 2, col );
485t[3] = INNER_PRODUCT( other, *this, 3, col );
486_mat[0][col] = t[0];
487_mat[1][col] = t[1];
488_mat[2][col] = t[2];
489_mat[3][col] = t[3];
490}
491
492}
493
494void ofMatrix4x4::postMult( const ofMatrix4x4& other )
495{
496// brute force method requiring a copy
497//ofMatrix4x4 tmp(*this * other);
498// *this = tmp;
499
500// more efficient method just use a float[4] for temporary storage.
501float t[4];
502for(int row=0; row<4; ++row)
503{
504t[0] = INNER_PRODUCT( *this, other, row, 0 );
505t[1] = INNER_PRODUCT( *this, other, row, 1 );
506t[2] = INNER_PRODUCT( *this, other, row, 2 );
507t[3] = INNER_PRODUCT( *this, other, row, 3 );
508SET_ROW(row, t[0], t[1], t[2], t[3] )
509}
510}
511
512#undef INNER_PRODUCT
513
514// orthoNormalize the 3x3 rotation matrix
515void ofMatrix4x4::makeOrthoNormalOf(const ofMatrix4x4& rhs)
516{
517float x_colMag = (rhs._mat[0][0] * rhs._mat[0][0]) + (rhs._mat[1][0] * rhs._mat[1][0]) + (rhs._mat[2][0] * rhs._mat[2][0]);
518float y_colMag = (rhs._mat[0][1] * rhs._mat[0][1]) + (rhs._mat[1][1] * rhs._mat[1][1]) + (rhs._mat[2][1] * rhs._mat[2][1]);
519float z_colMag = (rhs._mat[0][2] * rhs._mat[0][2]) + (rhs._mat[1][2] * rhs._mat[1][2]) + (rhs._mat[2][2] * rhs._mat[2][2]);
520
521if(!equivalent((double)x_colMag, 1.0) && !equivalent((double)x_colMag, 0.0))
522{
523x_colMag = sqrt(x_colMag);
524_mat[0][0] = rhs._mat[0][0] / x_colMag;
525_mat[1][0] = rhs._mat[1][0] / x_colMag;
526_mat[2][0] = rhs._mat[2][0] / x_colMag;
527}
528else
529{
530_mat[0][0] = rhs._mat[0][0];
531_mat[1][0] = rhs._mat[1][0];
532_mat[2][0] = rhs._mat[2][0];
533}
534
535if(!equivalent((double)y_colMag, 1.0) && !equivalent((double)y_colMag, 0.0))
536{
537y_colMag = sqrt(y_colMag);
538_mat[0][1] = rhs._mat[0][1] / y_colMag;
539_mat[1][1] = rhs._mat[1][1] / y_colMag;
540_mat[2][1] = rhs._mat[2][1] / y_colMag;
541}
542else
543{
544_mat[0][1] = rhs._mat[0][1];
545_mat[1][1] = rhs._mat[1][1];
546_mat[2][1] = rhs._mat[2][1];
547}
548
549if(!equivalent((double)z_colMag, 1.0) && !equivalent((double)z_colMag, 0.0))
550{
551z_colMag = sqrt(z_colMag);
552_mat[0][2] = rhs._mat[0][2] / z_colMag;
553_mat[1][2] = rhs._mat[1][2] / z_colMag;
554_mat[2][2] = rhs._mat[2][2] / z_colMag;
555}
556else
557{
558_mat[0][2] = rhs._mat[0][2];
559_mat[1][2] = rhs._mat[1][2];
560_mat[2][2] = rhs._mat[2][2];
561}
562
563_mat[3][0] = rhs._mat[3][0];
564_mat[3][1] = rhs._mat[3][1];
565_mat[3][2] = rhs._mat[3][2];
566
567_mat[0][3] = rhs._mat[0][3];
568_mat[1][3] = rhs._mat[1][3];
569_mat[2][3] = rhs._mat[2][3];
570_mat[3][3] = rhs._mat[3][3];
571
572}
573
574
575/** 4x3 matrix invert, not right hand column is assumed to be 0,0,0,1. */
576bool invert_4x3( const ofMatrix4x4& src, ofMatrix4x4 & dst);
577
578/** full 4x4 matrix invert. */
579bool invert_4x4( const ofMatrix4x4& rhs, ofMatrix4x4 & dst);
580
581bool ofMatrix4x4::makeInvertOf(const ofMatrix4x4 & rhs){
582bool is_4x3 = (rhs._mat[0][3] == 0.0f && rhs._mat[1][3] == 0.0f && rhs._mat[2][3] == 0.0f && rhs._mat[3][3] == 1.0f);
583return is_4x3 ? invert_4x3(rhs,*this) : invert_4x4(rhs,*this);
584}
585
586ofMatrix4x4 ofMatrix4x4::getInverse() const
587{
588ofMatrix4x4 inverse;
589inverse.makeInvertOf(*this);
590return inverse;
591}
592
593
594
595
596
597/******************************************
598Matrix inversion technique:
599Given a matrix mat, we want to invert it.
600mat = [ r00 r01 r02 a
601r10 r11 r12 b
602r20 r21 r22 c
603tx ty tz d ]
604We note that this matrix can be split into three matrices.
605mat = rot * trans * corr, where rot is rotation part, trans is translation part, and corr is the correction due to perspective (if any).
606rot = [ r00 r01 r02 0
607r10 r11 r12 0
608r20 r21 r22 0
6090 0 0 1 ]
610trans = [ 1 0 0 0
6110 1 0 0
6120 0 1 0
613tx ty tz 1 ]
614corr = [ 1 0 0 px
6150 1 0 py
6160 0 1 pz
6170 0 0 s ]
618where the elements of corr are obtained from linear combinations of the elements of rot, trans, and mat.
619So the inverse is mat' = (trans * corr)' * rot', where rot' must be computed the traditional way, which is easy since it is only a 3x3 matrix.
620This problem is simplified if [px py pz s] = [0 0 0 1], which will happen if mat was composed only of rotations, scales, and translations (which is common). In this case, we can ignore corr entirely which saves on a lot of computations.
621******************************************/
622
623bool invert_4x3( const ofMatrix4x4& src, ofMatrix4x4 & dst )
624{
625if (&src==&dst)
626{
627ofMatrix4x4 tm(src);
628return invert_4x3(tm,dst);
629}
630
631float r00, r01, r02,
632r10, r11, r12,
633r20, r21, r22;
634// Copy rotation components directly into registers for speed
635r00 = src._mat[0][0]; r01 = src._mat[0][1]; r02 = src._mat[0][2];
636r10 = src._mat[1][0]; r11 = src._mat[1][1]; r12 = src._mat[1][2];
637r20 = src._mat[2][0]; r21 = src._mat[2][1]; r22 = src._mat[2][2];
638
639// Partially compute inverse of rot
640dst._mat[0][0] = r11*r22 - r12*r21;
641dst._mat[0][1] = r02*r21 - r01*r22;
642dst._mat[0][2] = r01*r12 - r02*r11;
643
644// Compute determinant of rot from 3 elements just computed
645float one_over_det = 1.0/(r00*dst._mat[0][0] + r10*dst._mat[0][1] + r20*dst._mat[0][2]);
646r00 *= one_over_det; r10 *= one_over_det; r20 *= one_over_det; // Saves on later computations
647
648// Finish computing inverse of rot
649dst._mat[0][0] *= one_over_det;
650dst._mat[0][1] *= one_over_det;
651dst._mat[0][2] *= one_over_det;
652dst._mat[0][3] = 0.0;
653dst._mat[1][0] = r12*r20 - r10*r22; // Have already been divided by det
654dst._mat[1][1] = r00*r22 - r02*r20; // same
655dst._mat[1][2] = r02*r10 - r00*r12; // same
656dst._mat[1][3] = 0.0;
657dst._mat[2][0] = r10*r21 - r11*r20; // Have already been divided by det
658dst._mat[2][1] = r01*r20 - r00*r21; // same
659dst._mat[2][2] = r00*r11 - r01*r10; // same
660dst._mat[2][3] = 0.0;
661dst._mat[3][3] = 1.0;
662
663// We no longer need the rxx or det variables anymore, so we can reuse them for whatever we want. But we will still rename them for the sake of clarity.
664
665#define d r22
666d = src._mat[3][3];
667
668if( square(d-1.0) > 1.0e-6 ) // Involves perspective, so we must
669{ // compute the full inverse
670
671ofMatrix4x4 TPinv;
672dst._mat[3][0] = dst._mat[3][1] = dst._mat[3][2] = 0.0;
673
674#define px r00
675#define py r01
676#define pz r02
677#define one_over_s one_over_det
678#define a r10
679#define b r11
680#define c r12
681
682a = src._mat[0][3]; b = src._mat[1][3]; c = src._mat[2][3];
683px = dst._mat[0][0]*a + dst._mat[0][1]*b + dst._mat[0][2]*c;
684py = dst._mat[1][0]*a + dst._mat[1][1]*b + dst._mat[1][2]*c;
685pz = dst._mat[2][0]*a + dst._mat[2][1]*b + dst._mat[2][2]*c;
686
687#undef a
688#undef b
689#undef c
690#define tx r10
691#define ty r11
692#define tz r12
693
694tx = src._mat[3][0]; ty = src._mat[3][1]; tz = src._mat[3][2];
695one_over_s = 1.0/(d - (tx*px + ty*py + tz*pz));
696
697tx *= one_over_s; ty *= one_over_s; tz *= one_over_s; // Reduces number of calculations later on
698
699// Compute inverse of trans*corr
700TPinv._mat[0][0] = tx*px + 1.0;
701TPinv._mat[0][1] = ty*px;
702TPinv._mat[0][2] = tz*px;
703TPinv._mat[0][3] = -px * one_over_s;
704TPinv._mat[1][0] = tx*py;
705TPinv._mat[1][1] = ty*py + 1.0;
706TPinv._mat[1][2] = tz*py;
707TPinv._mat[1][3] = -py * one_over_s;
708TPinv._mat[2][0] = tx*pz;
709TPinv._mat[2][1] = ty*pz;
710TPinv._mat[2][2] = tz*pz + 1.0;
711TPinv._mat[2][3] = -pz * one_over_s;
712TPinv._mat[3][0] = -tx;
713TPinv._mat[3][1] = -ty;
714TPinv._mat[3][2] = -tz;
715TPinv._mat[3][3] = one_over_s;
716
717dst.preMult(TPinv); // Finish computing full inverse of mat
718
719#undef px
720#undef py
721#undef pz
722#undef one_over_s
723#undef d
724}
725else // Rightmost column is [0; 0; 0; 1] so it can be ignored
726{
727tx = src._mat[3][0]; ty = src._mat[3][1]; tz = src._mat[3][2];
728
729// Compute translation components of mat'
730dst._mat[3][0] = -(tx*dst._mat[0][0] + ty*dst._mat[1][0] + tz*dst._mat[2][0]);
731dst._mat[3][1] = -(tx*dst._mat[0][1] + ty*dst._mat[1][1] + tz*dst._mat[2][1]);
732dst._mat[3][2] = -(tx*dst._mat[0][2] + ty*dst._mat[1][2] + tz*dst._mat[2][2]);
733
734#undef tx
735#undef ty
736#undef tz
737}
738
739return true;
740}
741
742
743template <class T>
744inline T SGL_ABS(T a)
745{
746return (a >= 0 ? a : -a);
747}
748
749#ifndef SGL_SWAP
750#define SGL_SWAP(a,b,temp) ((temp)=(a),(a)=(b),(b)=(temp))
751#endif
752
753bool invert_4x4( const ofMatrix4x4& src, ofMatrix4x4&dst )
754{
755if (&src==&dst) {
756ofMatrix4x4 tm(src);
757return invert_4x4(tm,dst);
758}
759
760unsigned int indxc[4], indxr[4], ipiv[4];
761unsigned int i,j,k,l,ll;
762unsigned int icol = 0;
763unsigned int irow = 0;
764double temp, pivinv, dum, big;
765
766// copy in place this may be unnecessary
767dst = src;
768
769for (j=0; j<4; j++) ipiv[j]=0;
770
771for(i=0;i<4;i++)
772{
773big=0.0;
774for (j=0; j<4; j++)
775if (ipiv[j] != 1)
776for (k=0; k<4; k++)
777{
778if (ipiv[k] == 0)
779{
780if (SGL_ABS(dst(j,k)) >= big)
781{
782big = SGL_ABS(dst(j,k));
783irow=j;
784icol=k;
785}
786}
787else if (ipiv[k] > 1)
788return false;
789}
790++(ipiv[icol]);
791if (irow != icol)
792for (l=0; l<4; l++) SGL_SWAP(dst(irow,l),
793dst(icol,l),
794temp);
795
796indxr[i]=irow;
797indxc[i]=icol;
798if (dst(icol,icol) == 0)
799return false;
800
801pivinv = 1.0/dst(icol,icol);
802dst(icol,icol) = 1;
803for (l=0; l<4; l++) dst(icol,l) *= pivinv;
804for (ll=0; ll<4; ll++)
805if (ll != icol)
806{
807dum=dst(ll,icol);
808dst(ll,icol) = 0;
809for (l=0; l<4; l++)dst(ll,l) -= dst(icol,l)*dum;
810}
811}
812for (int lx=4; lx>0; --lx)
813{
814if (indxr[lx-1] != indxc[lx-1])
815for (k=0; k<4; k++) SGL_SWAP(dst(k,indxr[lx-1]),
816dst(k,indxc[lx-1]),temp);
817}
818
819return true;
820}
821
822void ofMatrix4x4::makeOrthoMatrix(double left, double right,
823double bottom, double top,
824double zNear, double zFar)
825{
826// note transpose of ofMatrix4x4 wr.t OpenGL documentation, since the OSG use post multiplication rather than pre.
827double tx = -(right+left)/(right-left);
828double ty = -(top+bottom)/(top-bottom);
829double tz = -(zFar+zNear)/(zFar-zNear);
830SET_ROW(0, 2.0/(right-left), 0.0, 0.0, 0.0 )
831SET_ROW(1, 0.0, 2.0/(top-bottom), 0.0, 0.0 )
832SET_ROW(2, 0.0, 0.0, -2.0/(zFar-zNear), 0.0 )
833SET_ROW(3, tx, ty, tz, 1.0 )
834}
835
836bool ofMatrix4x4::getOrtho(double& left, double& right,
837double& bottom, double& top,
838double& zNear, double& zFar) const
839{
840if (_mat[0][3]!=0.0 || _mat[1][3]!=0.0 || _mat[2][3]!=0.0 || _mat[3][3]!=1.0) return false;
841
842zNear = (_mat[3][2]+1.0) / _mat[2][2];
843zFar = (_mat[3][2]-1.0) / _mat[2][2];
844
845left = -(1.0+_mat[3][0]) / _mat[0][0];
846right = (1.0-_mat[3][0]) / _mat[0][0];
847
848bottom = -(1.0+_mat[3][1]) / _mat[1][1];
849top = (1.0-_mat[3][1]) / _mat[1][1];
850
851return true;
852}
853
854
855void ofMatrix4x4::makeFrustumMatrix(double left, double right,
856double bottom, double top,
857double zNear, double zFar)
858{
859// note transpose of ofMatrix4x4 wr.t OpenGL documentation, since the OSG use post multiplication rather than pre.
860double A = (right+left)/(right-left);
861double B = (top+bottom)/(top-bottom);
862double C = -(zFar+zNear)/(zFar-zNear);
863double D = -2.0*zFar*zNear/(zFar-zNear);
864SET_ROW(0, 2.0*zNear/(right-left), 0.0, 0.0, 0.0 )
865SET_ROW(1, 0.0, 2.0*zNear/(top-bottom), 0.0, 0.0 )
866SET_ROW(2, A, B, C, -1.0 )
867SET_ROW(3, 0.0, 0.0, D, 0.0 )
868}
869
870bool ofMatrix4x4::getFrustum(double& left, double& right,
871double& bottom, double& top,
872double& zNear, double& zFar) const
873{
874if (_mat[0][3]!=0.0 || _mat[1][3]!=0.0 || _mat[2][3]!=-1.0 || _mat[3][3]!=0.0) return false;
875
876
877zNear = _mat[3][2] / (_mat[2][2]-1.0);
878zFar = _mat[3][2] / (1.0+_mat[2][2]);
879
880left = zNear * (_mat[2][0]-1.0) / _mat[0][0];
881right = zNear * (1.0+_mat[2][0]) / _mat[0][0];
882
883top = zNear * (1.0+_mat[2][1]) / _mat[1][1];
884bottom = zNear * (_mat[2][1]-1.0) / _mat[1][1];
885
886return true;
887}
888
889
890void ofMatrix4x4::makePerspectiveMatrix(double fovy,double aspectRatio,
891double zNear, double zFar)
892{
893// calculate the appropriate left, right etc.
894double tan_fovy = tan(ofDegToRad(fovy*0.5));
895double right = tan_fovy * aspectRatio * zNear;
896double left = -right;
897double top = tan_fovy * zNear;
898double bottom = -top;
899makeFrustumMatrix(left,right,bottom,top,zNear,zFar);
900}
901
902bool ofMatrix4x4::getPerspective(double& fovy,double& aspectRatio,
903double& zNear, double& zFar) const
904{
905double right = 0.0;
906double left = 0.0;
907double top = 0.0;
908double bottom = 0.0;
909if (getFrustum(left,right,bottom,top,zNear,zFar))
910{
911fovy = ofRadToDeg(atan(top/zNear)-atan(bottom/zNear));
912aspectRatio = (right-left)/(top-bottom);
913return true;
914}
915return false;
916}
917
918void ofMatrix4x4::makeLookAtViewMatrix(const ofVec3f& eye,const ofVec3f& center,const ofVec3f& up)
919{
920ofVec3f zaxis = (eye - center).getNormalized();
921ofVec3f xaxis = up.getCrossed(zaxis).getNormalized();
922ofVec3f yaxis = zaxis.getCrossed(xaxis);
923
924_mat[0].set(xaxis.x, yaxis.x, zaxis.x, 0);
925_mat[1].set(xaxis.y, yaxis.y, zaxis.y, 0);
926_mat[2].set(xaxis.z, yaxis.z, zaxis.z, 0);
927_mat[3].set(-xaxis.dot(eye), -yaxis.dot(eye), -zaxis.dot(eye), 1);
928}
929
930void ofMatrix4x4::makeLookAtMatrix(const ofVec3f& eye,const ofVec3f& center,const ofVec3f& up)
931{
932ofVec3f zaxis = (eye - center).getNormalized();
933ofVec3f xaxis = up.getCrossed(zaxis).getNormalized();
934ofVec3f yaxis = zaxis.getCrossed(xaxis);
935
936_mat[0].set(xaxis.x, xaxis.y, xaxis.z, 0);
937_mat[1].set(yaxis.x, yaxis.y, yaxis.z, 0);
938_mat[2].set(zaxis.x, zaxis.y, zaxis.z, 0);
939_mat[3].set(eye.x, eye.y, eye.z, 1);
940}
941
942void ofMatrix4x4::getLookAt(ofVec3f& eye,ofVec3f& center,ofVec3f& up,float lookDistance) const
943{
944ofMatrix4x4 inv;
945inv.makeInvertOf(*this);
946eye = ofVec3f(0.0,0.0,0.0)*inv;
947up = transform3x3(*this,ofVec3f(0.0,1.0,0.0));
948center = transform3x3(*this,ofVec3f(0.0,0.0,-1));
949center.normalize();
950center = eye + center*lookDistance;
951}
952
953
954
955typedef ofQuaternion HVect;
956typedef double _HMatrix[4][4];
957typedef struct
958{
959ofVec4f t; // Translation Component;
960ofQuaternion q; // Essential Rotation
961ofQuaternion u; //Stretch rotation
962HVect k; //Sign of determinant
963double f; // Sign of determinant
964} _affineParts;
965
966
967enum QuatPart {X, Y, Z, W};
968
969#define SQRTHALF (0.7071067811865475244)
970static ofQuaternion qxtoz(0,SQRTHALF,0,SQRTHALF);
971static ofQuaternion qytoz(SQRTHALF,0,0,SQRTHALF);
972static ofQuaternion qppmm( 0.5, 0.5,-0.5,-0.5);
973static ofQuaternion qpppp( 0.5, 0.5, 0.5, 0.5);
974static ofQuaternion qmpmm(-0.5, 0.5,-0.5,-0.5);
975static ofQuaternion qpppm( 0.5, 0.5, 0.5,-0.5);
976static ofQuaternion q0001( 0.0, 0.0, 0.0, 1.0);
977static ofQuaternion q1000( 1.0, 0.0, 0.0, 0.0);
978
979/** Copy nxn matrix A to C using "gets" for assignment **/
980#define matrixCopy(C, gets, A, n) {int i, j; for (i=0;i<n;i++) for (j=0;j<n;j++)\
981C[i][j] gets (A[i][j]);}
982
983/** Copy transpose of nxn matrix A to C using "gets" for assignment **/
984#define mat_tpose(AT,gets,A,n) {int i,j; for(i=0;i<n;i++) for(j=0;j<n;j++)\
985AT[i][j] gets (A[j][i]);}
986
987/** Fill out 3x3 matrix to 4x4 **/
988#define mat_pad(A) (A[W][X]=A[X][W]=A[W][Y]=A[Y][W]=A[W][Z]=A[Z][W]=0,A[W][W]=1)
989
990
991/** Assign nxn matrix C the element-wise combination of A and B using "op" **/
992#define matBinop(C,gets,A,op,B,n) {int i,j; for(i=0;i<n;i++) for(j=0;j<n;j++)\
993C[i][j] gets (A[i][j]) op (B[i][j]);}
994
995/** Copy nxn matrix A to C using "gets" for assignment **/
996#define mat_copy(C,gets,A,n) {int i,j; for(i=0;i<n;i++) for(j=0;j<n;j++)\
997C[i][j] gets (A[i][j]);}
998
999/** Multiply the upper left 3x3 parts of A and B to get AB **/
1000void mat_mult(_HMatrix A, _HMatrix B, _HMatrix AB)
1001{
1002int i, j;
1003for (i=0; i<3; i++) for (j=0; j<3; j++)
1004AB[i][j] = A[i][0]*B[0][j] + A[i][1]*B[1][j] + A[i][2]*B[2][j];
1005}
1006
1007double mat_norm(_HMatrix M, int tpose)
1008{
1009int i;
1010double sum, max;
1011max = 0.0;
1012for (i=0; i<3; i++) {
1013if (tpose) sum = fabs(M[0][i])+fabs(M[1][i])+fabs(M[2][i]);
1014else sum = fabs(M[i][0])+fabs(M[i][1])+fabs(M[i][2]);
1015if (max<sum) max = sum;
1016}
1017return max;
1018}
1019
1020double norm_inf(_HMatrix M) {return mat_norm(M, 0);}
1021double norm_one(_HMatrix M) {return mat_norm(M, 1);}
1022
1023static _HMatrix mat_id = {{1,0,0,0},{0,1,0,0},{0,0,1,0},{0,0,0,1}};
1024
1025/** Return index of column of M containing maximum abs entry, or -1 if M=0 **/
1026int find_max_col(_HMatrix M)
1027{
1028double abs, max;
1029int i, j, col;
1030max = 0.0; col = -1;
1031for (i=0; i<3; i++) for (j=0; j<3; j++) {
1032abs = M[i][j]; if (abs<0.0) abs = -abs;
1033if (abs>max) {max = abs; col = j;}
1034}
1035return col;
1036}
1037
1038void vcross(double *va, double *vb, double *v)
1039{
1040v[0] = va[1]*vb[2] - va[2]*vb[1];
1041v[1] = va[2]*vb[0] - va[0]*vb[2];
1042v[2] = va[0]*vb[1] - va[1]*vb[0];
1043}
1044
1045/** Return dot product of length 3 vectors va and vb **/
1046double vdot(double *va, double *vb)
1047{
1048return (va[0]*vb[0] + va[1]*vb[1] + va[2]*vb[2]);
1049}
1050
1051
1052/** Set MadjT to transpose of inverse of M times determinant of M **/
1053void adjoint_transpose(_HMatrix M, _HMatrix MadjT)
1054{
1055vcross(M[1], M[2], MadjT[0]);
1056vcross(M[2], M[0], MadjT[1]);
1057vcross(M[0], M[1], MadjT[2]);
1058}
1059
1060/** Setup u for Household reflection to zero all v components but first **/
1061void make_reflector(double *v, double *u)
1062{
1063double s = sqrt(vdot(v, v));
1064u[0] = v[0]; u[1] = v[1];
1065u[2] = v[2] + ((v[2]<0.0) ? -s : s);
1066s = sqrt(2.0/vdot(u, u));
1067u[0] = u[0]*s; u[1] = u[1]*s; u[2] = u[2]*s;
1068}
1069
1070/** Apply Householder reflection represented by u to column vectors of M **/
1071void reflect_cols(_HMatrix M, double *u)
1072{
1073int i, j;
1074for (i=0; i<3; i++) {
1075double s = u[0]*M[0][i] + u[1]*M[1][i] + u[2]*M[2][i];
1076for (j=0; j<3; j++) M[j][i] -= u[j]*s;
1077}
1078}
1079
1080/** Apply Householder reflection represented by u to row vectors of M **/
1081void reflect_rows(_HMatrix M, double *u)
1082{
1083int i, j;
1084for (i=0; i<3; i++) {
1085double s = vdot(u, M[i]);
1086for (j=0; j<3; j++) M[i][j] -= u[j]*s;
1087}
1088}
1089
1090/** Find orthogonal factor Q of rank 1 (or less) M **/
1091void do_rank1(_HMatrix M, _HMatrix Q)
1092{
1093double v1[3], v2[3], s;
1094int col;
1095mat_copy(Q,=,mat_id,4);
1096/* If rank(M) is 1, we should find a non-zero column in M */
1097col = find_max_col(M);
1098if (col<0) return; /* Rank is 0 */
1099v1[0] = M[0][col]; v1[1] = M[1][col]; v1[2] = M[2][col];
1100make_reflector(v1, v1); reflect_cols(M, v1);
1101v2[0] = M[2][0]; v2[1] = M[2][1]; v2[2] = M[2][2];
1102make_reflector(v2, v2); reflect_rows(M, v2);
1103s = M[2][2];
1104if (s<0.0) Q[2][2] = -1.0;
1105reflect_cols(Q, v1); reflect_rows(Q, v2);
1106}
1107
1108/** Find orthogonal factor Q of rank 2 (or less) M using adjoint transpose **/
1109void do_rank2(_HMatrix M, _HMatrix MadjT, _HMatrix Q)
1110{
1111double v1[3], v2[3];
1112double w, x, y, z, c, s, d;
1113int col;
1114/* If rank(M) is 2, we should find a non-zero column in MadjT */
1115col = find_max_col(MadjT);
1116if (col<0) {do_rank1(M, Q); return;} /* Rank<2 */
1117v1[0] = MadjT[0][col]; v1[1] = MadjT[1][col]; v1[2] = MadjT[2][col];
1118make_reflector(v1, v1); reflect_cols(M, v1);
1119vcross(M[0], M[1], v2);
1120make_reflector(v2, v2); reflect_rows(M, v2);
1121w = M[0][0]; x = M[0][1]; y = M[1][0]; z = M[1][1];
1122if (w*z>x*y) {
1123c = z+w; s = y-x; d = sqrt(c*c+s*s); c = c/d; s = s/d;
1124Q[0][0] = Q[1][1] = c; Q[0][1] = -(Q[1][0] = s);
1125} else {
1126c = z-w; s = y+x; d = sqrt(c*c+s*s); c = c/d; s = s/d;
1127Q[0][0] = -(Q[1][1] = c); Q[0][1] = Q[1][0] = s;
1128}
1129Q[0][2] = Q[2][0] = Q[1][2] = Q[2][1] = 0.0; Q[2][2] = 1.0;
1130reflect_cols(Q, v1); reflect_rows(Q, v2);
1131}
1132
1133/* Return product of quaternion q by scalar w. */
1134ofQuaternion Qt_Scale(ofQuaternion q, double w)
1135{
1136ofQuaternion qq;
1137qq.w() = q.w()*w;
1138qq.x() = q.x()*w;
1139qq.y() = q.y()*w;
1140qq.z() = q.z()*w;
1141return (qq);
1142}
1143
1144/* Construct a unit quaternion from rotation matrix. Assumes matrix is
1145* used to multiply column vector on the left: vnew = mat vold. Works
1146* correctly for right-handed coordinate system and right-handed rotations.
1147* Translation and perspective components ignored. */
1148
1149ofQuaternion quatFromMatrix(_HMatrix mat)
1150{
1151/* This algorithm avoids near-zero divides by looking for a large component
1152* - first w, then x, y, or z. When the trace is greater than zero,
1153* |w| is greater than 1/2, which is as small as a largest component can be.
1154* Otherwise, the largest diagonal entry corresponds to the largest of |x|,
1155* |y|, or |z|, one of which must be larger than |w|, and at least 1/2. */
1156ofQuaternion qu = q0001;
1157double tr, s;
1158
1159tr = mat[X][X] + mat[Y][Y]+ mat[Z][Z];
1160if (tr >= 0.0)
1161{
1162s = sqrt(tr + mat[W][W]);
1163qu.w() = s*0.5;
1164s = 0.5 / s;
1165qu.x() = (mat[Z][Y] - mat[Y][Z]) * s;
1166qu.y() = (mat[X][Z] - mat[Z][X]) * s;
1167qu.z() = (mat[Y][X] - mat[X][Y]) * s;
1168}
1169else
1170{
1171int h = X;
1172if (mat[Y][Y] > mat[X][X]) h = Y;
1173if (mat[Z][Z] > mat[h][h]) h = Z;
1174switch (h) {
1175#define caseMacro(i,j,k,I,J,K) \
1176case I:\
1177s = sqrt( (mat[I][I] - (mat[J][J]+mat[K][K])) + mat[W][W] );\
1178qu.i() = s*0.5;\
1179s = 0.5 / s;\
1180qu.j() = (mat[I][J] + mat[J][I]) * s;\
1181qu.k() = (mat[K][I] + mat[I][K]) * s;\
1182qu.w() = (mat[K][J] - mat[J][K]) * s;\
1183break
1184caseMacro(x,y,z,X,Y,Z);
1185caseMacro(y,z,x,Y,Z,X);
1186caseMacro(z,x,y,Z,X,Y);
1187}
1188}
1189if (mat[W][W] != 1.0) qu = Qt_Scale(qu, 1/sqrt(mat[W][W]));
1190return (qu);
1191}
1192
1193
1194/******* Polar Decomposition *******/
1195/* Polar Decomposition of 3x3 matrix in 4x4,
1196* M = QS. See Nicholas Higham and Robert S. Schreiber,
1197* Fast Polar Decomposition of An Arbitrary Matrix,
1198* Technical Report 88-942, October 1988,
1199* Department of Computer Science, Cornell University.
1200*/
1201
1202double polarDecomp( _HMatrix M, _HMatrix Q, _HMatrix S)
1203{
1204
1205#define TOL 1.0e-6
1206_HMatrix Mk, MadjTk, Ek;
1207double det, M_one, M_inf, MadjT_one, MadjT_inf, E_one, gamma, g1, g2;
1208int i, j;
1209
1210mat_tpose(Mk,=,M,3);
1211M_one = norm_one(Mk); M_inf = norm_inf(Mk);
1212
1213do
1214{
1215adjoint_transpose(Mk, MadjTk);
1216det = vdot(Mk[0], MadjTk[0]);
1217if (det==0.0)
1218{
1219do_rank2(Mk, MadjTk, Mk);
1220break;
1221}
1222
1223MadjT_one = norm_one(MadjTk);
1224MadjT_inf = norm_inf(MadjTk);
1225
1226gamma = sqrt(sqrt((MadjT_one*MadjT_inf)/(M_one*M_inf))/fabs(det));
1227g1 = gamma*0.5;
1228g2 = 0.5/(gamma*det);
1229matrixCopy(Ek,=,Mk,3);
1230matBinop(Mk,=,g1*Mk,+,g2*MadjTk,3);
1231mat_copy(Ek,-=,Mk,3);
1232E_one = norm_one(Ek);
1233M_one = norm_one(Mk);
1234M_inf = norm_inf(Mk);
1235
1236} while(E_one>(M_one*TOL));
1237
1238mat_tpose(Q,=,Mk,3); mat_pad(Q);
1239mat_mult(Mk, M, S); mat_pad(S);
1240
1241for (i=0; i<3; i++)
1242for (j=i; j<3; j++)
1243S[i][j] = S[j][i] = 0.5*(S[i][j]+S[j][i]);
1244return (det);
1245}
1246
1247/******* Spectral Decomposition *******/
1248/* Compute the spectral decomposition of symmetric positive semi-definite S.
1249* Returns rotation in U and scale factors in result, so that if K is a diagonal
1250* matrix of the scale factors, then S = U K (U transpose). Uses Jacobi method.
1251* See Gene H. Golub and Charles F. Van Loan. Matrix Computations. Hopkins 1983.
1252*/
1253HVect spectDecomp(_HMatrix S, _HMatrix U)
1254{
1255HVect kv;
1256double Diag[3],OffD[3]; /* OffD is off-diag (by omitted index) */
1257double g,h,fabsh,fabsOffDi,t,theta,c,s,tau,ta,OffDq,a,b;
1258static char nxt[] = {Y,Z,X};
1259int sweep, i, j;
1260mat_copy(U,=,mat_id,4);
1261Diag[X] = S[X][X]; Diag[Y] = S[Y][Y]; Diag[Z] = S[Z][Z];
1262OffD[X] = S[Y][Z]; OffD[Y] = S[Z][X]; OffD[Z] = S[X][Y];
1263for (sweep=20; sweep>0; sweep--) {
1264double sm = fabs(OffD[X])+fabs(OffD[Y])+fabs(OffD[Z]);
1265if (sm==0.0) break;
1266for (i=Z; i>=X; i--) {
1267int p = nxt[i]; int q = nxt[p];
1268fabsOffDi = fabs(OffD[i]);
1269g = 100.0*fabsOffDi;
1270if (fabsOffDi>0.0) {
1271h = Diag[q] - Diag[p];
1272fabsh = fabs(h);
1273if (fabsh+g==fabsh) {
1274t = OffD[i]/h;
1275} else {
1276theta = 0.5*h/OffD[i];
1277t = 1.0/(fabs(theta)+sqrt(theta*theta+1.0));
1278if (theta<0.0) t = -t;
1279}
1280c = 1.0/sqrt(t*t+1.0); s = t*c;
1281tau = s/(c+1.0);
1282ta = t*OffD[i]; OffD[i] = 0.0;
1283Diag[p] -= ta; Diag[q] += ta;
1284OffDq = OffD[q];
1285OffD[q] -= s*(OffD[p] + tau*OffD[q]);
1286OffD[p] += s*(OffDq - tau*OffD[p]);
1287for (j=Z; j>=X; j--) {
1288a = U[j][p]; b = U[j][q];
1289U[j][p] -= s*(b + tau*a);
1290U[j][q] += s*(a - tau*b);
1291}
1292}
1293}
1294}
1295kv.x() = Diag[X]; kv.y() = Diag[Y]; kv.z() = Diag[Z]; kv.w() = 1.0;
1296return (kv);
1297}
1298
1299/* Return conjugate of quaternion. */
1300ofQuaternion Qt_Conj(ofQuaternion q)
1301{
1302ofQuaternion qq;
1303qq.x() = -q.x(); qq.y() = -q.y(); qq.z() = -q.z(); qq.w() = q.w();
1304return (qq);
1305}
1306
1307/* Return quaternion product qL * qR. Note: order is important!
1308* To combine rotations, use the product Mul(qSecond, qFirst),
1309* which gives the effect of rotating by qFirst then qSecond. */
1310ofQuaternion Qt_Mul(ofQuaternion qL, ofQuaternion qR)
1311{
1312ofQuaternion qq;
1313qq.w() = qL.w()*qR.w() - qL.x()*qR.x() - qL.y()*qR.y() - qL.z()*qR.z();
1314qq.x() = qL.w()*qR.x() + qL.x()*qR.w() + qL.y()*qR.z() - qL.z()*qR.y();
1315qq.y() = qL.w()*qR.y() + qL.y()*qR.w() + qL.z()*qR.x() - qL.x()*qR.z();
1316qq.z() = qL.w()*qR.z() + qL.z()*qR.w() + qL.x()*qR.y() - qL.y()*qR.x();
1317return (qq);
1318}
1319
1320/* Construct a (possibly non-unit) quaternion from real components. */
1321ofQuaternion Qt_(double x, double y, double z, double w)
1322{
1323ofQuaternion qq;
1324qq.x() = x; qq.y() = y; qq.z() = z; qq.w() = w;
1325return (qq);
1326}
1327
1328/******* Spectral Axis Adjustment *******/
1329
1330/* Given a unit quaternion, q, and a scale vector, k, find a unit quaternion, p,
1331* which permutes the axes and turns freely in the plane of duplicate scale
1332* factors, such that q p has the largest possible w component, i.e. the
1333* smallest possible angle. Permutes k's components to go with q p instead of q.
1334* See Ken Shoemake and Tom Duff. Matrix Animation and Polar Decomposition.
1335* Proceedings of Graphics Interface 1992. Details on p. 262-263.
1336*/
1337ofQuaternion snuggle(ofQuaternion q, HVect *k)
1338{
1339#define sgn(n,v) ((n)?-(v):(v))
1340#define swap(a,i,j) {a[3]=a[i]; a[i]=a[j]; a[j]=a[3];}
1341#define cycle(a,p) if (p) {a[3]=a[0]; a[0]=a[1]; a[1]=a[2]; a[2]=a[3];}\
1342else {a[3]=a[2]; a[2]=a[1]; a[1]=a[0]; a[0]=a[3];}
1343
1344ofQuaternion p = q0001;
1345double ka[4];
1346int i, turn = -1;
1347ka[X] = k->x(); ka[Y] = k->y(); ka[Z] = k->z();
1348
1349if (ka[X]==ka[Y]) {
1350if (ka[X]==ka[Z])
1351turn = W;
1352else turn = Z;
1353}
1354else {
1355if (ka[X]==ka[Z])
1356turn = Y;
1357else if (ka[Y]==ka[Z])
1358turn = X;
1359}
1360if (turn>=0) {
1361ofQuaternion qtoz, qp;
1362unsigned int win;
1363double mag[3], t;
1364switch (turn) {
1365default: return (Qt_Conj(q));
1366case X: q = Qt_Mul(q, qtoz = qxtoz); swap(ka,X,Z) break;
1367case Y: q = Qt_Mul(q, qtoz = qytoz); swap(ka,Y,Z) break;
1368case Z: qtoz = q0001; break;
1369}
1370q = Qt_Conj(q);
1371mag[0] = (double)q.z()*q.z()+(double)q.w()*q.w()-0.5;
1372mag[1] = (double)q.x()*q.z()-(double)q.y()*q.w();
1373mag[2] = (double)q.y()*q.z()+(double)q.x()*q.w();
1374
1375bool neg[3];
1376for (i=0; i<3; i++)
1377{
1378neg[i] = (mag[i]<0.0);
1379if (neg[i]) mag[i] = -mag[i];
1380}
1381
1382if (mag[0]>mag[1]) {
1383if (mag[0]>mag[2])
1384win = 0;
1385else win = 2;
1386}
1387else {
1388if (mag[1]>mag[2]) win = 1;
1389else win = 2;
1390}
1391
1392switch (win) {
1393case 0: if (neg[0]) p = q1000; else p = q0001; break;
1394case 1: if (neg[1]) p = qppmm; else p = qpppp; cycle(ka,0) break;
1395case 2: if (neg[2]) p = qmpmm; else p = qpppm; cycle(ka,1) break;
1396}
1397
1398qp = Qt_Mul(q, p);
1399t = sqrt(mag[win]+0.5);
1400p = Qt_Mul(p, Qt_(0.0,0.0,-qp.z()/t,qp.w()/t));
1401p = Qt_Mul(qtoz, Qt_Conj(p));
1402}
1403else {
1404double qa[4], pa[4];
1405unsigned int lo, hi;
1406bool par = false;
1407bool neg[4];
1408double all, big, two;
1409qa[0] = q.x(); qa[1] = q.y(); qa[2] = q.z(); qa[3] = q.w();
1410for (i=0; i<4; i++) {
1411pa[i] = 0.0;
1412neg[i] = (qa[i]<0.0);
1413if (neg[i]) qa[i] = -qa[i];
1414par ^= neg[i];
1415}
1416
1417/* Find two largest components, indices in hi and lo */
1418if (qa[0]>qa[1]) lo = 0;
1419else lo = 1;
1420
1421if (qa[2]>qa[3]) hi = 2;
1422else hi = 3;
1423
1424if (qa[lo]>qa[hi]) {
1425if (qa[lo^1]>qa[hi]) {
1426hi = lo; lo ^= 1;
1427}
1428else {
1429hi ^= lo; lo ^= hi; hi ^= lo;
1430}
1431}
1432else {
1433if (qa[hi^1]>qa[lo]) lo = hi^1;
1434}
1435
1436all = (qa[0]+qa[1]+qa[2]+qa[3])*0.5;
1437two = (qa[hi]+qa[lo])*SQRTHALF;
1438big = qa[hi];
1439if (all>two) {
1440if (all>big) {/*all*/
1441{int i; for (i=0; i<4; i++) pa[i] = sgn(neg[i], 0.5);}
1442cycle(ka,par);
1443}
1444else {/*big*/ pa[hi] = sgn(neg[hi],1.0);}
1445} else {
1446if (two>big) { /*two*/
1447pa[hi] = sgn(neg[hi],SQRTHALF);
1448pa[lo] = sgn(neg[lo], SQRTHALF);
1449if (lo>hi) {
1450hi ^= lo; lo ^= hi; hi ^= lo;
1451}
1452if (hi==W) {
1453hi = "\001\002\000"[lo];
1454lo = 3-hi-lo;
1455}
1456swap(ka,hi,lo);
1457}
1458else {/*big*/
1459pa[hi] = sgn(neg[hi],1.0);
1460}
1461}
1462p.x() = -pa[0]; p.y() = -pa[1]; p.z() = -pa[2]; p.w() = pa[3];
1463}
1464k->x() = ka[X]; k->y() = ka[Y]; k->z() = ka[Z];
1465return (p);
1466}
1467
1468/******* Decompose Affine Matrix *******/
1469
1470/* Decompose 4x4 affine matrix A as TFRUK(U transpose), where t contains the
1471* translation components, q contains the rotation R, u contains U, k contains
1472* scale factors, and f contains the sign of the determinant.
1473* Assumes A transforms column vectors in right-handed coordinates.
1474* See Ken Shoemake and Tom Duff. Matrix Animation and Polar Decomposition.
1475* Proceedings of Graphics Interface 1992.
1476*/
1477void decompAffine(_HMatrix A, _affineParts * parts)
1478{
1479_HMatrix Q, S, U;
1480ofQuaternion p;
1481
1482//Translation component.
1483parts->t = ofVec4f(A[X][W], A[Y][W], A[Z][W], 0);
1484double det = polarDecomp(A, Q, S);
1485if (det<0.0)
1486{
1487matrixCopy(Q, =, -Q, 3);
1488parts->f = -1;
1489}
1490else
1491parts->f = 1;
1492
1493parts->q = quatFromMatrix(Q);
1494parts->k = spectDecomp(S, U);
1495parts->u = quatFromMatrix(U);
1496p = snuggle(parts->u, &parts->k);
1497parts->u = Qt_Mul(parts->u, p);
1498}
1499
1500void ofMatrix4x4::decompose( ofVec3f& t,
1501ofQuaternion& r,
1502ofVec3f& s,
1503ofQuaternion& so ) const{
1504
1505_affineParts parts;
1506_HMatrix hmatrix;
1507
1508// Transpose copy of LTW
1509for ( int i =0; i<4; i++)
1510{
1511for ( int j=0; j<4; j++)
1512{
1513hmatrix[i][j] = (*this)(j,i);
1514}
1515}
1516
1517decompAffine(hmatrix, &parts);
1518
1519double mul = 1.0;
1520if (parts.t[W] != 0.0)
1521mul = 1.0 / parts.t[W];
1522
1523t.x = parts.t[X] * mul;
1524t.y = parts.t[Y] * mul;
1525t.z = parts.t[Z] * mul;
1526
1527r.set(parts.q.x(), parts.q.y(), parts.q.z(), parts.q.w());
1528
1529mul = 1.0;
1530if (parts.k.w() != 0.0)
1531mul = 1.0 / parts.k.w();
1532
1533// mul be sign of determinant to support negative scales.
1534mul *= parts.f;
1535s.x= parts.k.x() * mul;
1536s.y = parts.k.y() * mul;
1537s.z = parts.k.z() * mul;
1538
1539so.set(parts.u.x(), parts.u.y(), parts.u.z(), parts.u.w());
1540}
1541
1542#undef SET_ROW
1543
1544std::ostream& operator<<(std::ostream& os, const ofMatrix4x4& M) {
1545int w = 8;
1546os << std::setw(w)
1547<< M._mat[0][0] << ", " << std::setw(w)
1548<< M._mat[0][1] << ", " << std::setw(w)
1549<< M._mat[0][2] << ", " << std::setw(w)
1550<< M._mat[0][3] << std::endl;
1551
1552os << std::setw(w)
1553<< M._mat[1][0] << ", " << std::setw(w)
1554<< M._mat[1][1] << ", " << std::setw(w)
1555<< M._mat[1][2] << ", " << std::setw(w)
1556<< M._mat[1][3] << std::endl;
1557
1558os << std::setw(w)
1559<< M._mat[2][0] << ", " << std::setw(w)
1560<< M._mat[2][1] << ", " << std::setw(w)
1561<< M._mat[2][2] << ", " << std::setw(w)
1562<< M._mat[2][3] << std::endl;
1563
1564os << std::setw(w)
1565<< M._mat[3][0] << ", " << std::setw(w)
1566<< M._mat[3][1] << ", " << std::setw(w)
1567<< M._mat[3][2] << ", " << std::setw(w)
1568<< M._mat[3][3];
1569
1570return os;
1571}
1572
1573std::istream& operator>>(std::istream& is, ofMatrix4x4& M) {
1574is >> M._mat[0][0]; is.ignore(2);
1575is >> M._mat[0][1]; is.ignore(2);
1576is >> M._mat[0][2]; is.ignore(2);
1577is >> M._mat[0][3]; is.ignore(1);
1578
1579is >> M._mat[1][0]; is.ignore(2);
1580is >> M._mat[1][1]; is.ignore(2);
1581is >> M._mat[1][2]; is.ignore(2);
1582is >> M._mat[1][3]; is.ignore(1);
1583
1584is >> M._mat[2][0]; is.ignore(2);
1585is >> M._mat[2][1]; is.ignore(2);
1586is >> M._mat[2][2]; is.ignore(2);
1587is >> M._mat[2][3]; is.ignore(1);
1588
1589is >> M._mat[3][0]; is.ignore(2);
1590is >> M._mat[3][1]; is.ignore(2);
1591is >> M._mat[3][2]; is.ignore(2);
1592is >> M._mat[3][3];
1593return is;
1594}
1595