home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 10 / ioProg_10.iso / soft / optima / samples.z / grTransform.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-03-23  |  15.5 KB  |  545 lines

  1. #include <stdlib.h>
  2. #include <string.h>
  3. #include <math.h>
  4.  
  5. #include "grtransform.hpp"
  6.  
  7.  
  8. // ---------- grBaseTransform --------- //
  9.  
  10. grBaseTransform::grBaseTransform( void )        // DEFAULT CTOR -- IDENTITY
  11. //--------------------------------------
  12. {
  13.     uint    i, j;
  14.     double * row;
  15.  
  16.     for( i = 0; i < 4; i++ ) {
  17.         row = _storage + 4 * i;
  18.         _rows[ i ] = row;
  19.         for( j = 0; j < 4; j++ ) {
  20.             row[ j ] = 0.0;
  21.         }
  22.         row[ i ] = 1.0;
  23.     }
  24. }
  25.  
  26. grBaseTransform::grBaseTransform(               // COPY CTOR
  27.     const grBaseTransform & o )                 // -- transform to copy
  28. //-------------------------------
  29. {
  30.     uint i;
  31.  
  32.     for( i = 0; i < 4; i++ ) {
  33.         _rows[ i ] = _storage + 4 * i;
  34.     }
  35.     copy( o );
  36. }
  37.  
  38. void grBaseTransform::copy(                     // COPY ANOTHER TRANSFORM
  39.     const grBaseTransform & xfrm )              // -- transform to copy
  40. //--------------------------------
  41. {
  42.     memcpy( _storage, xfrm._storage, sizeof( double ) * 16 );
  43. }
  44.  
  45. grBaseTransform & grBaseTransform::operator =(  // ASSIGNMENT OPERATOR
  46.     const grBaseTransform & o )                 // -- transform to copy
  47. //--------------------------------------------
  48. {
  49.     copy( o );
  50.     return *this;
  51. }
  52.  
  53. grBaseTransform & grBaseTransform::operator *=( // LEFT MULTIPLY BY TRANSFORM
  54.     const grBaseTransform & xfrm )              // -- transform to multiply by
  55. //---------------------------------------------
  56. {
  57.     grBaseTransform     product;
  58.     uint                i, j;
  59.     double               tmp;
  60.     double *             row1;
  61.     double *             row2;
  62.  
  63.     for( i = 0; i < 4; i++ ) {
  64.         row1 = xfrm._rows[ i ];
  65.         row2 = product._rows[ i ];
  66.         for( j = 0; j < 4; j++ ) {
  67.             tmp = row1[ 0 ] * _rows[ 0 ][ j ];
  68.             tmp += row1[ 1 ] * _rows[ 1 ][ j ];
  69.             tmp += row1[ 2 ] * _rows[ 2 ][ j ];
  70.             tmp += row1[ 3 ] * _rows[ 3 ][ j ];
  71.             row2[ j ] = tmp;
  72.         }
  73.     }
  74.  
  75.     copy( product );
  76.  
  77.     return *this;
  78. }
  79.  
  80. grPoint3 & grBaseTransform::apply(          // APPLY TO A POINT
  81.     grPoint3 & point ) const                // -- point to apply to
  82. //--------------------------------
  83. {
  84.     uint    i;
  85.     double   result[ 4 ];
  86.     double * row;
  87.     double   tmp;
  88.  
  89.     for( i = 0; i < 4; i++ ) {
  90.         row = _rows[ i ];
  91.  
  92.         tmp = row[ 0 ] * point._coords[ 0 ];
  93.         tmp += row[ 1 ] * point._coords[ 1 ];
  94.         tmp += row[ 2 ] * point._coords[ 2 ];
  95.         tmp += row[ 3 ] * point._coords[ 3 ];
  96.         result[ i ] = tmp;
  97.     }
  98.  
  99.     /* copy result */
  100.     memcpy( point._coords, result, sizeof( double ) * 4 );
  101.  
  102.     return point;
  103. }
  104.  
  105. grVector & grBaseTransform::apply(          // APPLY TO A VECTOR
  106.     grVector & vec ) const                  // -- vector to apply to
  107. //--------------------------------
  108. {
  109.     uint    i;
  110.     double   result[ 4 ];
  111.     double * row;
  112.     double   tmp;
  113.  
  114.     for( i = 0; i < 4; i++ ) {
  115.         row = _rows[ i ];
  116.  
  117.         tmp = row[ 0 ] * vec._coords[ 0 ];
  118.         tmp += row[ 1 ] * vec._coords[ 1 ];
  119.         tmp += row[ 2 ] * vec._coords[ 2 ];
  120.         tmp += row[ 3 ] * vec._coords[ 3 ];
  121.         result[ i ] = tmp;
  122.     }
  123.  
  124.     /* copy result */
  125.     memcpy( vec._coords, result, sizeof( double ) * 4 );
  126.  
  127.     return vec;
  128. }
  129.  
  130. void grBaseTransform::transpose( void ) // TAKE TRANSPOSE OF MATRIX
  131. //-------------------------------------
  132. {
  133.     double tmp;
  134.     uint  i, j;
  135.  
  136.     for( i = 0; i < 4; i++ ) {
  137.         for( j = i + 1; j < 4; j++ ) {
  138.             tmp = _rows[ i ][ j ];
  139.             _rows[ i ][ j ] = _rows[ j ][ i ];
  140.             _rows[ j ][ i ] = tmp;
  141.         }
  142.     }
  143. }
  144.  
  145. // ----------- grChangeBase ----------- //
  146.  
  147. grChangeBase::grChangeBase(             // CONSTRUCTOR
  148.     const grPoint3 & origin,            // -- origin of new coordinates
  149.     const grVector & ux,                // -- unit vector along new x
  150.     const grVector & uy,                // -- unit vector along new y
  151.     const grVector & uz )               // -- unit vector along new z
  152. //--------------------------
  153. {
  154.     grTranslate trans( grPoint3Origin - origin );
  155.     grTransform rotate;
  156.     uint        i;
  157.  
  158. #if 0
  159.     grAssert( 1.0 - grEPSILON < ux.length() && ux.length() < 1.0 + grEPSILON );
  160.     grAssert( 1.0 - grEPSILON < uy.length() && uy.length() < 1.0 + grEPSILON );
  161.     grAssert( 1.0 - grEPSILON < uz.length() && uz.length() < 1.0 + grEPSILON );
  162.  
  163.     memcpy( rotate._rows[ 0 ], ux._coords, sizeof( double ) * 3 );
  164.     memcpy( rotate._rows[ 1 ], uy._coords, sizeof( double ) * 3 );
  165.     memcpy( rotate._rows[ 2 ], uz._coords, sizeof( double ) * 3 );
  166.  
  167.     copy( rotate );
  168.     *this *= trans;
  169. #else
  170.     memcpy( _rows[ 0 ], ux._coords, sizeof( double ) * 3 );
  171.     memcpy( _rows[ 1 ], uy._coords, sizeof( double ) * 3 );
  172.     memcpy( _rows[ 2 ], uz._coords, sizeof( double ) * 3 );
  173.  
  174.     for( i = 0; i < 3; i++ ) {
  175.         _rows[ i ][ 3 ] = -origin._coords[ i ];
  176.     }
  177. #endif
  178. }
  179.  
  180. // ------------ grRotation ------------ //
  181.  
  182. #if 1
  183. /*
  184.  * Rotate with a general origin and general rotation axis.
  185.  * - translate, rotate, rotate, rotate, rotate, rotate, translate
  186.  * Hearn and Baker p. 416
  187.  */
  188. grRotation::grRotation(                 // CONSTRUCTOR
  189.     const grPoint3 & origin,            // -- origin of rotation
  190.     const grVector & direct,            // -- second point for direction
  191.     double amount )                     // -- degrees counterclockwise
  192. //--------------------------
  193. {
  194.     grVector    axis( direct);
  195.     grTranslate trn( grPoint3Origin - origin ); 
  196.     grTranslate trn_inv( origin - grPoint3Origin );
  197.     grTransform Rx;
  198.     grTransform Ry;
  199.     grTransform Rz;
  200.     double       d;
  201.  
  202.     axis.normalize();
  203.     grAssert( dot( axis, axis ) > (1.0 - grEPSILON) );
  204.  
  205.     d = sqrt( axis.y() * axis.y() + axis.z() * axis.z() );
  206.     if( d > grEPSILON ) {
  207.         Rx._rows[ 1 ][ 1 ] = axis.z() / d;
  208.         Rx._rows[ 1 ][ 2 ] = -1.0 * axis.y() / d;
  209.         Rx._rows[ 2 ][ 1 ] = axis.y() / d;
  210.         Rx._rows[ 2 ][ 2 ] = axis.z() / d;
  211.     }
  212.  
  213.     Ry._rows[ 0 ][ 0 ] = d;
  214.     Ry._rows[ 0 ][ 2 ] = -1.0 *  axis.x();
  215.     Ry._rows[ 2 ][ 0 ] = axis.x();
  216.     Ry._rows[ 2 ][ 2 ] = d;
  217.  
  218.     Rz._rows[ 0 ][ 0 ] = cos( amount );
  219.     Rz._rows[ 0 ][ 1 ] = -1.0 * sin( amount );
  220.     Rz._rows[ 1 ][ 0 ] = sin( amount );
  221.     Rz._rows[ 1 ][ 1 ] = cos( amount );
  222.  
  223.     *this *= trn;
  224.     *this *= Rx;
  225.     *this *= Ry;
  226.     *this *= Rz;
  227.  
  228.     Rx.transpose();
  229.     Ry.transpose();
  230.  
  231.     // NOTE: don't invert the Rz transform -- that does the work!
  232.  
  233.     *this *= Ry;
  234.     *this *= Rx;
  235.     *this *= trn_inv;
  236. }
  237. #else
  238. /*
  239.  * Rotate with a general origin and general rotation axis
  240.  * quaternion method, Hearn and Baker p. 420
  241.  */
  242. grRotation::grRotation(                 // CONSTRUCTOR
  243.     const grPoint3 & origin,            // -- origin of rotation
  244.     const grPoint3 & direct,            // -- second point for direction
  245.     double amount )                     // -- degrees counterclockwise
  246. //--------------------------
  247. {
  248.     grVector    axis( direct - origin );
  249.     grVector    v;
  250.     grTranslate trn( grPoint3Origin - origin ); 
  251.     grTranslate trn_inv( origin - grPoint3Origin );
  252.     grTransform R;
  253.     double       s;
  254.     double       a, b, c;
  255.     double       t_aa, t_ab, t_ac, t_sa;
  256.     double       t_bb, t_bc, t_sb;
  257.     double       t_cc, t_sc;
  258.  
  259.     axis.normalize();
  260.     if( dot( axis, axis ) == 0 ) {
  261.         grError( "grRotation: invalid axis" );
  262.     }
  263.  
  264.     s = cos( amount / 2.0 );
  265.     v = sin( amount / 2.0 ) * axis;
  266.     a = v.x();
  267.     b = v.y();
  268.     c = v.z();
  269.  
  270.     t_aa = 2.0 * a * a;
  271.     t_bb = 2.0 * b * b;
  272.     t_cc = 2.0 * c * c;
  273.  
  274.     t_ab = 2.0 * a * b;
  275.     t_ac = 2.0 * a * c;
  276.     t_sa = 2.0 * s * a;
  277.  
  278.     t_bc = 2.0 * b * c;
  279.     t_sb = 2.0 * s * b;
  280.  
  281.     t_sc = 2.0 * s * c;
  282.  
  283.     R._rows[ 0 ][ 0 ] = 1.0  - t_bb - t_cc;
  284.     R._rows[ 0 ][ 1 ] = t_ab - t_sc;
  285.     R._rows[ 0 ][ 2 ] = t_ac + t_sb;
  286.  
  287.     R._rows[ 1 ][ 0 ] = t_ab + t_sc;
  288.     R._rows[ 1 ][ 1 ] = 1.0  - t_aa - t_cc;
  289.     R._rows[ 1 ][ 2 ] = t_bc - t_sa;
  290.  
  291.     R._rows[ 2 ][ 0 ] = t_ac - t_sb;
  292.     R._rows[ 2 ][ 1 ] = t_bc + t_sa;
  293.     R._rows[ 2 ][ 2 ] = 1.0  - t_aa - t_bb;
  294.  
  295.     *this *= trn;
  296.     *this *= R;
  297.     *this *= trn_inv;
  298. }
  299. #endif
  300.  
  301. /*
  302.  * Trivial rotation about a coordinate axis, origin at (0,0,0)
  303.  */
  304. grRotation::grRotation(                 // CONSTRUCTOR
  305.     int axis,                           // -- coordinate axis
  306.     double amount )                     // -- radians counter-clockwise
  307. //---------------------
  308. {
  309.     double c_theta;                     // -- cosine of amount
  310.     double s_theta;                     // -- sine of amount
  311.  
  312.     c_theta = cos( amount );
  313.     s_theta = sin( amount );
  314.  
  315.     switch( axis ) {
  316.     case X:
  317.         _rows[ 1 ][ 1 ] = c_theta;
  318.         _rows[ 1 ][ 2 ] = -1.0 * s_theta;
  319.         _rows[ 2 ][ 1 ] = s_theta;
  320.         _rows[ 2 ][ 2 ] = c_theta;
  321.         break;
  322.     case Y:
  323.         _rows[ 0 ][ 0 ] = c_theta;
  324.         _rows[ 0 ][ 2 ] = s_theta;
  325.         _rows[ 2 ][ 0 ] = -1.0 * s_theta;
  326.         _rows[ 2 ][ 2 ] = c_theta;
  327.         break;
  328.     case Z:
  329.         _rows[ 0 ][ 0 ] = c_theta;
  330.         _rows[ 0 ][ 1 ] = -1.0 * s_theta;
  331.         _rows[ 1 ][ 0 ] = s_theta;
  332.         _rows[ 1 ][ 1 ] = c_theta;
  333.         break;
  334.     default:
  335.         grError( "grRotation: invalid axis" );
  336.     }
  337. }
  338.  
  339. // -------------- grScale ------------- //
  340.  
  341. /*
  342.  * Scale with respect to the coordinate axes: (Hearn and Baker, p. 420)
  343.  *  [  sx  0.0  0.0  ( 1.0 - sx ) * xf  0.0 ]
  344.  *  [ 0.0   sy  0.0  ( 1.0 - sy ) * yf  0.0 ]
  345.  *  [ 0.0  0.0   sz  ( 1.0 - sz ) * zf  0.0 ]
  346.  *  [ 0.0  0.0  0.0                0.0  1.0 ]
  347.  */
  348. grScale::grScale(                       // CONSTRUCTOR
  349.     const grPoint3 & origin,            // -- scale origin
  350.     double sx, double sy, double sz )   // -- scale parameters
  351. //--------------------------------
  352. {
  353.     _rows[ 0 ][ 0 ] = sx;
  354.     _rows[ 1 ][ 1 ] = sy;
  355.     _rows[ 2 ][ 2 ] = sz;
  356.  
  357.     _rows[ 0 ][ 3 ] = (1.0 - sx) * origin.x();
  358.     _rows[ 1 ][ 3 ] = (1.0 - sy) * origin.y();
  359.     _rows[ 2 ][ 3 ] = (1.0 - sz) * origin.z();
  360. }
  361.  
  362. /*
  363.  * Scale in a general direction:
  364.  *  - translate scale origin to coordinate origin
  365.  *  - rotate scale direction to match z-axis
  366.  *  - scale along z-axis
  367.  *  - reverse rotation
  368.  *  - reverse translation
  369.  */
  370. grScale::grScale(                       // CONSTRUCTOR
  371.     const grPoint3 & origin,            // -- origin of scale
  372.     const grVector & direction,         // -- direction of scale
  373.     double amt )                        // -- amount to scale by
  374. //-----------------------------
  375. {
  376.     grVector    axis( direction );
  377.     grTranslate trn( grPoint3Origin - origin ); 
  378.     grTranslate trn_inv( origin - grPoint3Origin );
  379.     grTransform Rx;
  380.     grTransform Ry;
  381.     grPoint3    O( 0.0, 0.0, 0.0 );
  382.     grScale     scale( O, 1.0, 1.0, amt );
  383.     double       d;
  384.  
  385.     axis.normalize();
  386.     grAssert( dot( axis, axis ) > (1.0 - grEPSILON) );
  387.  
  388.     d = sqrt( axis.y() * axis.y() + axis.z() * axis.z() );
  389.     if( d > grEPSILON ) {
  390.         Rx._rows[ 1 ][ 1 ] = axis.z() / d;
  391.         Rx._rows[ 1 ][ 2 ] = -1.0 * axis.y() / d;
  392.         Rx._rows[ 2 ][ 1 ] = axis.y() / d;
  393.         Rx._rows[ 2 ][ 2 ] = axis.z() / d;
  394.     }
  395.  
  396.     Ry._rows[ 0 ][ 0 ] = d;
  397.     Ry._rows[ 0 ][ 2 ] = -1.0 *  axis.x();
  398.     Ry._rows[ 2 ][ 0 ] = axis.x();
  399.     Ry._rows[ 2 ][ 2 ] = d;
  400.  
  401.     *this *= trn;
  402.     *this *= Rx;
  403.     *this *= Ry;
  404.  
  405.     *this *= scale;
  406.  
  407.     // invert Rx and Ry by transposing them
  408.     Rx.transpose();
  409.     Ry.transpose();
  410.  
  411.     // NOTE: don't invert the Rz transform -- that does the work!
  412.  
  413.     *this *= Ry;
  414.     *this *= Rx;
  415.     *this *= trn_inv;
  416. }
  417.  
  418. // ------------ grTranslate ----------- //
  419.  
  420. grTranslate::grTranslate(               // PERFORM GENERAL TRANSLATION
  421.     const grVector & translate )        // -- amount to translate by
  422. //------------------------------
  423. {
  424.     uint i;
  425.  
  426.     for( i = 0; i < 3; i++ ) {
  427.         _rows[ i ][ 3 ] = translate._coords[ i ];
  428.     }
  429. }
  430.  
  431. // ----------- grPerspective ---------- //
  432.  
  433. /*
  434.  * Perform the perspective projection.
  435.  * Although this is based on the version in class,
  436.  * it is transposed as I am using column vectors.
  437.  */
  438.  
  439. grPerspective::grPerspective(           // CONSTRUCTOR
  440.     double fovy,                        // -- field of view, in abs degrees
  441.     double aspect,                      // -- aspect ratio(horz angle/vert)
  442.     double n,                           // -- distance to near clipping
  443.     double f )                          // -- distance to far clipping
  444. //---------------------------
  445. {
  446.     double ctan;
  447.  
  448.     ctan = 1.0 / tan( fovy / 2.0 );
  449.  
  450.     _rows[ 0 ][ 0 ] = ctan / aspect;
  451.     _rows[ 1 ][ 1 ] = ctan;
  452.  
  453.     _rows[ 2 ][ 2 ] = (f + n) / (n - f);
  454.     _rows[ 2 ][ 3 ] = 2 * f * n / (n - f);      // transpose
  455.     _rows[ 3 ][ 2 ] = -1.0;                     // transpose
  456.     _rows[ 3 ][ 3 ] = 0.0;
  457. }
  458.  
  459. // ------------- grShearXY ------------ //
  460.  
  461. grShearXY::grShearXY(                   // CONSTRUCTOR
  462.     double shx,                         // -- x parameter
  463.     double shy )                        // -- y parameter
  464. //-------------------
  465. {
  466.     _rows[ 0 ][ 2 ] = shx;
  467.     _rows[ 0 ][ 2 ] = shy;
  468. }
  469.  
  470. // ------------ grTransform ----------- //
  471.  
  472. /*
  473.  * Change from one coordinate system to another
  474.  * using unit x, y, z vectors of the target given in the source
  475.  * Hearn and Baker p. 428
  476.  */
  477. grTransform & grTransform::changeBase(  // PERFORM CHANGE OF BASIS
  478.     const grPoint3 & origin,            // -- origin of new coordinates
  479.     const grVector & ux,                // -- unit vector along new x
  480.     const grVector & uy,                // -- unit vector along new y
  481.     const grVector & uz )               // -- unit vector along new z
  482. //------------------------------------
  483. {
  484.     grChangeBase cb( origin, ux, uy, uz );
  485.  
  486.     *this *= cb;
  487.     return *this;
  488. }
  489.  
  490. grTransform & grTransform::rotate(          // PERFORM GENERAL ROTATION
  491.     const grPoint3 & origin,                // -- origin of rotation
  492.     const grVector & axis,                  // -- axis of rotation
  493.     double angle )                          // -- degrees counter-clockwise
  494. //--------------------------------
  495. {
  496.     grRotation rot( origin, axis, angle );
  497.  
  498.     *this *= rot;
  499.     return *this;
  500. }
  501.  
  502. grTransform & grTransform::rotate(      // PERFORM TRIVIAL ROTATION
  503.     int axis,                           // -- coordinate axis
  504.     double amount )                     // -- radians counter-clockwise
  505. //--------------------------------
  506. {
  507.     grRotation rot( axis, amount );
  508.  
  509.     *this *= rot;
  510.     return *this;
  511. }
  512.  
  513. grTransform & grTransform::scale(       // PERFORM SCALE RELATIVE TO COORD
  514.     const grPoint3 & origin,            // -- scale origin
  515.     double sx, double sy, double sz )   // -- scale parameters
  516. //--------------------------------
  517. {
  518.     grScale scale( origin, sx, sy, sz );
  519.  
  520.     *this *= scale;
  521.     return *this;
  522. }
  523.  
  524. grTransform & grTransform::scale(       // CONSTRUCTOR
  525.     const grPoint3 & origin,            // -- origin of scale
  526.     const grVector & direction,         // -- direction of scale
  527.     double amt )                        // -- amount to scale by
  528. //-------------------------------
  529. {
  530.     grScale scale( origin, direction, amt );
  531.  
  532.     *this *= scale;
  533.     return *this;
  534. }
  535.  
  536. grTransform & grTransform::translate(   // PERFORM GENERAL TRANSLATION
  537.     const grVector & translate )        // -- amount to translate by
  538. //-----------------------------------
  539. {
  540.     grTranslate trans( translate );
  541.  
  542.     *this *= trans;
  543.     return *this;
  544. }
  545.