glut/lib/gle/view.c
/*
 * The uview_dire subroutine computes and returns a 4x4 rotation
 * matrix that puts the negative z axis along the direction v21 and 
 * puts the y axis along the up vector.
 * 
 * It computes exactly the same matrix as the code above
 * (uview_direction), but with an entirely different (and slower)
 * algorithm.
 *
 * Note that the code below is slightly less robust than that above --
 * it may croak if the supplied vectors are of zero length, or are
 * parallel to each other ... 
 */
The uview_dire subroutine computes and returns a 4x4 rotation
matrix that puts the negative z axis along the direction v21 and
puts the y axis along the up vector.

It computes exactly the same matrix as the code above
(uview_direction), but with an entirely different (and slower)
algorithm.

Note that the code below is slightly less robust than that above
it may croak if the supplied vectors are of zero length, or are
parallel to each other
The uview_dire subroutine computes and returns a 4x4 rotation matrix that puts the negative z axis along the direction v21 and puts the y axis along the up vector . It computes exactly the same matrix as the code above ( uview_direction ) but with an entirely different ( and slower ) algorithm . Note that the code below is slightly less robust than that above it may croak if the supplied vectors are of zero length or are parallel to each other
void uview_dire (float m[4][4],		
                 float v21[3],		
                 float up[3])		
{
   double theta;
   float v_hat_21 [3];
   float z_hat [3];
   float v_cross_z [3];
   float u[3];
   float y_hat [3];
   float u_cross_y [3];
   double cosine;
   float zmat [4][4];
   float upmat[4][4];
   float dot;
   if ((v21[0] != 0.0 ) || (v21[1] != 0.0)) {
      VEC_COPY (v_hat_21, v21);    
      VEC_NORMALIZE (v_hat_21);
      cosine = - v_hat_21 [2];
      theta = - acos (cosine);
      z_hat[0] = 0.0;
      z_hat[1] = 0.0;
      z_hat[2] = -1.0;
      VEC_CROSS_PRODUCT (v_cross_z, v_hat_21, z_hat);
      VEC_NORMALIZE (v_cross_z);
      urot_axis (zmat, (float) theta, v_cross_z);
   } else {
      IDENTIFY_MATRIX_4X4 (zmat);
      if (v21[2] > 0.0) {
         zmat[0][0] = -1.0;
         zmat[2][2] = -1.0;
      }
   }
   VEC_COPY (u, up);
   VEC_PERP (u, u, v_hat_21);
   y_hat[0] = zmat [1][0];
   y_hat[1] = zmat [1][1];
   y_hat[2] = zmat [1][2];
   VEC_DOT_PRODUCT (dot, y_hat, u);
   if ((-1.0 < dot) && (dot < 1.0))  {
      VEC_NORMALIZE (u);
      VEC_DOT_PRODUCT (cosine, u, y_hat);
      theta = - acos (cosine);
      VEC_CROSS_PRODUCT (u_cross_y, u, y_hat);
      VEC_NORMALIZE (u_cross_y);
      urot_axis (upmat, (float) theta, u_cross_y);
   } else {
      IDENTIFY_MATRIX_4X4 (upmat);
      if (dot == -1.0) {
         upmat[0][0] = -1.0;
         upmat[1][1] = -1.0;
      }
   }
   MATRIX_PRODUCT_4X4 (m, zmat, upmat);
}
void uview_dire ( float m [ 4 ] [ 4 ] , float v21 [ 3 ] , float up [ 3 ] ) { double theta ; float v_hat_21 [ 3 ] ; float z_hat [ 3 ] ; float v_cross_z [ 3 ] ; float u [ 3 ] ; float y_hat [ 3 ] ; float u_cross_y [ 3 ] ; double cosine ; float zmat [ 4 ] [ 4 ] ; float upmat [ 4 ] [ 4 ] ; float dot ; if ( ( v21 [ 0 ] != 0.0 ) || ( v21 [ 1 ] != 0.0 ) ) { VEC_COPY ( v_hat_21 , v21 ) ; VEC_NORMALIZE ( v_hat_21 ) ; cosine = - v_hat_21 [ 2 ] ; theta = - acos ( cosine ) ; z_hat [ 0 ] = 0.0 ; z_hat [ 1 ] = 0.0 ; z_hat [ 2 ] = -1.0 ; VEC_CROSS_PRODUCT ( v_cross_z , v_hat_21 , z_hat ) ; VEC_NORMALIZE ( v_cross_z ) ; urot_axis ( zmat , ( float ) theta , v_cross_z ) ; } else { IDENTIFY_MATRIX_4X4 ( zmat ) ; if ( v21 [ 2 ] > 0.0 ) { zmat [ 0 ] [ 0 ] = -1.0 ; zmat [ 2 ] [ 2 ] = -1.0 ; } } VEC_COPY ( u , up ) ; VEC_PERP ( u , u , v_hat_21 ) ; y_hat [ 0 ] = zmat [ 1 ] [ 0 ] ; y_hat [ 1 ] = zmat [ 1 ] [ 1 ] ; y_hat [ 2 ] = zmat [ 1 ] [ 2 ] ; VEC_DOT_PRODUCT ( dot , y_hat , u ) ; if ( ( -1.0 < dot ) && ( dot < 1.0 ) ) { VEC_NORMALIZE ( u ) ; VEC_DOT_PRODUCT ( cosine , u , y_hat ) ; theta = - acos ( cosine ) ; VEC_CROSS_PRODUCT ( u_cross_y , u , y_hat ) ; VEC_NORMALIZE ( u_cross_y ) ; urot_axis ( upmat , ( float ) theta , u_cross_y ) ; } else { IDENTIFY_MATRIX_4X4 ( upmat ) ; if ( dot == -1.0 ) { upmat [ 0 ] [ 0 ] = -1.0 ; upmat [ 1 ] [ 1 ] = -1.0 ; } } MATRIX_PRODUCT_4X4 ( m , zmat , upmat ) ; }
The uview_dire subroutine computes and returns a 4x4 rotation
 matrix that puts the negative z axis along the direction v21 and
 puts the y axis along the up vector.
