C:/jkyprian/devel/lib3ds/lib3ds/matrix.c

00001 /*
00002  * The 3D Studio File Format Library
00003  * Copyright (C) 1996-2007 by Jan Eric Kyprianidis <www.kyprianidis.com>
00004  * All rights reserved.
00005  *
00006  * This program is  free  software;  you can redistribute it and/or modify it
00007  * under the terms of the  GNU Lesser General Public License  as published by 
00008  * the  Free Software Foundation;  either version 2.1 of the License,  or (at 
00009  * your option) any later version.
00010  *
00011  * This  program  is  distributed in  the  hope that it will  be useful,  but
00012  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
00013  * or  FITNESS FOR A  PARTICULAR PURPOSE.  See the  GNU Lesser General Public  
00014  * License for more details.
00015  *
00016  * You should  have received  a copy of the GNU Lesser General Public License
00017  * along with  this program;  if not, write to the  Free Software Foundation,
00018  * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019  *
00020  * $Id: matrix.c,v 1.14 2007/06/20 17:04:08 jeh Exp $
00021  */
00022 #include <lib3ds/matrix.h>
00023 #include <lib3ds/quat.h>
00024 #include <lib3ds/vector.h>
00025 #include <string.h>
00026 #include <math.h>
00027 
00028 
00047 void
00048 lib3ds_matrix_zero(Lib3dsMatrix m)
00049 {
00050   int i,j;
00051 
00052   for (i=0; i<4; i++) {
00053     for (j=0; j<4; j++) m[i][j]=0.0f;
00054   }
00055 }
00056 
00057 
00065 void
00066 lib3ds_matrix_identity(Lib3dsMatrix m)
00067 {
00068   int i,j;
00069 
00070   for (i=0; i<4; i++) {
00071     for (j=0; j<4; j++) m[i][j]=0.0;
00072   }
00073   for (i=0; i<4; i++) m[i][i]=1.0;
00074 }
00075 
00076 
00082 void
00083 lib3ds_matrix_copy(Lib3dsMatrix dest, Lib3dsMatrix src)
00084 {
00085   memcpy(dest, src, sizeof(Lib3dsMatrix)); 
00086 }
00087 
00088 
00094 void 
00095 lib3ds_matrix_neg(Lib3dsMatrix m)
00096 {
00097   int i,j;
00098 
00099   for (j=0; j<4; j++) {
00100     for (i=0; i<4; i++) {
00101       m[j][i]=-m[j][i];
00102     }
00103   }
00104 }
00105 
00106 
00112 void 
00113 lib3ds_matrix_abs(Lib3dsMatrix m)
00114 {
00115   int i,j;
00116 
00117   for (j=0; j<4; j++) {
00118     for (i=0; i<4; i++) {
00119       m[j][i]=(Lib3dsFloat)fabs(m[j][i]);
00120     }
00121   }
00122 }
00123 
00124 
00130 void
00131 lib3ds_matrix_transpose(Lib3dsMatrix m)
00132 {
00133   int i,j;
00134   Lib3dsFloat swp;
00135 
00136   for (j=0; j<4; j++) {
00137     for (i=j+1; i<4; i++) {
00138       swp=m[j][i];
00139       m[j][i]=m[i][j];
00140       m[i][j]=swp;
00141     }
00142   }
00143 }
00144 
00145 
00151 void
00152 _lib3ds_matrix_add(Lib3dsMatrix m, Lib3dsMatrix a, Lib3dsMatrix b)
00153 {
00154   int i,j;
00155 
00156   for (j=0; j<4; j++) {
00157     for (i=0; i<4; i++) {
00158       m[j][i]=a[j][i]+b[j][i];
00159     }
00160   }
00161 }
00162 
00163 
00173 void
00174 _lib3ds_matrix_sub(Lib3dsMatrix m, Lib3dsMatrix a, Lib3dsMatrix b)
00175 {
00176   int i,j;
00177 
00178   for (j=0; j<4; j++) {
00179     for (i=0; i<4; i++) {
00180       m[j][i]=a[j][i]-b[j][i];
00181     }
00182   }
00183 }
00184 
00185 
00191 void
00192 lib3ds_matrix_mult(Lib3dsMatrix m, Lib3dsMatrix n)
00193 {
00194   Lib3dsMatrix tmp;
00195   int i,j,k;
00196   Lib3dsFloat ab;
00197 
00198   memcpy(tmp, m, sizeof(Lib3dsMatrix)); 
00199   for (j=0; j<4; j++) {
00200     for (i=0; i<4; i++) {
00201       ab=0.0f;
00202       for (k=0; k<4; k++) ab+=tmp[k][i]*n[j][k];
00203       m[j][i]=ab;
00204     }
00205   }
00206 }
00207 
00208 
00217 void
00218 lib3ds_matrix_scalar(Lib3dsMatrix m, Lib3dsFloat k)
00219 {
00220   int i,j;
00221 
00222   for (j=0; j<4; j++) {
00223     for (i=0; i<4; i++) {
00224       m[j][i]*=k;
00225     }
00226   }
00227 }
00228 
00229 
00230 static Lib3dsFloat
00231 det2x2(
00232   Lib3dsFloat a, Lib3dsFloat b,
00233   Lib3dsFloat c, Lib3dsFloat d) 
00234 {
00235   return((a)*(d)-(b)*(c));
00236 }
00237 
00238 
00239 static Lib3dsFloat
00240 det3x3(
00241   Lib3dsFloat a1, Lib3dsFloat a2, Lib3dsFloat a3,
00242   Lib3dsFloat b1, Lib3dsFloat b2, Lib3dsFloat b3,
00243   Lib3dsFloat c1, Lib3dsFloat c2, Lib3dsFloat c3)
00244 {
00245   return(
00246     a1*det2x2(b2,b3,c2,c3)-
00247     b1*det2x2(a2,a3,c2,c3)+
00248     c1*det2x2(a2,a3,b2,b3)
00249   );
00250 }
00251 
00252 
00258 Lib3dsFloat
00259 lib3ds_matrix_det(Lib3dsMatrix m)
00260 {
00261   Lib3dsFloat a1,a2,a3,a4,b1,b2,b3,b4,c1,c2,c3,c4,d1,d2,d3,d4;
00262 
00263   a1 = m[0][0];
00264   b1 = m[1][0];
00265   c1 = m[2][0];
00266   d1 = m[3][0];
00267   a2 = m[0][1];
00268   b2 = m[1][1];
00269   c2 = m[2][1];
00270   d2 = m[3][1];
00271   a3 = m[0][2];
00272   b3 = m[1][2];
00273   c3 = m[2][2];
00274   d3 = m[3][2];
00275   a4 = m[0][3];
00276   b4 = m[1][3];
00277   c4 = m[2][3];
00278   d4 = m[3][3];
00279   return(
00280     a1 * det3x3(b2, b3, b4, c2, c3, c4, d2, d3, d4)-
00281     b1 * det3x3(a2, a3, a4, c2, c3, c4, d2, d3, d4)+
00282     c1 * det3x3(a2, a3, a4, b2, b3, b4, d2, d3, d4)-
00283     d1 * det3x3(a2, a3, a4, b2, b3, b4, c2, c3, c4)
00284   );
00285 }
00286 
00287 
00293 void
00294 lib3ds_matrix_adjoint(Lib3dsMatrix m)
00295 {
00296   Lib3dsFloat a1,a2,a3,a4,b1,b2,b3,b4,c1,c2,c3,c4,d1,d2,d3,d4;
00297 
00298   a1 = m[0][0];
00299   b1 = m[1][0];
00300   c1 = m[2][0];
00301   d1 = m[3][0];
00302   a2 = m[0][1];
00303   b2 = m[1][1];
00304   c2 = m[2][1];
00305   d2 = m[3][1];
00306   a3 = m[0][2];
00307   b3 = m[1][2];
00308   c3 = m[2][2];
00309   d3 = m[3][2];
00310   a4 = m[0][3];
00311   b4 = m[1][3];
00312   c4 = m[2][3];
00313   d4 = m[3][3];
00314   m[0][0]=  det3x3 (b2, b3, b4, c2, c3, c4, d2, d3, d4);
00315   m[0][1]= -det3x3 (a2, a3, a4, c2, c3, c4, d2, d3, d4);
00316   m[0][2]=  det3x3 (a2, a3, a4, b2, b3, b4, d2, d3, d4);
00317   m[0][3]= -det3x3 (a2, a3, a4, b2, b3, b4, c2, c3, c4);
00318   m[1][0]= -det3x3 (b1, b3, b4, c1, c3, c4, d1, d3, d4);
00319   m[1][1]=  det3x3 (a1, a3, a4, c1, c3, c4, d1, d3, d4);
00320   m[1][2]= -det3x3 (a1, a3, a4, b1, b3, b4, d1, d3, d4);
00321   m[1][3]=  det3x3 (a1, a3, a4, b1, b3, b4, c1, c3, c4);
00322   m[2][0]=  det3x3 (b1, b2, b4, c1, c2, c4, d1, d2, d4);
00323   m[2][1]= -det3x3 (a1, a2, a4, c1, c2, c4, d1, d2, d4);
00324   m[2][2]=  det3x3 (a1, a2, a4, b1, b2, b4, d1, d2, d4);
00325   m[2][3]= -det3x3 (a1, a2, a4, b1, b2, b4, c1, c2, c4);
00326   m[3][0]= -det3x3 (b1, b2, b3, c1, c2, c3, d1, d2, d3);
00327   m[3][1]=  det3x3 (a1, a2, a3, c1, c2, c3, d1, d2, d3);
00328   m[3][2]= -det3x3 (a1, a2, a3, b1, b2, b3, d1, d2, d3);
00329   m[3][3]=  det3x3 (a1, a2, a3, b1, b2, b3, c1, c2, c3);
00330 }
00331 
00332 
00343 Lib3dsBool
00344 lib3ds_matrix_inv(Lib3dsMatrix m)
00345 {                          
00346   int i,j,k;               
00347   int pvt_i[4], pvt_j[4];            /* Locations of pivot elements */
00348   Lib3dsFloat pvt_val;               /* Value of current pivot element */
00349   Lib3dsFloat hold;                  /* Temporary storage */
00350   Lib3dsFloat determinat;            
00351 
00352   determinat = 1.0f;
00353   for (k=0; k<4; k++)  {
00354     /* Locate k'th pivot element */
00355     pvt_val=m[k][k];            /* Initialize for search */
00356     pvt_i[k]=k;
00357     pvt_j[k]=k;
00358     for (i=k; i<4; i++) {
00359       for (j=k; j<4; j++) {
00360         if (fabs(m[i][j]) > fabs(pvt_val)) {
00361           pvt_i[k]=i;
00362           pvt_j[k]=j;
00363           pvt_val=m[i][j];
00364         }
00365       }
00366     }
00367 
00368     /* Product of pivots, gives determinant when finished */
00369     determinat*=pvt_val;
00370     if (fabs(determinat)<LIB3DS_EPSILON) {    
00371       return(LIB3DS_FALSE);  /* Matrix is singular (zero determinant) */
00372     }
00373 
00374     /* "Interchange" rows (with sign change stuff) */
00375     i=pvt_i[k];
00376     if (i!=k) {               /* If rows are different */
00377       for (j=0; j<4; j++) {
00378         hold=-m[k][j];
00379         m[k][j]=m[i][j];
00380         m[i][j]=hold;
00381       }
00382     }
00383 
00384     /* "Interchange" columns */
00385     j=pvt_j[k];
00386     if (j!=k) {              /* If columns are different */
00387       for (i=0; i<4; i++) {
00388         hold=-m[i][k];
00389         m[i][k]=m[i][j];
00390         m[i][j]=hold;
00391       }
00392     }
00393     
00394     /* Divide column by minus pivot value */
00395     for (i=0; i<4; i++) {
00396       if (i!=k) m[i][k]/=( -pvt_val) ; 
00397     }
00398 
00399     /* Reduce the matrix */
00400     for (i=0; i<4; i++) {
00401       hold = m[i][k];
00402       for (j=0; j<4; j++) {
00403         if (i!=k && j!=k) m[i][j]+=hold*m[k][j];
00404       }
00405     }
00406 
00407     /* Divide row by pivot */
00408     for (j=0; j<4; j++) {
00409       if (j!=k) m[k][j]/=pvt_val;
00410     }
00411 
00412     /* Replace pivot by reciprocal (at last we can touch it). */
00413     m[k][k] = 1.0f/pvt_val;
00414   }
00415 
00416   /* That was most of the work, one final pass of row/column interchange */
00417   /* to finish */
00418   for (k=4-2; k>=0; k--) { /* Don't need to work with 1 by 1 corner*/
00419     i=pvt_j[k];            /* Rows to swap correspond to pivot COLUMN */
00420     if (i!=k) {            /* If rows are different */
00421       for(j=0; j<4; j++) {
00422         hold = m[k][j];
00423         m[k][j]=-m[i][j];
00424         m[i][j]=hold;
00425       }
00426     }
00427 
00428     j=pvt_i[k];           /* Columns to swap correspond to pivot ROW */
00429     if (j!=k)             /* If columns are different */
00430     for (i=0; i<4; i++) {
00431       hold=m[i][k];
00432       m[i][k]=-m[i][j];
00433       m[i][j]=hold;
00434     }
00435   }
00436   return(LIB3DS_TRUE);                          
00437 }
00438 
00439 
00445 void
00446 lib3ds_matrix_translate_xyz(Lib3dsMatrix m, Lib3dsFloat x, Lib3dsFloat y, Lib3dsFloat z)
00447 {
00448   int i;
00449   
00450   for (i=0; i<3; i++) {
00451     m[3][i]+= m[0][i]*x + m[1][i]*y + m[2][i]*z;
00452   }
00453 }
00454 
00455 
00461 void
00462 lib3ds_matrix_translate(Lib3dsMatrix m, Lib3dsVector t)
00463 {
00464   int i;
00465   
00466   for (i=0; i<3; i++) {
00467     m[3][i]+= m[0][i]*t[0] + m[1][i]*t[1] + m[2][i]*t[2];
00468   }
00469 }
00470 
00471 
00477 void
00478 lib3ds_matrix_scale_xyz(Lib3dsMatrix m, Lib3dsFloat x, Lib3dsFloat y, Lib3dsFloat z)
00479 {
00480   int i;
00481 
00482   for (i=0; i<4; i++) {
00483     m[0][i]*=x;
00484     m[1][i]*=y;
00485     m[2][i]*=z;
00486   }
00487 }
00488 
00489 
00495 void
00496 lib3ds_matrix_scale(Lib3dsMatrix m, Lib3dsVector s)
00497 {
00498   int i;
00499 
00500   for (i=0; i<4; i++) {
00501     m[0][i]*=s[0];
00502     m[1][i]*=s[1];
00503     m[2][i]*=s[2];
00504   }
00505 }
00506 
00507 
00513 void
00514 lib3ds_matrix_rotate_x(Lib3dsMatrix m, Lib3dsFloat phi)
00515 {
00516   Lib3dsFloat SinPhi,CosPhi;
00517   Lib3dsFloat a1[4],a2[4];
00518 
00519   SinPhi=(Lib3dsFloat)sin(phi);
00520   CosPhi=(Lib3dsFloat)cos(phi);
00521   memcpy(a1,m[1],4*sizeof(Lib3dsFloat));
00522   memcpy(a2,m[2],4*sizeof(Lib3dsFloat));
00523   m[1][0]=CosPhi*a1[0]+SinPhi*a2[0];
00524   m[1][1]=CosPhi*a1[1]+SinPhi*a2[1];
00525   m[1][2]=CosPhi*a1[2]+SinPhi*a2[2];
00526   m[1][3]=CosPhi*a1[3]+SinPhi*a2[3];
00527   m[2][0]=-SinPhi*a1[0]+CosPhi*a2[0];
00528   m[2][1]=-SinPhi*a1[1]+CosPhi*a2[1];
00529   m[2][2]=-SinPhi*a1[2]+CosPhi*a2[2];
00530   m[2][3]=-SinPhi*a1[3]+CosPhi*a2[3];
00531 }
00532 
00533 
00539 void
00540 lib3ds_matrix_rotate_y(Lib3dsMatrix m, Lib3dsFloat phi)
00541 {
00542   Lib3dsFloat SinPhi,CosPhi;
00543   Lib3dsFloat a0[4],a2[4];
00544 
00545   SinPhi=(Lib3dsFloat)sin(phi);
00546   CosPhi=(Lib3dsFloat)cos(phi);
00547   memcpy(a0,m[0],4*sizeof(Lib3dsFloat));
00548   memcpy(a2,m[2],4*sizeof(Lib3dsFloat));
00549   m[0][0]=CosPhi*a0[0]-SinPhi*a2[0];
00550   m[0][1]=CosPhi*a0[1]-SinPhi*a2[1];
00551   m[0][2]=CosPhi*a0[2]-SinPhi*a2[2];
00552   m[0][3]=CosPhi*a0[3]-SinPhi*a2[3];
00553   m[2][0]=SinPhi*a0[0]+CosPhi*a2[0];
00554   m[2][1]=SinPhi*a0[1]+CosPhi*a2[1];
00555   m[2][2]=SinPhi*a0[2]+CosPhi*a2[2];
00556   m[2][3]=SinPhi*a0[3]+CosPhi*a2[3];
00557 }
00558 
00559 
00565 void
00566 lib3ds_matrix_rotate_z(Lib3dsMatrix m, Lib3dsFloat phi)
00567 {
00568   Lib3dsFloat SinPhi,CosPhi;
00569   Lib3dsFloat a0[4],a1[4];
00570   
00571   SinPhi=(Lib3dsFloat)sin(phi);
00572   CosPhi=(Lib3dsFloat)cos(phi);
00573   memcpy(a0,m[0],4*sizeof(Lib3dsFloat));
00574   memcpy(a1,m[1],4*sizeof(Lib3dsFloat));
00575   m[0][0]=CosPhi*a0[0]+SinPhi*a1[0];
00576   m[0][1]=CosPhi*a0[1]+SinPhi*a1[1];
00577   m[0][2]=CosPhi*a0[2]+SinPhi*a1[2];
00578   m[0][3]=CosPhi*a0[3]+SinPhi*a1[3];
00579   m[1][0]=-SinPhi*a0[0]+CosPhi*a1[0];
00580   m[1][1]=-SinPhi*a0[1]+CosPhi*a1[1];
00581   m[1][2]=-SinPhi*a0[2]+CosPhi*a1[2];
00582   m[1][3]=-SinPhi*a0[3]+CosPhi*a1[3];
00583 }
00584 
00585 
00591 void
00592 lib3ds_matrix_rotate(Lib3dsMatrix m, Lib3dsQuat q)
00593 {
00594   Lib3dsFloat s,xs,ys,zs,wx,wy,wz,xx,xy,xz,yy,yz,zz,l;
00595   Lib3dsMatrix R;
00596 
00597   l=q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3];
00598   if (fabs(l)<LIB3DS_EPSILON) {
00599     s=1.0f;
00600   }
00601   else {
00602     s=2.0f/l;
00603   }
00604 
00605   xs = q[0] * s;   ys = q[1] * s;  zs = q[2] * s;
00606   wx = q[3] * xs;  wy = q[3] * ys; wz = q[3] * zs;
00607   xx = q[0] * xs;  xy = q[0] * ys; xz = q[0] * zs;
00608   yy = q[1] * ys;  yz = q[1] * zs; zz = q[2] * zs;
00609 
00610   R[0][0]=1.0f - (yy +zz);
00611   R[1][0]=xy - wz;
00612   R[2][0]=xz + wy;
00613   R[0][1]=xy + wz;
00614   R[1][1]=1.0f - (xx +zz);
00615   R[2][1]=yz - wx;
00616   R[0][2]=xz - wy;
00617   R[1][2]=yz + wx;
00618   R[2][2]=1.0f - (xx + yy);
00619   R[3][0]=R[3][1]=R[3][2]=R[0][3]=R[1][3]=R[2][3]=0.0f;
00620   R[3][3]=1.0f;
00621 
00622   lib3ds_matrix_mult(m,R);
00623 }
00624 
00625 
00631 void
00632 lib3ds_matrix_rotate_axis(Lib3dsMatrix m, Lib3dsVector axis, Lib3dsFloat angle)
00633 {
00634   Lib3dsQuat q;
00635   
00636   lib3ds_quat_axis_angle(q,axis,angle);
00637   lib3ds_matrix_rotate(m,q);
00638 }
00639 
00640 
00655 void
00656 lib3ds_matrix_camera(Lib3dsMatrix matrix, Lib3dsVector pos,
00657   Lib3dsVector tgt, Lib3dsFloat roll)
00658 {
00659   Lib3dsMatrix M;
00660   Lib3dsVector x, y, z;
00661 
00662   lib3ds_vector_sub(y, tgt, pos);
00663   lib3ds_vector_normalize(y);
00664 
00665   if (y[0] != 0. || y[1] != 0) {
00666     z[0] = 0;
00667     z[1] = 0;
00668     z[2] = 1.0;
00669   }
00670   else {        /* Special case:  looking straight up or down z axis */
00671     z[0] = -1.0;
00672     z[1] = 0;
00673     z[2] = 0;
00674   }
00675 
00676   lib3ds_vector_cross(x, y, z);
00677   lib3ds_vector_cross(z, x, y);
00678   lib3ds_vector_normalize(x);
00679   lib3ds_vector_normalize(z);
00680 
00681   lib3ds_matrix_identity(M);
00682   M[0][0] = x[0];
00683   M[1][0] = x[1];
00684   M[2][0] = x[2];
00685   M[0][1] = y[0];
00686   M[1][1] = y[1];
00687   M[2][1] = y[2];
00688   M[0][2] = z[0];
00689   M[1][2] = z[1];
00690   M[2][2] = z[2];
00691 
00692   lib3ds_matrix_identity(matrix);
00693   lib3ds_matrix_rotate_y(matrix, roll);
00694   lib3ds_matrix_mult(matrix, M);
00695   lib3ds_matrix_translate_xyz(matrix, -pos[0],-pos[1],-pos[2]);
00696 }
00697 
00698 
00702 void
00703 lib3ds_matrix_dump(Lib3dsMatrix matrix)
00704 {
00705   int i,j;
00706 
00707   for (i=0; i<4; ++i) {
00708     for (j=0; j<4; ++j) {
00709       printf("%f ", matrix[j][i]);
00710     }
00711     printf("\n");
00712   }
00713 }
00714 
00715 
00716 
00717 
00718 

Hosted by
SourceForge.net Logo
Generated at Wed Jun 20 18:51:36 2007 by Doxygen 1.5.2