Counter Strike : Global Offensive Source Code
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.

873 lines
20 KiB

  1. //====== Copyright � 1996-2009, Valve Corporation, All rights reserved. =======
  2. //
  3. // DmeEyeball
  4. //
  5. //=============================================================================
  6. // Valve includes
  7. #include "datamodel/dmelementfactoryhelper.h"
  8. #include "mdlobjects/dmeskinner.h"
  9. #include "movieobjects/dmedag.h"
  10. #include "movieobjects/dmemodel.h"
  11. #include "mathlib/mathlib.h"
  12. // memdbgon must be the last include file in a .cpp file!!!
  13. #include "tier0/memdbgon.h"
  14. //-----------------------------------------------------------------------------
  15. // Class for a unit Super Ellipsoid at the origin
  16. //-----------------------------------------------------------------------------
  17. class CSuperEllipsoid
  18. {
  19. public:
  20. CSuperEllipsoid(
  21. double powerXZ = 1.0,
  22. double powerY = 1.0 );
  23. bool IntersectFromOriginThroughPoint(
  24. Vector point,
  25. double dDistance ) const;
  26. // Evaluate for root finding: [ | x | ^ ( 2 / powerXZ ) + | z | ^ ( 2 / powerXZ ) ] ^ ( powerXZ / powerY ) + | y | ^ powerY - 1 = 0
  27. double RootEvaluate( const Vector &p ) const;
  28. protected:
  29. static void EvaluateRayFromOrigin(
  30. const Vector &rayDirection,
  31. double dDistance,
  32. Vector &pointOnRay );
  33. static bool IntersectUnitBoxFromOrigin(
  34. const Vector &rayDirection,
  35. double &dMin,
  36. double &dMax );
  37. void SolveHit(
  38. double v0,
  39. const Vector &intPoint0,
  40. double v1,
  41. const Vector &intPoint1,
  42. Vector &intPoint ) const;
  43. static const double s_dEpsilon;
  44. double m_powerXZ;
  45. double m_powerY;
  46. int m_nMaxIterations;
  47. };
  48. //-----------------------------------------------------------------------------
  49. // Expose this class to the scene database
  50. //-----------------------------------------------------------------------------
  51. IMPLEMENT_ELEMENT_FACTORY( DmeSkinnerVolume, CDmeSkinnerVolume );
  52. //-----------------------------------------------------------------------------
  53. //
  54. //-----------------------------------------------------------------------------
  55. void CDmeSkinnerVolume::OnConstruction()
  56. {
  57. m_mMatrix.Init( this, "matrix" );
  58. m_flStrength.Init( this, "strength", 1.0f );
  59. m_flFalloff.Init( this, "falloff", 0.0f );
  60. m_nFalloffType.Init( this, "falloffType", FT_LINEAR );
  61. m_flPowerY.InitAndSet( this, "powerY", 1.0f );
  62. m_flPowerXZ.InitAndSet( this, "powerXZ", 1.0f );
  63. }
  64. //-----------------------------------------------------------------------------
  65. //
  66. //-----------------------------------------------------------------------------
  67. void CDmeSkinnerVolume::OnDestruction()
  68. {
  69. }
  70. //-----------------------------------------------------------------------------
  71. // Expose this class to the scene database
  72. //-----------------------------------------------------------------------------
  73. IMPLEMENT_ELEMENT_FACTORY( DmeSkinnerJoint, CDmeSkinnerJoint );
  74. //-----------------------------------------------------------------------------
  75. //
  76. //-----------------------------------------------------------------------------
  77. void CDmeSkinnerJoint::OnConstruction()
  78. {
  79. m_mBindWorldMatrix.Init( this, "bindWorldMatrix" );
  80. m_eVolumeList.Init( this, "volumeList" );
  81. }
  82. //-----------------------------------------------------------------------------
  83. //
  84. //-----------------------------------------------------------------------------
  85. void CDmeSkinnerJoint::OnDestruction()
  86. {
  87. }
  88. //-----------------------------------------------------------------------------
  89. // Expose this class to the scene database
  90. //-----------------------------------------------------------------------------
  91. IMPLEMENT_ELEMENT_FACTORY( DmeSkinner, CDmeSkinner );
  92. //-----------------------------------------------------------------------------
  93. //
  94. //-----------------------------------------------------------------------------
  95. void CDmeSkinner::OnConstruction()
  96. {
  97. }
  98. //-----------------------------------------------------------------------------
  99. //
  100. //-----------------------------------------------------------------------------
  101. void CDmeSkinner::OnDestruction()
  102. {
  103. }
  104. //-----------------------------------------------------------------------------
  105. //
  106. //-----------------------------------------------------------------------------
  107. bool CDmeSkinner::ReskinMeshes( CDmeModel *pDmeModel, int nJointPerVertexCount )
  108. {
  109. CUtlStack< CDmeDag * > depthFirstStack;
  110. depthFirstStack.Push( pDmeModel );
  111. CDmeDag *pDmeDag;
  112. CDmeMesh *pDmeMesh;
  113. while ( depthFirstStack.Count() > 0 )
  114. {
  115. depthFirstStack.Pop( pDmeDag );
  116. if ( !pDmeDag )
  117. continue;
  118. pDmeMesh = CastElement< CDmeMesh >( pDmeDag->GetShape() );
  119. if ( pDmeMesh )
  120. {
  121. ReskinMesh( pDmeModel, pDmeMesh, nJointPerVertexCount );
  122. }
  123. for ( int i = pDmeDag->GetChildCount() - 1; i >= 0; --i )
  124. {
  125. depthFirstStack.Push( pDmeDag->GetChild( i ) );
  126. }
  127. }
  128. return true;
  129. }
  130. //-----------------------------------------------------------------------------
  131. //
  132. //-----------------------------------------------------------------------------
  133. class CJointWeight
  134. {
  135. public:
  136. int m_nJointDataIndex;
  137. float m_flWeight;
  138. };
  139. //-----------------------------------------------------------------------------
  140. //
  141. //-----------------------------------------------------------------------------
  142. class CVertexWeight
  143. {
  144. public:
  145. CVertexWeight( int nWeightsPerVertex )
  146. : m_nWeightPerVertex( MAX( 0, nWeightsPerVertex ) )
  147. {
  148. }
  149. int m_nWeightPerVertex;
  150. CUtlVector< CJointWeight > m_weights; // Sorted Weight List
  151. static int SortWeights( const CJointWeight *pLhs, const CJointWeight *pRhs );
  152. int Count() const {
  153. return MIN( m_nWeightPerVertex, m_weights.Count() );
  154. }
  155. void Reset()
  156. {
  157. m_weights.Purge();
  158. }
  159. void AddWeight(
  160. int nJointDataIndex,
  161. float flWeight );
  162. void Sort();
  163. float ComputeTotalWeight() const
  164. {
  165. float flTotalWeight = 0.0f;
  166. const int nWeightCount = Count();
  167. for ( int i = 0; i < nWeightCount; ++i )
  168. {
  169. flTotalWeight += m_weights[ i ].m_flWeight;
  170. }
  171. return flTotalWeight;
  172. }
  173. float GetWeight( int nWeightIndex ) const
  174. {
  175. if ( nWeightIndex < m_weights.Count() )
  176. return m_weights[ nWeightIndex ].m_flWeight;
  177. return 0.0f;
  178. }
  179. int GetJointIndex( int nWeightIndex ) const
  180. {
  181. if ( nWeightIndex < m_weights.Count() )
  182. return m_weights[ nWeightIndex ].m_nJointDataIndex;
  183. return 0;
  184. }
  185. };
  186. //-----------------------------------------------------------------------------
  187. //
  188. //-----------------------------------------------------------------------------
  189. void CVertexWeight::AddWeight(
  190. int nJointDataIndex,
  191. float flWeight )
  192. {
  193. CJointWeight &jointWeight = m_weights[ m_weights.AddToTail() ];
  194. jointWeight.m_nJointDataIndex = nJointDataIndex;
  195. jointWeight.m_flWeight = flWeight;
  196. }
  197. //-----------------------------------------------------------------------------
  198. //
  199. //-----------------------------------------------------------------------------
  200. void CVertexWeight::Sort()
  201. {
  202. m_weights.Sort( SortWeights );
  203. }
  204. //-----------------------------------------------------------------------------
  205. // Sort them from highest to lowest
  206. //-----------------------------------------------------------------------------
  207. int CVertexWeight::SortWeights( const CJointWeight *pLhs, const CJointWeight *pRhs )
  208. {
  209. if ( pLhs->m_flWeight < pRhs->m_flWeight )
  210. return 1;
  211. if ( pLhs->m_flWeight > pRhs->m_flWeight )
  212. return -1;
  213. return 0;
  214. }
  215. //-----------------------------------------------------------------------------
  216. //
  217. //-----------------------------------------------------------------------------
  218. bool CDmeSkinner::ReskinMesh( CDmeModel *pDmeModel, CDmeMesh *pDmeMesh, int nJointPerVertexCount )
  219. {
  220. if ( !pDmeMesh )
  221. return false;
  222. CDmeDag *pDmeDagMeshParent = FindReferringElement< CDmeDag >( pDmeMesh, "shape" );
  223. if ( !pDmeDagMeshParent )
  224. return false;
  225. CDmeVertexData *pDmeVertexData = pDmeMesh->GetBindBaseState();
  226. if ( !pDmeVertexData )
  227. {
  228. Error( "CDmeSkinner: No \"bind\" base state on DmeMesh \"%s\"\n", pDmeMesh->GetName() );
  229. return false;
  230. }
  231. FieldIndex_t nJointWeightsField = -1;
  232. FieldIndex_t nJointIndicesField = -1;
  233. pDmeVertexData->CreateJointWeightsAndIndices( nJointPerVertexCount, &nJointWeightsField, &nJointIndicesField );
  234. if ( nJointWeightsField < 0 || nJointIndicesField < 0 )
  235. {
  236. Error( "CDmeSkinner: Couldn't create jointWeights & jointIndices fields on DmeMesh \"%s\"\n", pDmeMesh->GetName() );
  237. return false;
  238. }
  239. pDmeVertexData->RemoveAllVertexData( nJointWeightsField );
  240. pDmeVertexData->RemoveAllVertexData( nJointIndicesField );
  241. const CUtlVector< Vector > &positions = pDmeVertexData->GetPositionData();
  242. CUtlVector< float > jointWeights;
  243. CUtlVector< int > jointIndices;
  244. struct s_VolumeStruct
  245. {
  246. CDmeSkinnerVolume *m_pDmeSkinnerVolume;
  247. VMatrix m_mMat;
  248. };
  249. struct s_JointStruct
  250. {
  251. s_JointStruct()
  252. : m_pDmeSkinnerJoint( NULL )
  253. , m_nJointIndex( -1 )
  254. {
  255. }
  256. s_JointStruct( const s_JointStruct &rhs )
  257. {
  258. m_pDmeSkinnerJoint = rhs.m_pDmeSkinnerJoint;
  259. m_nJointIndex = rhs.m_nJointIndex;
  260. m_volumes.CopyArray( rhs.m_volumes.Base(), m_volumes.Count() );
  261. }
  262. CDmeSkinnerJoint *m_pDmeSkinnerJoint;
  263. int m_nJointIndex;
  264. CUtlVector< s_VolumeStruct > m_volumes;
  265. };
  266. CUtlVector< s_JointStruct > volumeJointList;
  267. {
  268. matrix3x4_t gwm;
  269. pDmeDagMeshParent->GetAbsTransform( gwm );
  270. VMatrix gwvm;
  271. gwvm.CopyFrom3x4( gwm );
  272. VMatrix vm; // Volume matrix
  273. VMatrix vmi; // Volume matrix inverse
  274. matrix3x4_t m0;
  275. matrix3x4_t m1;
  276. CUtlStack< CDmeDag * > depthFirstStack;
  277. depthFirstStack.Push( this );
  278. CDmeDag *pDmeDag;
  279. CDmeSkinnerJoint *pDmeSkinnerJoint;
  280. CDmeSkinnerVolume *pDmeSkinnerVolume;
  281. while ( depthFirstStack.Count() > 0 )
  282. {
  283. depthFirstStack.Pop( pDmeDag );
  284. if ( !pDmeDag )
  285. continue;
  286. pDmeSkinnerJoint = CastElement< CDmeSkinnerJoint >( pDmeDag );
  287. if ( pDmeSkinnerJoint )
  288. {
  289. if ( pDmeSkinnerJoint->m_eVolumeList.Count() > 0 )
  290. {
  291. int nJointIndex = pDmeModel->GetJointIndex( pDmeSkinnerJoint->GetName() );
  292. if ( nJointIndex < 0 ) // This joint isn't in the joint list as well as it's children, so ignore
  293. {
  294. Warning( "DmeSkinner: Skinner Joint %s isn't in DmeModel %s.jointList, ignoring it and all children\n", pDmeSkinnerJoint->GetName(), pDmeModel->GetName() );
  295. continue;
  296. }
  297. s_JointStruct &js = volumeJointList[ volumeJointList.AddToTail() ];
  298. js.m_pDmeSkinnerJoint = pDmeSkinnerJoint;
  299. js.m_nJointIndex = nJointIndex;
  300. for ( int i = 0; i < pDmeSkinnerJoint->m_eVolumeList.Count(); ++i )
  301. {
  302. pDmeSkinnerVolume = CastElement< CDmeSkinnerVolume >( pDmeSkinnerJoint->m_eVolumeList[ i ] );
  303. if ( !pDmeSkinnerVolume )
  304. continue;
  305. s_VolumeStruct &vs = js.m_volumes[ js.m_volumes.AddToTail() ];
  306. vs.m_pDmeSkinnerVolume = pDmeSkinnerVolume;
  307. pDmeSkinnerVolume->m_mMatrix.Get().MatrixMul( pDmeSkinnerJoint->m_mBindWorldMatrix.Get(), vm );
  308. vm.InverseGeneral( vmi );
  309. vmi.MatrixMul( gwvm, vs.m_mMat );
  310. vs.m_mMat = vs.m_mMat.Transpose();
  311. }
  312. }
  313. }
  314. for ( int i = pDmeDag->GetChildCount() - 1; i >= 0; --i )
  315. {
  316. depthFirstStack.Push( pDmeDag->GetChild( i ) );
  317. }
  318. }
  319. }
  320. Vector v;
  321. Vector sv;
  322. CVertexWeight vw( nJointPerVertexCount );
  323. for ( int i = 0; i < positions.Count(); ++i )
  324. {
  325. vw.Reset();
  326. const Vector &p = positions[ i ];
  327. for ( int j = 0; j < volumeJointList.Count(); ++j )
  328. {
  329. const s_JointStruct &js = volumeJointList[ j ];
  330. float flMaxWeight = 0.0f;
  331. for ( int k = 0; k < js.m_volumes.Count(); ++k )
  332. {
  333. const s_VolumeStruct &vs = js.m_volumes[ k ];
  334. const CDmeSkinnerVolume *pDmeSkinnerVolume = vs.m_pDmeSkinnerVolume;
  335. vs.m_mMat.V3Mul( p, v );
  336. float f = pDmeSkinnerVolume->m_flFalloff;
  337. float l = 0.0;
  338. float w = 0.0;
  339. if ( pDmeSkinnerVolume->IsEllipse() )
  340. {
  341. l = v.Length();
  342. w = RemapValClamped( l, 1.0f, f + 1.0f, 1.0f, 0.0f );
  343. }
  344. else
  345. {
  346. double dIFS = 1.0 / ( 1.0 + static_cast< double >( f ) );
  347. sv.x = v.x * dIFS;
  348. sv.y = v.y * dIFS;
  349. sv.z = v.z * dIFS;
  350. if ( CSuperEllipsoid( pDmeSkinnerVolume->m_flPowerXZ, pDmeSkinnerVolume->m_flPowerY ).IntersectFromOriginThroughPoint( sv, l ) )
  351. {
  352. if ( l == 0.0 )
  353. {
  354. w = 1.0;
  355. }
  356. else
  357. {
  358. w = RemapValClamped( sv.Length(), l * dIFS, l, 1.0, 0.0 );
  359. }
  360. }
  361. }
  362. float s = pDmeSkinnerVolume->m_flStrength;
  363. switch ( pDmeSkinnerVolume->m_nFalloffType )
  364. {
  365. case CDmeSkinnerVolume::FT_SMOOTH:
  366. w = ( cosf( ( 1.0f - w ) * M_PI ) + 1.0f ) / 2.0f;
  367. break;
  368. case CDmeSkinnerVolume::FT_SPIKE:
  369. w = 1.0f - cosf( w * M_PI / 2.0 );
  370. break;
  371. case CDmeSkinnerVolume::FT_DOME:
  372. w = cosf( ( 1.0f - w ) * M_PI / 2.0 );
  373. break;
  374. default:
  375. break;
  376. }
  377. w = fabs( w * s );
  378. if ( w > 0.00001 && w > flMaxWeight )
  379. {
  380. flMaxWeight = w;
  381. }
  382. }
  383. if ( flMaxWeight > 0.0 )
  384. {
  385. vw.AddWeight( js.m_nJointIndex, flMaxWeight );
  386. }
  387. }
  388. vw.Sort();
  389. const float flTotalWeight = vw.ComputeTotalWeight();
  390. if ( vw.Count() <= 0 || flTotalWeight <= 0 )
  391. {
  392. Warning( "Mesh Vertex %s.v[%d] is not influenced by any volume\n", pDmeDagMeshParent->GetName(), i );
  393. }
  394. else
  395. {
  396. for ( int j = 0; j < nJointPerVertexCount; ++j )
  397. {
  398. jointIndices.AddToTail( vw.GetJointIndex( j ) );
  399. jointWeights.AddToTail( vw.GetWeight( j ) / flTotalWeight );
  400. }
  401. }
  402. }
  403. pDmeVertexData->AddVertexData( nJointIndicesField, jointIndices.Count() );
  404. pDmeVertexData->SetVertexData( nJointIndicesField, 0, jointIndices.Count(), AT_INT, jointIndices.Base() );
  405. pDmeVertexData->AddVertexData( nJointWeightsField, jointWeights.Count() );
  406. pDmeVertexData->SetVertexData( nJointWeightsField, 0, jointWeights.Count(), AT_FLOAT, jointWeights.Base() );
  407. return true;
  408. }
  409. //====== Copyright (c) 1996-2009, Valve Corporation, All rights reserved. =====
  410. //
  411. // TODO: This belongs in a lib somewhere, comes from sdktools/maya/vsSkinner
  412. //
  413. //=============================================================================
  414. //-----------------------------------------------------------------------------
  415. // Statics
  416. //-----------------------------------------------------------------------------
  417. const double CSuperEllipsoid::s_dEpsilon = 1.0e-6;
  418. //-----------------------------------------------------------------------------
  419. //
  420. //-----------------------------------------------------------------------------
  421. CSuperEllipsoid::CSuperEllipsoid(
  422. double powerXZ /* = 1.0 */,
  423. double powerY /* = 1.0 */ )
  424. : m_powerXZ( powerXZ )
  425. , m_powerY( powerY )
  426. , m_nMaxIterations( 100 )
  427. {
  428. }
  429. //-----------------------------------------------------------------------------
  430. //
  431. //-----------------------------------------------------------------------------
  432. double CSuperEllipsoid::RootEvaluate( const Vector &p ) const
  433. {
  434. return pow( pow( abs( static_cast< double >( p.x ) ), 2.0 / m_powerXZ ) + pow( abs( static_cast< double >( p.z ) ), 2.0 / m_powerXZ ), m_powerXZ / m_powerY ) + pow( abs( static_cast< double >( p.y ) ), 2.0 / m_powerY ) - 1.0;
  435. }
  436. //-----------------------------------------------------------------------------
  437. //
  438. //-----------------------------------------------------------------------------
  439. bool CSuperEllipsoid::IntersectFromOriginThroughPoint(
  440. Vector point,
  441. double dDistance ) const
  442. {
  443. if ( abs( point.x ) < s_dEpsilon ) point.x = 0.0;
  444. if ( abs( point.y ) < s_dEpsilon ) point.y = 0.0;
  445. if ( abs( point.z ) < s_dEpsilon ) point.z = 0.0;
  446. // Point Is The Origin
  447. if ( point.Length() < s_dEpsilon )
  448. {
  449. dDistance = 0.0;
  450. return true;
  451. }
  452. // Check for early exit cases
  453. const double dVal = RootEvaluate( point );
  454. // Close enough
  455. if ( abs( dVal ) < s_dEpsilon )
  456. {
  457. dDistance = point.Length();
  458. return true;
  459. }
  460. // Outside of the Super Ellipsoid
  461. if ( dVal > 0.0 )
  462. return false;
  463. Vector rayDirection = point;
  464. rayDirection.NormalizeInPlace();
  465. double dMin = 0.0;
  466. double dMax = 0.0;
  467. if ( !IntersectUnitBoxFromOrigin( rayDirection, dMin, dMax ) )
  468. return false;
  469. // This ought to work!
  470. dMin = point.Length();
  471. Vector intPoint0;
  472. EvaluateRayFromOrigin( rayDirection, dMin, intPoint0 );
  473. const double v0 = RootEvaluate( intPoint0 );
  474. if ( abs( v0 ) < s_dEpsilon )
  475. {
  476. dDistance = dMin;
  477. return true;
  478. }
  479. Vector intPoint1;
  480. EvaluateRayFromOrigin( rayDirection, dMax, intPoint1 );
  481. const double v1 = RootEvaluate( intPoint1 );
  482. if ( abs( v1 ) < s_dEpsilon )
  483. {
  484. dDistance = dMax;
  485. return true;
  486. }
  487. Vector intPoint;
  488. SolveHit( v0, intPoint0, v1, intPoint1, intPoint );
  489. dDistance = VectorLength( intPoint );
  490. return true;
  491. }
  492. //-----------------------------------------------------------------------------
  493. //
  494. //-----------------------------------------------------------------------------
  495. void CSuperEllipsoid::EvaluateRayFromOrigin(
  496. const Vector &rayDirection,
  497. double dDistance,
  498. Vector &pointOnRay )
  499. {
  500. pointOnRay = rayDirection * dDistance;
  501. }
  502. //-----------------------------------------------------------------------------
  503. //
  504. //-----------------------------------------------------------------------------
  505. bool CSuperEllipsoid::IntersectUnitBoxFromOrigin(
  506. const Vector &rayDirection,
  507. double &dMin,
  508. double &dMax )
  509. {
  510. static const double dMaxValue = 1.0;
  511. static const double dMinValue = -dMaxValue;
  512. const double dMaxBound = sqrt( 3.0 * dMaxValue * dMaxValue );
  513. const double dMinBound = -dMaxBound;
  514. double tMin = 0.0;
  515. double tMax = 0.0;
  516. /* Left/right. */
  517. if ( abs( rayDirection.x ) > s_dEpsilon )
  518. {
  519. if ( rayDirection.x > s_dEpsilon )
  520. {
  521. dMin = dMinValue / rayDirection.x;
  522. dMax = dMaxValue / rayDirection.x;
  523. if ( dMax < s_dEpsilon )
  524. return false;
  525. }
  526. else
  527. {
  528. dMax = dMinValue / rayDirection.x;
  529. if ( dMax < s_dEpsilon )
  530. return false;
  531. dMin = dMaxValue / rayDirection.x;
  532. }
  533. if ( dMin > dMax )
  534. return false;
  535. }
  536. else
  537. {
  538. dMin = dMinBound;
  539. dMax = dMaxBound;
  540. }
  541. /* Top/bottom. */
  542. if ( abs( rayDirection.y ) > s_dEpsilon )
  543. {
  544. if ( rayDirection.y > s_dEpsilon )
  545. {
  546. tMin = dMinValue / rayDirection.y;
  547. tMax = dMaxValue / rayDirection.y;
  548. }
  549. else
  550. {
  551. tMax = dMinValue / rayDirection.y;
  552. tMin = dMaxValue / rayDirection.y;
  553. }
  554. if ( tMax < dMax )
  555. {
  556. if ( tMax < s_dEpsilon )
  557. return false;
  558. if ( tMin > dMin )
  559. {
  560. if ( tMin > tMax )
  561. return false;
  562. dMin = tMin;
  563. }
  564. else
  565. {
  566. if ( dMin > tMax )
  567. return false;
  568. }
  569. dMax = tMax;
  570. }
  571. else
  572. {
  573. if ( tMin > dMin )
  574. {
  575. if ( tMin > dMax )
  576. return false;
  577. dMin = tMin;
  578. }
  579. }
  580. }
  581. /* Front/back. */
  582. if ( abs( rayDirection.z ) > s_dEpsilon )
  583. {
  584. if ( rayDirection.z > s_dEpsilon )
  585. {
  586. tMin = dMinValue / rayDirection.z;
  587. tMax = dMaxValue / rayDirection.z;
  588. }
  589. else
  590. {
  591. tMax = dMinValue / rayDirection.z;
  592. tMin = dMaxValue / rayDirection.z;
  593. }
  594. if ( tMax < dMax )
  595. {
  596. if ( tMax < s_dEpsilon )
  597. return false;
  598. if ( tMin > dMin )
  599. {
  600. if ( tMin > tMax )
  601. return false;
  602. dMin = tMin;
  603. }
  604. else
  605. {
  606. if ( dMin > tMax )
  607. return false;
  608. }
  609. dMax = tMax;
  610. }
  611. else
  612. {
  613. if ( tMin > dMin )
  614. {
  615. if ( tMin > dMax )
  616. return false;
  617. dMin = tMin;
  618. }
  619. }
  620. }
  621. return true;
  622. }
  623. //-----------------------------------------------------------------------------
  624. //
  625. //-----------------------------------------------------------------------------
  626. void CSuperEllipsoid::SolveHit(
  627. double v0,
  628. const Vector &intPoint0,
  629. double v1,
  630. const Vector &intPoint1,
  631. Vector &intPoint ) const
  632. {
  633. Vector p0 = intPoint0;
  634. Vector p1 = intPoint1;
  635. double x;
  636. Vector p2;
  637. double v2;
  638. Vector p3;
  639. double v3;
  640. for ( int i = 0; i < m_nMaxIterations; ++i )
  641. {
  642. if ( abs( v0 ) < s_dEpsilon )
  643. {
  644. intPoint = p0;
  645. return;
  646. }
  647. if ( fabs( v1 ) < s_dEpsilon )
  648. {
  649. intPoint = p1;
  650. return;
  651. }
  652. x = abs( v0 ) / abs( v1 - v0 );
  653. VectorSubtract( p1, p0, p2 );
  654. VectorMultiply( p2, x, p2 );
  655. VectorAdd( p0, p2, p2 );
  656. v2 = RootEvaluate( p2 );
  657. VectorSubtract( p1, p0, p3 );
  658. VectorMultiply( p3, 0.5, p3 );
  659. VectorAdd( p0, p3, p3 );
  660. v3 = RootEvaluate( p3 );
  661. if ( v2 * v3 < 0.0 )
  662. {
  663. v0 = v2;
  664. p0 = p2;
  665. v1 = v3;
  666. p1 = p3;
  667. }
  668. else
  669. {
  670. if ( abs( v2 ) < abs( v3 ) )
  671. {
  672. if ( v0 * v2 < 0.0 )
  673. {
  674. v1 = v2;
  675. p1 = p2;
  676. }
  677. else
  678. {
  679. v0 = v2;
  680. p0 = p2;
  681. }
  682. }
  683. else
  684. {
  685. if ( v0 * v3 < 0.0 )
  686. {
  687. v1 = v3;
  688. p1 = p3;
  689. }
  690. else
  691. {
  692. v0 = v3;
  693. p0 = p3;
  694. }
  695. }
  696. }
  697. }
  698. if ( fabs( v0 ) < fabs( v1 ) )
  699. {
  700. intPoint = p0;
  701. }
  702. else
  703. {
  704. intPoint = p1;
  705. }
  706. }