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

panda/src/mathutil/look_at_src.cxx

Go to the documentation of this file.
00001 // Filename: look_at_src.cxx
00002 // Created by:  drose (25Apr97)
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 INLINE_MATHUTIL FLOATNAME(LMatrix3)
00020 make_xi_mat(const FLOATNAME(LVector2) &x) {
00021   return FLOATNAME(LMatrix3)(1.0f,     0,     0,
00022                              0,  x[0],  x[1],
00023                              0, -x[1],  x[0]);
00024 }
00025 
00026 
00027 INLINE_MATHUTIL FLOATNAME(LMatrix3)
00028 make_x_mat(const FLOATNAME(LVector2) &x) {
00029   return FLOATNAME(LMatrix3)(1.0f,     0,     0,
00030                              0,  x[1],  x[0],
00031                              0, -x[0],  x[1]);
00032 }
00033 
00034 
00035 INLINE_MATHUTIL FLOATNAME(LMatrix3)
00036 make_y_mat(const FLOATNAME(LVector2) &y) {
00037   return FLOATNAME(LMatrix3)(y[1],     0, -y[0],
00038                                 0,     1.0f,     0,
00039                              y[0],     0,  y[1]);
00040 }
00041 
00042 
00043 INLINE_MATHUTIL FLOATNAME(LMatrix3)
00044 make_z_mat(const FLOATNAME(LVector2) &z) {
00045   return FLOATNAME(LMatrix3)(z[1], -z[0],     0,
00046                              z[0],  z[1],     0,
00047                                 0,     0,     1.0f);
00048 }
00049 
00050 ////////////////////////////////////////////////////////////////////
00051 //     Function: heads_up
00052 //  Description: Given two vectors defining a forward direction and an
00053 //               up vector, constructs the matrix that rotates things
00054 //               from the defined coordinate system to y-forward and
00055 //               z-up.  The up vector will be rotated to z-up first,
00056 //               then the forward vector will be rotated as nearly to
00057 //               y-forward as possible.  This will only have a
00058 //               different effect from look_at() if the forward and up
00059 //               vectors are not perpendicular.
00060 ////////////////////////////////////////////////////////////////////
00061 void
00062 heads_up(FLOATNAME(LMatrix3) &mat, const FLOATNAME(LVector3) &fwd,
00063          const FLOATNAME(LVector3) &up, CoordinateSystem cs) {
00064   if (cs == CS_default) {
00065     cs = default_coordinate_system;
00066   }
00067 
00068   if (cs == CS_zup_right || cs == CS_zup_left) {
00069     // Z-up.
00070 
00071     // y is the projection of the up vector into the XZ plane.  Its
00072     // angle to the Z axis is the amount to rotate about the Y axis to
00073     // bring the up vector into the YZ plane.
00074 
00075     FLOATNAME(LVector2) y(up[0], up[2]);
00076     FLOATTYPE d = dot(y, y);
00077     if (d==0.0f) {
00078       y = FLOATNAME(LVector2)(0.0f, 1.0f);
00079     } else {
00080       y /= csqrt(d);
00081     }
00082 
00083     // x is the up vector rotated into the YZ plane.  Its angle to the Z
00084     // axis is the amount to rotate about the X axis to bring the up
00085     // vector to the Z axis.
00086 
00087     FLOATNAME(LVector2) x(up[1], up[0]*y[0]+up[2]*y[1]);
00088     d = dot(x, x);
00089     if (d==0.0f) {
00090       x = FLOATNAME(LVector2)(0.0f, 1.0f);
00091     } else {
00092       x /= csqrt(d);
00093     }
00094 
00095     // Now apply both rotations to the forward vector.  This will rotate
00096     // the forward vector by the same amount we would have had to rotate
00097     // the up vector to bring it to the Z axis.  If the vectors were
00098     // perpendicular, this will put the forward vector somewhere in the
00099     // XY plane.
00100 
00101     // z is the projection of the newly rotated fwd vector into the XY
00102     // plane.  Its angle to the Y axis is the amount to rotate about the
00103     // Z axis in order to bring the fwd vector to the Y axis.
00104     FLOATNAME(LVector2) z(fwd[0]*y[1] - fwd[2]*y[0],
00105                           -fwd[0]*y[0]*x[0] + fwd[1]*x[1] - fwd[2]*y[1]*x[0]);
00106     d = dot(z, z);
00107     if (d==0.0f) {
00108       z = FLOATNAME(LVector2)(0.0f, 1.0f);
00109     } else {
00110       z /= csqrt(d);
00111     }
00112 
00113     // Now build the net rotation matrix.
00114     if (cs == CS_zup_right) {
00115       mat =
00116         make_z_mat(z) *
00117         make_x_mat(x) *
00118         make_y_mat(y);
00119     } else { // cs == CS_zup_left
00120       mat =
00121         make_z_mat(z) *
00122         make_x_mat(-x) *
00123         make_y_mat(-y);
00124     }
00125   } else {
00126     // Y-up.
00127 
00128     // z is the projection of the forward vector into the XY plane.  Its
00129     // angle to the Y axis is the amount to rotate about the Z axis to
00130     // bring the forward vector into the YZ plane.
00131 
00132     FLOATNAME(LVector2) z(up[0], up[1]);
00133     FLOATTYPE d = dot(z, z);
00134     if (d==0.0f) {
00135       z = FLOATNAME(LVector2)(0.0f, 1.0f);
00136     } else {
00137       z /= csqrt(d);
00138     }
00139 
00140     // x is the forward vector rotated into the YZ plane.  Its angle to
00141     // the Y axis is the amount to rotate about the X axis to bring the
00142     // forward vector to the Y axis.
00143 
00144     FLOATNAME(LVector2) x(up[0]*z[0] + up[1]*z[1], up[2]);
00145     d = dot(x, x);
00146     if (d==0.0f) {
00147       x = FLOATNAME(LVector2)(1.0f, 0.0f);
00148     } else {
00149       x /= csqrt(d);
00150     }
00151 
00152     // Now apply both rotations to the up vector.  This will rotate
00153     // the up vector by the same amount we would have had to rotate
00154     // the forward vector to bring it to the Y axis.  If the vectors were
00155     // perpendicular, this will put the up vector somewhere in the
00156     // XZ plane.
00157 
00158     // y is the projection of the newly rotated up vector into the XZ
00159     // plane.  Its angle to the Z axis is the amount to rotate about the
00160     // Y axis in order to bring the up vector to the Z axis.
00161     FLOATNAME(LVector2) y(fwd[0]*z[1] - fwd[1]*z[0],
00162                           -fwd[0]*x[1]*z[0] - fwd[1]*x[1]*z[1] + fwd[2]*x[0]);
00163     d = dot(y, y);
00164     if (d==0.0f) {
00165       y = FLOATNAME(LVector2)(0.0f, 1.0f);
00166     } else {
00167       y /= csqrt(d);
00168     }
00169 
00170     // Now build the net rotation matrix.
00171     if (cs == CS_yup_right) {
00172       mat =
00173         make_y_mat(y) *
00174         make_xi_mat(-x) *
00175         make_z_mat(-z);
00176     } else { // cs == CS_yup_left
00177       mat =
00178         make_y_mat(y) *
00179         make_xi_mat(x) *
00180         make_z_mat(z);
00181     }
00182   }
00183 }
00184 
00185 
00186 ////////////////////////////////////////////////////////////////////
00187 //     Function: look_at
00188 //  Description: Given two vectors defining a forward direction and an
00189 //               up vector, constructs the matrix that rotates things
00190 //               from the defined coordinate system to y-forward and
00191 //               z-up.  The forward vector will be rotated to
00192 //               y-forward first, then the up vector will be rotated
00193 //               as nearly to z-up as possible.  This will only have a
00194 //               different effect from heads_up() if the forward and
00195 //               up vectors are not perpendicular.
00196 ////////////////////////////////////////////////////////////////////
00197 void
00198 look_at(FLOATNAME(LMatrix3) &mat, const FLOATNAME(LVector3) &fwd,
00199         const FLOATNAME(LVector3) &up, CoordinateSystem cs) {
00200   if (cs == CS_default) {
00201     cs = default_coordinate_system;
00202   }
00203 
00204   if (cs == CS_zup_right || cs == CS_zup_left) {
00205     // Z-up.
00206 
00207     // z is the projection of the forward vector into the XY plane.  Its
00208     // angle to the Y axis is the amount to rotate about the Z axis to
00209     // bring the forward vector into the YZ plane.
00210 
00211     FLOATNAME(LVector2) z(fwd[0], fwd[1]);
00212     FLOATTYPE d = dot(z, z);
00213     if (d==0.0f) {
00214       z = FLOATNAME(LVector2)(0.0f, 1.0f);
00215     } else {
00216       z /= csqrt(d);
00217     }
00218 
00219     // x is the forward vector rotated into the YZ plane.  Its angle to
00220     // the Y axis is the amount to rotate about the X axis to bring the
00221     // forward vector to the Y axis.
00222 
00223     FLOATNAME(LVector2) x(fwd[0]*z[0] + fwd[1]*z[1], fwd[2]);
00224     d = dot(x, x);
00225     if (d==0.0f) {
00226       x = FLOATNAME(LVector2)(1.0f, 0.0f);
00227     } else {
00228       x /= csqrt(d);
00229     }
00230 
00231     // Now apply both rotations to the up vector.  This will rotate
00232     // the up vector by the same amount we would have had to rotate
00233     // the forward vector to bring it to the Y axis.  If the vectors were
00234     // perpendicular, this will put the up vector somewhere in the
00235     // XZ plane.
00236 
00237     // y is the projection of the newly rotated up vector into the XZ
00238     // plane.  Its angle to the Z axis is the amount to rotate about the
00239     // Y axis in order to bring the up vector to the Z axis.
00240     FLOATNAME(LVector2) y(up[0]*z[1] - up[1]*z[0],
00241                           -up[0]*x[1]*z[0] - up[1]*x[1]*z[1] + up[2]*x[0]);
00242     d = dot(y, y);
00243     if (d==0.0f) {
00244       y = FLOATNAME(LVector2)(0.0f, 1.0f);
00245     } else {
00246       y /= csqrt(d);
00247     }
00248 
00249     // Now build the net rotation matrix.
00250     if (cs == CS_zup_right) {
00251       mat =
00252         make_y_mat(y) *
00253         make_xi_mat(x) *
00254         make_z_mat(z);
00255     } else { // cs == CS_zup_left
00256       mat =
00257         make_y_mat(-y) *
00258         make_xi_mat(-x) *
00259         make_z_mat(z);
00260     }
00261   } else {
00262     // Y-up.
00263 
00264     // y is the projection of the up vector into the XZ plane.  Its
00265     // angle to the Z axis is the amount to rotate about the Y axis to
00266     // bring the up vector into the YZ plane.
00267 
00268     FLOATNAME(LVector2) y(fwd[0], fwd[2]);
00269     FLOATTYPE d = dot(y, y);
00270     if (d==0.0f) {
00271       y = FLOATNAME(LVector2)(0.0f, 1.0f);
00272     } else {
00273       y /= csqrt(d);
00274     }
00275 
00276     // x is the up vector rotated into the YZ plane.  Its angle to the Z
00277     // axis is the amount to rotate about the X axis to bring the up
00278     // vector to the Z axis.
00279 
00280     FLOATNAME(LVector2) x(fwd[1], fwd[0]*y[0]+fwd[2]*y[1]);
00281     d = dot(x, x);
00282     if (d==0.0f) {
00283       x = FLOATNAME(LVector2)(0.0f, 1.0f);
00284     } else {
00285       x /= csqrt(d);
00286     }
00287 
00288     // Now apply both rotations to the forward vector.  This will rotate
00289     // the forward vector by the same amount we would have had to rotate
00290     // the up vector to bring it to the Z axis.  If the vectors were
00291     // perpendicular, this will put the forward vector somewhere in the
00292     // XY plane.
00293 
00294     // z is the projection of the newly rotated fwd vector into the XY
00295     // plane.  Its angle to the Y axis is the amount to rotate about the
00296     // Z axis in order to bring the fwd vector to the Y axis.
00297     FLOATNAME(LVector2) z(up[0]*y[1] - up[2]*y[0],
00298                           -up[0]*y[0]*x[0] + up[1]*x[1] - up[2]*y[1]*x[0]);
00299     d = dot(z, z);
00300     if (d==0.0f) {
00301       z = FLOATNAME(LVector2)(0.0f, 1.0f);
00302     } else {
00303       z /= csqrt(d);
00304     }
00305 
00306     // Now build the net rotation matrix.
00307     if (cs == CS_yup_right) {
00308       mat =
00309         make_z_mat(z) *
00310         make_x_mat(x) *
00311         make_y_mat(-y);
00312     } else { // cs == CS_yup_left
00313       mat =
00314         make_z_mat(-z) *
00315         make_x_mat(-x) *
00316         make_y_mat(-y);
00317     }
00318   }
00319 }

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