Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1083 lines
31 KiB

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