Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

/ray/src/lib/numerics/3d/omatrix.cc

Go to the documentation of this file.
00001 /*
00002  * lib/numerics/3d/omatrix.cc
00003  * 
00004  * 3x4 object transform matrix. 
00005  * 
00006  * Copyright (c) 2004 by Wolfgang Wieser ] wwieser (a) gmx <*> de [ 
00007  * 
00008  * This file may be distributed and/or modified under the terms of the 
00009  * GNU General Public License version 2 as published by the Free Software 
00010  * Foundation. (See COPYING.GPL for details.)
00011  * 
00012  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00013  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00014  * 
00015  */
00016 
00017 #include "omatrix.h"
00018 
00019 namespace NUM   // numerics
00020 {
00021 
00022 
00023 // This is a hack which makes sure that the required instances for dbl 
00024 // and flt are emitted. 
00025 void _OMatrixInstantiationDummy()
00026 {
00027     {
00028         OMatrix<dbl> *a=NULL,b(OMatrix<dbl>::Mul,*a,*a);
00029         *a*=b; *a/=b;
00030         Vector3<dbl> *v=NULL;
00031         OMatrix<dbl> c(OMatrix<dbl>::Rotate,*v,0.1);
00032         OMatrix<dbl> d(OMatrix<dbl>::Invers,c);
00033     }
00034     {
00035         OMatrix<flt> *a=NULL,b(OMatrix<flt>::Mul,*a,*a);
00036         *a*=b; *a/=b;
00037         Vector3<flt> *v=NULL;
00038         OMatrix<flt> c(OMatrix<flt>::Rotate,*v,0.1);
00039         OMatrix<flt> d(OMatrix<flt>::Invers,c);
00040     }
00041 }
00042 
00043 
00044 template<typename T>OMatrix<T>::OMatrix(
00045     enum OMatrix<T>::_Mul,const OMatrix<T> &a,const OMatrix<T> &b)
00046 {
00047     for(short int i=0; i<3; i++)
00048     {
00049         for(short int j=0; j<3; j++)
00050         {   m[i][j] = a.m[i][0]*b.m[0][j]
00051                     + a.m[i][1]*b.m[1][j]
00052                     + a.m[i][2]*b.m[2][j];  }
00053         m[i][3] = a.m[i][0]*b.m[0][3]
00054                 + a.m[i][1]*b.m[1][3]
00055                 + a.m[i][2]*b.m[2][3]
00056                 + a.m[i][3];
00057     }
00058 }
00059 
00060 
00061 template<typename T>OMatrix<T> &OMatrix<T>::operator*=(const OMatrix<T> &b)
00062 {
00063     T tmp[4];
00064     
00065     for(short int i=0; i<3; i++)
00066     {
00067         // Compute row [i] in result matrix. 
00068         tmp[0]=m[i][0];  tmp[1]=m[i][1];  tmp[2]=m[i][2];  tmp[3]=m[i][3];
00069         
00070         for(short int j=0; j<3; j++)
00071         {   m[i][j] = tmp[0]*b.m[0][j]
00072                     + tmp[1]*b.m[1][j]
00073                     + tmp[2]*b.m[2][j];  }
00074         
00075         m[i][3] = tmp[0]*b.m[0][3]
00076                 + tmp[1]*b.m[1][3]
00077                 + tmp[2]*b.m[2][3]
00078                 + tmp[3];
00079     }
00080     
00081     return(*this);
00082 }
00083 
00084 
00085 template<typename T>OMatrix<T> &OMatrix<T>::operator/=(const OMatrix<T> &a)
00086 {
00087     T tmp[3];
00088     
00089     for(short int j=0; j<3; j++)
00090     {
00091         // Compute column [j] in result matrix. 
00092         tmp[0]=m[0][j];  tmp[1]=m[1][j];  tmp[2]=m[2][j];
00093         
00094         for(short int i=0; i<3; i++)
00095         {   m[i][j] = a.m[i][0]*tmp[0]
00096                     + a.m[i][1]*tmp[1]
00097                     + a.m[i][2]*tmp[2];  }
00098     }
00099     
00100     // Compute column [3] (last one) in result matrix. 
00101     tmp[0]=m[0][3];  tmp[1]=m[1][3];  tmp[2]=m[2][3];
00102     for(short int j=0; j<3; j++)
00103     {
00104         m[j][3] = a.m[j][0]*tmp[0]
00105                 + a.m[j][1]*tmp[1]
00106                 + a.m[j][2]*tmp[2]
00107                 + a.m[j][3];
00108     }
00109     
00110     return(*this);
00111 }
00112 
00113 
00114 template<typename T>OMatrix<T>::OMatrix(
00115     enum OMatrix<T>::_Rotate,const Vector3<T> &axis,T angle)
00116 {
00117     T s,c;
00118     sincos(angle,&s,&c);
00119     T c1=1-c;
00120     
00126     
00127     T sq;
00128     sq=sqr(axis[0]);  m[0][0] = sq + c*(1-sq);
00129     sq=sqr(axis[1]);  m[1][1] = sq + c*(1-sq);
00130     sq=sqr(axis[2]);  m[2][2] = sq + c*(1-sq);
00131     
00132     T tmp = axis[0]*axis[1]*c1;
00133     T tmp2 = axis[2]*s;
00134     m[0][1] = tmp + tmp2;
00135     m[1][0] = tmp - tmp2;
00136     
00137     tmp = axis[0]*axis[2]*c1;
00138     tmp2 = axis[1]*s;
00139     m[0][2] = tmp - tmp2;
00140     m[2][0] = tmp + tmp2;
00141     
00142     tmp = axis[1]*axis[2]*c1;
00143     tmp2 = axis[0]*s;
00144     m[1][2] = tmp + tmp2;
00145     m[2][1] = tmp - tmp2;
00146 }
00147 
00148 
00149 template<typename T>OMatrix<T>::OMatrix(
00150     enum OMatrix<T>::_Invers,const OMatrix<T> &a)
00151 {
00152     // This is turbo-inversion; self-derived formula for my strange 
00153     // 3x4 matrices. But fortunately, it turns out that these matrices 
00154     // CAN be inverted and that the inversion is quite much faster 
00155     // (in number of multiplications) than the 4x4 matrix inversion. 
00156     // This rocks!                                 (Wolfgang Wieser)
00157     
00158     T a0211 = a[0][2]*a[1][1];
00159     T a2201 = a[2][2]*a[0][1];
00160     T a1221 = a[1][2]*a[2][1];
00161     T a0022 = a[0][0]*a[2][2];
00162     T a2012 = a[2][0]*a[1][2];
00163     T a1002 = a[1][0]*a[0][2];
00164     // Calculate the determinant. fact is then 1/determinant. 
00165     T fact = a0022*a[1][1] - a0211*a[2][0]
00166            + a2012*a[0][1] - a2201*a[1][0]
00167            + a1002*a[2][1] - a1221*a[0][0];
00168     fact=1/fact;
00169     
00170     // First row of res: 
00171     m[0][0] = (a[1][1]*a[2][2] - a1221)*fact;
00172     m[0][1] = (a[2][1]*a[0][2] - a2201)*fact;
00173     m[0][2] = (a[0][1]*a[1][2] - a0211)*fact;
00174     
00175     // Second row of m: 
00176     m[1][0] = (a2012 - a[1][0]*a[2][2])*fact;
00177     m[1][1] = (a0022 - a[2][0]*a[0][2])*fact;
00178     m[1][2] = (a1002 - a[0][0]*a[1][2])*fact;
00179     
00180     // Third row of m: 
00181     m[2][0] = (a[1][0]*a[2][1] - a[2][0]*a[1][1])*fact;
00182     m[2][1] = (a[2][0]*a[0][1] - a[0][0]*a[2][1])*fact;
00183     m[2][2] = (a[0][0]*a[1][1] - a[1][0]*a[0][1])*fact;
00184     
00185     // Translation column of m: 
00186     // Note: This uses already computed values from the other part of the 
00187     //       result matrix. 
00188     m[0][3] = - m[0][0] * a[0][3] - m[0][1] * a[1][3] - m[0][2] * a[2][3];
00189     m[1][3] = - m[1][0] * a[0][3] - m[1][1] * a[1][3] - m[1][2] * a[2][3];
00190     m[2][3] = - m[2][0] * a[0][3] - m[2][1] * a[1][3] - m[2][2] * a[2][3];
00191 }
00192 
00193 }  // end of namespace NUM
00194 
00195 
00196 #if 0
00197 // Little test program. 
00198 
00199 typedef NUM::OMatrix<dbl> OMatrix;
00200 
00201 #include <stdio.h>  /* test program */
00202 #include <stdlib.h>
00203 
00204 static void Print(const OMatrix &m)
00205 {
00206     for(int r=0; r<3; r++)
00207     {
00208         for(int c=0; c<4; c++)
00209         {
00210             char tmp[32];
00211             snprintf(tmp,32,"%g",m[r][c]);
00212             printf("%12s  ",tmp);
00213         }
00214         printf("\n");
00215     }
00216 }
00217 
00218 int main()
00219 {
00220     OMatrix a,b;
00221     for(int i=0; i<20; i++)
00222     {
00223         // Yeah... this is a hack but I just wanna test the stuff!
00224         for(int i=0; i<12; i++)
00225         {
00226             a[0][i]=dbl(rand())/RAND_MAX*10;
00227             b[0][i]=dbl(rand())/RAND_MAX*10;
00228         }
00229         
00230         OMatrix p1=a*b;
00231         OMatrix p2=a;  p2*=b;
00232         OMatrix p3=b;  p3/=a;
00233         
00234         if(!NUM::equal(p1,p2,1e-10) || !NUM::equal(p1,p3,1e-10))
00235         {  printf("OOPS: NEQ\n");  }
00236     }
00237     
00238     for(int _i=0; _i<20; _i++)
00239     {
00240         // Yeah... this is a hack but I just wanna test the stuff!
00241         for(int i=0; i<12; i++)
00242         {  a[0][i]=dbl(rand())/RAND_MAX*10;  }
00243         
00244         OMatrix inv(OMatrix::Invers,a);
00245         
00246         b=inv*a-OMatrix(OMatrix::Ident);
00247         if(!b.IsNull(1e-12))
00248         {  printf("OOPS(INV)\n");  Print(b);  }
00249         
00250         b=a*inv-OMatrix(OMatrix::Ident);
00251         if(!b.IsNull(1e-12))
00252         {  printf("OOPS(INV)\n");  Print(b);  }
00253     }
00254     
00255     printf("DONE\n");
00256 }
00257 #endif

Generated on Sat Feb 19 22:33:45 2005 for Ray by doxygen 1.3.5