_Matrix4.cc

Go to the documentation of this file.
00001 #include <vecmath/Export>
00002 
00003 #include <vecmath/_Matrix4.h>
00004 #include <vecmath/GMatrix.h>
00005 
00006 const double Math::PI = M_PI;
00007 const double Math::MAXDOUBLE = DBL_MAX;
00008 const double Math::MINDOUBLE = DBL_MIN;
00009 const double Math::EPSILON = 1.0e-12;
00010 
00011 
00012 template <class Type>
00013 void _Matrix4<Type>::add(Type d, const _Matrix4<Type>& m)
00014 {
00015     set(m.m00 + d, m.m01 + d, m.m02 + d, m.m03 + d,
00016         m.m10 + d, m.m11 + d, m.m12 + d, m.m13 + d,
00017         m.m20 + d, m.m21 + d, m.m22 + d, m.m23 + d,
00018         m.m30 + d, m.m31 + d, m.m32 + d, m.m33 + d);
00019 }
00020 
00021 template <class Type>
00022 void _Matrix4<Type>::add(const _Matrix4<Type>& m1, const _Matrix4<Type>& m2)
00023 {
00024     set(m1.m00 + m2.m00, m1.m01 + m2.m01, m1.m02 + m2.m02, m1.m03 + m2.m03,
00025         m1.m10 + m2.m10, m1.m11 + m2.m11, m1.m12 + m2.m12, m1.m13 + m2.m13,
00026         m1.m20 + m2.m20, m1.m21 + m2.m21, m1.m22 + m2.m22, m1.m23 + m2.m23,
00027         m1.m30 + m2.m30, m1.m31 + m2.m31, m1.m32 + m2.m32, m1.m33 + m2.m33);
00028 }
00029 
00030 template <class Type>
00031 void _Matrix4<Type>::adjoint(const _Matrix4<Type>& m)
00032 {
00033     Type d = m.determinant();
00034     //cerr << "Deter " << d << endl << m <<  endl;
00035 
00036     Type t[4][4];
00037 
00038     t[0][0]=  _Matrix3<Type>::determinant3x3(m.m11, m.m12, m.m13,
00039                                              m.m21, m.m22, m.m23,
00040                                              m.m31, m.m32, m.m33) / d;
00041     t[1][0]= -_Matrix3<Type>::determinant3x3(m.m10, m.m12, m.m13,
00042                                              m.m20, m.m22, m.m23,
00043                                              m.m30, m.m32, m.m33) / d;
00044     t[2][0]=  _Matrix3<Type>::determinant3x3(m.m10, m.m11, m.m13,
00045                                              m.m20, m.m21, m.m23,
00046                                              m.m30, m.m31, m.m33) / d;
00047     t[3][0]= -_Matrix3<Type>::determinant3x3(m.m10, m.m11, m.m12,
00048                                              m.m20, m.m21, m.m22,
00049                                              m.m30, m.m31, m.m32) / d;
00050 
00051     // ***
00052     t[0][1]= -_Matrix3<Type>::determinant3x3(m.m01, m.m02, m.m03,
00053                                              m.m21, m.m22, m.m23,
00054                                              m.m31, m.m32, m.m33) / d;
00055     t[1][1]=  _Matrix3<Type>::determinant3x3(m.m00, m.m02, m.m03,
00056                                              m.m20, m.m22, m.m23,
00057                                              m.m30, m.m32, m.m33) / d;
00058     t[2][1]= -_Matrix3<Type>::determinant3x3(m.m00, m.m01, m.m03,
00059                                              m.m20, m.m21, m.m23,
00060                                              m.m30, m.m31, m.m33) / d;
00061     t[3][1]=  _Matrix3<Type>::determinant3x3(m.m00, m.m01, m.m02,
00062                                              m.m20, m.m21, m.m22,
00063                                              m.m30, m.m31, m.m32) / d;
00064 
00065     // ***
00066     t[0][2]=  _Matrix3<Type>::determinant3x3(m.m01, m.m02, m.m03,
00067                                              m.m11, m.m12, m.m13,
00068                                              m.m31, m.m32, m.m33) / d;
00069     t[1][2]= -_Matrix3<Type>::determinant3x3(m.m00, m.m02, m.m03,
00070                                              m.m10, m.m12, m.m13,
00071                                              m.m30, m.m32, m.m33) / d;
00072     t[2][2]=  _Matrix3<Type>::determinant3x3(m.m00, m.m01, m.m03,
00073                                              m.m10, m.m11, m.m13,
00074                                              m.m30, m.m31, m.m33) / d;
00075     t[3][2]= -_Matrix3<Type>::determinant3x3(m.m00, m.m01, m.m02,
00076                                              m.m10, m.m11, m.m12,
00077                                              m.m30, m.m31, m.m32) / d;
00078 
00079     // ***
00080     t[0][3]= -_Matrix3<Type>::determinant3x3(m.m01, m.m02, m.m03,
00081                                              m.m11, m.m12, m.m13,
00082                                              m.m21, m.m22, m.m23) / d;
00083     t[1][3]=  _Matrix3<Type>::determinant3x3(m.m00, m.m02, m.m03,
00084                                              m.m10, m.m12, m.m13,
00085                                              m.m20, m.m22, m.m23) / d;
00086     t[2][3]= -_Matrix3<Type>::determinant3x3(m.m00, m.m01, m.m03,
00087                                              m.m10, m.m11, m.m13,
00088                                              m.m20, m.m21, m.m23) / d;
00089     t[3][3]=  _Matrix3<Type>::determinant3x3(m.m00, m.m01, m.m02,
00090                                              m.m10, m.m11, m.m12,
00091                                              m.m20, m.m21, m.m22) / d;
00092 
00093     set((Type*)t);
00094 }
00095 
00096 
00097 template <class Type>
00098 bool _Matrix4<Type>::epsilonEquals(const _Matrix4<Type>& m, Type epsilon) const
00099 {
00100     return (Math::epsilonEquals(m00, m.m00, epsilon) &&
00101             Math::epsilonEquals(m01, m.m01, epsilon) &&
00102             Math::epsilonEquals(m02, m.m02, epsilon) &&
00103             Math::epsilonEquals(m03, m.m03, epsilon) &&
00104             Math::epsilonEquals(m10, m.m10, epsilon) &&
00105             Math::epsilonEquals(m11, m.m11, epsilon) &&
00106             Math::epsilonEquals(m12, m.m12, epsilon) &&
00107             Math::epsilonEquals(m13, m.m13, epsilon) &&
00108             Math::epsilonEquals(m20, m.m20, epsilon) &&
00109             Math::epsilonEquals(m21, m.m21, epsilon) &&
00110             Math::epsilonEquals(m22, m.m22, epsilon) &&
00111             Math::epsilonEquals(m23, m.m23, epsilon) &&
00112             Math::epsilonEquals(m30, m.m30, epsilon) &&
00113             Math::epsilonEquals(m31, m.m31, epsilon) &&
00114             Math::epsilonEquals(m32, m.m32, epsilon) &&
00115             Math::epsilonEquals(m33, m.m33, epsilon));
00116 }
00117 
00118 
00119 template <class Type>
00120 void _Matrix4<Type>::get(_Matrix3<double>& m) const
00121 {
00122     double tmp_scale[3];
00123     double tmp_rot[9];
00124     getScaleRotate(tmp_scale, tmp_rot);
00125     m.set(tmp_rot);
00126 }
00127 
00128 template <class Type>
00129 Type _Matrix4<Type>::get(_Matrix3<double>& m, _Vector3<double>& v) const
00130 {
00131     double tmp_scale[3];
00132     double tmp_rot[9];
00133     getScaleRotate(tmp_scale, tmp_rot);
00134     m.set(tmp_rot);
00135     get(v);
00136     return Math::max3(tmp_scale);
00137 }
00138 
00139 template <class Type>
00140 void _Matrix4<Type>::get(_Matrix3<double>& m, _Vector3<double>& v, _Vector3<double>& s) const
00141 {
00142     double tmp_scale[3];
00143     double tmp_rot[9];
00144     getScaleRotate(tmp_scale, tmp_rot);
00145     m.set(tmp_rot);
00146     s.set(tmp_scale);
00147     get(v);
00148 }
00149 
00150 template <class Type>
00151 void _Matrix4<Type>::get(_Matrix3<float>& m) const
00152 {
00153     double tmp_scale[3];
00154     double tmp_rot[9];
00155     getScaleRotate(tmp_scale, tmp_rot);
00156     m.set(tmp_rot);
00157 }
00158 
00159 template <class Type>
00160 Type _Matrix4<Type>::get(_Matrix3<float>& m, _Vector3<float>& v) const
00161 {
00162     double tmp_scale[3];
00163     double tmp_rot[9];
00164     getScaleRotate(tmp_scale, tmp_rot);
00165     m.set(tmp_rot);
00166     get(v);
00167     return Math::max3(tmp_scale);
00168 }
00169 
00170 template <class Type>
00171 void _Matrix4<Type>::get(_Matrix3<float>& m, _Vector3<float>& v, _Vector3<float>& s) const
00172 {
00173     double tmp_scale[3];
00174     double tmp_rot[9];
00175     getScaleRotate(tmp_scale, tmp_rot);
00176     m.set(tmp_rot);
00177     s.set(tmp_scale);
00178     get(v);
00179 }
00180 
00181 template <class Type>
00182 void _Matrix4<Type>::get(_Quat4<double>& q) const
00183 {
00184     double tmp_scale[3];
00185     double tmp_rot[9];
00186     getScaleRotate(tmp_scale, tmp_rot);
00187     q.set(tmp_rot);
00188 }
00189 
00190 template <class Type>
00191 void _Matrix4<Type>::get(_Quat4<float>& q) const
00192 {
00193     double tmp_scale[3];
00194     double tmp_rot[9];
00195     getScaleRotate(tmp_scale, tmp_rot);
00196     q.set(tmp_rot);
00197 }
00198 
00199 template <class Type>
00200 void _Matrix4<Type>::getColumn(int column, _Vector4<Type>& v) const
00201 {
00202     switch (column) {
00203     case 0: v.set(m00, m10, m20, m30); break;
00204     case 1: v.set(m01, m11, m21, m31); break;
00205     case 2: v.set(m02, m12, m22, m32); break;
00206     case 3: v.set(m03, m13, m23, m33); break;
00207     }
00208 }
00209 
00210 
00211 template <class Type>
00212 void _Matrix4<Type>::getColumn(int column, Type c[]) const
00213 {
00214     switch (column) {
00215     case 0: c[0] = m00; c[1] = m10; c[2] = m20; c[3] = m30; break;
00216     case 1: c[0] = m01; c[1] = m11; c[2] = m21; c[3] = m31; break;
00217     case 2: c[0] = m02; c[1] = m12; c[2] = m22; c[3] = m32; break;
00218     case 3: c[0] = m02; c[1] = m12; c[2] = m22; c[3] = m32; break;
00219     }
00220 }
00221 
00222 template <class Type>
00223 Type _Matrix4<Type>::getElement(int row, int column) const
00224 {
00225     if (row >= 0 && row < 4 || column >= 0 || column < 4)
00226         return operator()(row, column);
00227     else
00228         return 0;
00229 }
00230 
00231 // extension
00232 //  template <class Type>
00233 //  void _Matrix4<Type>::getEuler(_Vector4<Type>& v) const
00234 //  {
00235 //  }
00236 
00237 template <class Type>
00238 void _Matrix4<Type>::getRotationScale(_Matrix3<double>& m3d) const
00239 {
00240     m3d.set(m00, m01, m02,
00241             m10, m11, m12,
00242             m20, m21, m22);
00243 }
00244 
00245 template <class Type>
00246 void _Matrix4<Type>::getRotationScale(_Matrix3<float>& m3f) const
00247 {
00248     m3f.set(m00, m01, m02,
00249             m10, m11, m12,
00250             m20, m21, m22);
00251 }
00252 
00253 template <class Type>
00254 void _Matrix4<Type>::getRow(int row, _Vector4<Type>& v) const
00255 {
00256     switch (row) {
00257     case 0: v.set(m00, m01, m02, m03); break;
00258     case 1: v.set(m10, m11, m12, m13); break;
00259     case 2: v.set(m20, m21, m22, m23); break;
00260     case 3: v.set(m30, m31, m32, m33); break;
00261     default:
00262         break;
00263     }
00264 }
00265 
00266 template <class Type>
00267 void _Matrix4<Type>::getRow(int row, Type c[4]) const
00268 {
00269     switch (row) {
00270     case 0: c[0] = m00; c[1] = m01; c[2] = m02; c[3] = m03; break;
00271     case 1: c[0] = m10; c[1] = m11; c[2] = m12; c[3] = m13; break;
00272     case 2: c[0] = m20; c[1] = m21; c[2] = m22; c[3] = m23; break;
00273     case 3: c[0] = m20; c[1] = m21; c[2] = m22; c[3] = m23; break;
00274     }
00275 }
00276 
00277 template <class Type>
00278 double _Matrix4<Type>::getScale() const {
00279     double tmp_scale[3];
00280     double tmp_rot[9];
00281     getScaleRotate(tmp_scale, tmp_rot);
00282     return Math::max3(tmp_scale);
00283 }
00284 
00285 template <class Type>
00286 void _Matrix4<Type>::getScaleRotate(double scale[3], double rot[9]) const
00287 {
00288     double tmp[9];
00289     get3x3(tmp);
00290     _Matrix3<Type>::compute_svd(tmp, scale, rot, false);
00291 }
00292 
00293 template <class Type>
00294 void _Matrix4<Type>::invert(const _Matrix4<Type>& m)
00295 {
00296     int ai[4];
00297     Type tmp[16];
00298     m.get(tmp);
00299 
00300     Type ad[16];
00301 
00302     for (int i = 0; i < 16; i++)
00303         ad[i] = 0.0;
00304     ad[0] = ad[5] = ad[10] = ad[15] = 1.0;
00305     luBacksubstitution(tmp, ai, ad);
00306     set(ad);
00307 }
00308 
00309 template <class Type>
00310 void _Matrix4<Type>::luBacksubstitution(Type ad[16], int ai[4], Type ad1[16])
00311 {
00312     int j1 = 0;
00313     for(int i1 = 0; i1 < 4; i1++) {
00314         int k1 = i1;
00315         int j = -1;
00316         for(int i = 0; i < 4; i++) {
00317             int k = ai[j1 + i];
00318             Type d = ad1[k1 + 4 * k];
00319             ad1[k1 + 4 * k] = ad1[k1 + 4 * i];
00320             if(j >= 0) {
00321                 int l1 = i * 4;
00322                 for(int l = j; l <= i - 1; l++)
00323                     d -= ad[l1 + l] * ad1[k1 + 4 * l];
00324 
00325             } else
00326                 if(d != 0.0)
00327                     j = i;
00328             ad1[k1 + 4 * i] = d;
00329         }
00330 
00331         int i2 = 12;
00332         ad1[k1 + 12] /= ad[i2 + 3];
00333         i2 -= 4;
00334         ad1[k1 + 8] = (ad1[k1 + 8] - ad[i2 + 3] * ad1[k1 + 12]) / ad[i2 + 2];
00335         i2 -= 4;
00336         ad1[k1 + 4] = (ad1[k1 + 4] - ad[i2 + 2] * ad1[k1 + 8] - ad[i2 + 3] * ad1[k1 + 12]) / ad[i2 + 1];
00337         i2 -= 4;
00338         ad1[k1] = (ad1[k1] - ad[i2 + 1] * ad1[k1 + 4] - ad[i2 + 2] * ad1[k1 + 8] - ad[i2 + 3] * ad1[k1 + 12]) / ad[i2];
00339     }
00340 }
00341 
00342 template <class Type>
00343 bool _Matrix4<Type>::luDecomposition(Type ad[], int ai[])
00344 {
00345     //_Matrix4<Type> s(ad);
00346     //cout << "Decom "  << s << endl;
00347     Type ad1[4];
00348     int k = 0;
00349     int l = 0;
00350 
00351     for(int i = 4; i-- != 0;) {
00352         Type d = 0.0;
00353         for(int j = 4; j-- != 0;) {
00354             Type d1 = ad[k++];
00355             d1 = fabs(d1);
00356             if(d1 > d)
00357                 d = d1;
00358         }
00359 
00360         if(d == 0.0)
00361             return false;
00362         ad1[l++] = 1.0 / d;
00363     }
00364 
00365     int j1 = 0;
00366     for (int i1 = 0; i1 < 4; i1++) {
00367         for (int k1 = 0; k1 < i1; k1++) {
00368             int j3 = j1 + 4 * k1 + i1;
00369             Type d2 = ad[j3];
00370             int k2 = k1;
00371             int i4 = j1 + 4 * k1;
00372             for (int l4 = j1 + i1; k2-- != 0; l4 += 4) {
00373                 d2 -= ad[i4] * ad[l4];
00374                 i4++;
00375             }
00376 
00377             ad[j3] = d2;
00378         }
00379 
00380         Type d4 = 0.0;
00381         int j2 = -1;
00382         for (int l1 = i1; l1 < 4; l1++) {
00383             int k3 = j1 + 4 * l1 + i1;
00384             Type d3 = ad[k3];
00385             int l2 = i1;
00386             int j4 = j1 + 4 * l1;
00387             for (int i5 = j1 + i1; l2-- != 0; i5 += 4) {
00388                 d3 -= ad[j4] * ad[i5];
00389                 j4++;
00390             }
00391 
00392             ad[k3] = d3;
00393             Type d5;
00394             if ((d5 = ad1[l1] * fabs(d3)) >= d4) {
00395                 d4 = d5;
00396                 j2 = l1;
00397             }
00398         }
00399 
00400         if (i1 != j2) {
00401             int i3 = 4;
00402             int k4 = j1 + 4 * j2;
00403             int j5 = j1 + 4 * i1;
00404             while (i3-- != 0) {
00405                 double d6 = ad[k4];
00406                 ad[k4++] = ad[j5];
00407                 ad[j5++] = d6;
00408             }
00409             ad1[j2] = ad1[i1];
00410         }
00411         ai[i1] = j2;
00412         if (ad[j1 + 4 * i1 + i1] == 0.0)
00413             return false;
00414 
00415         if(i1 != 3) {
00416             Type d7 = ad[j1 + 4 * i1 + i1];
00417             int l3 = j1 + 4 * (i1 + 1) + i1;
00418             for (int i2 = 3 - i1; i2-- != 0;) {
00419                 ad[l3] /= d7;
00420                 l3 += 4;
00421             }
00422 
00423         }
00424     }
00425 
00426     return true;
00427 }
00428 
00429 template <class Type>
00430 void _Matrix4<Type>::mul(Type d, const _Matrix4<Type>& m)
00431 {
00432     set(m.m00 * d, m.m01 * d, m.m02 * d, m.m03 * d,
00433         m.m10 * d, m.m11 * d, m.m12 * d, m.m13 * d,
00434         m.m20 * d, m.m21 * d, m.m22 * d, m.m23 * d,
00435         m.m30 * d, m.m31 * d, m.m32 * d, m.m33 * d);
00436 }
00437 
00438 template <class Type>
00439 void _Matrix4<Type>::mul(const _Matrix4<Type>& m)
00440 {
00441     mul(*this, m);
00442 }
00443 
00444 template <class Type>
00445 void _Matrix4<Type>::mul(const _Matrix4<Type>& m1, const _Matrix4<Type>& m2)
00446 {
00447     if(this != &m1 && this != &m2) {
00448         m00 = m1.m00 * m2.m00 + m1.m01 * m2.m10 + m1.m02 * m2.m20 + m1.m03 * m2.m30;
00449         m01 = m1.m00 * m2.m01 + m1.m01 * m2.m11 + m1.m02 * m2.m21 + m1.m03 * m2.m31;
00450         m02 = m1.m00 * m2.m02 + m1.m01 * m2.m12 + m1.m02 * m2.m22 + m1.m03 * m2.m32;
00451         m03 = m1.m00 * m2.m03 + m1.m01 * m2.m13 + m1.m02 * m2.m23 + m1.m03 * m2.m33;
00452         m10 = m1.m10 * m2.m00 + m1.m11 * m2.m10 + m1.m12 * m2.m20 + m1.m13 * m2.m30;
00453         m11 = m1.m10 * m2.m01 + m1.m11 * m2.m11 + m1.m12 * m2.m21 + m1.m13 * m2.m31;
00454         m12 = m1.m10 * m2.m02 + m1.m11 * m2.m12 + m1.m12 * m2.m22 + m1.m13 * m2.m32;
00455         m13 = m1.m10 * m2.m03 + m1.m11 * m2.m13 + m1.m12 * m2.m23 + m1.m13 * m2.m33;
00456         m20 = m1.m20 * m2.m00 + m1.m21 * m2.m10 + m1.m22 * m2.m20 + m1.m23 * m2.m30;
00457         m21 = m1.m20 * m2.m01 + m1.m21 * m2.m11 + m1.m22 * m2.m21 + m1.m23 * m2.m31;
00458         m22 = m1.m20 * m2.m02 + m1.m21 * m2.m12 + m1.m22 * m2.m22 + m1.m23 * m2.m32;
00459         m23 = m1.m20 * m2.m03 + m1.m21 * m2.m13 + m1.m22 * m2.m23 + m1.m23 * m2.m33;
00460         m30 = m1.m30 * m2.m00 + m1.m31 * m2.m10 + m1.m32 * m2.m20 + m1.m33 * m2.m30;
00461         m31 = m1.m30 * m2.m01 + m1.m31 * m2.m11 + m1.m32 * m2.m21 + m1.m33 * m2.m31;
00462         m32 = m1.m30 * m2.m02 + m1.m31 * m2.m12 + m1.m32 * m2.m22 + m1.m33 * m2.m32;
00463         m33 = m1.m30 * m2.m03 + m1.m31 * m2.m13 + m1.m32 * m2.m23 + m1.m33 * m2.m33;
00464     } else {
00465         Type d0 = m1.m00 * m2.m00 + m1.m01 * m2.m10 + m1.m02 * m2.m20 + m1.m03 * m2.m30;
00466         Type d1 = m1.m00 * m2.m01 + m1.m01 * m2.m11 + m1.m02 * m2.m21 + m1.m03 * m2.m31;
00467         Type d2 = m1.m00 * m2.m02 + m1.m01 * m2.m12 + m1.m02 * m2.m22 + m1.m03 * m2.m32;
00468         Type d3 = m1.m00 * m2.m03 + m1.m01 * m2.m13 + m1.m02 * m2.m23 + m1.m03 * m2.m33;
00469         Type d4 = m1.m10 * m2.m00 + m1.m11 * m2.m10 + m1.m12 * m2.m20 + m1.m13 * m2.m30;
00470         Type d5 = m1.m10 * m2.m01 + m1.m11 * m2.m11 + m1.m12 * m2.m21 + m1.m13 * m2.m31;
00471         Type d6 = m1.m10 * m2.m02 + m1.m11 * m2.m12 + m1.m12 * m2.m22 + m1.m13 * m2.m32;
00472         Type d7 = m1.m10 * m2.m03 + m1.m11 * m2.m13 + m1.m12 * m2.m23 + m1.m13 * m2.m33;
00473         Type d8 = m1.m20 * m2.m00 + m1.m21 * m2.m10 + m1.m22 * m2.m20 + m1.m23 * m2.m30;
00474         Type d9 = m1.m20 * m2.m01 + m1.m21 * m2.m11 + m1.m22 * m2.m21 + m1.m23 * m2.m31;
00475         Type d10 = m1.m20 * m2.m02 + m1.m21 * m2.m12 + m1.m22 * m2.m22 + m1.m23 * m2.m32;
00476         Type d11 = m1.m20 * m2.m03 + m1.m21 * m2.m13 + m1.m22 * m2.m23 + m1.m23 * m2.m33;
00477         Type d12 = m1.m30 * m2.m00 + m1.m31 * m2.m10 + m1.m32 * m2.m20 + m1.m33 * m2.m30;
00478         Type d13 = m1.m30 * m2.m01 + m1.m31 * m2.m11 + m1.m32 * m2.m21 + m1.m33 * m2.m31;
00479         Type d14 = m1.m30 * m2.m02 + m1.m31 * m2.m12 + m1.m32 * m2.m22 + m1.m33 * m2.m32;
00480         Type d15 = m1.m30 * m2.m03 + m1.m31 * m2.m13 + m1.m32 * m2.m23 + m1.m33 * m2.m33;
00481         set(d0,   d1,  d2,  d3,
00482             d4,   d5,  d6,  d7,
00483             d8,   d9, d10, d11,
00484             d12, d13, d14, d15);
00485     }
00486 }
00487 
00488 template <class Type>
00489 void _Matrix4<Type>::mulTransposeBoth(const _Matrix4<Type>& m1, const _Matrix4<Type>& m2)
00490 {
00491     if (this != &m1 && this != &m2) {
00492         m00 = m1.m00 * m2.m00 + m1.m10 * m2.m01 + m1.m20 * m2.m02 + m1.m30 * m2.m03;
00493         m01 = m1.m00 * m2.m10 + m1.m10 * m2.m11 + m1.m20 * m2.m12 + m1.m30 * m2.m13;
00494         m02 = m1.m00 * m2.m20 + m1.m10 * m2.m21 + m1.m20 * m2.m22 + m1.m30 * m2.m23;
00495         m03 = m1.m00 * m2.m30 + m1.m10 * m2.m31 + m1.m20 * m2.m32 + m1.m30 * m2.m33;
00496         m10 = m1.m01 * m2.m00 + m1.m11 * m2.m01 + m1.m21 * m2.m02 + m1.m31 * m2.m03;
00497         m11 = m1.m01 * m2.m10 + m1.m11 * m2.m11 + m1.m21 * m2.m12 + m1.m31 * m2.m13;
00498         m12 = m1.m01 * m2.m20 + m1.m11 * m2.m21 + m1.m21 * m2.m22 + m1.m31 * m2.m23;
00499         m13 = m1.m01 * m2.m30 + m1.m11 * m2.m31 + m1.m21 * m2.m32 + m1.m31 * m2.m33;
00500         m20 = m1.m02 * m2.m00 + m1.m12 * m2.m01 + m1.m22 * m2.m02 + m1.m32 * m2.m03;
00501         m21 = m1.m02 * m2.m10 + m1.m12 * m2.m11 + m1.m22 * m2.m12 + m1.m32 * m2.m13;
00502         m22 = m1.m02 * m2.m20 + m1.m12 * m2.m21 + m1.m22 * m2.m22 + m1.m32 * m2.m23;
00503         m23 = m1.m02 * m2.m30 + m1.m12 * m2.m31 + m1.m22 * m2.m32 + m1.m32 * m2.m33;
00504         m30 = m1.m03 * m2.m00 + m1.m13 * m2.m01 + m1.m23 * m2.m02 + m1.m33 * m2.m03;
00505         m31 = m1.m03 * m2.m10 + m1.m13 * m2.m11 + m1.m23 * m2.m12 + m1.m33 * m2.m13;
00506         m32 = m1.m03 * m2.m20 + m1.m13 * m2.m21 + m1.m23 * m2.m22 + m1.m33 * m2.m23;
00507         m33 = m1.m03 * m2.m30 + m1.m13 * m2.m31 + m1.m23 * m2.m32 + m1.m33 * m2.m33;
00508     } else {
00509         Type d0 = m1.m00 * m2.m00 + m1.m10 * m2.m01 + m1.m20 * m2.m02 + m1.m30 * m2.m03;
00510         Type d1 = m1.m00 * m2.m10 + m1.m10 * m2.m11 + m1.m20 * m2.m12 + m1.m30 * m2.m13;
00511         Type d2 = m1.m00 * m2.m20 + m1.m10 * m2.m21 + m1.m20 * m2.m22 + m1.m30 * m2.m23;
00512         Type d3 = m1.m00 * m2.m30 + m1.m10 * m2.m31 + m1.m20 * m2.m32 + m1.m30 * m2.m33;
00513         Type d4 = m1.m01 * m2.m00 + m1.m11 * m2.m01 + m1.m21 * m2.m02 + m1.m31 * m2.m03;
00514         Type d5 = m1.m01 * m2.m10 + m1.m11 * m2.m11 + m1.m21 * m2.m12 + m1.m31 * m2.m13;
00515         Type d6 = m1.m01 * m2.m20 + m1.m11 * m2.m21 + m1.m21 * m2.m22 + m1.m31 * m2.m23;
00516         Type d7 = m1.m01 * m2.m30 + m1.m11 * m2.m31 + m1.m21 * m2.m32 + m1.m31 * m2.m33;
00517         Type d8 = m1.m02 * m2.m00 + m1.m12 * m2.m01 + m1.m22 * m2.m02 + m1.m32 * m2.m03;
00518         Type d9 = m1.m02 * m2.m10 + m1.m12 * m2.m11 + m1.m22 * m2.m12 + m1.m32 * m2.m13;
00519         Type d10 = m1.m02 * m2.m20 + m1.m12 * m2.m21 + m1.m22 * m2.m22 + m1.m32 * m2.m23;
00520         Type d11 = m1.m02 * m2.m30 + m1.m12 * m2.m31 + m1.m22 * m2.m32 + m1.m32 * m2.m33;
00521         Type d12 = m1.m03 * m2.m00 + m1.m13 * m2.m01 + m1.m23 * m2.m02 + m1.m33 * m2.m03;
00522         Type d13 = m1.m03 * m2.m10 + m1.m13 * m2.m11 + m1.m23 * m2.m12 + m1.m33 * m2.m13;
00523         Type d14 = m1.m03 * m2.m20 + m1.m13 * m2.m21 + m1.m23 * m2.m22 + m1.m33 * m2.m23;
00524         Type d15 = m1.m03 * m2.m30 + m1.m13 * m2.m31 + m1.m23 * m2.m32 + m1.m33 * m2.m33;
00525         set(d0,   d1,  d2,  d3,
00526             d4,   d5,  d6,  d7,
00527             d8,   d9, d10, d11,
00528             d12, d13, d14, d15);
00529     }
00530 }
00531 
00532 template <class Type>
00533 void _Matrix4<Type>::mulTransposeLeft(const _Matrix4<Type>& m1, const _Matrix4<Type>& m2)
00534 {
00535     if (this != &m1 && this != &m2) {
00536         m00 = m1.m00 * m2.m00 + m1.m10 * m2.m10 + m1.m20 * m2.m20 + m1.m30 * m2.m30;
00537         m01 = m1.m00 * m2.m01 + m1.m10 * m2.m11 + m1.m20 * m2.m21 + m1.m30 * m2.m31;
00538         m02 = m1.m00 * m2.m02 + m1.m10 * m2.m12 + m1.m20 * m2.m22 + m1.m30 * m2.m32;
00539         m03 = m1.m00 * m2.m03 + m1.m10 * m2.m13 + m1.m20 * m2.m23 + m1.m30 * m2.m33;
00540         m10 = m1.m01 * m2.m00 + m1.m11 * m2.m10 + m1.m21 * m2.m20 + m1.m31 * m2.m30;
00541         m11 = m1.m01 * m2.m01 + m1.m11 * m2.m11 + m1.m21 * m2.m21 + m1.m31 * m2.m31;
00542         m12 = m1.m01 * m2.m02 + m1.m11 * m2.m12 + m1.m21 * m2.m22 + m1.m31 * m2.m32;
00543         m13 = m1.m01 * m2.m03 + m1.m11 * m2.m13 + m1.m21 * m2.m23 + m1.m31 * m2.m33;
00544         m20 = m1.m02 * m2.m00 + m1.m12 * m2.m10 + m1.m22 * m2.m20 + m1.m32 * m2.m30;
00545         m21 = m1.m02 * m2.m01 + m1.m12 * m2.m11 + m1.m22 * m2.m21 + m1.m32 * m2.m31;
00546         m22 = m1.m02 * m2.m02 + m1.m12 * m2.m12 + m1.m22 * m2.m22 + m1.m32 * m2.m32;
00547         m23 = m1.m02 * m2.m03 + m1.m12 * m2.m13 + m1.m22 * m2.m23 + m1.m32 * m2.m33;
00548         m30 = m1.m03 * m2.m00 + m1.m13 * m2.m10 + m1.m23 * m2.m20 + m1.m33 * m2.m30;
00549         m31 = m1.m03 * m2.m01 + m1.m13 * m2.m11 + m1.m23 * m2.m21 + m1.m33 * m2.m31;
00550         m32 = m1.m03 * m2.m02 + m1.m13 * m2.m12 + m1.m23 * m2.m22 + m1.m33 * m2.m32;
00551         m33 = m1.m03 * m2.m03 + m1.m13 * m2.m13 + m1.m23 * m2.m23 + m1.m33 * m2.m33;
00552     } else {
00553         Type d0 = m1.m00 * m2.m00 + m1.m10 * m2.m10 + m1.m20 * m2.m20 + m1.m30 * m2.m30;
00554         Type d1 = m1.m00 * m2.m01 + m1.m10 * m2.m11 + m1.m20 * m2.m21 + m1.m30 * m2.m31;
00555         Type d2 = m1.m00 * m2.m02 + m1.m10 * m2.m12 + m1.m20 * m2.m22 + m1.m30 * m2.m32;
00556         Type d3 = m1.m00 * m2.m03 + m1.m10 * m2.m13 + m1.m20 * m2.m23 + m1.m30 * m2.m33;
00557         Type d4 = m1.m01 * m2.m00 + m1.m11 * m2.m10 + m1.m21 * m2.m20 + m1.m31 * m2.m30;
00558         Type d5 = m1.m01 * m2.m01 + m1.m11 * m2.m11 + m1.m21 * m2.m21 + m1.m31 * m2.m31;
00559         Type d6 = m1.m01 * m2.m02 + m1.m11 * m2.m12 + m1.m21 * m2.m22 + m1.m31 * m2.m32;
00560         Type d7 = m1.m01 * m2.m03 + m1.m11 * m2.m13 + m1.m21 * m2.m23 + m1.m31 * m2.m33;
00561         Type d8 = m1.m02 * m2.m00 + m1.m12 * m2.m10 + m1.m22 * m2.m20 + m1.m32 * m2.m30;
00562         Type d9 = m1.m02 * m2.m01 + m1.m12 * m2.m11 + m1.m22 * m2.m21 + m1.m32 * m2.m31;
00563         Type d10 = m1.m02 * m2.m02 + m1.m12 * m2.m12 + m1.m22 * m2.m22 + m1.m32 * m2.m32;
00564         Type d11 = m1.m02 * m2.m03 + m1.m12 * m2.m13 + m1.m22 * m2.m23 + m1.m32 * m2.m33;
00565         Type d12 = m1.m03 * m2.m00 + m1.m13 * m2.m10 + m1.m23 * m2.m20 + m1.m33 * m2.m30;
00566         Type d13 = m1.m03 * m2.m01 + m1.m13 * m2.m11 + m1.m23 * m2.m21 + m1.m33 * m2.m31;
00567         Type d14 = m1.m03 * m2.m02 + m1.m13 * m2.m12 + m1.m23 * m2.m22 + m1.m33 * m2.m32;
00568         Type d15 = m1.m03 * m2.m03 + m1.m13 * m2.m13 + m1.m23 * m2.m23 + m1.m33 * m2.m33;
00569         set(d0,   d1,  d2,  d3,
00570             d4,   d5,  d6,  d7,
00571             d8,   d9, d10, d11,
00572             d12, d13, d14, d15);
00573     }
00574 }
00575 
00576 template <class Type>
00577 void _Matrix4<Type>::mulTransposeRight(const _Matrix4<Type>& m1, const _Matrix4<Type>& m2)
00578 {
00579     if (this != &m1 && this != &m2) {
00580         m00 = m1.m00 * m2.m00 + m1.m01 * m2.m01 + m1.m02 * m2.m02 + m1.m03 * m2.m03;
00581         m01 = m1.m00 * m2.m10 + m1.m01 * m2.m11 + m1.m02 * m2.m12 + m1.m03 * m2.m13;
00582         m02 = m1.m00 * m2.m20 + m1.m01 * m2.m21 + m1.m02 * m2.m22 + m1.m03 * m2.m23;
00583         m03 = m1.m00 * m2.m30 + m1.m01 * m2.m31 + m1.m02 * m2.m32 + m1.m03 * m2.m33;
00584         m10 = m1.m10 * m2.m00 + m1.m11 * m2.m01 + m1.m12 * m2.m02 + m1.m13 * m2.m03;
00585         m11 = m1.m10 * m2.m10 + m1.m11 * m2.m11 + m1.m12 * m2.m12 + m1.m13 * m2.m13;
00586         m12 = m1.m10 * m2.m20 + m1.m11 * m2.m21 + m1.m12 * m2.m22 + m1.m13 * m2.m23;
00587         m13 = m1.m10 * m2.m30 + m1.m11 * m2.m31 + m1.m12 * m2.m32 + m1.m13 * m2.m33;
00588         m20 = m1.m20 * m2.m00 + m1.m21 * m2.m01 + m1.m22 * m2.m02 + m1.m23 * m2.m03;
00589         m21 = m1.m20 * m2.m10 + m1.m21 * m2.m11 + m1.m22 * m2.m12 + m1.m23 * m2.m13;
00590         m22 = m1.m20 * m2.m20 + m1.m21 * m2.m21 + m1.m22 * m2.m22 + m1.m23 * m2.m23;
00591         m23 = m1.m20 * m2.m30 + m1.m21 * m2.m31 + m1.m22 * m2.m32 + m1.m23 * m2.m33;
00592         m30 = m1.m30 * m2.m00 + m1.m31 * m2.m01 + m1.m32 * m2.m02 + m1.m33 * m2.m03;
00593         m31 = m1.m30 * m2.m10 + m1.m31 * m2.m11 + m1.m32 * m2.m12 + m1.m33 * m2.m13;
00594         m32 = m1.m30 * m2.m20 + m1.m31 * m2.m21 + m1.m32 * m2.m22 + m1.m33 * m2.m23;
00595         m33 = m1.m30 * m2.m30 + m1.m31 * m2.m31 + m1.m32 * m2.m32 + m1.m33 * m2.m33;
00596     } else {
00597         Type d0 = m1.m00 * m2.m00 + m1.m01 * m2.m01 + m1.m02 * m2.m02 + m1.m03 * m2.m03;
00598         Type d1 = m1.m00 * m2.m10 + m1.m01 * m2.m11 + m1.m02 * m2.m12 + m1.m03 * m2.m13;
00599         Type d2 = m1.m00 * m2.m20 + m1.m01 * m2.m21 + m1.m02 * m2.m22 + m1.m03 * m2.m23;
00600         Type d3 = m1.m00 * m2.m30 + m1.m01 * m2.m31 + m1.m02 * m2.m32 + m1.m03 * m2.m33;
00601         Type d4 = m1.m10 * m2.m00 + m1.m11 * m2.m01 + m1.m12 * m2.m02 + m1.m13 * m2.m03;
00602         Type d5 = m1.m10 * m2.m10 + m1.m11 * m2.m11 + m1.m12 * m2.m12 + m1.m13 * m2.m13;
00603         Type d6 = m1.m10 * m2.m20 + m1.m11 * m2.m21 + m1.m12 * m2.m22 + m1.m13 * m2.m23;
00604         Type d7 = m1.m10 * m2.m30 + m1.m11 * m2.m31 + m1.m12 * m2.m32 + m1.m13 * m2.m33;
00605         Type d8 = m1.m20 * m2.m00 + m1.m21 * m2.m01 + m1.m22 * m2.m02 + m1.m23 * m2.m03;
00606         Type d9 = m1.m20 * m2.m10 + m1.m21 * m2.m11 + m1.m22 * m2.m12 + m1.m23 * m2.m13;
00607         Type d10 = m1.m20 * m2.m20 + m1.m21 * m2.m21 + m1.m22 * m2.m22 + m1.m23 * m2.m23;
00608         Type d11 = m1.m20 * m2.m30 + m1.m21 * m2.m31 + m1.m22 * m2.m32 + m1.m23 * m2.m33;
00609         Type d12 = m1.m30 * m2.m00 + m1.m31 * m2.m01 + m1.m32 * m2.m02 + m1.m33 * m2.m03;
00610         Type d13 = m1.m30 * m2.m10 + m1.m31 * m2.m11 + m1.m32 * m2.m12 + m1.m33 * m2.m13;
00611         Type d14 = m1.m30 * m2.m20 + m1.m31 * m2.m21 + m1.m32 * m2.m22 + m1.m33 * m2.m23;
00612         Type d15 = m1.m30 * m2.m30 + m1.m31 * m2.m31 + m1.m32 * m2.m32 + m1.m33 * m2.m33;
00613         set(d0,   d1,  d2,  d3,
00614             d4,   d5,  d6,  d7,
00615             d8,   d9, d10, d11,
00616             d12, d13, d14, d15);
00617     }
00618 }
00619 
00620 template <class Type>
00621 void _Matrix4<Type>::rotX(double angle)
00622 {
00623     double s = sin(angle);
00624     double c = cos(angle);
00625 
00626     set(1.0, 0.0, 0.0, 0.0,
00627         0.0,   c,  -s, 0.0,
00628         0.0,   s,   c, 0.0,
00629         0.0, 0.0, 0.0, 1.0);
00630 }
00631 
00632 template <class Type>
00633 void _Matrix4<Type>::rotY(double angle)
00634 {
00635     double s = sin(angle);
00636     double c = cos(angle);
00637 
00638     set(c  , 0.0,   s, 0.0,
00639         0.0, 1.0, 0.0, 0.0,
00640         -s , 0.0,   c, 0.0,
00641         0.0, 0.0, 0.0, 1.0);
00642 }
00643 
00644 template <class Type>
00645 void _Matrix4<Type>::rotZ(double angle)
00646 {
00647     double s = sin(angle);
00648     double c = cos(angle);
00649 
00650     set(c  ,  -s, 0.0, 0.0,
00651         s  ,   c, 0.0, 0.0,
00652         0.0, 0.0, 1.0, 0.0,
00653         0.0, 0.0, 0.0, 1.0);
00654 }
00655 
00656 // extension
00657 template <class Type>
00658 void _Matrix4<Type>::rotationGL(double angle, const _Vector3<Type>& axisRot)
00659 {
00660     double c = cos(angle), s = sin(angle), t = 1.0 - c;
00661     _Vector3<Type> axis;
00662     axis.normalize(axisRot);
00663     set(t * axis.x * axis.x + c,
00664         t * axis.x * axis.y - s * axis.z,
00665         t * axis.x * axis.z + s * axis.y,
00666         0.0,
00667         t * axis.x * axis.y + s * axis.z,
00668         t * axis.y * axis.y + c,
00669         t * axis.y * axis.z - s * axis.x,
00670         0.0,
00671         t * axis.x * axis.z - s * axis.y,
00672         t * axis.y * axis.z + s * axis.x,
00673         t * axis.z * axis.z + c,
00674         0.0,
00675         0.0, 0.0, 0.0, 1.0);
00676 }
00677 
00678 template <class Type>
00679 void _Matrix4<Type>::setColumn(int column, Type x, Type y, Type z, Type w)
00680 {
00681     switch (column) {
00682     case 0: m00 = x; m10 = y; m20 = z; m30 =w; break;
00683     case 1: m01 = x; m11 = y; m21 = z; m31 =w; break;
00684     case 2: m02 = x; m12 = y; m22 = z; m32 =w; break;
00685     case 3: m03 = x; m13 = y; m23 = z; m33 =w; break;
00686     }
00687 }
00688 
00689 template <class Type>
00690 void _Matrix4<Type>::setElement(int row, int column, Type value)
00691 {
00692     if (row >= 0 && row < 4 || column >= 0 || column < 4) {
00693         operator()(row, column) = value;
00694         return;
00695     }
00696 }
00697 
00698 template <class Type>
00699 void _Matrix4<Type>::setRow(int row, Type x, Type y, Type z, Type w)
00700 {
00701     switch (row) {
00702     case 0: m00 = x, m01 = y, m02 = z, m03 =w; break;
00703     case 1: m10 = x, m11 = y, m12 = z, m13 =w; break;
00704     case 2: m20 = x, m21 = y, m22 = z, m23 =w; break;
00705     case 3: m30 = x, m31 = y, m32 = z, m33 =w; break;
00706     }
00707 }
00708 
00709 template <class Type>
00710 void _Matrix4<Type>::sub(const _Matrix4<Type>& m1, const _Matrix4<Type>& m2)
00711 {
00712     set(m1.m00 - m2.m00, m1.m01 - m2.m01, m1.m02 - m2.m02, m1.m03 - m2.m03,
00713         m1.m10 - m2.m10, m1.m11 - m2.m11, m1.m12 - m2.m12, m1.m13 - m2.m13,
00714         m1.m20 - m2.m20, m1.m21 - m2.m21, m1.m22 - m2.m22, m1.m23 - m2.m23,
00715         m1.m30 - m2.m30, m1.m31 - m2.m31, m1.m32 - m2.m32, m1.m33 - m2.m33);
00716 }
00717 
00718 #if 0
00719 template <class Type>
00720 void _Matrix4<Type>::setRotation(const _AxisAngle4<double>& a)
00721 {
00722     Matrix3d m3(a);
00723     setRotation(m3);
00724 }
00725 
00726 template <class Type>
00727 void _Matrix4<Type>::setRotation(const _AxisAngle4<float>& a)
00728 {
00729     Matrix3f m3(a);
00730     setRotation(m3);
00731 }
00732 #endif
00733 
00734 template <class Type>
00735 void _Matrix4<Type>::setRotation(const _Matrix3<double>& m)
00736 {
00737     setRotationScale3x3(m.m00, m.m01, m.m02,
00738                         m.m10, m.m11, m.m12,
00739                         m.m20, m.m21, m.m22);
00740 }
00741 
00742 template <class Type>
00743 void _Matrix4<Type>::setRotation(const _Matrix3<float>& m)
00744 {
00745     setRotationScale3x3(m.m00, m.m01, m.m02,
00746                         m.m10, m.m11, m.m12,
00747                         m.m20, m.m21, m.m22);
00748 }
00749 
00750 template <class Type>
00751 void _Matrix4<Type>::setRotation(const _Quat4<double>& q)
00752 {
00753     Matrix3d m3;
00754     m3.set(q);
00755     setRotation(m3);
00756 }
00757 
00758 template <class Type>
00759 void _Matrix4<Type>::setRotation(const _Quat4<float>& q)
00760 {
00761     Matrix3f m3;
00762     m3.set(q);
00763     setRotation(m3);
00764 }
00765 
00766 
00767 template <class Type>
00768 void _Matrix4<Type>::transform(const _Tuple3<double>& t, _Tuple3<double>& t1) const
00769 {
00770     double x = t.x, y = t.y;
00771 
00772     t1.x = m00 * x + m01 * y + m02 * t.z + m03;
00773     t1.y = m10 * x + m11 * y + m12 * t.z + m13;
00774     t1.z = m20 * x + m21 * y + m22 * t.z + m23;
00775 }
00776 
00777 template <class Type>
00778 void _Matrix4<Type>::transform(const _Tuple3<float>& t, _Tuple3<float>& t1) const
00779 {
00780     float x = t.x, y = t.y;
00781 
00782     t1.x = m00 * x + m01 * y + m02 * t.z + m03;
00783     t1.y = m10 * x + m11 * y + m12 * t.z + m13;
00784     t1.z = m20 * x + m21 * y + m22 * t.z + m23;
00785 }
00786 
00787 
00788 template <class Type>
00789 void _Matrix4<Type>::transform(const _Tuple4<double>& t, _Tuple4<double>& t1) const
00790 {
00791     double x = t.x, y = t.y, z = t.z;
00792 
00793     t1.x = m00 * x + m01 * y + m02 * z + m03 * t.w;
00794     t1.y = m10 * x + m11 * y + m12 * z + m13 * t.w;
00795     t1.z = m20 * x + m21 * y + m22 * z + m23 * t.w;
00796     t1.w = m30 * x + m31 * y + m32 * z + m33 * t.w;
00797 }
00798 
00799 template <class Type>
00800 void _Matrix4<Type>::transform(const _Tuple4<float>& t, _Tuple4<float>& t1) const
00801 {
00802     float x = t.x, y = t.y, z = t.z;
00803 
00804     t1.x = m00 * x + m01 * y + m02 * z + m03 * t.w;
00805     t1.y = m10 * x + m11 * y + m12 * z + m13 * t.w;
00806     t1.z = m20 * x + m21 * y + m22 * z + m23 * t.w;
00807     t1.w = m30 * x + m31 * y + m32 * z + m33 * t.w;
00808 }
00809 
00810 template <class Type>
00811 void _Matrix4<Type>::transpose()
00812 {
00813     Math::swap(m10, m01);
00814     Math::swap(m20, m02);
00815     Math::swap(m30, m03);
00816     Math::swap(m12, m21);
00817     Math::swap(m13, m31);
00818     Math::swap(m23, m32);
00819 }
00820 
00821 template <class Type>
00822 void _Matrix4<Type>::transpose(const _Matrix4<Type>& m)
00823 {
00824     if (this != &m)  {
00825         set(m.m00, m.m10, m.m20, m.m30,
00826             m.m01, m.m11, m.m21, m.m31,
00827             m.m02, m.m12, m.m22, m.m32,
00828             m.m03, m.m13, m.m23, m.m33);
00829     } else
00830         transpose();
00831 }
00832 
00833 template <class Type>
00834 std::ostream& operator <<(std::ostream& os, const _Matrix4<Type>& m)
00835 {
00836     os << "{ ";
00837     for (int i = 0; i < 4; i++) {
00838         for (int j = 0; j < 4; j++) {
00839             //double d = m.getElement(i/4, i%4);
00840             double d = m(i, j);
00841             if (Math::abs(d) < 1e-15)
00842                 d = 0.0;
00843             os << d;
00844             if (i < 3 || j < 3)
00845                 os << ", ";
00846         }
00847 
00848         if (i < 3)
00849             os << std::endl << "  ";
00850         else
00851             os << " }" << std::endl;
00852     }
00853 
00854     return os;
00855 }
00856 
00857 template <class Type>
00858 std::ostream& operator <<(std::ostream& os, const _Matrix4<Type>* m)
00859 {
00860     return os << *m;
00861 }
00862 
00863 template class _Matrix4<float>;
00864 template class _Matrix4<double>;
00865 template std::ostream& operator <<(std::ostream&, const _Matrix4<double>&);
00866 template std::ostream& operator <<(std::ostream&, const _Matrix4<double>*);
00867 template std::ostream& operator <<(std::ostream&, const _Matrix4<float>&);
00868 template std::ostream& operator <<(std::ostream&, const _Matrix4<float>*);
00869 

Generated on Thu Sep 29 13:39:45 2005 for vecmath by  doxygen 1.4.4