Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

panda/src/linmath/compose_matrix_src.cxx

Go to the documentation of this file.
00001 // Filename: compose_matrix_src.cxx
00002 // Created by:  drose (27Jan99)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 
00019 
00020 ////////////////////////////////////////////////////////////////////
00021 //     Function: compose_matrix
00022 //  Description: Computes the 3x3 matrix from scale and rotation.
00023 ////////////////////////////////////////////////////////////////////
00024 void
00025 compose_matrix(FLOATNAME(LMatrix3) &mat,
00026                const FLOATNAME(LVecBase3) &scale,
00027                const FLOATNAME(LVecBase3) &hpr,
00028                CoordinateSystem cs) {
00029 
00030   // temp_hpr_fix blocks use the correct way.  need to keep other way as default until
00031   // legacy tools are fixed to work with correct way
00032 
00033   if (temp_hpr_fix) {
00034     mat.scale_multiply(scale,
00035       FLOATNAME(LMatrix3)::rotate_mat_normaxis(hpr[2], FLOATNAME(LVector3)::forward(cs), cs) *
00036       FLOATNAME(LMatrix3)::rotate_mat_normaxis(hpr[1], FLOATNAME(LVector3)::right(cs), cs) *
00037       FLOATNAME(LMatrix3)::rotate_mat_normaxis(hpr[0], FLOATNAME(LVector3)::up(cs), cs));
00038   } else {
00039     mat.scale_multiply(scale,
00040       FLOATNAME(LMatrix3)::rotate_mat_normaxis(hpr[1], FLOATNAME(LVector3)::right(cs), cs) *
00041       FLOATNAME(LMatrix3)::rotate_mat_normaxis(hpr[0], FLOATNAME(LVector3)::up(cs), cs) *
00042       FLOATNAME(LMatrix3)::rotate_mat_normaxis(hpr[2], FLOATNAME(LVector3)::back(cs), cs));
00043   }
00044 }
00045 
00046 ////////////////////////////////////////////////////////////////////
00047 //     Function: unwind_yup_rotation
00048 //  Description: Extracts the rotation about the x, y, and z axes from
00049 //               the given hpr & scale matrix.  Adjusts the matrix
00050 //               to eliminate the rotation.
00051 //
00052 //               This function assumes the matrix is stored in a
00053 //               right-handed Y-up coordinate system.
00054 ////////////////////////////////////////////////////////////////////
00055 static void
00056 unwind_yup_rotation(FLOATNAME(LMatrix3) &mat, FLOATNAME(LVecBase3) &hpr) {
00057 
00058   typedef FLOATNAME(LMatrix3) Matrix;
00059 
00060   if (temp_hpr_fix) {
00061     // Extract the axes from the matrix.
00062     FLOATNAME(LVector3) x, y, z;
00063     mat.get_row(x,0);
00064     mat.get_row(y,1);
00065     mat.get_row(z,2);
00066 
00067     // Project Z into the XZ plane.
00068     FLOATNAME(LVector2) xz(z[0], z[2]);
00069     xz = normalize(xz);
00070 
00071     // Compute the rotation about the +Y (up) axis.  This is yaw, or
00072     // "heading".
00073     FLOATTYPE heading = rad_2_deg(((FLOATTYPE)atan2(xz[0], xz[1])));
00074 
00075     // Unwind the heading, and continue.
00076     Matrix rot_y;
00077     rot_y = Matrix::rotate_mat_normaxis(-heading, FLOATNAME(LVector3)(0.0f, 1.0f, 0.0f),
00078                                CS_yup_right);
00079 
00080     x = x * rot_y;
00081     y = y * rot_y;
00082     z = z * rot_y;
00083 
00084     // Project the rotated Z into the YZ plane.
00085     FLOATNAME(LVector2) yz(z[1], z[2]);
00086     yz = normalize(yz);
00087 
00088     // Compute the rotation about the +X (right) axis.  This is pitch.
00089     FLOATTYPE pitch = rad_2_deg((FLOATTYPE)(-atan2(yz[0], yz[1])));
00090 
00091     // Unwind the pitch.
00092     Matrix rot_x;
00093     rot_x = Matrix::rotate_mat_normaxis(-pitch, FLOATNAME(LVector3)(1.0f, 0.0f, 0.0f),
00094                                CS_yup_right);
00095 
00096     x = x * rot_x;
00097     y = y * rot_x;
00098     z = z * rot_x;
00099 
00100     // Project the rotated X onto the XY plane.
00101     FLOATNAME(LVector2) xy(x[0], x[1]);
00102     xy = normalize(xy);
00103 
00104     // Compute the rotation about the +Z (back) axis.  This is roll.
00105     FLOATTYPE roll = -rad_2_deg(((FLOATTYPE)atan2(xy[1], xy[0])));
00106 
00107     // Unwind the roll from the axes, and continue.
00108     Matrix rot_z;
00109     rot_z = Matrix::rotate_mat_normaxis(-roll, FLOATNAME(LVector3)(0.0f, 0.0f, 1.0f),
00110                                CS_yup_right);
00111 
00112     x = x * rot_z;
00113     y = y * rot_z;
00114     z = z * rot_z;
00115 
00116     // Reset the matrix to reflect the unwinding.
00117     mat.set_row(0, x);
00118     mat.set_row(1, y);
00119     mat.set_row(2, z);
00120 
00121     // Return the three rotation components.
00122     hpr[0] = heading;
00123     hpr[1] = pitch;
00124     hpr[2] = roll;
00125   } else {
00126 
00127     // Extract the axes from the matrix.
00128     FLOATNAME(LVector3) x, y, z;
00129     mat.get_row(x,0);
00130     mat.get_row(y,1);
00131     mat.get_row(z,2);
00132 
00133     // Project X onto the XY plane.
00134     FLOATNAME(LVector2) xy(x[0], x[1]);
00135     xy = normalize(xy);
00136 
00137     // Compute the rotation about the +Z (back) axis.  This is roll.
00138     FLOATTYPE roll = rad_2_deg(((FLOATTYPE)atan2(xy[1], xy[0])));
00139 
00140     // Unwind the roll from the axes, and continue.
00141     Matrix rot_z;
00142     rot_z = Matrix::rotate_mat_normaxis(-roll, FLOATNAME(LVector3)(0.0f, 0.0f, 1.0f),
00143                                CS_yup_right);
00144 
00145     x = x * rot_z;
00146     y = y * rot_z;
00147     z = z * rot_z;
00148 
00149     // Project the rotated X into the XZ plane.
00150     FLOATNAME(LVector2) xz(x[0], x[2]);
00151     xz = normalize(xz);
00152 
00153     // Compute the rotation about the +Y (up) axis.  This is yaw, or
00154     // "heading".
00155     FLOATTYPE heading = rad_2_deg(((FLOATTYPE)-atan2(xz[1], xz[0])));
00156 
00157     // Unwind the heading, and continue.
00158     Matrix rot_y;
00159     rot_y = Matrix::rotate_mat_normaxis(-heading, FLOATNAME(LVector3)(0.0f, 1.0f, 0.0f),
00160                                CS_yup_right);
00161 
00162     x = x * rot_y;
00163     y = y * rot_y;
00164     z = z * rot_y;
00165 
00166     // Project the rotated Z into the YZ plane.
00167     FLOATNAME(LVector2) yz(z[1], z[2]);
00168     yz = normalize(yz);
00169 
00170     // Compute the rotation about the +X (right) axis.  This is pitch.
00171     FLOATTYPE pitch = rad_2_deg(((FLOATTYPE)-atan2(yz[0], yz[1])));
00172 
00173     // Unwind the pitch.
00174     Matrix rot_x;
00175     rot_x = Matrix::rotate_mat_normaxis(-pitch, FLOATNAME(LVector3)(1.0f, 0.0f, 0.0f),
00176                                CS_yup_right);
00177 
00178     x = x * rot_x;
00179     y = y * rot_x;
00180     z = z * rot_x;
00181 
00182     // Reset the matrix to reflect the unwinding.
00183     mat.set_row(0, x);
00184     mat.set_row(1, y);
00185     mat.set_row(2, z);
00186 
00187     // Return the three rotation components.
00188     hpr[0] = heading;
00189     hpr[1] = pitch;
00190     hpr[2] = roll;
00191   }
00192 }
00193 
00194 ////////////////////////////////////////////////////////////////////
00195 //     Function: unwind_yup_rotation
00196 //  Description: Extracts the rotation about the x, y, and z axes from
00197 //               the given hpr & scale matrix, given the indicated
00198 //               roll amount as a hint.  Adjusts the matrix to
00199 //               eliminate the rotation.
00200 //
00201 //               This function assumes the matrix is stored in a
00202 //               right-handed Y-up coordinate system.
00203 ////////////////////////////////////////////////////////////////////
00204 static void
00205 unwind_yup_rotation(FLOATNAME(LMatrix3) &mat, FLOATNAME(LVecBase3) &hpr,
00206                     FLOATTYPE roll) {
00207   if (temp_hpr_fix) {
00208     unwind_yup_rotation(mat, hpr);
00209     return;
00210   }
00211 
00212   typedef FLOATNAME(LMatrix3) Matrix;
00213 
00214   // Extract the axes from the matrix.
00215   FLOATNAME(LVector3) x, y, z;
00216   mat.get_row(x,0);
00217   mat.get_row(y,1);
00218   mat.get_row(z,2);
00219 
00220   // Unwind the roll from the axes, and continue.
00221   Matrix rot_z;
00222   rot_z = Matrix::rotate_mat_normaxis(-roll, FLOATNAME(LVector3)(0.0f, 0.0f, 1.0f),
00223                              CS_yup_right);
00224 
00225   x = x * rot_z;
00226   y = y * rot_z;
00227   z = z * rot_z;
00228 
00229   // Project the rotated X into the XZ plane.
00230   FLOATNAME(LVector2) xz(x[0], x[2]);
00231   xz = normalize(xz);
00232 
00233   // Compute the rotation about the +Y (up) axis.  This is yaw, or
00234   // "heading".
00235   FLOATTYPE heading = rad_2_deg(((FLOATTYPE)-atan2(xz[1], xz[0])));
00236 
00237   // Unwind the heading, and continue.
00238   Matrix rot_y;
00239   rot_y = Matrix::rotate_mat_normaxis(-heading, FLOATNAME(LVector3)(0.0f, 1.0f, 0.0f),
00240                              CS_yup_right);
00241 
00242   x = x * rot_y;
00243   y = y * rot_y;
00244   z = z * rot_y;
00245 
00246   // Project the rotated Z into the YZ plane.
00247   FLOATNAME(LVector2) yz(z[1], z[2]);
00248   yz = normalize(yz);
00249 
00250   // Compute the rotation about the +X (right) axis.  This is pitch.
00251   FLOATTYPE pitch = rad_2_deg(((FLOATTYPE)-atan2(yz[0], yz[1])));
00252 
00253   // Unwind the pitch.
00254   Matrix rot_x;
00255   rot_x = Matrix::rotate_mat_normaxis(-pitch, FLOATNAME(LVector3)(1.0f, 0.0f, 0.0f),
00256                              CS_yup_right);
00257 
00258   x = x * rot_x;
00259   y = y * rot_x;
00260   z = z * rot_x;
00261 
00262   // Reset the matrix to reflect the unwinding.
00263   mat.set_row(0, x);
00264   mat.set_row(1, y);
00265   mat.set_row(2, z);
00266 
00267   // Return the three rotation components.
00268   hpr[0] = heading;
00269   hpr[1] = pitch;
00270   hpr[2] = roll;
00271 }
00272 
00273 ////////////////////////////////////////////////////////////////////
00274 //     Function: unwind_zup_rotation
00275 //  Description: Extracts the rotation about the x, y, and z axes from
00276 //               the given hpr & scale matrix.  Adjusts the matrix
00277 //               to eliminate the rotation.
00278 //
00279 //               This function assumes the matrix is stored in a
00280 //               right-handed Z-up coordinate system.
00281 ////////////////////////////////////////////////////////////////////
00282 static void
00283 unwind_zup_rotation(FLOATNAME(LMatrix3) &mat, FLOATNAME(LVecBase3) &hpr) {
00284   if (temp_hpr_fix) {
00285     typedef FLOATNAME(LMatrix3) Matrix;
00286 
00287     // Extract the axes from the matrix.
00288     FLOATNAME(LVector3) x, y, z;
00289     mat.get_row(x,0);
00290     mat.get_row(y,1);
00291     mat.get_row(z,2);
00292 
00293     // Project Y into the XY plane.
00294     FLOATNAME(LVector2) xy(y[0], y[1]);
00295     xy = normalize(xy);
00296 
00297     // Compute the rotation about the +Z (up) axis.  This is yaw, or
00298     // "heading".
00299     FLOATTYPE heading = -rad_2_deg(((FLOATTYPE)atan2(xy[0], xy[1])));
00300 
00301     // Unwind the heading, and continue.
00302     Matrix rot_z;
00303     rot_z = Matrix::rotate_mat_normaxis(-heading, FLOATNAME(LVector3)(0.0f, 0.0f, 1.0f),
00304                                CS_zup_right);
00305 
00306     x = x * rot_z;
00307     y = y * rot_z;
00308     z = z * rot_z;
00309 
00310     // Project the rotated Y into the YZ plane.
00311     FLOATNAME(LVector2) yz(y[1], y[2]);
00312     yz = normalize(yz);
00313 
00314     // Compute the rotation about the +X (right) axis.  This is pitch.
00315     FLOATTYPE pitch = rad_2_deg(((FLOATTYPE)atan2(yz[1], yz[0])));
00316 
00317     // Unwind the pitch.
00318     Matrix rot_x;
00319     rot_x = Matrix::rotate_mat_normaxis(-pitch, FLOATNAME(LVector3)(1.0f, 0.0f, 0.0f),
00320                                CS_zup_right);
00321 
00322     x = x * rot_x;
00323     y = y * rot_x;
00324     z = z * rot_x;
00325 
00326     // Project X into the XZ plane.
00327     FLOATNAME(LVector2) xz(x[0], x[2]);
00328     xz = normalize(xz);
00329 
00330     // Compute the rotation about the -Y (back) axis.  This is roll.
00331     FLOATTYPE roll = -rad_2_deg(((FLOATTYPE)atan2(xz[1], xz[0])));
00332 
00333     // Unwind the roll from the axes, and continue.
00334     Matrix rot_y;
00335     rot_y = Matrix::rotate_mat_normaxis(-roll, FLOATNAME(LVector3)(0.0f, 1.0f, 0.0f),
00336                                CS_zup_right);
00337 
00338     x = x * rot_y;
00339     y = y * rot_y;
00340     z = z * rot_y;
00341 
00342     // Reset the matrix to reflect the unwinding.
00343     mat.set_row(0, x);
00344     mat.set_row(1, y);
00345     mat.set_row(2, z);
00346 
00347     // Return the three rotation components.
00348     hpr[0] = heading;
00349     hpr[1] = pitch;
00350     hpr[2] = roll;
00351 
00352   } else {
00353     typedef FLOATNAME(LMatrix3) Matrix;
00354 
00355     // Extract the axes from the matrix.
00356     FLOATNAME(LVector3) x, y, z;
00357     mat.get_row(x,0);
00358     mat.get_row(y,1);
00359     mat.get_row(z,2);
00360 
00361 
00362     // Project X into the XZ plane.
00363     FLOATNAME(LVector2) xz(x[0], x[2]);
00364     xz = normalize(xz);
00365 
00366     // Compute the rotation about the -Y (back) axis.  This is roll.
00367     FLOATTYPE roll = rad_2_deg(((FLOATTYPE)atan2(xz[1], xz[0])));
00368 
00369     if (y[1] < 0.0f) {
00370       if (roll < 0.0f) {
00371         roll += 180.0;
00372       } else {
00373         roll -= 180.0;
00374       }
00375     }
00376 
00377     // Unwind the roll from the axes, and continue.
00378     Matrix rot_y;
00379     rot_y = Matrix::rotate_mat_normaxis(roll, FLOATNAME(LVector3)(0.0f, 1.0f, 0.0f),
00380                                CS_zup_right);
00381 
00382     x = x * rot_y;
00383     y = y * rot_y;
00384     z = z * rot_y;
00385 
00386     // Project the rotated X into the XY plane.
00387     FLOATNAME(LVector2) xy(x[0], x[1]);
00388     xy = normalize(xy);
00389 
00390     // Compute the rotation about the +Z (up) axis.  This is yaw, or
00391     // "heading".
00392     FLOATTYPE heading = rad_2_deg(((FLOATTYPE)atan2(xy[1], xy[0])));
00393 
00394     // Unwind the heading, and continue.
00395     Matrix rot_z;
00396     rot_z = Matrix::rotate_mat_normaxis(-heading, FLOATNAME(LVector3)(0.0f, 0.0f, 1.0f),
00397                                CS_zup_right);
00398 
00399     x = x * rot_z;
00400     y = y * rot_z;
00401     z = z * rot_z;
00402 
00403     // Project the rotated Y into the YZ plane.
00404     FLOATNAME(LVector2) yz(y[1], y[2]);
00405     yz = normalize(yz);
00406 
00407     // Compute the rotation about the +X (right) axis.  This is pitch.
00408     FLOATTYPE pitch = rad_2_deg(((FLOATTYPE)atan2(yz[1], yz[0])));
00409 
00410     // Unwind the pitch.
00411     Matrix rot_x;
00412     rot_x = Matrix::rotate_mat_normaxis(-pitch, FLOATNAME(LVector3)(1.0f, 0.0f, 0.0f),
00413                                CS_zup_right);
00414 
00415     x = x * rot_x;
00416     y = y * rot_x;
00417     z = z * rot_x;
00418 
00419     // Reset the matrix to reflect the unwinding.
00420     mat.set_row(0, x);
00421     mat.set_row(1, y);
00422     mat.set_row(2, z);
00423 
00424     // Return the three rotation components.
00425     hpr[0] = heading;
00426     hpr[1] = pitch;
00427     hpr[2] = roll;
00428   }
00429 }
00430 
00431 ////////////////////////////////////////////////////////////////////
00432 //     Function: unwind_zup_rotation
00433 //  Description: Extracts the rotation about the x, y, and z axes from
00434 //               the given hpr & scale matrix, given the indicated
00435 //               roll amount as a hint.  Adjusts the matrix to
00436 //               eliminate the rotation.
00437 //
00438 //               This function assumes the matrix is stored in a
00439 //               right-handed Z-up coordinate system.
00440 ////////////////////////////////////////////////////////////////////
00441 static void
00442 unwind_zup_rotation(FLOATNAME(LMatrix3) &mat, FLOATNAME(LVecBase3) &hpr,
00443                     FLOATTYPE roll) {
00444   if (temp_hpr_fix) {
00445     unwind_zup_rotation(mat, hpr);
00446     return;
00447   }
00448 
00449   typedef FLOATNAME(LMatrix3) Matrix;
00450 
00451   // Extract the axes from the matrix.
00452   FLOATNAME(LVector3) x, y, z;
00453   mat.get_row(x,0);
00454   mat.get_row(y,1);
00455   mat.get_row(z,2);
00456 
00457   // Unwind the roll from the axes, and continue.
00458   Matrix rot_y;
00459   rot_y = Matrix::rotate_mat_normaxis(roll, FLOATNAME(LVector3)(0.0f, 1.0f, 0.0f),
00460                              CS_zup_right);
00461 
00462   x = x * rot_y;
00463   y = y * rot_y;
00464   z = z * rot_y;
00465 
00466   // Project the rotated X into the XY plane.
00467   FLOATNAME(LVector2) xy(x[0], x[1]);
00468   xy = normalize(xy);
00469 
00470   // Compute the rotation about the +Z (up) axis.  This is yaw, or
00471   // "heading".
00472   FLOATTYPE heading = rad_2_deg(((FLOATTYPE)atan2(xy[1], xy[0])));
00473 
00474   // Unwind the heading, and continue.
00475   Matrix rot_z;
00476   rot_z = Matrix::rotate_mat_normaxis(-heading, FLOATNAME(LVector3)(0.0f, 0.0f, 1.0f),
00477                              CS_zup_right);
00478 
00479   x = x * rot_z;
00480   y = y * rot_z;
00481   z = z * rot_z;
00482 
00483   // Project the rotated Y into the YZ plane.
00484   FLOATNAME(LVector2) yz(y[1], y[2]);
00485   yz = normalize(yz);
00486 
00487   // Compute the rotation about the +X (right) axis.  This is pitch.
00488   FLOATTYPE pitch = rad_2_deg(((FLOATTYPE)atan2(yz[1], yz[0])));
00489 
00490   // Unwind the pitch.
00491   Matrix rot_x;
00492   rot_x = Matrix::rotate_mat_normaxis(-pitch, FLOATNAME(LVector3)(1.0f, 0.0f, 0.0f),
00493                              CS_zup_right);
00494 
00495   x = x * rot_x;
00496   y = y * rot_x;
00497   z = z * rot_x;
00498 
00499   // Reset the matrix to reflect the unwinding.
00500   mat.set_row(0, x);
00501   mat.set_row(1, y);
00502   mat.set_row(2, z);
00503 
00504   // Return the three rotation components.
00505   hpr[0] = heading;
00506   hpr[1] = pitch;
00507   hpr[2] = roll;
00508 }
00509 
00510 ////////////////////////////////////////////////////////////////////
00511 //     Function: decompose_matrix
00512 //  Description: Extracts out the components of a 3x3 rotation matrix.
00513 //               Returns true if the scale and hpr completely describe
00514 //               the matrix, or false if there is also a shear
00515 //               component or if the matrix is not affine.
00516 ////////////////////////////////////////////////////////////////////
00517 bool
00518 decompose_matrix(const FLOATNAME(LMatrix3) &mat,
00519                  FLOATNAME(LVecBase3) &scale,
00520                  FLOATNAME(LVecBase3) &hpr,
00521                  CoordinateSystem cs) {
00522   if (cs == CS_default) {
00523     cs = default_coordinate_system;
00524   }
00525 
00526   // Extract the rotation and scale, according to the coordinate
00527   // system of choice.
00528   bool bMatHasNoShear,bIsLeftHandedMat;
00529 
00530   FLOATNAME(LMatrix3) new_mat(mat);
00531 
00532   switch (cs) {
00533   case CS_zup_right:
00534     {
00535       unwind_zup_rotation(new_mat, hpr);
00536           bIsLeftHandedMat = false;
00537     }
00538     break;
00539 
00540   case CS_yup_right:
00541     {
00542       unwind_yup_rotation(new_mat, hpr);
00543           bIsLeftHandedMat = false;
00544         }
00545     break;
00546 
00547   case CS_zup_left:
00548     {
00549           new_mat._m.m._02 = -new_mat._m.m._02;
00550           new_mat._m.m._12 = -new_mat._m.m._12;
00551           new_mat._m.m._20 = -new_mat._m.m._20;
00552           new_mat._m.m._21 = -new_mat._m.m._21;
00553 /*
00554       FLOATNAME(LMatrix3) lm(mat(0, 0), mat(0, 1), -mat(0, 2),
00555                            mat(1, 0), mat(1, 1), -mat(1, 2),
00556                            -mat(2, 0), -mat(2, 1), mat(2, 2));
00557 */
00558       unwind_zup_rotation(new_mat, hpr);
00559           bIsLeftHandedMat = true;
00560     }
00561     break;
00562 
00563   case CS_yup_left:
00564     {
00565           new_mat._m.m._02 = -new_mat._m.m._02;
00566           new_mat._m.m._12 = -new_mat._m.m._12;
00567           new_mat._m.m._20 = -new_mat._m.m._20;
00568           new_mat._m.m._21 = -new_mat._m.m._21;
00569 /*
00570       FLOATNAME(LMatrix3) lm(mat(0, 0), mat(0, 1), -mat(0, 2),
00571                            mat(1, 0), mat(1, 1), -mat(1, 2),
00572                            -mat(2, 0), -mat(2, 1), mat(2, 2));
00573 */
00574       unwind_yup_rotation(new_mat, hpr);
00575           bIsLeftHandedMat = true;
00576     }
00577     break;
00578 
00579   default:
00580     linmath_cat.error()
00581       << "Unexpected coordinate system: " << (int)cs << "\n";
00582     return false;
00583   }
00584 
00585    scale[2] = new_mat._m.m._22;
00586    if(bIsLeftHandedMat) {
00587            scale[0] = -new_mat._m.m._00;
00588            scale[1] = -new_mat._m.m._11;
00589    } else {
00590            scale[0] = new_mat._m.m._00;
00591            scale[1] = new_mat._m.m._11;
00592    }
00593 
00594    bMatHasNoShear =
00595         (fabs(new_mat(0, 1)) + fabs(new_mat(0, 2)) +
00596          fabs(new_mat(1, 0)) + fabs(new_mat(1, 2)) +
00597          fabs(new_mat(2, 0)) + fabs(new_mat(2, 1))) < 0.0001;
00598 
00599   return bMatHasNoShear;
00600 }
00601 
00602 ////////////////////////////////////////////////////////////////////
00603 //     Function: decompose_matrix
00604 //  Description: Extracts out the components of a 3x3 rotation matrix.
00605 //               Returns true if the scale and hpr completely describe
00606 //               the matrix, or false if there is also a shear
00607 //               component or if the matrix is not affine.
00608 //
00609 //               This flavor of the function accepts an expected roll
00610 //               amount.  This amount will be used as the roll
00611 //               component, rather than attempting to determine roll
00612 //               by examining the matrix; this helps alleviate roll
00613 //               instability due to roundoff errors or gimbal lock.
00614 ////////////////////////////////////////////////////////////////////
00615 bool
00616 decompose_matrix(const FLOATNAME(LMatrix3) &mat,
00617                  FLOATNAME(LVecBase3) &scale,
00618                  FLOATNAME(LVecBase3) &hpr,
00619                  FLOATTYPE roll,
00620                  CoordinateSystem cs) {
00621   if (cs == CS_default) {
00622     cs = default_coordinate_system;
00623   }
00624 
00625   // Extract the rotation and scale, according to the coordinate
00626   // system of choice.
00627   bool bMatHasNoShear,bIsLeftHandedMat;
00628 
00629   FLOATNAME(LMatrix3) new_mat(mat);
00630 
00631   switch (cs) {
00632   case CS_zup_right:
00633     {
00634       unwind_zup_rotation(new_mat, hpr, roll);
00635           bIsLeftHandedMat = false;
00636     }
00637     break;
00638 
00639   case CS_yup_right:
00640     {
00641       unwind_yup_rotation(new_mat, hpr, roll);
00642           bIsLeftHandedMat = false;
00643         }
00644     break;
00645 
00646   case CS_zup_left:
00647     {
00648           new_mat._m.m._02 = -new_mat._m.m._02;
00649           new_mat._m.m._12 = -new_mat._m.m._12;
00650           new_mat._m.m._20 = -new_mat._m.m._20;
00651           new_mat._m.m._21 = -new_mat._m.m._21;
00652 /*
00653       FLOATNAME(LMatrix3) lm(mat(0, 0), mat(0, 1), -mat(0, 2),
00654                            mat(1, 0), mat(1, 1), -mat(1, 2),
00655                            -mat(2, 0), -mat(2, 1), mat(2, 2));
00656 */
00657       unwind_zup_rotation(new_mat, hpr, roll);
00658           bIsLeftHandedMat = true;
00659     }
00660     break;
00661 
00662   case CS_yup_left:
00663     {
00664           new_mat._m.m._02 = -new_mat._m.m._02;
00665           new_mat._m.m._12 = -new_mat._m.m._12;
00666           new_mat._m.m._20 = -new_mat._m.m._20;
00667           new_mat._m.m._21 = -new_mat._m.m._21;
00668 /*
00669       FLOATNAME(LMatrix3) lm(mat(0, 0), mat(0, 1), -mat(0, 2),
00670                            mat(1, 0), mat(1, 1), -mat(1, 2),
00671                            -mat(2, 0), -mat(2, 1), mat(2, 2));
00672 */
00673       unwind_yup_rotation(new_mat, hpr, roll);
00674           bIsLeftHandedMat = true;
00675     }
00676     break;
00677 
00678   default:
00679     linmath_cat.error()
00680       << "Unexpected coordinate system: " << (int)cs << "\n";
00681     return false;
00682   }
00683 
00684    scale[2] = new_mat._m.m._22;
00685    if(bIsLeftHandedMat) {
00686            scale[0] = -new_mat._m.m._00;
00687            scale[1] = -new_mat._m.m._11;
00688    } else {
00689            scale[0] = new_mat._m.m._00;
00690            scale[1] = new_mat._m.m._11;
00691    }
00692 
00693    bMatHasNoShear =
00694         (fabs(new_mat(0, 1)) + fabs(new_mat(0, 2)) +
00695          fabs(new_mat(1, 0)) + fabs(new_mat(1, 2)) +
00696          fabs(new_mat(2, 0)) + fabs(new_mat(2, 1))) < 0.0001;
00697 
00698   return bMatHasNoShear;
00699 }
00700 

Generated on Fri May 2 00:40:02 2003 for Panda by doxygen1.3