home *** CD-ROM | disk | FTP | other *** search
/ Photo CD Demo 1 / Demo.bin / gems / gemsiii / rnd_rttn.c < prev    next >
C/C++ Source or Header  |  1992-03-16  |  3KB  |  67 lines

  1.  
  2. #include <math.h>
  3. #include "GraphicsGems.h"
  4.  
  5. /*=========================================================================*
  6.  *  R A N D _ R O T A T I O N      Author: Jim Arvo, 1991                  *
  7.  *                                                                         *
  8.  *  This routine maps three values (x[0], x[1], x[2]) in the range [0,1]   *
  9.  *  into a 3x3 rotation matrix, M.  Uniformly distributed random variables *
  10.  *  x0, x1, and x2 create uniformly distributed random rotation matrices.  *
  11.  *  To create small uniformly distributed "perturbations", supply          *
  12.  *  samples in the following ranges                                        *
  13.  *                                                                         *
  14.  *      x[0] in [ 0, d ]                                                   *
  15.  *      x[1] in [ 0, 1 ]                                                   *
  16.  *      x[2] in [ 0, d ]                                                   *
  17.  *                                                                         *
  18.  * where 0 < d < 1 controls the size of the perturbation.  Any of the      *
  19.  * random variables may be stratified (or "jittered") for a slightly more  *
  20.  * even distribution.                                                      *
  21.  *                                                                         *
  22.  *=========================================================================*/
  23. void rand_rotation( float x[], Matrix3 *M )
  24.     {
  25.     float theta = x[0] * PITIMES2; /* Rotation about the pole (Z).      */
  26.     float phi   = x[1] * PITIMES2; /* For direction of pole deflection. */
  27.     float z     = x[2] * 2.0;      /* For magnitude of pole deflection. */
  28.  
  29.     /* Compute a vector V used for distributing points over the sphere  */
  30.     /* via the reflection I - V Transpose(V).  This formulation of V    */
  31.     /* will guarantee that if x[1] and x[2] are uniformly distributed,  */
  32.     /* the reflected points will be uniform on the sphere.  Note that V */
  33.     /* has length sqrt(2) to eliminate the 2 in the Householder matrix. */
  34.  
  35.     float r  = sqrt( z );
  36.     float Vx = sin( phi ) * r;
  37.     float Vy = cos( phi ) * r;
  38.     float Vz = sqrt( 2.0 - z );    
  39.  
  40.     /* Compute the row vector S = Transpose(V) * R, where R is a simple */
  41.     /* rotation by theta about the z-axis.  No need to compute Sz since */
  42.     /* it's just Vz.                                                    */
  43.  
  44.     float st = sin( theta );
  45.     float ct = cos( theta );
  46.     float Sx = Vx * ct - Vy * st;
  47.     float Sy = Vx * st + Vy * ct;
  48.  
  49.     /* Construct the rotation matrix  ( V Transpose(V) - I ) R, which   */
  50.     /* is equivalent to V S - R.                                        */
  51.  
  52.     M->element[0][0] = Vx * Sx - ct;
  53.     M->element[0][1] = Vx * Sy - st;
  54.     M->element[0][2] = Vx * Vz;
  55.  
  56.     M->element[1][0] = Vy * Sx + st;
  57.     M->element[1][1] = Vy * Sy - ct;
  58.     M->element[1][2] = Vy * Vz;
  59.  
  60.     M->element[2][0] = Vz * Sx;
  61.     M->element[2][1] = Vz * Sy;
  62.     M->element[2][2] = 1.0 - z;   /* This equals Vz * Vz - 1.0 */
  63.     }
  64.  
  65.  
  66.  
  67.