The uview_dire subroutine computes and returns a 4x4 rotation matrix that puts the negative z axis along the direction v21 and puts the y axis along the up vector .
/* returned */ /* input */ /* input */ /* perform rotation to z-axis only if not already 
    * pointing down z */ /* find the unit vector that points in the v21 direction */ /* cosine theta equals v_hat dot z_hat */ /* Take cros product with z -- we need this, because we will rotate
       * about this axis */ /* compute rotation matrix that takes -z axis to the v21 axis */ /* if its pointing down the positive z-axis, flip it, so that
          * we point down negative z-axis.  We flip x so that the partiy
          * isn't destroyed (looks like a rotation)
          */ /* --------------------- */ /* OK, now compute the part that takes the y-axis to the up vector */ /* the rotation blows up, if the up vector is not perpendicular to
    * the v21 vector.  Let us make sure that this is so. */ /* need to run the y axis through above x-form, to see where it went */ /* perform rotation to up-axis only if not already 
    * pointing along y axis */ /* make sure that up really is a unit vector */ /* cosine phi equals y_hat dot up_vec */ /* Take cross product with y */ /* As a matter of fact, u_cross_y points either in the v21 direction,
       * or in the minus v21 direction.  In either case, we needed to compute 
       * it, because the the arccosine function returns values only for 
       * 0 to 180 degree, not 0 to 360, which is what we need.  The 
       * cross-product helps us make up for this.
       */ /* rotate about the NEW z axis (i.e. v21) by the cosine */ /* if its pointing along the negative y-axis, flip it, so that
          * we point along the positive y-axis.  We flip x so that the partiy
          * isn't destroyed (looks like a rotation)
          */