root/juggler/tags/1.0.5/Math/vjMatrix.cpp

Revision 7539, 24.1 kB (checked in by anonymous, 7 years ago)

This commit was manufactured by cvs2svn to create tag
'RELENG_1_0_5_RELEASE'.

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