home *** CD-ROM | disk | FTP | other *** search
/ PC Format (South-Africa) 2001 May / PCFMay2001.iso / Xenon / C++ / FreeCommandLineTools.exe / Include / dxvector.h < prev    next >
Encoding:
C/C++ Source or Header  |  2000-01-31  |  35.2 KB  |  1,198 lines

  1. /*******************************************************************************
  2. * DXVector.h *
  3. *------------*
  4. *   Description:
  5. *       This is the header file for the vector and matrix classes.
  6. *-------------------------------------------------------------------------------
  7. *  Created By: Mike Arnstein                            Date: 04/11/97
  8. *  Copyright (C) 1997 Microsoft Corporation
  9. *  All Rights Reserved
  10. *
  11. *-------------------------------------------------------------------------------
  12. *  Revisions:
  13. *
  14. *******************************************************************************/
  15. #ifndef DXVector_h
  16. #pragma option push -b -a8 -pc -A- /*P_O_Push*/
  17. #define DXVector_h
  18.  
  19. #ifndef _INC_MATH
  20. #include <math.h>
  21. #endif
  22.  
  23. #ifndef _INC_CRTDBG
  24. #include <crtdbg.h>
  25. #endif
  26.  
  27. //=== Constants ====================================================
  28.  
  29.  
  30. //=== Class, Enum, Struct and Union Declarations ===================
  31. class CDXMatrix4x4F;
  32.  
  33. //=== Enumerated Set Definitions ===================================
  34.  
  35. //=== Function Type Definitions ====================================
  36. float det4x4( CDXMatrix4x4F *pIn );
  37. float det3x3( float a1, float a2, float a3, float b1, float b2, float b3, 
  38.               float c1, float c2, float c3 );
  39. float det2x2( float a, float b, float c, float d );
  40.  
  41. //=== Class, Struct and Union Definitions ==========================
  42.  
  43. /*** CDXVec ************
  44. *   This template implements basic vector operations for each of the
  45. *   union types
  46. */
  47. #define CDXV_C CDXVec<TYPE, eBndType>
  48. #define CDXV_T ((TYPE*)u.D)
  49. #define CDXV_O( OtherVec ) ((TYPE*)OtherVec.u.D)
  50.  
  51. template<class TYPE, DXBNDTYPE eBndType>
  52. class CDXVec : public DXVEC
  53. {
  54.   /*=== Methods =======*/
  55.   public:
  56.     /*--- Constructors ---*/
  57.     CDXVec() { eType = eBndType; ZeroVector(); }
  58.     CDXVec(BOOL bInit) { eType = eBndType; if (bInit) ZeroVector(); }
  59.     CDXVec( TYPE x, TYPE y, TYPE z, TYPE t )
  60.         { eType = eBndType; CDXV_T[DXB_X] = x; CDXV_T[DXB_Y] = y;
  61.                             CDXV_T[DXB_Z] = z; CDXV_T[DXB_T] = t; }
  62.     CDXVec( const CDXVec& Other ) { memcpy( this, (void *)&Other, sizeof(DXVEC) ); }
  63.     CDXVec( const DXVEC Other ) { memcpy( this, &Other, sizeof(DXVEC) ); }
  64.     operator TYPE *() { return CDXV_T; }
  65.     operator const TYPE *() { return CDXV_T; }
  66.  
  67.     /*--- operations ---*/
  68.     void ZeroVector( void ) { memset( u.D, 0, sizeof(TYPE) * 4); }
  69.  
  70.     /*--- operators ---*/
  71.     TYPE&  operator[]( int index ) const { return CDXV_T[index]; }
  72.     TYPE&  operator[]( long index ) const { return CDXV_T[index]; }
  73.     TYPE&  operator[]( USHORT index ) const { return CDXV_T[index]; }
  74.     TYPE&  operator[]( DWORD index ) const { return CDXV_T[index]; }
  75.     CDXV_C operator+(const CDXV_C& v);
  76.     CDXV_C operator-(const CDXV_C& v);
  77.     void   operator=(const CDXV_C& srcVector);
  78.     void   operator+=(const CDXV_C& vOther);
  79.     void   operator-=(const CDXV_C& vOther);
  80.     BOOL   operator==(const CDXV_C& otherVector) const;
  81.     BOOL   operator!=(const CDXV_C& otherVector) const;
  82. };
  83.  
  84. template<class TYPE, DXBNDTYPE eBndType>
  85. CDXV_C CDXV_C::operator+( const CDXV_C& srcVector )
  86. {
  87.     CDXV_C Result( this );
  88.     CDXV_O( Result )[DXB_X] += CDXV_O( srcVector )[DXB_X];
  89.     CDXV_O( Result )[DXB_Y] += CDXV_O( srcVector )[DXB_Y];
  90.     CDXV_O( Result )[DXB_Z] += CDXV_O( srcVector )[DXB_Z];
  91.     CDXV_O( Result )[DXB_T] += CDXV_O( srcVector )[DXB_T];
  92.     return Result;
  93. } /* CDXVec::operator+ */
  94.  
  95. template<class TYPE, DXBNDTYPE eBndType>
  96. CDXV_C CDXV_C::operator-( const CDXV_C& srcVector )
  97. {
  98.     CDXV_C Result( this );
  99.     CDXV_O( Result )[DXB_X] -= CDXV_O( srcVector )[DXB_X];
  100.     CDXV_O( Result )[DXB_Y] -= CDXV_O( srcVector )[DXB_Y];
  101.     CDXV_O( Result )[DXB_Z] -= CDXV_O( srcVector )[DXB_Z];
  102.     CDXV_O( Result )[DXB_T] -= CDXV_O( srcVector )[DXB_T];
  103.     return Result;
  104. } /* CDXVec::operator- */
  105.  
  106. template<class TYPE, DXBNDTYPE eBndType>
  107. void CDXV_C::operator=( const CDXV_C& srcVector )
  108. {
  109.     memcpy( this, &srcVector, sizeof(CDXVec) );
  110. } /* CDXVec::operator= */
  111.  
  112. template<class TYPE, DXBNDTYPE eBndType>
  113. BOOL CDXV_C::operator==(const CDXV_C& otherVector) const
  114. {
  115.     return !memcmp( this, &otherVector, sizeof(otherVector) );
  116. } /* CDXVec::operator== */
  117.  
  118. template<class TYPE, DXBNDTYPE eBndType>
  119. BOOL CDXV_C::operator!=(const CDXV_C& otherVector) const
  120. {
  121.     return memcmp( this, &otherVector, sizeof(otherVector) );
  122. } /* CDXVec::operator!= */
  123.  
  124. template<class TYPE, DXBNDTYPE eBndType>
  125. void CDXV_C::operator+=(const CDXV_C& vOther)
  126. {
  127.     CDXV_T[DXB_X] += CDXV_O( vOther )[DXB_X];
  128.     CDXV_T[DXB_Y] += CDXV_O( vOther )[DXB_Y];
  129.     CDXV_T[DXB_Z] += CDXV_O( vOther )[DXB_Z];
  130.     CDXV_T[DXB_T] += CDXV_O( vOther )[DXB_T];
  131. } /* CDXVec::operator+= */
  132.  
  133. template<class TYPE, DXBNDTYPE eBndType>
  134. void CDXV_C::operator-=(const CDXVec& vOther)
  135. {
  136.     CDXV_T[DXB_X] -= CDXV_O( vOther )[DXB_X];
  137.     CDXV_T[DXB_Y] -= CDXV_O( vOther )[DXB_Y];
  138.     CDXV_T[DXB_Z] -= CDXV_O( vOther )[DXB_Z];
  139.     CDXV_T[DXB_T] -= CDXV_O( vOther )[DXB_T];
  140. } /* CDXVec::operator-= */
  141.  
  142. typedef CDXVec<long, DXBT_DISCRETE> CDXDVec;
  143. typedef CDXVec<LONGLONG, DXBT_DISCRETE64> CDXDVec64;
  144. typedef CDXVec<float, DXBT_CONTINUOUS> CDXCVec;
  145. typedef CDXVec<double, DXBT_CONTINUOUS64> CDXCVec64;
  146.  
  147. /*** CDX2DXForm ************
  148. *   This class implements basic matrix operation based on the GDI XFORM
  149. *   structure.
  150. */
  151. //const DX2DXFORM g_DX2DXFORMIdentity = { 1., 0., 0., 1., 0., 0., DX2DXO_IDENTITY };
  152.  
  153. class CDX2DXForm : public DX2DXFORM
  154. {
  155.   /*=== Methods =======*/
  156. public:
  157.     /*--- Constructors ---*/
  158.     CDX2DXForm() { SetIdentity(); }
  159.     CDX2DXForm( const CDX2DXForm& Other ) { memcpy( this, &Other, sizeof(*this) ); }
  160.     CDX2DXForm( const DX2DXFORM& Other ) { memcpy( this, &Other, sizeof(*this) ); }
  161.  
  162.     /*--- methods ---*/
  163.     void DetermineOp( void );
  164.     void Set( const DX2DXFORM& Other ) { memcpy( this, &Other, sizeof(*this) ); DetermineOp(); }
  165.     void ZeroMatrix( void ) { memset( this, 0, sizeof( *this ) ); }
  166.     void SetIdentity( void ) {  
  167.         eM11 = 1.;
  168.         eM12 = 0.;
  169.         eM21 = 0.;
  170.         eM22 = 1.;
  171.         eDx = 0.;
  172.         eDy = 0.;
  173.         eOp = DX2DXO_IDENTITY;
  174.     }
  175.     BOOL IsIdentity() const { return eOp == DX2DXO_IDENTITY; }
  176.     void Scale( float sx, float sy );
  177.     void Rotate( float Rotation );
  178.     void Translate( float dx, float dy );
  179.     BOOL Invert();
  180.     void TransformBounds( const DXBNDS& Bnds, DXBNDS& ResultBnds ) const;
  181.     void TransformPoints( const DXFPOINT InPnts[], DXFPOINT OutPnts[], ULONG ulCount ) const;
  182.     void GetMinMaxScales( float& MinScale, float& MaxScale );
  183.  
  184.     /*--- operators ---*/
  185.     DXFPOINT operator*( const DXFPOINT& v ) const;
  186.     CDX2DXForm operator*( const CDX2DXForm& Other ) const;
  187. };
  188.  
  189. //=== CDX2DXForm methods ==============================================================
  190. inline void CDX2DXForm::DetermineOp( void )
  191. {
  192.     if( ( eM12 == 0. ) && ( eM21 == 0. ) )
  193.     {
  194.         if( ( eM11 == 1. ) && ( eM22 == 1. ) )
  195.         {
  196.             eOp = ( ( eDx == 0 ) && ( eDy == 0 ) )?(DX2DXO_IDENTITY):(DX2DXO_TRANSLATE);
  197.         }
  198.         else
  199.         {
  200.             eOp = ( ( eDx == 0 ) && ( eDy == 0 ) )?(DX2DXO_SCALE):(DX2DXO_SCALE_AND_TRANS);
  201.         }
  202.     }
  203.     else
  204.     {
  205.         eOp = ( ( eDx == 0 ) && ( eDy == 0 ) )?(DX2DXO_GENERAL):(DX2DXO_GENERAL_AND_TRANS);
  206.     }
  207. } /* CDX2DXForm::DetermineOp */
  208.  
  209. inline float DXSq( float f ) { return f * f; }
  210.  
  211. // This function computes the Min and Max scale that a matrix represents.
  212. // In other words, what is the maximum/minimum length that a line of length 1
  213. // could get stretched/shrunk to if the line was transformed by this matrix.
  214. //
  215. // The function uses eigenvalues; and returns two float numbers. Both are
  216. // non-negative; and MaxScale >= MinScale.
  217. // 
  218. inline void CDX2DXForm::GetMinMaxScales( float& MinScale, float& MaxScale )
  219. {
  220.     if( ( eM12 == 0. ) && ( eM21 == 0. ) )
  221.     {
  222.         // Let MinScale = abs(eM11)
  223.         if (eM11 < 0)
  224.             MinScale = -eM11;
  225.         else
  226.             MinScale = eM11;
  227.  
  228.         // Let MaxScale = abs(eM22)
  229.         if (eM22 < 0)
  230.             MaxScale = -eM22;
  231.         else
  232.             MaxScale = eM22;
  233.  
  234.         // Swap Min/Max if necessary
  235.         if (MinScale > MaxScale)
  236.         {
  237.             float flTemp = MinScale;
  238.             MinScale = MaxScale;
  239.             MaxScale = flTemp;
  240.         }
  241.     }
  242.     else
  243.     {
  244.         float t1 = DXSq(eM11) + DXSq(eM12) + DXSq(eM21) + DXSq(eM22);
  245.         if( t1 == 0. )
  246.         {
  247.             MinScale = MaxScale = 0;
  248.         }
  249.         else
  250.         {
  251.             float t2 = (float)sqrt( (DXSq(eM12 + eM21) + DXSq(eM11 - eM22)) *
  252.                                     (DXSq(eM12 - eM21) + DXSq(eM11 + eM22)) );
  253.  
  254.             // Due to floating point error; t1 may end up less than t2;
  255.             // but that would mean that the min scale was small (relative
  256.             // to max scale)
  257.             if (t1 <= t2)
  258.                 MinScale = 0;
  259.             else
  260.                 MinScale = (float)sqrt( (t1 - t2) * .5f );
  261.  
  262.             MaxScale = (float)sqrt( (t1 + t2) * .5f );
  263.         }
  264.     }
  265. } /* CDX2DXForm::GetMinMaxScales */
  266.  
  267. inline void CDX2DXForm::Rotate( float Rotation )
  268. {
  269.     double Angle = Rotation * (3.1415926535/180.0);
  270.     float CosZ   = (float)cos( Angle );
  271.     float SinZ   = (float)sin( Angle );
  272.     if (CosZ > 0.0F && CosZ < 0.0000005F)
  273.     {
  274.         CosZ = .0F;
  275.     }
  276.     if (SinZ > -0.0000005F && SinZ < .0F)
  277.     {
  278.         SinZ = .0F;
  279.     }
  280.  
  281.     float M11 = ( CosZ * eM11 ) + ( SinZ * eM21 ); 
  282.     float M21 = (-SinZ * eM11 ) + ( CosZ * eM21 );
  283.     float M12 = ( CosZ * eM12 ) + ( SinZ * eM22 ); 
  284.     float M22 = (-SinZ * eM12 ) + ( CosZ * eM22 );
  285.     eM11 = M11; eM21 = M21; eM12 = M12; eM22 = M22;
  286.     DetermineOp();
  287. } /* CDX2DXForm::Rotate */
  288.  
  289. inline void CDX2DXForm::Scale( float sx, float sy )
  290. {
  291.     eM11 *= sx;
  292.     eM12 *= sx;
  293.     eDx  *= sx;
  294.     eM21 *= sy;
  295.     eM22 *= sy;
  296.     eDy  *= sy;
  297.     DetermineOp();
  298. } /* CDX2DXForm::Scale */
  299.  
  300. inline void CDX2DXForm::Translate( float dx, float dy )
  301. {
  302.     eDx += dx;
  303.     eDy += dy;
  304.     DetermineOp();
  305. } /* CDX2DXForm::Translate */
  306.  
  307. inline void CDX2DXForm::TransformBounds( const DXBNDS& Bnds, DXBNDS& ResultBnds ) const
  308. {
  309.     ResultBnds = Bnds;
  310.     if( eOp != DX2DXO_IDENTITY )
  311.     {
  312.         ResultBnds.u.D[DXB_X].Min = (long)(( eM11 * Bnds.u.D[DXB_X].Min ) + ( eM12 * Bnds.u.D[DXB_Y].Min ) + eDx);
  313.         ResultBnds.u.D[DXB_X].Max = (long)(( eM11 * Bnds.u.D[DXB_X].Max ) + ( eM12 * Bnds.u.D[DXB_Y].Max ) + eDx);
  314.         ResultBnds.u.D[DXB_Y].Min = (long)(( eM21 * Bnds.u.D[DXB_X].Min ) + ( eM22 * Bnds.u.D[DXB_Y].Min ) + eDy);
  315.         ResultBnds.u.D[DXB_Y].Max = (long)(( eM21 * Bnds.u.D[DXB_X].Max ) + ( eM22 * Bnds.u.D[DXB_Y].Max ) + eDy);
  316.     }
  317. } /* CDX2DXForm::TransformBounds */
  318.  
  319. inline void CDX2DXForm::TransformPoints( const DXFPOINT InPnts[], DXFPOINT OutPnts[], ULONG ulCount ) const
  320. {
  321.     ULONG i;
  322.     switch( eOp )
  323.     {
  324.       case DX2DXO_IDENTITY:
  325.         memcpy( OutPnts, InPnts, ulCount * sizeof( DXFPOINT ) );
  326.         break;
  327.       case DX2DXO_TRANSLATE:
  328.         for( i = 0; i < ulCount; ++i )
  329.         {
  330.             OutPnts[i].x = InPnts[i].x + eDx;
  331.             OutPnts[i].y = InPnts[i].y + eDy;
  332.         }
  333.         break;
  334.       case DX2DXO_SCALE:
  335.         for( i = 0; i < ulCount; ++i )
  336.         {
  337.             OutPnts[i].x = InPnts[i].x * eM11;
  338.             OutPnts[i].y = InPnts[i].y * eM22;
  339.         }
  340.         break;
  341.       case DX2DXO_SCALE_AND_TRANS:
  342.         for( i = 0; i < ulCount; ++i )
  343.         {
  344.             OutPnts[i].x = (InPnts[i].x * eM11) + eDx;
  345.             OutPnts[i].y = (InPnts[i].y * eM22) + eDy;
  346.         }
  347.         break;
  348.       case DX2DXO_GENERAL:
  349.         for( i = 0; i < ulCount; ++i )
  350.         {
  351.             OutPnts[i].x = ( InPnts[i].x * eM11 ) + ( InPnts[i].y * eM12 );
  352.             OutPnts[i].y = ( InPnts[i].x * eM21 ) + ( InPnts[i].y * eM22 );
  353.         }
  354.         break;
  355.       case DX2DXO_GENERAL_AND_TRANS:
  356.         for( i = 0; i < ulCount; ++i )
  357.         {
  358.             OutPnts[i].x = ( InPnts[i].x * eM11 ) + ( InPnts[i].y * eM12 ) + eDx;
  359.             OutPnts[i].y = ( InPnts[i].x * eM21 ) + ( InPnts[i].y * eM22 ) + eDy;
  360.         }
  361.         break;
  362.       default:
  363.         _ASSERT( 0 );   // invalid operation id
  364.     }
  365. } /* CDX2DXForm::TransformPoints */
  366.  
  367. inline DXFPOINT CDX2DXForm::operator*( const DXFPOINT& v ) const
  368. {
  369.     DXFPOINT NewPnt;
  370.     NewPnt.x = ( v.x * eM11 ) + ( v.y * eM12 ) + eDx;
  371.     NewPnt.y = ( v.x * eM21 ) + ( v.y * eM22 ) + eDy;
  372.     return NewPnt;
  373. } /* CDX2DXForm::operator* */
  374.  
  375. inline CDX2DXForm CDX2DXForm::operator*( const CDX2DXForm& Other ) const
  376. {
  377.     DX2DXFORM x;
  378.     x.eM11 = ( eM11 * Other.eM11 ) + ( eM12 * Other.eM21 );
  379.     x.eM12 = ( eM11 * Other.eM12 ) + ( eM12 * Other.eM22 );
  380.     x.eDx  = ( eM11 * Other.eDx  ) + ( eM12 * Other.eDy  ) + eDx;
  381.  
  382.     x.eM21 = ( eM21 * Other.eM11 ) + ( eM22 * Other.eM21 );
  383.     x.eM22 = ( eM21 * Other.eM12 ) + ( eM22 * Other.eM22 );
  384.     x.eDy  = ( eM21 * Other.eDx  ) + ( eM22 * Other.eDy  ) + eDy;
  385.     return x;
  386. } /* CDX2DXForm::operator*= */
  387.  
  388. inline BOOL CDX2DXForm::Invert()
  389. {
  390.     switch( eOp )
  391.     {
  392.     case DX2DXO_IDENTITY:
  393.         break;
  394.     case DX2DXO_TRANSLATE:
  395.         eDx = -eDx;
  396.         eDy = -eDy;
  397.         break;
  398.     case DX2DXO_SCALE:
  399.  
  400.         if (eM11 == 0.0 || eM22 == 0.0)
  401.             return false;
  402.         eM11 = 1.0f / eM11;
  403.         eM22 = 1.0f / eM22;
  404.         break;
  405.  
  406.     case DX2DXO_SCALE_AND_TRANS:
  407.         {
  408.             if (eM11 == 0.0f || eM22 == 0.0f)
  409.                 return false;
  410.  
  411.             // Our old equation was F = aG + b
  412.             // The inverse is G = F/a - b/a where a is eM11 and b is eDx
  413.             float flOneOverA = 1.0f / eM11;
  414.             eDx = -eDx * flOneOverA;
  415.             eM11 = flOneOverA;
  416.  
  417.             // Our old equation was F = aG + b
  418.             // The inverse is G = F/a - b/a where a is eM22 and b is eDy
  419.  
  420.             flOneOverA = 1.0f / eM22;
  421.             eDy = -eDy * flOneOverA;
  422.             eM22 = flOneOverA;
  423.             break;
  424.         }
  425.  
  426.     case DX2DXO_GENERAL:
  427.     case DX2DXO_GENERAL_AND_TRANS:
  428.         {
  429.             // The inverse of A=  |a b| is | d -c|*(1/Det) where Det is the determinant of A
  430.             //                    |c d|    |-b  a|
  431.             // Det(A) = ad - bc
  432.  
  433.             // Compute determininant
  434.             float flDet = (eM11 * eM22 -  eM12 * eM21);
  435.             if (flDet == 0.0f)
  436.                 return FALSE;
  437.  
  438.             float flCoef = 1.0f / flDet;
  439.  
  440.             // Remember old value of eM11
  441.             float flM11Original = eM11;
  442.  
  443.             eM11 = flCoef * eM22;
  444.             eM12 = -flCoef * eM12;
  445.             eM21 = -flCoef * eM21;
  446.             eM22 = flCoef * flM11Original;
  447.  
  448.             // If we have a translation; then we need to 
  449.             // compute new values for that translation
  450.             if (eOp == DX2DXO_GENERAL_AND_TRANS)
  451.             {
  452.                 // Remember original value of eDx
  453.                 float eDxOriginal = eDx;
  454.  
  455.                 eDx = -eM11 * eDx - eM12 * eDy;
  456.                 eDy = -eM21 * eDxOriginal - eM22 * eDy;
  457.             }
  458.         }
  459.         break;
  460.  
  461.     default:
  462.         _ASSERT( 0 );   // invalid operation id
  463.     }
  464.  
  465.     // We don't need to call DetermineOp here
  466.     // because the op doesn't change when inverted
  467.     // i.e. a scale remains a scale, etc.
  468.  
  469.     return true;
  470. } /* CDX2DXForm::Invert */
  471.  
  472. /*** CDXMatrix4x4F ************
  473. *   This class implements basic matrix operation based on a 4x4 array.
  474. */
  475. //const float g_DXMat4X4Identity[4][4] =
  476. //{
  477. //    { 1.0, 0. , 0. , 0.  },
  478. //    { 0. , 1.0, 0. , 0.  },
  479. //    { 0. , 0. , 1.0, 0.  },
  480. //    { 0. , 0. , 0. , 1.0 }
  481. //};
  482.  
  483. class CDXMatrix4x4F
  484. {
  485. public:
  486.   /*=== Member Data ===*/
  487.     float m_Coeff[4][4];
  488.  
  489.   /*=== Methods =======*/
  490. public:
  491.     /*--- Constructors ---*/
  492.     CDXMatrix4x4F() { SetIdentity(); }
  493.     CDXMatrix4x4F( const CDXMatrix4x4F& Other )
  494.         { CopyMemory( (void *)&m_Coeff, (void *)&Other.m_Coeff, sizeof(m_Coeff) ); }
  495.     CDXMatrix4x4F( DX2DXFORM& XForm );
  496.  
  497.     /*--- operations ---*/
  498.     void ZeroMatrix( void ) { memset( m_Coeff, 0, sizeof( m_Coeff ) ); }
  499.     void SetIdentity( void ) {
  500.         memset( m_Coeff, 0, sizeof( m_Coeff ) );
  501.         m_Coeff[0][0] = m_Coeff[1][1] = m_Coeff[2][2] = m_Coeff[3][3] = 1.0;
  502.     }
  503.     void SetCoefficients( float Coeff[4][4] ) { memcpy( m_Coeff, Coeff, sizeof( m_Coeff )); }
  504.     void GetCoefficients( float Coeff[4][4] ) { memcpy( Coeff, m_Coeff, sizeof( m_Coeff )); }
  505.  
  506.     //BOOL IsIdentity();
  507.     void Scale( float sx, float sy, float sz );
  508.     void Rotate( float rx, float ry, float rz );
  509.     void Translate( float dx, float dy, float dz );
  510.     BOOL Invert();
  511.     BOOL GetInverse( CDXMatrix4x4F *pIn );
  512.     void Transpose();
  513.     void GetTranspose( CDXMatrix4x4F *pIn );
  514.     void GetAdjoint( CDXMatrix4x4F *pIn );
  515.     HRESULT InitFromSafeArray( SAFEARRAY *psa );
  516.     HRESULT GetSafeArray( SAFEARRAY **ppsa ) const;
  517.     void TransformBounds( DXBNDS& Bnds, DXBNDS& ResultBnds );
  518.  
  519.     /*--- operators ---*/
  520.     CDXDVec operator*( CDXDVec& v) const;
  521.     CDXCVec operator*( CDXCVec& v) const;
  522.     CDXMatrix4x4F operator*(CDXMatrix4x4F Matrix) const;
  523.     void operator*=(CDXMatrix4x4F Matrix) const;
  524.     void CDXMatrix4x4F::operator=(const CDXMatrix4x4F srcMatrix);
  525.     void CDXMatrix4x4F::operator+=(const CDXMatrix4x4F otherMatrix);
  526.     void CDXMatrix4x4F::operator-=(const CDXMatrix4x4F otherMatrix);
  527.     BOOL CDXMatrix4x4F::operator==(const CDXMatrix4x4F otherMatrix) const;
  528.     BOOL CDXMatrix4x4F::operator!=(const CDXMatrix4x4F otherMatrix) const;
  529. };
  530.  
  531. inline CDXMatrix4x4F::CDXMatrix4x4F( DX2DXFORM& XForm )
  532. {
  533.     SetIdentity();
  534.     m_Coeff[0][0] = XForm.eM11;
  535.     m_Coeff[0][1] = XForm.eM12;
  536.     m_Coeff[1][0] = XForm.eM21;
  537.     m_Coeff[1][1] = XForm.eM22;
  538.     m_Coeff[0][3] = XForm.eDx;
  539.     m_Coeff[1][3] = XForm.eDy;
  540. }
  541.  
  542. // Additional Operations
  543.  
  544. inline void CDXMatrix4x4F::operator=(const CDXMatrix4x4F srcMatrix)
  545. {
  546.     CopyMemory( (void *)m_Coeff, (const void *)srcMatrix.m_Coeff, sizeof(srcMatrix.m_Coeff) );
  547. } /* CDXMatrix4x4F::operator= */
  548.  
  549. inline BOOL CDXMatrix4x4F::operator==(const CDXMatrix4x4F otherMatrix) const
  550. {
  551.     return !memcmp( (void *)m_Coeff, (const void *)otherMatrix.m_Coeff, sizeof(otherMatrix.m_Coeff) );
  552. } /* CDXMatrix4x4F::operator== */
  553.  
  554. inline BOOL CDXMatrix4x4F::operator!=(const CDXMatrix4x4F otherMatrix) const
  555. {
  556.     return memcmp( (void *)m_Coeff, (const void *)otherMatrix.m_Coeff, sizeof(otherMatrix.m_Coeff) );
  557. } /* CDXMatrix4x4F::operator!= */
  558.  
  559. inline void CDXMatrix4x4F::operator+=(const CDXMatrix4x4F otherMatrix)
  560. {
  561.     for( int i = 0; i < 4; i++ )
  562.         for( int j = 0; j < 4; j++ )
  563.             m_Coeff[i][j] += otherMatrix.m_Coeff[i][j];
  564. } /* CDXMatrix4x4F::operator+= */
  565.  
  566. inline void CDXMatrix4x4F::operator-=(const CDXMatrix4x4F otherMatrix) 
  567. {
  568.     for( int i = 0; i < 4; i++ )
  569.         for( int j = 0; j < 4; j++ )
  570.             m_Coeff[i][j] -= otherMatrix.m_Coeff[i][j];
  571. } /* CDXMatrix4x4F::operator-= */
  572.  
  573. inline CDXDVec CDXMatrix4x4F::operator*(CDXDVec& v) const
  574. {
  575.     CDXDVec t;
  576.     float temp;
  577.     temp = v[0]*m_Coeff[0][0]+v[1]*m_Coeff[1][0]+v[2]*m_Coeff[2][0]+v[3]*m_Coeff[3][0];
  578.     t[0] = (long)((temp < 0) ? temp -= .5 : temp += .5);
  579.     temp = v[0]*m_Coeff[0][1]+v[1]*m_Coeff[1][1]+v[2]*m_Coeff[2][1]+v[3]*m_Coeff[3][1];
  580.     t[1] = (long)((temp < 0) ? temp -= .5 : temp += .5);
  581.     temp = v[0]*m_Coeff[0][2]+v[1]*m_Coeff[1][2]+v[2]*m_Coeff[2][2]+v[3]*m_Coeff[3][2];
  582.     t[2] = (long)((temp < 0) ? temp -= .5 : temp += .5);
  583.     temp = v[0]*m_Coeff[0][3]+v[1]*m_Coeff[1][3]+v[2]*m_Coeff[2][3]+v[3]*m_Coeff[3][3];
  584.     t[3] = (long)((temp < 0) ? temp -= .5 : temp += .5);
  585.     return t;
  586. } /* CDXMatrix4x4F::operator*(DXDVEC) */
  587.  
  588. inline CDXCVec CDXMatrix4x4F::operator*(CDXCVec& v) const
  589. {
  590.     CDXCVec t;
  591.     t[0] = v[0]*m_Coeff[0][0]+v[1]*m_Coeff[1][0]+v[2]*m_Coeff[2][0]+v[3]*m_Coeff[3][0];
  592.     t[1] = v[0]*m_Coeff[0][1]+v[1]*m_Coeff[1][1]+v[2]*m_Coeff[2][1]+v[3]*m_Coeff[3][1];
  593.     t[2] = v[0]*m_Coeff[0][2]+v[1]*m_Coeff[1][2]+v[2]*m_Coeff[2][2]+v[3]*m_Coeff[3][2];
  594.     t[3] = v[0]*m_Coeff[0][3]+v[1]*m_Coeff[1][3]+v[2]*m_Coeff[2][3]+v[3]*m_Coeff[3][3];
  595.     return t;
  596. } /* CDXMatrix4x4F::operator*(DXCVEC) */
  597.  
  598. inline CDXMatrix4x4F CDXMatrix4x4F::operator*(CDXMatrix4x4F Mx) const
  599. {
  600.     CDXMatrix4x4F t;
  601.     int i, j;
  602.  
  603.     for( i = 0; i < 4; i++ )
  604.     {
  605.         for( j = 0; j < 4; j++ )
  606.         {
  607.             t.m_Coeff[i][j] =   m_Coeff[i][0] * Mx.m_Coeff[0][j] + 
  608.                                 m_Coeff[i][1] * Mx.m_Coeff[1][j] +
  609.                                 m_Coeff[i][2] * Mx.m_Coeff[2][j] +
  610.                                 m_Coeff[i][3] * Mx.m_Coeff[3][j];
  611.         }
  612.     }
  613.  
  614.     return t;
  615. } /* CDXMatrix4x4F::operator*(CDXMatrix4x4F) */
  616.             
  617. inline void CDXMatrix4x4F::operator*=(CDXMatrix4x4F Mx) const
  618. {
  619.     CDXMatrix4x4F t;
  620.     int i, j;
  621.  
  622.     for( i = 0; i < 4; i++ )
  623.     {
  624.         for( j = 0; j < 4; j++ )
  625.         {
  626.             t.m_Coeff[i][j] =   m_Coeff[i][0] * Mx.m_Coeff[0][j] + 
  627.                                 m_Coeff[i][1] * Mx.m_Coeff[1][j] +
  628.                                 m_Coeff[i][2] * Mx.m_Coeff[2][j] +
  629.                                 m_Coeff[i][3] * Mx.m_Coeff[3][j];
  630.         }
  631.     }
  632.  
  633.     CopyMemory( (void *)m_Coeff, (void *)t.m_Coeff, sizeof(m_Coeff) );
  634. } /* CDXMatrix4x4F::operator*=(CDXMatrix4x4F) */
  635.             
  636.  
  637. inline void CDXMatrix4x4F::Scale( float sx, float sy, float sz )
  638. {
  639.     if( sx != 1. )
  640.     {
  641.         m_Coeff[0][0] *= sx;
  642.         m_Coeff[0][1] *= sx;
  643.         m_Coeff[0][2] *= sx;
  644.         m_Coeff[0][3] *= sx;
  645.     }
  646.     if( sy != 1. )
  647.     {
  648.         m_Coeff[1][0] *= sy;
  649.         m_Coeff[1][1] *= sy;
  650.         m_Coeff[1][2] *= sy;
  651.         m_Coeff[1][3] *= sy;
  652.     }
  653.     if( sz != 1. )
  654.     {
  655.         m_Coeff[2][0] *= sz;
  656.         m_Coeff[2][1] *= sz;
  657.         m_Coeff[2][2] *= sz;
  658.         m_Coeff[2][3] *= sz;
  659.     }
  660. } /* CDXMatrix4x4F::Scale */
  661.  
  662. inline void CDXMatrix4x4F::Translate( float dx, float dy, float dz )
  663. {
  664.     float a, b, c, d;
  665.     a = b = c = d = 0;
  666.     if( dx != 0. )
  667.     {
  668.         a += m_Coeff[0][0]*dx;
  669.         b += m_Coeff[0][1]*dx;
  670.         c += m_Coeff[0][2]*dx;
  671.         d += m_Coeff[0][3]*dx;
  672.     }
  673.     if( dy != 0. )
  674.     {
  675.         a += m_Coeff[1][0]*dy;
  676.         b += m_Coeff[1][1]*dy;
  677.         c += m_Coeff[1][2]*dy;
  678.         d += m_Coeff[1][3]*dy;
  679.     }
  680.     if( dz != 0. )
  681.     {
  682.         a += m_Coeff[2][0]*dz;
  683.         b += m_Coeff[2][1]*dz;
  684.         c += m_Coeff[2][2]*dz;
  685.         d += m_Coeff[2][3]*dz;
  686.     }
  687.     m_Coeff[3][0] += a;
  688.     m_Coeff[3][1] += b;
  689.     m_Coeff[3][2] += c;
  690.     m_Coeff[3][3] += d;
  691. } /* CDXMatrix4x4F::Translate */
  692.  
  693. inline void CDXMatrix4x4F::Rotate( float rx, float ry, float rz )
  694. {
  695.     const float l_dfCte = (const float)(3.1415926535/180.0);
  696.  
  697.     float lAngleY = 0.0;
  698.     float lAngleX = 0.0;
  699.     float lAngleZ = 0.0;
  700.     float lCosX = 1.0;
  701.     float lSinX = 0.0;
  702.     float lCosY = 1.0;
  703.     float lSinY = 0.0;
  704.     float lCosZ = 1.0;
  705.     float lSinZ = 0.0;
  706.  
  707.     // calculate rotation angle sines and cosines
  708.     if( rx != 0 )
  709.     {
  710.         lAngleX = rx * l_dfCte;
  711.         lCosX = (float)cos(lAngleX);
  712.         lSinX = (float)sin(lAngleX);
  713.         if (lCosX > 0.0F && lCosX < 0.0000005F)
  714.         {
  715.             lCosX = .0F;
  716.         }
  717.         if (lSinX > -0.0000005F && lSinX < .0F)
  718.         {
  719.             lSinX = .0F;
  720.         }
  721.     }
  722.     if( ry != 0 )
  723.     {
  724.         lAngleY = ry * l_dfCte;
  725.         lCosY = (float)cos(lAngleY);
  726.         lSinY = (float)sin(lAngleY);
  727.         if (lCosY > 0.0F && lCosY < 0.0000005F)
  728.         {
  729.             lCosY = .0F;
  730.         }
  731.         if (lSinY > -0.0000005F && lSinY < .0F)
  732.         {
  733.             lSinY = .0F;
  734.         }
  735.     }
  736.     if( rz != 0 )
  737.     {
  738.         lAngleZ = rz * l_dfCte;
  739.         lCosZ = (float)cos(lAngleZ);
  740.         lSinZ = (float)sin(lAngleZ);
  741.         if (lCosZ > 0.0F && lCosZ < 0.0000005F)
  742.         {
  743.             lCosZ = .0F;
  744.         }
  745.         if (lSinZ > -0.0000005F && lSinZ < .0F)
  746.         {
  747.             lSinZ = .0F;
  748.         }
  749.     }
  750.  
  751.     float u, v;
  752.     int i;
  753.  
  754.     //--- X Rotation
  755.     for( i = 0; i < 4; i++ )
  756.     {
  757.         u = m_Coeff[1][i]; 
  758.         v = m_Coeff[2][i];
  759.         m_Coeff[1][i] = lCosX*u+lSinX*v; 
  760.         m_Coeff[2][i] = -lSinX*u+lCosX*v;
  761.     }
  762.  
  763.     //--- Y Rotation
  764.     for( i = 0; i < 4; i++ )
  765.     {
  766.         u = m_Coeff[0][i];
  767.         v = m_Coeff[2][i];
  768.         m_Coeff[0][i] = lCosY*u-lSinY*v; 
  769.         m_Coeff[2][i] = lSinY*u+lCosY*v;
  770.     }
  771.  
  772.     //--- Z Rotation
  773.     for( i = 0; i < 4; i++ )
  774.     {
  775.         u = m_Coeff[0][i];
  776.         v = m_Coeff[1][i];
  777.         m_Coeff[0][i] = lCosZ*u+lSinZ*v; 
  778.         m_Coeff[1][i] = -lSinZ*u+lCosZ*v;
  779.     }
  780. }
  781.  
  782. /*
  783. inline BOOL CDXMatrix4x4F::IsIdentity()
  784. {
  785.     return  !memcmp( m_Coeff, g_DXMat4X4Identity, sizeof(g_DXMat4X4Identity) );
  786. } /* CDXMatrix4x4F::IsIdentity */
  787.  
  788.  
  789. /*
  790.    Uses Gaussian elimination to invert the 4 x 4 non-linear matrix in t and
  791.    return the result in Mx.  The matrix t is destroyed in the process.
  792. */
  793. inline BOOL CDXMatrix4x4F::Invert()
  794. {
  795.     int i,j,k,Pivot;
  796.     float PValue;
  797.     CDXMatrix4x4F Mx;
  798.     Mx.SetIdentity();
  799.  
  800. /* Find pivot element.  Use partial pivoting by row */
  801.     for( i = 0;i < 4; i++ )
  802.     {
  803.         Pivot = 0;
  804.         for( j = 0; j < 4; j++ )
  805.         {
  806.             if( fabs(m_Coeff[i][j]) > fabs(m_Coeff[i][Pivot]) ) Pivot = j;
  807.         }
  808.  
  809.         if( m_Coeff[i][Pivot] == 0.0 )
  810.         {
  811.             ZeroMatrix();   /* Singular Matrix */
  812.             return FALSE; 
  813.         }
  814.  
  815. /* Normalize */
  816.         PValue = m_Coeff[i][Pivot];
  817.         for( j = 0; j < 4; j++ )
  818.         {
  819.             m_Coeff[i][j] /= PValue;
  820.             Mx.m_Coeff[i][j] /= PValue;
  821.         }
  822.  
  823. /* Zeroing */
  824.         for( j = 0; j < 4; j++ )
  825.         {
  826.             if( j != i )
  827.             {
  828.                 PValue = m_Coeff[j][Pivot];
  829.                 for( k = 0; k < 4; k++ )
  830.                 {
  831.                     m_Coeff[j][k] -= PValue*m_Coeff[i][k];
  832.                     Mx.m_Coeff[j][k] -= PValue*Mx.m_Coeff[i][k];
  833.                 }
  834.             }
  835.         }
  836.     }
  837.  
  838. /* Reorder rows */
  839.     for( i = 0; i < 4; i++ )
  840.     {
  841.         if( m_Coeff[i][i] != 1.0 )
  842.         {
  843.             for( j = i + 1; j < 4; j++ )
  844.                 if( m_Coeff[j][i] == 1.0 ) break;
  845.             if( j >= 4 )
  846.             {
  847.                 ZeroMatrix();
  848.                 return FALSE;
  849.             }
  850.  
  851.             //--- swap rows i and j of original
  852.             for( k = 0; k < 4; k++ )
  853.             {
  854.                 m_Coeff[i][k] += m_Coeff[j][k];
  855.                 m_Coeff[j][k] = m_Coeff[i][k] - m_Coeff[j][k];
  856.                 m_Coeff[i][k] -= m_Coeff[j][k];
  857.             }
  858.             
  859.             //--- swap rows i and j of result
  860.             for( k = 0; k < 4; k++ )
  861.             {
  862.                 Mx.m_Coeff[i][k] += Mx.m_Coeff[j][k];
  863.                 Mx.m_Coeff[j][k] = Mx.m_Coeff[i][k] - Mx.m_Coeff[j][k];
  864.                 Mx.m_Coeff[i][k] -= Mx.m_Coeff[j][k];
  865.             }
  866.         }
  867.     }
  868.     *this = Mx;
  869.     return TRUE;
  870. } /* CDXMatrix4x4F::Invert */
  871.  
  872. inline void CDXMatrix4x4F::Transpose()
  873. {
  874.     float temp;
  875.  
  876.     temp = m_Coeff[0][1];
  877.     m_Coeff[0][1] = m_Coeff[1][0];
  878.     m_Coeff[1][0] = temp;
  879.  
  880.     temp = m_Coeff[0][2];
  881.     m_Coeff[0][2] = m_Coeff[2][0];
  882.     m_Coeff[2][0] = temp;
  883.  
  884.     temp = m_Coeff[0][3];
  885.     m_Coeff[0][3] = m_Coeff[3][0];
  886.     m_Coeff[3][0] = temp;
  887.  
  888.     temp = m_Coeff[1][2];
  889.     m_Coeff[1][2] = m_Coeff[2][1];
  890.     m_Coeff[2][1] = temp;
  891.  
  892.     temp = m_Coeff[1][3];
  893.     m_Coeff[1][3] = m_Coeff[3][1];
  894.     m_Coeff[3][1] = temp;
  895.  
  896.     temp = m_Coeff[2][3];
  897.     m_Coeff[2][3] = m_Coeff[3][2];
  898.     m_Coeff[3][2] = temp;
  899.  
  900. } /* CDXMatrix4x4F::Transpose */
  901.  
  902. inline void CDXMatrix4x4F::GetTranspose( CDXMatrix4x4F *m )
  903. {
  904.     float temp;
  905.  
  906.     (*this) = *m;
  907.  
  908.     temp = m_Coeff[0][1];
  909.     m_Coeff[0][1] = m_Coeff[1][0];
  910.     m_Coeff[1][0] = temp;
  911.  
  912.     temp = m_Coeff[0][2];
  913.     m_Coeff[0][2] = m_Coeff[2][0];
  914.     m_Coeff[2][0] = temp;
  915.  
  916.     temp = m_Coeff[0][3];
  917.     m_Coeff[0][3] = m_Coeff[3][0];
  918.     m_Coeff[3][0] = temp;
  919.  
  920.     temp = m_Coeff[1][2];
  921.     m_Coeff[1][2] = m_Coeff[2][1];
  922.     m_Coeff[2][1] = temp;
  923.  
  924.     temp = m_Coeff[1][3];
  925.     m_Coeff[1][3] = m_Coeff[3][1];
  926.     m_Coeff[3][1] = temp;
  927.  
  928.     temp = m_Coeff[2][3];
  929.     m_Coeff[2][3] = m_Coeff[3][2];
  930.     m_Coeff[3][2] = temp;
  931.  
  932. } /* CDXMatrix4x4F::Transpose */
  933.  
  934.  
  935. /*
  936. Matrix Inversion
  937. by Richard Carling
  938. from "Graphics Gems", Academic Press, 1990
  939. */
  940.  
  941. #define SMALL_NUMBER    1.e-8
  942. /* 
  943.  *   inverse( original_matrix, inverse_matrix )
  944.  * 
  945.  *    calculate the inverse of a 4x4 matrix
  946.  *
  947.  *     -1     
  948.  *     A  = ___1__ adjoint A
  949.  *         det A
  950.  */
  951.  
  952. inline BOOL CDXMatrix4x4F::GetInverse( CDXMatrix4x4F *pIn )
  953. {
  954.     int i, j;
  955.     float det;
  956.  
  957.     /* calculate the adjoint matrix */
  958.  
  959.     GetAdjoint( pIn );
  960.  
  961.     /*  calculate the 4x4 determinant
  962.      *  if the determinant is zero, 
  963.      *  then the inverse matrix is not unique.
  964.      */
  965.  
  966.     det = det4x4( pIn );
  967.  
  968.     if( fabs( det ) < SMALL_NUMBER )
  969.     {
  970.         //  Non-singular matrix, no inverse!
  971.         return FALSE;;
  972.     }
  973.  
  974.     /* scale the adjoint matrix to get the inverse */
  975.  
  976.     for( i = 0; i < 4; i++ )
  977.         for( j = 0; j < 4; j++ )
  978.             m_Coeff[i][j] = m_Coeff[i][j] / det;
  979.  
  980.     return TRUE;
  981. }
  982.  
  983.  
  984. /* 
  985.  *   adjoint( original_matrix, inverse_matrix )
  986.  * 
  987.  *     calculate the adjoint of a 4x4 matrix
  988.  *
  989.  *      Let  a   denote the minor determinant of matrix A obtained by
  990.  *           ij
  991.  *
  992.  *      deleting the ith row and jth column from A.
  993.  *
  994.  *                    i+j
  995.  *     Let  b   = (-1)    a
  996.  *          ij            ji
  997.  *
  998.  *    The matrix B = (b  ) is the adjoint of A
  999.  *                     ij
  1000.  */
  1001. inline void CDXMatrix4x4F::GetAdjoint( CDXMatrix4x4F *pIn )
  1002. {
  1003.     float a1, a2, a3, a4, b1, b2, b3, b4;
  1004.     float c1, c2, c3, c4, d1, d2, d3, d4;
  1005.  
  1006.     /* assign to individual variable names to aid  */
  1007.     /* selecting correct values  */
  1008.  
  1009.     a1 = pIn->m_Coeff[0][0]; b1 = pIn->m_Coeff[0][1]; 
  1010.     c1 = pIn->m_Coeff[0][2]; d1 = pIn->m_Coeff[0][3];
  1011.  
  1012.     a2 = pIn->m_Coeff[1][0]; b2 = pIn->m_Coeff[1][1]; 
  1013.     c2 = pIn->m_Coeff[1][2]; d2 = pIn->m_Coeff[1][3];
  1014.  
  1015.     a3 = pIn->m_Coeff[2][0]; b3 = pIn->m_Coeff[2][1];
  1016.     c3 = pIn->m_Coeff[2][2]; d3 = pIn->m_Coeff[2][3];
  1017.  
  1018.     a4 = pIn->m_Coeff[3][0]; b4 = pIn->m_Coeff[3][1]; 
  1019.     c4 = pIn->m_Coeff[3][2]; d4 = pIn->m_Coeff[3][3];
  1020.  
  1021.  
  1022.     /* row column labeling reversed since we transpose rows & columns */
  1023.  
  1024.     m_Coeff[0][0]  =   det3x3( b2, b3, b4, c2, c3, c4, d2, d3, d4);
  1025.     m_Coeff[1][0]  = - det3x3( a2, a3, a4, c2, c3, c4, d2, d3, d4);
  1026.     m_Coeff[2][0]  =   det3x3( a2, a3, a4, b2, b3, b4, d2, d3, d4);
  1027.     m_Coeff[3][0]  = - det3x3( a2, a3, a4, b2, b3, b4, c2, c3, c4);
  1028.         
  1029.     m_Coeff[0][1]  = - det3x3( b1, b3, b4, c1, c3, c4, d1, d3, d4);
  1030.     m_Coeff[1][1]  =   det3x3( a1, a3, a4, c1, c3, c4, d1, d3, d4);
  1031.     m_Coeff[2][1]  = - det3x3( a1, a3, a4, b1, b3, b4, d1, d3, d4);
  1032.     m_Coeff[3][1]  =   det3x3( a1, a3, a4, b1, b3, b4, c1, c3, c4);
  1033.         
  1034.     m_Coeff[0][2]  =   det3x3( b1, b2, b4, c1, c2, c4, d1, d2, d4);
  1035.     m_Coeff[1][2]  = - det3x3( a1, a2, a4, c1, c2, c4, d1, d2, d4);
  1036.     m_Coeff[2][2]  =   det3x3( a1, a2, a4, b1, b2, b4, d1, d2, d4);
  1037.     m_Coeff[3][2]  = - det3x3( a1, a2, a4, b1, b2, b4, c1, c2, c4);
  1038.         
  1039.     m_Coeff[0][3]  = - det3x3( b1, b2, b3, c1, c2, c3, d1, d2, d3);
  1040.     m_Coeff[1][3]  =   det3x3( a1, a2, a3, c1, c2, c3, d1, d2, d3);
  1041.     m_Coeff[2][3]  = - det3x3( a1, a2, a3, b1, b2, b3, d1, d2, d3);
  1042.     m_Coeff[3][3]  =   det3x3( a1, a2, a3, b1, b2, b3, c1, c2, c3);
  1043. }
  1044. /*
  1045.  * float = det4x4( matrix )
  1046.  * 
  1047.  * calculate the determinant of a 4x4 matrix.
  1048.  */
  1049. inline float det4x4( CDXMatrix4x4F *pIn )
  1050. {
  1051.     float ans;
  1052.     float a1, a2, a3, a4, b1, b2, b3, b4, c1, c2, c3, c4, d1, d2, d3, d4;
  1053.  
  1054.     /* assign to individual variable names to aid selecting */
  1055.     /*  correct elements */
  1056.  
  1057.     a1 = pIn->m_Coeff[0][0]; b1 = pIn->m_Coeff[0][1]; 
  1058.     c1 = pIn->m_Coeff[0][2]; d1 = pIn->m_Coeff[0][3];
  1059.  
  1060.     a2 = pIn->m_Coeff[1][0]; b2 = pIn->m_Coeff[1][1]; 
  1061.     c2 = pIn->m_Coeff[1][2]; d2 = pIn->m_Coeff[1][3];
  1062.  
  1063.     a3 = pIn->m_Coeff[2][0]; b3 = pIn->m_Coeff[2][1]; 
  1064.     c3 = pIn->m_Coeff[2][2]; d3 = pIn->m_Coeff[2][3];
  1065.  
  1066.     a4 = pIn->m_Coeff[3][0]; b4 = pIn->m_Coeff[3][1]; 
  1067.     c4 = pIn->m_Coeff[3][2]; d4 = pIn->m_Coeff[3][3];
  1068.  
  1069.     ans = a1 * det3x3( b2, b3, b4, c2, c3, c4, d2, d3, d4 )
  1070.         - b1 * det3x3( a2, a3, a4, c2, c3, c4, d2, d3, d4 )
  1071.         + c1 * det3x3( a2, a3, a4, b2, b3, b4, d2, d3, d4 )
  1072.         - d1 * det3x3( a2, a3, a4, b2, b3, b4, c2, c3, c4 );
  1073.     return ans;
  1074. }
  1075.  
  1076. /*
  1077.  * float = det3x3(  a1, a2, a3, b1, b2, b3, c1, c2, c3 )
  1078.  * 
  1079.  * calculate the determinant of a 3x3 matrix
  1080.  * in the form
  1081.  *
  1082.  *     | a1,  b1,  c1 |
  1083.  *     | a2,  b2,  c2 |
  1084.  *     | a3,  b3,  c3 |
  1085.  */
  1086.  
  1087. inline float det3x3( float a1, float a2, float a3, 
  1088.                      float b1, float b2, float b3, 
  1089.                      float c1, float c2, float c3 )
  1090. {
  1091.     float ans;
  1092.  
  1093.     ans = a1 * det2x2( b2, b3, c2, c3 )
  1094.         - b1 * det2x2( a2, a3, c2, c3 )
  1095.         + c1 * det2x2( a2, a3, b2, b3 );
  1096.     return ans;
  1097. }
  1098.  
  1099. /*
  1100.  * float = det2x2( float a, float b, float c, float d )
  1101.  * 
  1102.  * calculate the determinant of a 2x2 matrix.
  1103.  */
  1104. inline float det2x2( float a, float b, float c, float d )
  1105. {
  1106.     float ans = a * d - b * c;
  1107.     return ans;
  1108. }
  1109.  
  1110. inline HRESULT CDXMatrix4x4F::InitFromSafeArray( SAFEARRAY * /*pSA*/ )
  1111. {
  1112.     HRESULT hr = S_OK;
  1113. #if 0
  1114.     long *pData;
  1115.  
  1116.     if( !pSA || ( pSA->cDims != 1 ) ||
  1117.          ( pSA->cbElements != sizeof(float) ) ||
  1118.          ( pSA->rgsabound->lLbound   != 1 ) ||
  1119.          ( pSA->rgsabound->cElements != 8 ) 
  1120.       )
  1121.     {
  1122.         hr = E_INVALIDARG;
  1123.     }
  1124.     else
  1125.     {
  1126.         hr = SafeArrayAccessData(pSA, (void **)&pData);
  1127.  
  1128.         if( SUCCEEDED( hr ) )
  1129.         {
  1130.             for( int i = 0; i < 4; ++i )
  1131.             {
  1132.                 m_Bounds[i].Min = pData[i];
  1133.                 m_Bounds[i].Max = pData[i+4];
  1134.                 m_Bounds[i].SampleRate = SampleRate;
  1135.             }
  1136.  
  1137.             hr = SafeArrayUnaccessData( pSA );
  1138.         }
  1139.     }
  1140. #endif
  1141.     return hr;
  1142. } /* CDXMatrix4x4F::InitFromSafeArray */
  1143.  
  1144. inline HRESULT CDXMatrix4x4F::GetSafeArray( SAFEARRAY ** /*ppSA*/ ) const
  1145. {
  1146.     HRESULT hr = S_OK;
  1147. #if 0
  1148.     SAFEARRAY *pSA;
  1149.  
  1150.     if( !ppSA )
  1151.     {
  1152.         hr = E_POINTER;
  1153.     }
  1154.     else
  1155.     {
  1156.         SAFEARRAYBOUND rgsabound;
  1157.         rgsabound.lLbound   = 1;
  1158.         rgsabound.cElements = 16;
  1159.  
  1160.         if( !(pSA = SafeArrayCreate( VT_I4, 1, &rgsabound ) ) )
  1161.         {
  1162.             hr = E_OUTOFMEMORY;
  1163.         }
  1164.         else
  1165.         {
  1166.             long *pData;
  1167.             hr = SafeArrayAccessData( pSA, (void **)&pData );
  1168.  
  1169.             if( SUCCEEDED( hr ) )
  1170.             {
  1171.                 for( int i = 0; i < 4; ++i )
  1172.                 {
  1173.                     pData[i]   = m_Bounds[i].Min;
  1174.                     pData[i+4] = m_Bounds[i].Max;
  1175.                 }
  1176.  
  1177.                 hr = SafeArrayUnaccessData( pSA );
  1178.             }
  1179.         }
  1180.  
  1181.         if( SUCCEEDED( hr ) )
  1182.         {
  1183.             *ppSA = pSA;
  1184.         }
  1185.     }
  1186. #endif
  1187.     return hr;
  1188. } /* CDXMatrix4x4F::GetSafeArray */
  1189.  
  1190. inline void CDXMatrix4x4F::TransformBounds( DXBNDS& /*Bnds*/, DXBNDS& /*ResultBnds*/ )
  1191. {
  1192.  
  1193. } /* CDXMatrix4x4F::TransformBounds */
  1194.  
  1195. #pragma option pop /*P_O_Pop*/
  1196. #endif  // DXVector_h
  1197.     
  1198.