root/juggler/branches/1.0/Math/vjMatrix.cpp

Revision 10845, 23.8 kB (checked in by patrickh, 6 years ago)

Move overloaded operators into the header so that they can actually
be used. Inlining them in the .cpp file wasn't terribly useful to
anyone.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /*************** <auto-copyright.pl BEGIN do not edit this line> **************
2  *
3  * VR Juggler is (C) Copyright 1998, 1999, 2000, 2001, 2002
4  *   by Iowa State University
5  *
6  * Original Authors:
7  *   Allen Bierbaum, Christopher Just,
8  *   Patrick Hartling, Kevin Meinert,
9  *   Carolina Cruz-Neira, Albert Baker
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Library General Public
13  * License as published by the Free Software Foundation; either
14  * version 2 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Library General Public License for more details.
20  *
21  * You should have received a copy of the GNU Library General Public
22  * License along with this library; if not, write to the
23  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24  * Boston, MA 02111-1307, USA.
25  *
26  * -----------------------------------------------------------------
27  * File:          $RCSfile$
28  * Date modified: $Date$
29  * Version:       $Revision$
30  * -----------------------------------------------------------------
31  *
32  *************** <auto-copyright.pl END do not edit this line> ***************/
33
34
35 #include <vjConfig.h>
36
37 #include <Kernel/vjAssert.h>
38 #include <Math/vjMatrix.h>
39 #include <Math/vjVec3.h>
40 #include <Math/vjCoord.h>
41 #include <Math/vjQuat.h>
42
43 // Clamps an angle that is a cos or sin value [-1,1]
44 static inline void limitAngle(float& angle)
45 {
46    if(angle > 1.0f)
47       angle = 1.0f;
48    else if(angle < -1.0f)
49       angle = -1.0f;
50 }
51
52 // Clamp an angle to zero if it is close
53 static inline void zeroClampAngle(float& angle)
54 {
55    if(fabs(angle) < 1e-6)
56       angle = 0.0f;
57 }
58
59 vjMatrix::vjMatrix(vjCoord coord)
60 {
61    makeXYZEuler(coord.orient[0], coord.orient[1], coord.orient[2]);
62    setTrans(coord.pos[0], coord.pos[1], coord.pos[2]);
63 }
64
65 void vjMatrix::makeXYZEuler(float xRot, float yRot, float zRot)
66 {
67    float sx = sin(VJ_DEG2RAD(xRot));  float cx = cos(VJ_DEG2RAD(xRot));
68    float sy = sin(VJ_DEG2RAD(yRot));  float cy = cos(VJ_DEG2RAD(yRot));
69    float sz = sin(VJ_DEG2RAD(zRot));  float cz = cos(VJ_DEG2RAD(zRot));
70
71    // Derived by simply multiplying out the matrices by hand
72    // X*Y*Z
73    mat[0][0] = cy*cz;              mat[1][0] = -cy*sz;              mat[2][0] = sy;      mat[3][0] = 0.0f;
74    mat[0][1] = sx*sy*cz + cx*sz;   mat[1][1] = -sx*sy*sz + cx*cz;   mat[2][1] = -sx*cy;  mat[3][1] = 0.0f;
75    mat[0][2] = -cx*sy*cz + sx*sz;  mat[1][2] = cx*sy*sz + sx*cz;    mat[2][2] = cx*cy;   mat[3][2] = 0.0f;
76    mat[0][3] = 0.0f;               mat[1][3] = 0.0f;                mat[2][3] = 0.0f;    mat[3][3] = 1.0f;
77
78    zeroClamp();     // Clamp ~ zero values
79 }
80
81 void vjMatrix::getXYZEuler(float& xRot, float& yRot, float& zRot) const
82 {
83    float cz;
84
85    zRot = atan2f(-mat[1][0], mat[0][0]);     // -(-cy*sz)/(cy*cz) - cy falls out
86    xRot = atan2f(-mat[2][1], mat[2][2]);     // -(sx*cy)/(cx*cy) - cy falls out
87    cz = cos(zRot);
88    yRot = atan2f(mat[2][0], mat[0][0]/cz);   // (sy)/((cy*cz)/cz)
89
90    xRot = VJ_RAD2DEG(xRot);
91    yRot = VJ_RAD2DEG(yRot);
92    zRot = VJ_RAD2DEG(zRot);
93 }
94
95 // ------------------------------------------------------------------- //
96
97 void vjMatrix::makeZYXEuler(float zRot, float yRot, float xRot)
98 {
99    float sx = sin(VJ_DEG2RAD(xRot));  float cx = cos(VJ_DEG2RAD(xRot));
100    float sy = sin(VJ_DEG2RAD(yRot));  float cy = cos(VJ_DEG2RAD(yRot));
101    float sz = sin(VJ_DEG2RAD(zRot));  float cz = cos(VJ_DEG2RAD(zRot));
102
103    // Derived by simply multiplying out the matrices by hand
104    // Z*Y*Z
105    mat[0][0] = cy*cz;      mat[1][0] = -cx*sz + sx*sy*cz;   mat[2][0] = sx*sz + cx*sy*cz;    mat[3][0] = 0.0f;
106    mat[0][1] = cy*sz;      mat[1][1] = cx*cz + sx*sy*sz;    mat[2][1] = -sx*cz + cx*sy*sz;   mat[3][1] = 0.0f;
107    mat[0][2] = -sy;        mat[1][2] = sx*cy;               mat[2][2] = cx*cy;               mat[3][2] = 0.0f;
108    mat[0][3] = 0.0f;       mat[1][3] = 0.0f;                mat[2][3] = 0.0f;                mat[3][3] = 1.0f;
109
110    zeroClamp();     // Clamp ~ zero values
111 }
112
113 void vjMatrix::getZYXEuler(float& zRot, float& yRot, float& xRot) const
114 {
115    float sx;
116
117    zRot = atan2f(mat[0][1], mat[0][0]);      // (cy*sz)/(cy*cz) - cy falls out
118    xRot = atan2f(mat[1][2], mat[2][2]);      // (sx*cy)/(cx*cy) - cy falls out
119    sx = sinf(xRot);
120    yRot = atan2f(-mat[0][2],(mat[1][2]/sx) );   // -(-sy)/((sx*cy)/sx)
121
122    xRot = VJ_RAD2DEG(xRot);
123    yRot = VJ_RAD2DEG(yRot);
124    zRot = VJ_RAD2DEG(zRot);
125 }
126
127 // -------------------------------------------------------------- //
128
129 void vjMatrix::makeZXYEuler(float zRot, float xRot, float yRot)
130 {
131    float sx = sin(VJ_DEG2RAD(xRot));  float cx = cos(VJ_DEG2RAD(xRot));
132    float sy = sin(VJ_DEG2RAD(yRot));  float cy = cos(VJ_DEG2RAD(yRot));
133    float sz = sin(VJ_DEG2RAD(zRot));  float cz = cos(VJ_DEG2RAD(zRot));
134
135    // Derived by simply multiplying out the matrices by hand
136    // Z*X*Y
137    mat[0][0] = cy*cz - sx*sy*sz;    mat[1][0] = -cx*sz;     mat[2][0] = sy*cz + sx*cy*sz;    mat[3][0] = 0.0f;
138    mat[0][1] = cy*sz + sx*sy*cz;    mat[1][1] = cx*cz;      mat[2][1] = sy*sz - sx*cy*cz;    mat[3][1] = 0.0f;
139    mat[0][2] = -cx*sy;              mat[1][2] = sx;         mat[2][2] = cx*cy;               mat[3][2] = 0.0f;
140    mat[0][3] = 0.0f;                mat[1][3] = 0.0f;       mat[2][3] = 0.0f;               mat[3][3] = 1.0f;
141
142    zeroClamp();     // Clamp ~ zero values
143 }
144
145 //: extract the yaw information from the matrix
146 //  returned value is from -180 to 180, where 0 is none
147 // Rotation around Y axis
148 float vjMatrix::getYRot() const
149 {
150    const vjVec3 forwardPoint( 0, 0, -1 );       // -Z
151    const vjVec3 originPoint( 0, 0, 0 );
152    vjVec3 endPoint, startPoint;
153    endPoint.xformFull( *this, forwardPoint );
154    startPoint.xformFull( *this, originPoint );
155    vjVec3 directionVector = endPoint - startPoint;
156
157    // constrain the direction to x/z plane only
158    directionVector[VJ_Y] = 0.0f;                   // Eliminate Y value
159    directionVector.normalize();
160    float y_rot = VJ_RAD2DEG( acosf(directionVector.dot( forwardPoint )) );
161    vjVec3 whichSide = forwardPoint.cross(directionVector);
162    if (whichSide[VJ_Y] < 0.0f)   // If dir vector to "right" (negative) side of forward
163       y_rot = -y_rot;
164
165    return y_rot;
166 }
167
168 //: extract the pitch information from the matrix
169 //  returned value is from -180 to 180, where 0 none
170 // Rotation around X axis
171 float vjMatrix::getXRot() const
172 {
173    const vjVec3 forwardPoint( 0, 0, -1 );    // -Z
174    const vjVec3 originPoint( 0, 0, 0 );
175    vjVec3 endPoint, startPoint;
176    endPoint.xformFull( *this, forwardPoint );
177    startPoint.xformFull( *this, originPoint );
178    vjVec3 directionVector = endPoint - startPoint;
179
180    // constrain the direction to y/z plane only
181    directionVector[VJ_X] = 0.0f;                // Eliminate X value
182    directionVector.normalize();
183    float x_rot = VJ_RAD2DEG( acosf(directionVector.dot( forwardPoint )) );
184    vjVec3 whichSide = forwardPoint.cross(directionVector);
185    if (whichSide[VJ_X] < 0.0f)      // If dir vector to "bottom" (negative) side of forward
186       x_rot = -x_rot;
187
188    return x_rot;
189 }
190
191 //: extract the roll information from the matrix
192 //  returned value is from -180 to 180, where 0 is no roll
193 // Rotation around Z axis
194 float vjMatrix::getZRot() const
195 {
196    const vjVec3 up_point( 0, 1, 0 );          // straight up (+Y)
197    const vjVec3 origin_point( 0, 0, 0 );
198    vjVec3 end_point, start_point;
199    end_point.xformFull( *this, up_point );
200    start_point.xformFull( *this, origin_point );
201    vjVec3 direction_vector = end_point - start_point;
202
203    // constrain the direction to x/y plane only
204    direction_vector[VJ_Z] = 0.0f;                    // Eliminate Z component
205    direction_vector.normalize();
206    float z_rot = VJ_RAD2DEG( acosf(direction_vector.dot( up_point )) );
207    vjVec3 which_side = up_point.cross(direction_vector);
208    if (which_side[VJ_Z] < 0.0f)                          // If dirVec it to right (neg side) of up_point
209       z_rot = -z_rot;
210
211    return z_rot;
212 }
213
214 // constrain the matrix rotation to a certain axis or axes
215 // result returned is a constrained matrix.
216 void vjMatrix::_kevn_constrainRotAxis( const bool& usePitch, const bool& useYaw, const bool& useRoll, vjMatrix& result )
217 {
218    // temporary matrix
219    vjMatrix constrainedMatrix;
220
221    // Restrict the rotation to only the axis specified
222    float xRot, yRot, zRot;
223    vjVec3 xAxis( 1, 0, 0 ), yAxis( 0, 1, 0 ), zAxis( 0, 0, 1 );
224
225    // Add back the translation:
226    vjVec3 trans;
227    this->getTrans( trans[0],trans[1],trans[2] );
228    constrainedMatrix.makeTrans( trans[0],trans[1],trans[2] );
229
230    // Add back pure pitch
231    if (usePitch) // allow rotation about X
232    {
233       vjMatrix mx;
234       xRot = this->getPitch();
235       mx.makeRot( xRot, xAxis );
236       constrainedMatrix.preMult( mx );
237    }
238
239    // Add back pure yaw
240    if (useYaw) // allow rotation about Y
241    {
242       vjMatrix my;
243       yRot = this->getYaw();
244       my.makeRot( yRot, yAxis );
245       constrainedMatrix.postMult( my );
246    }
247
248    // Add back pure roll
249    if (useRoll) // allow rotation about Z
250    {
251       vjMatrix mz;
252       zRot = this->getRoll();
253       mz.makeRot( zRot, zAxis );
254       constrainedMatrix.preMult( mz );
255    }
256
257    result.copy( constrainedMatrix );
258 }
259
260 // constrain the matrix rotation to a certain axis or axes
261 // result returned is a constrained matrix.
262 void vjMatrix::constrainRotAxis( const bool& allowXRot, const bool& allowYRot, const bool& allowZRot, vjMatrix& result )
263 {
264    // temporary matrix
265    vjMatrix constrainedMatrix;
266    constrainedMatrix = *this;
267    //vjMatrix inv_mat;
268
269    // Restrict the rotation to only the axis specified
270    float xRot, yRot, zRot;
271    //vjVec3 xAxis( 1, 0, 0 ), yAxis( 0, 1, 0 ), zAxis( 0, 0, 1 );
272
273    // Add back the translation:
274    /*
275    vjVec3 trans;
276    this->getTrans( trans[0],trans[1],trans[2] );
277    constrainedMatrix.makeTrans( trans[0],trans[1],trans[2] );
278    */
279
280    //_kevn_constrainRotAxis(allowXRot,allowYRot,allowZRot,constrainedMatrix);
281
282    ///*
283    this->getXYZEuler(xRot,yRot,zRot);
284    constrainedMatrix.makeXYZEuler(((allowXRot)?xRot:0.0f),((allowYRot)?yRot:0.0f),((allowZRot)?zRot:0.0f));
285    //*/
286
287
288    // Add back pure pitch
289    if (!allowXRot) // do not allow rotation about X
290    {
291       /*
292       vjMatrix mx;
293       xRot = constrainedMatrix.getXRot();
294       mx.makeRot( xRot, xAxis );
295       inv_mat.invert(mx);
296       constrainedMatrix.preMult( inv_mat );
297       */
298       /*
299       vjMatrix mx,mxInv;
300       constrainedMatrix.getXYZEuler(xRot,yRot,zRot);
301       mx.makeRot(xRot,xAxis);
302       mxInv.invert(mx);
303       constrainedMatrix.preMult(mxInv);                // Now we don't have X???
304       */
305    }
306
307    // Add back pure yaw
308    if (!allowYRot) // do not allow rotation about Y
309    {
310       /*
311       vjMatrix my;
312       yRot = constrainedMatrix.getYRot();
313       my.makeRot( yRot, yAxis );
314       inv_mat.invert(my);
315       constrainedMatrix.preMult( inv_mat );
316       */
317       /*
318       vjMatrix my,myInv;
319       constrainedMatrix.getZXYEuler(zRot,xRot,yRot);
320       my.makeRot(yRot,yAxis);
321       myInv.invert(my);
322       constrainedMatrix.postMult(myInv);                // Now we don't have Y???
323       */
324    }
325
326    // Add back pure roll
327    if (!allowZRot) // do not allow rotation about Z
328    {
329       /*
330       vjMatrix mz;
331       zRot = constrainedMatrix.getZRot();
332       mz.makeRot( zRot, zAxis );
333       inv_mat.invert(mz);
334       constrainedMatrix.preMult( inv_mat );
335       */
336       /*
337       vjMatrix mz,mzInv;
338       constrainedMatrix.getZYXEuler(zRot,yRot,xRot);
339       mz.makeRot(zRot,zAxis);
340       mzInv.invert(mz);
341       constrainedMatrix.preMult(mzInv);                // Now we don't have Z???
342       */
343    }
344
345    result = constrainedMatrix;
346 }
347
348 void vjMatrix::getZXYEuler(float& zRot, float& xRot, float& yRot) const
349 {
350    // Extract the rotation directly fromt he matrix
351    float x_angle;
352    float y_angle;
353    float z_angle;
354    float cos_y, sin_y;
355    float cos_x, sin_x;
356    float cos_z, sin_z;
357
358    sin_x = mat[1][2];
359    x_angle = asinf(sin_x);     // Get x angle
360    cos_x = cos(x_angle);
361    zeroClampAngle(cos_x);          // Clamp it to get a good test
362
363    // Check if cos_x = Zero
364    if(cos_x != 0.0f)     // ASSERT: cos_x != 0
365    {
366          // Get y Angle
367       cos_y = mat[2][2]/cos_x;
368       sin_y = -mat[0][2]/cos_x;
369       y_angle = atan2(cos_y, sin_y);
370
371          // Get z Angle
372       cos_z = mat[1][1]/cos_x;
373       sin_z = -mat[1][0]/cos_x;
374       z_angle = atan2(cos_z, sin_z);
375    }
376    else
377    {
378       // Arbitrarily set z_angle = 0
379       z_angle = 0;
380
381          // Get y Angle
382       cos_y = mat[0][0];
383       sin_y = mat[0][1];
384       y_angle = atan2(cos_y, sin_y);
385    }
386
387    xRot = VJ_RAD2DEG(x_angle);
388    yRot = VJ_RAD2DEG(y_angle);
389    zRot = VJ_RAD2DEG(z_angle);
390 }
391
392 // --------------------------------------------------------------------------- //
393
394 void vjMatrix::makeDirCos(vjVec3 secXAxis, vjVec3 secYAxis, vjVec3 secZAxis)
395 {
396    vjASSERT(secXAxis.isNormalized());
397    vjASSERT(secYAxis.isNormalized());
398    vjASSERT(secZAxis.isNormalized());
399
400    float Xa, Xb, Xy;    // Direction cosines of the secondary x-axis
401    float Ya, Yb, Yy;    // Direction cosines of the secondary y-axis
402    float Za, Zb, Zy;    // Direction cosines of the secondary z-axis
403
404    vjVec3 xAxis(1,0,0), yAxis(0,1,0), zAxis(0,0,1);   // The base axis to use
405
406    Xa = secXAxis.dot(xAxis);  Xb = secXAxis.dot(yAxis);  Xy = secXAxis.dot(zAxis);
407    Ya = secYAxis.dot(xAxis);  Yb = secYAxis.dot(yAxis);  Yy = secYAxis.dot(zAxis);
408    Za = secZAxis.dot(xAxis);  Zb = secZAxis.dot(yAxis);  Zy = secZAxis.dot(zAxis);
409
410    // Set the matrix correctly
411    set(Xa, Xb, Xy, 0,
412        Ya, Yb, Yy, 0,
413        Za, Zb, Zy, 0,
414        0,  0,  0, 1);
415 }
416
417 // From Watt & Watt
418 void    vjMatrix::makeQuaternion( const float* const q )
419 {
420    /*
421    // A piece of reference code for checking against...
422    const int W = VJ_W;
423    const int X = VJ_X;
424    const int Y = VJ_Y;
425    const int Z = VJ_Z;
426    const float* const quat = q;
427
428    mat[0][0]  = 1.0f  - 2.0f * (quat[Y] * quat[Y] + quat[Z] * quat[Z]);
429    mat[0][1]  = 2.0f         * (quat[X] * quat[Y] + quat[W] * quat[Z]);
430    mat[0][2]  = 2.0f         * (quat[X] * quat[Z] - quat[W] * quat[Y]);
431    mat[0][3]  = 0.0f;
432
433    mat[1][0]  = 2.0f         * (quat[X] * quat[Y] - quat[W] * quat[Z]);
434    mat[1][1]  = 1.0f  - 2.0f * (quat[X] * quat[X] + quat[Z] * quat[Z]);
435    mat[1][2]  = 2.0f         * (quat[Y] * quat[Z] + quat[W] * quat[X]);
436    mat[1][3]  = 0.0f;
437
438    mat[2][0]  = 2.0f         * (quat[X] * quat[Z] + quat[W] * quat[Y]);
439    mat[2][1]  = 2.0f         * (quat[Y] * quat[Z] - quat[W] * quat[X]);
440    mat[2][2] = 1.0f  - 2.0f * (quat[X] * quat[X] + quat[Y] * quat[Y]);
441    mat[2][3] = 0.0f;
442
443    mat[3][0] = 0;
444    mat[3][1] = 0;
445    mat[3][2] = 0;
446    mat[3][3] = 1.0f;
447    */
448
449
450    float wx, wy, wz, xx, yy, yz, xy, xz, zz, xs, ys, zs;
451    //float s;
452
453    //s = 2.0f/(q[VJ_X]*q[VJ_X] + q[VJ_Y]*q[VJ_Y] + q[VJ_Z]*q[VJ_Z] + q[VJ_W]*q[VJ_W]);
454
455    xs = q[VJ_X] + q[VJ_X]; ys = q[VJ_Y] + q[VJ_Y]; zs = q[VJ_Z] + q[VJ_Z];
456    xx = q[VJ_X] * xs;      xy = q[VJ_X] * ys;      xz = q[VJ_X] * zs;
457    yy = q[VJ_Y] * ys;      yz = q[VJ_Y] * zs;      zz = q[VJ_Z] * zs;
458    wx = q[VJ_W] * xs;      wy = q[VJ_W] * ys;      wz = q[VJ_W] * zs;
459
460    mat[0][0] = 1.0 - (yy+zz);
461     mat[0][1] = xy+wz;
462     mat[0][2] = xz-wy;
463     mat[0][3] = 0.0;
464
465     mat[1][0] = xy-wz;
466     mat[1][1] = 1.0 - (xx+zz);
467     mat[1][2] = yz+wx;
468     mat[1][3] = 0.0;
469
470     mat[2][0] = xz+wy;
471     mat[2][1] = yz-wx;
472     mat[2][2] = 1.0 - (xx+yy);
473     mat[2][3] = 0.0;
474
475     mat[3][0] = 0.0;
476     mat[3][1] = 0.0;
477     mat[3][2] = 0.0;
478     mat[3][3] = 1.0;
479 }
480
481 void vjMatrix::makeQuaternion( const vjQuat& q )
482 {
483    makeQuaternion(q.vec);
484 }
485
486 void  vjMatrix::makeRot(float _degrees, vjVec3 _axis)
487 {
488     _axis.normalize();  // NOTE: This could be eliminated by passing normalized
489              //       vector.  This could be by ref to make even faster
490     // GGI: pg 466
491     float s = sin(VJ_DEG2RAD(_degrees));
492     float c = cos(VJ_DEG2RAD(_degrees));
493     float t = 1-c;
494     float x = _axis[0];
495     float y = _axis[1];
496     float z = _axis[2];
497
498     /*
499     mat[0][0] = (t*x*x)+c;     mat[1][0] = (t*x*y)+(s*z); mat[2][0] = (t*x*z)-(s*y); mat[3][0] = 0.0f;
500     mat[0][1] = (t*x*y)-(s*z); mat[1][1] = (t*y*y)+c;     mat[2][1] = (t*y*z)+(s*x); mat[3][1] = 0.0f;
501     mat[0][2] = (t*x*z)+(s*y); mat[1][2] = (t*y*z)-(s*x); mat[2][2] = (t*z*z)+c;     mat[3][2] = 0.0f;
502     mat[0][3] = 0.0f;          mat[1][3] = 0.0f;          mat[2][3] = 0.0f;          mat[3][3] = 1.0f;
503     */
504
505     /* From: Introduction to robotic.  Craig.  Pg. 52 */
506     mat[0][0] = (t*x*x)+c;     mat[1][0] = (t*x*y)-(s*z); mat[2][0] = (t*x*z)+(s*y); mat[3][0] = 0.0f;
507     mat[0][1] = (t*x*y)+(s*z); mat[1][1] = (t*y*y)+c;     mat[2][1] = (t*y*z)-(s*x); mat[3][1] = 0.0f;
508     mat[0][2] = (t*x*z)-(s*y); mat[1][2] = (t*y*z)+(s*x); mat[2][2] = (t*z*z)+c;     mat[3][2] = 0.0f;
509     mat[0][3] = 0.0f;          mat[1][3] = 0.0f;          mat[2][3] = 0.0f;          mat[3][3] = 1.0f;
510          
511     zeroClamp();     // Clamp ~ zero values
512 }
513
514 void  vjMatrix::makeTrans(float _x, float _y, float _z)
515 {
516    makeIdent();
517    mat[3][0] = _x;
518    mat[3][1] = _y;
519    mat[3][2] = _z;
520 }
521
522 void vjMatrix::makeTrans(const vjVec3& trans)
523 { makeTrans(trans[0],trans[1],trans[2]); }
524
525 void vjMatrix::setTrans(float _x, float _y, float _z)
526 {
527    mat[3][0] = _x;
528    mat[3][1] = _y;
529    mat[3][2] = _z;
530 }
531
532 void vjMatrix::setTrans(const vjVec3& trans)
533 { setTrans(trans[0],trans[1],trans[2]); }
534
535
536 void vjMatrix::getTrans(float& _x, float& _y, float& _z) const
537 {
538    _x = mat[3][0];
539    _y = mat[3][1];
540    _z = mat[3][2];
541 }
542
543 vjVec3 vjMatrix::getTrans() const
544 {
545    vjVec3 trans;;
546    getTrans(trans[0],trans[1],trans[2]);
547    return trans;
548 }
549
550 void  vjMatrix::makeScale(float _x, float _y, float _z)
551 {
552     makeIdent();
553     mat[0][0] = _x;
554     mat[1][1] = _y;
555     mat[2][2] = _z;
556 }
557
558 void vjMatrix::preTrans(float _x, float _y, float _z, vjMatrix&  _m)
559 {
560     vjMatrix transMat;
561     transMat.makeTrans(_x, _y, _z);
562     transMat.postMult(_m);
563     *this = transMat;
564 }
565
566 //: Pre translate a matrix
567 //!POST: mat' = trans(_x,_y,_z) * _m
568 void vjMatrix::preTrans(vjVec3& _trans, vjMatrix&  _m)
569 { preTrans(_trans.vec[0], _trans.vec[1], _trans.vec[2], _m); }
570
571
572     /// mat = _m * trans(_x,_y,_z)
573 void vjMatrix::postTrans(const vjMatrix&  _m, float _x, float _y, float _z)
574 {
575     vjMatrix transMat;
576     transMat.makeTrans(_x, _y, _z);
577     transMat.preMult(_m);
578     *this = transMat;
579 }
580
581 //!POST: mat' = _m * trans(_x,_y,_z)
582 void vjMatrix::postTrans(const vjMatrix&  _m, vjVec3& _trans)
583 { postTrans(_m, _trans.vec[0], _trans.vec[1], _trans.vec[2]); }
584
585 void vjMatrix::preRot(const float& _degrees, const vjVec3& axis, vjMatrix&  _m)
586 {
587     vjMatrix rotMat;
588     rotMat.makeRot(_degrees, axis);
589     rotMat.postMult(_m);
590     *this = rotMat;
591 }
592
593 void vjMatrix::postRot(const vjMatrix&  _m, const float& _degrees, const vjVec3& axis)
594 {
595     vjMatrix rotMat;
596     rotMat.makeRot(_degrees, axis);
597     rotMat.preMult(_m);
598     *this = rotMat;
599 }
600
601 void vjMatrix::preXYZEuler(float x, float y, float z, vjMatrix& _m)
602 {
603     vjMatrix rotMat;
604     rotMat.makeXYZEuler(x, y, z);
605     rotMat.postMult(_m);
606     *this = rotMat;
607 }
608
609 void vjMatrix::postXYZEuler(vjMatrix& _m, float x, float y, float z)
610 {
611     vjMatrix rotMat;
612     rotMat.makeXYZEuler(x, y, z);
613     rotMat.preMult(_m);
614     *this = rotMat;
615 }
616
617     /// mat = scale(_xs,_ys,_zs) * _m;
618 void vjMatrix::preScale(float _xs, float _ys, float _zs, vjMatrix&  _m)
619 {
620     vjMatrix scaleMat;
621     scaleMat.makeScale(_xs, _ys, _zs);
622     scaleMat.postMult(_m);
623     *this = scaleMat;
624 }
625     /// mat = _m * scale(_xs,_ys,_zs)
626 void vjMatrix::postScale(const vjMatrix&  _m, float _xs, float _ys, float _zs)
627 {
628     vjMatrix scaleMat;
629     scaleMat.makeScale(_xs, _ys, _zs);
630     scaleMat.preMult(_m);
631     *this = scaleMat;
632 }
633
634     // Matrix Multiplication of A:(nxl) B:(lxm) ==> C:(nxm)
635     //   Cij = Sum(k=1,l) (Aik)(Bkj)
636     /// mat = mat * m
637     // NOTE: All accesses in the function are using the C/C++ indexing method
638 void vjMatrix::postMult(const vjMatrix&  _m)
639 {
640     vjMatrix prevMat = *this;     // May be sloooow!!!
641     zero();
642
643     for(int i=0;i<4;i++)
644    for(int j=0;j<4;j++)
645        for(int k=0;k<4;k++)
646       mat[j][i] += ( prevMat.mat[k][i] * _m.mat[j][k]);
647 }
648
649     // mat = m * mat
650 void vjMatrix::preMult(const vjMatrix&  _m)
651 {
652     vjMatrix prevMat = *this;     // May be sloooow!!!
653     zero();
654
655     for(int i=0;i<4;i++)
656    for(int j=0;j<4;j++)
657        for(int k=0;k<4;k++)
658       mat[i][j] += ( prevMat.mat[i][k] * _m.mat[k][j]);;
659 }
660
661
662 /*---------------------------------------------------------------------------*
663  | mat_inv: Compute the inverse of a n x n matrix, using the maximum pivot   |
664  |          strategy.  n <= MAX1.                                            |
665  *---------------------------------------------------------------------------*
666
667    Parameters:
668        a        a n x n square matrix
669        b        inverse of input a.
670        n        dimenstion of matrix a.
671 */
672 //void mat_inv( a, b, n )
673 //double  a[], b[];
674 //int     n;
675
676     /// Set mat = inverse(_m)
677 int vjMatrix::invert(vjMatrix& _m)
678
679 {
680         float*  a = _m.getFloatPtr();
681    float*  b = getFloatPtr();
682
683    int   n = 4;
684    //int      is, js;      // Was never referenced
685    int     i, j, k;
686         int     r[ 4], c[ 4], row[ 4], col[ 4];
687         float  m[ 4][ 4*2], pivot, max_m, tmp_m, fac;
688
689
690         /* Initialization */
691         for ( i = 0; i < n; i ++ )
692         {
693                 r[ i] = c[ i] = 0;
694                 row[ i] = col[ i] = 0;
695         }
696
697         /* Set working matrix */
698         for ( i = 0; i < n; i++ )
699         {
700                 for ( j = 0; j < n; j++ )
701                 {
702                         m[ i][ j] = a[ i * n + j];
703                         m[ i][ j + n] = ( i == j ) ? 1.0 : 0.0 ;
704                 }
705         }
706
707         /* Begin of loop */
708         for ( k = 0; k < n; k++ )
709         {
710                 /* Choosing the pivot */
711                 for ( i = 0, max_m = 0; i < n; i++ )
712                 {
713                         if ( row[ i]  )      continue;
714                         for ( j = 0; j < n; j++ )
715                         {
716                                 if ( col[ j] )          continue;
717                                 tmp_m = fabs( m[ i][ j]);
718                                 if ( tmp_m > max_m)
719                                 {
720                                         max_m = tmp_m;
721                                         r[ k] = i;
722                                         c[ k] = j;
723                                 }
724                         }
725                 }
726                 row[ r[k] ] = col[ c[k] ] = 1;
727                 pivot = m[ r[ k] ][ c[ k] ];
728
729
730                 if ( fabs( pivot) <= 1e-20)
731                 {
732                         std::cerr << "*** pivot = %f in mat_inv. ***\n";
733                         //exit( 0);
734          return -1;
735                 }
736
737                 /* Normalization */
738                 for ( j = 0; j < 2*n; j++ )
739                 {
740                         if ( j == c[ k] )
741                                 m[ r[ k]][ j] = 1.0;
742                         else
743                                 m[ r[ k]][ j] /= pivot;
744                 }
745
746                 /* Reduction */
747                 for ( i = 0; i < n; i++ )
748                 {
749                         if ( i == r[ k] )
750                                 continue;
751
752                         for ( j=0, fac = m[ i][ c[k]]; j < 2*n; j++ )
753                         {
754                                 if ( j == c[ k] )
755                                         m[ i][ j] = 0.0;
756                                 else
757                                         m[ i][ j] -= fac * m[ r[k]][ j];
758                         }
759                 }
760         }
761
762         /* Assign invers to a matrix */
763         for ( i = 0; i < n; i++ )
764                 for ( j = 0; j < n; j++ )
765                         row[ i] = ( c[ j] == i ) ? r[ j] : row[ i];
766
767         for ( i = 0; i < n; i++ )
768                 for ( j = 0; j < n; j++ )
769                         b[ i * n +  j] = m[ row[ i]][ j + n];
770
771    return 1;   // It worked
772 }
773
774    // ---- FRIEND FUNCTIONS ---- //
775 std::ostream& operator<<(std::ostream& out, vjMatrix& _mat)
776 {
777    for(int j=0;j<4;j++)
778    {
779       for(int i=0;i<4;i++)
780          out << _mat.mat[i][j] << " ";
781       out << std::endl;
782    }
783
784    return out;
785 }
786
Note: See TracBrowser for help on using the browser.