matrix.C

00001 /*
00002  * This file is part of the "Archon" framework.
00003  * (http://files3d.sourceforge.net)
00004  *
00005  * Copyright © 2002 by Kristian Spangsege and Brian Kristiansen.
00006  *
00007  * Permission to use, copy, modify, and distribute this software and
00008  * its documentation under the terms of the GNU General Public License is
00009  * hereby granted. No representations are made about the suitability of
00010  * this software for any purpose. It is provided "as is" without express
00011  * or implied warranty. See the GNU General Public License
00012  * (http://www.gnu.org/copyleft/gpl.html) for more details.
00013  *
00014  * The characters in this file are ISO8859-1 encoded.
00015  *
00016  * The documentation in this file is in "Doxygen" style
00017  * (http://www.doxygen.org).
00018  */
00019 
00020 #include <archon/math/matrix.H>
00021 
00022 namespace Archon
00023 {
00024   namespace Math
00025   {
00026     Matrix3x3 Matrix3x3::makeZero()
00027     {
00028       return Matrix3x3(Vector3::zero(), Vector3::zero(), Vector3::zero());
00029     }
00030 
00031     Matrix3x3 Matrix3x3::makeIdentity()
00032     {
00033        return Matrix3x3(Vector3(1, 0, 0), Vector3(0, 1, 0), Vector3(0, 0, 1));
00034     }
00035 
00036     const Matrix3x3 &Matrix3x3::zero()
00037     {
00038       static Matrix3x3 v = makeZero();
00039       return v;
00040     }
00041 
00042     const Matrix3x3 &Matrix3x3::identity()
00043     {
00044       static Matrix3x3 v = makeIdentity();
00045       return v;
00046     }
00047 
00048     /*
00049      * The rotation matrix may be calculated by the following formula:
00050      *
00051      *                                             [ 0 -z  y ]
00052      *   (cos v) I + (1 - cos v) A * A^T + (sin v) [ z  0 -x ]
00053      *                                             [-y  x  0 ]
00054      *
00055      * where v is the angle, A is the axis and x, y and z are the
00056      * scalar components of the axis. Think of the last matrix as
00057      * describing the relationship between the standard coordinate
00058      * axes of a right handed orthogonal coordinate system. In fact
00059      * the last matrix expresses the cross-product with the axis of
00060      * rotation.
00061      *
00062      * In 2-D this would look like:
00063      *
00064      *                                       [ 0 -1 ]
00065      *   (cos v) I + (1 - cos v) 0 + (sin v) [      ]
00066      *                                       [ 1  0 ]
00067      *
00068      * That is, the 3rd term vanishes and the last matrix now
00069      * expresses the concept of "perpendicular vector".
00070      *
00071      * This is easily seen by setting the axis to [ 0 0 1 ]^T and then
00072      * discarding the 3rd dimention.
00073      *
00074      * In 4-D we should compute the double-axis (or plane) rotation
00075      * matrix. But how does the last matrix look in 4-D? Somehow it
00076      * ought to reflect the generalization of the right hand rule
00077      * (RHR) in 4-D. Again we should expect that when inserting [ 0 0
00078      * 0 1 ]^T for the second axis and discarding the 4th dimention,
00079      * we should end up with the 3-D formula above.
00080      */
00081     void Matrix3x3::setRotation(const Rotation3 &r)
00082     {
00083       const double ca = cos(r.angle);
00084       const double sa = sin(r.angle);
00085 
00086       const double cx = (1 - ca) * r.axis[0];
00087       const double cy = (1 - ca) * r.axis[1];
00088       const double cz = (1 - ca) * r.axis[2];
00089 
00090       const double cxy = cx * r.axis[1];
00091       const double cyz = cy * r.axis[2];
00092       const double czx = cz * r.axis[0];
00093 
00094       const double sx = r.axis[0] * sa;
00095       const double sy = r.axis[1] * sa;
00096       const double sz = r.axis[2] * sa;
00097 
00098       x.set(ca + cx * r.axis[0], cxy + sz, czx - sy);
00099       y.set(cxy - sz, ca + cy * r.axis[1], cyz + sx);
00100       z.set(czx + sy, cyz - sx, ca + cz * r.axis[2]);
00101     }
00102 
00103     void Matrix3x3::setRotation(const Quaternion &q)
00104     {
00105       double xx = q.v[0] * q.v[0];
00106       double xy = q.v[0] * q.v[1];
00107       double xz = q.v[0] * q.v[2];
00108       double xw = q.v[0] * q.w;
00109 
00110       double yy = q.v[1] * q.v[1];
00111       double yz = q.v[1] * q.v[2];
00112       double yw = q.v[1] * q.w;
00113 
00114       double zz = q.v[2] * q.v[2];
00115       double zw = q.v[2] * q.w;
00116 
00117       x[0] = 1 - 2 * (yy + zz);
00118       y[0] =     2 * (xy - zw);
00119       z[0] =     2 * (xz + yw);
00120 
00121       x[1] =     2 * (xy + zw);
00122       y[1] = 1 - 2 * (xx + zz);
00123       z[1] =     2 * (yz - xw);
00124 
00125       x[2] =     2 * (xz - yw);
00126       y[2] =     2 * (yz + xw);
00127       z[2] = 1 - 2 * (xx + yy);
00128     }
00129 
00130     void Matrix3x3::setInverseOf(const Matrix3x3 &m)
00131     {
00132       x[0] = m.y[1] * m.z[2] - m.z[1] * m.y[2];
00133       y[0] = m.y[2] * m.z[0] - m.y[0] * m.z[2];
00134       z[0] = m.y[0] * m.z[1] - m.y[1] * m.z[0];
00135       x[1] = m.z[1] * m.x[2] - m.x[1] * m.z[2];
00136       y[1] = m.x[0] * m.z[2] - m.x[2] * m.z[0];
00137       z[1] = m.x[1] * m.z[0] - m.x[0] * m.z[1];
00138       x[2] = m.x[1] * m.y[2] - m.x[2] * m.y[1];
00139       y[2] = m.x[2] * m.y[0] - m.x[0] * m.y[2];
00140       z[2] = m.x[0] * m.y[1] - m.y[0] * m.x[1];
00141 
00142       operator/=(m.det());
00143     }
00144 
00145     std::ostream &operator<<(std::ostream &out, const Matrix3x3 &m)
00146     {
00147       out << m.getRow1() <<  "\n";
00148       out << m.getRow2() <<  "\n";
00149       out << m.getRow3() <<  "\n";
00150       return out;
00151     }
00152 
00153     void Matrix3x3::rotate(const Rotation3 &r)
00154     {
00155       operator*=(Matrix3x3(r));
00156     }
00157 
00161     void Matrix3x3::pitch(double angle)
00162     {
00163       rotate(Rotation3(Vector3(1, 0, 0), angle));
00164     }
00165 
00169     void Matrix3x3::yaw(double angle)
00170     {
00171       rotate(Rotation3(Vector3(0, 1, 0), angle));
00172     }
00173 
00177     void Matrix3x3::roll(double angle)
00178     {
00179       rotate(Rotation3(Vector3(0, 0, 1), angle));
00180     }
00181 
00190     void Matrix3x3::rotateRightHandedOrthoNormal(const Rotation3 &r)
00191     {
00192       Matrix3x3 m(r); m.map(x); m.map(y); x.normalize(); z = x; z *= y; z.normalize(); y = z; y *= x;
00193     }
00194 
00203     void Matrix3x3::pitchRightHandedOrthoNormal(double angle)
00204     {
00205       const Matrix3x3 m(Rotation3(x, angle));
00206       m.map(y);
00207       z = x;
00208       z *= y;
00209       z.normalize();
00210       y = z;
00211       y *= x;
00212     }
00213 
00222     void Matrix3x3::yawRightHandedOrthoNormal(double angle)
00223     {
00224       const Matrix3x3 m(Rotation3(y, angle));
00225       m.map(z);
00226       x = y;
00227       x *= z;
00228       x.normalize();
00229       z = x;
00230       z *= y;
00231     }
00232 
00241     void Matrix3x3::rollRightHandedOrthoNormal(double angle)
00242     {
00243       const Matrix3x3 m(Rotation3(z, angle));
00244       m.map(x);
00245       y = z;
00246       y *= x;
00247       y.normalize();
00248       x = y;
00249       x *= z;
00250     }
00251   }
00252 }
00253 

Generated on Sun Jul 30 22:55:43 2006 for Archon by  doxygen 1.4.4