Team Fortress 2 Source Code as on 22/4/2020
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.

1994 lines
52 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "BuildDisp.h"
  8. #include "DispColl.h"
  9. #include "tier0/dbg.h"
  10. //=============================================================================
  11. const float CDispCollTree::COLLISION_EPSILON = 0.01f;
  12. const float CDispCollTree::ONE_MINUS_COLLISION_EPSILON = 1.0f - COLLISION_EPSILON;
  13. //=============================================================================
  14. //
  15. // Displacement Collision Triangle Functions
  16. //
  17. //-----------------------------------------------------------------------------
  18. // Purpose: initialize the displacement triangles
  19. //-----------------------------------------------------------------------------
  20. void CDispCollTri::Init( void )
  21. {
  22. for( int i = 0; i < 3; i++ )
  23. {
  24. m_Points[i].x = 0.0f; m_Points[i].y = 0.0f; m_Points[i].z = 0.0f;
  25. m_PointNormals[i].x = 0.0f; m_PointNormals[i].y = 0.0f; m_PointNormals[i].z = 0.0f;
  26. }
  27. m_Normal.x = 0.0f; m_Normal.y = 0.0f; m_Normal.z = 0.0f;
  28. m_Distance = 0.0f;
  29. m_ProjAxes[0] = -1;
  30. m_ProjAxes[1] = -1;
  31. m_bIntersect = false;
  32. }
  33. //-----------------------------------------------------------------------------
  34. // Purpose:
  35. //-----------------------------------------------------------------------------
  36. inline void CDispCollTri::SetPoint( int index, Vector const &vert )
  37. {
  38. Assert( index >= 0 );
  39. Assert( index < 3 );
  40. m_Points[index].x = vert[0];
  41. m_Points[index].y = vert[1];
  42. m_Points[index].z = vert[2];
  43. }
  44. //-----------------------------------------------------------------------------
  45. // Purpose:
  46. //-----------------------------------------------------------------------------
  47. inline void CDispCollTri::SetPointNormal( int index, Vector const &normal )
  48. {
  49. Assert( index >= 0 );
  50. Assert( index < 3 );
  51. m_PointNormals[index].x = normal[0];
  52. m_PointNormals[index].y = normal[1];
  53. m_PointNormals[index].z = normal[2];
  54. }
  55. //-----------------------------------------------------------------------------
  56. // Purpose:
  57. //-----------------------------------------------------------------------------
  58. void CDispCollTri::CalcPlane( void )
  59. {
  60. //
  61. // calculate the plane normal and distance
  62. //
  63. Vector segment1, segment2, cross;
  64. segment1 = m_Points[1] - m_Points[0];
  65. segment2 = m_Points[2] - m_Points[0];
  66. cross = segment1.Cross( segment2 );
  67. m_Normal = cross;
  68. VectorNormalize(m_Normal);
  69. m_Distance = m_Normal.Dot( m_Points[0] );
  70. //
  71. // calculate the projection axes
  72. //
  73. if( FloatMakePositive( m_Normal[0] ) > FloatMakePositive( m_Normal[1] ) )
  74. {
  75. if( FloatMakePositive( m_Normal[0] ) > FloatMakePositive( m_Normal[2] ) )
  76. {
  77. m_ProjAxes[0] = 1;
  78. m_ProjAxes[1] = 2;
  79. }
  80. else
  81. {
  82. m_ProjAxes[0] = 0;
  83. m_ProjAxes[1] = 1;
  84. }
  85. }
  86. else
  87. {
  88. if( FloatMakePositive( m_Normal[1] ) > FloatMakePositive( m_Normal[2] ) )
  89. {
  90. m_ProjAxes[0] = 0;
  91. m_ProjAxes[1] = 2;
  92. }
  93. else
  94. {
  95. m_ProjAxes[0] = 0;
  96. m_ProjAxes[1] = 1;
  97. }
  98. }
  99. }
  100. //-----------------------------------------------------------------------------
  101. // Purpose:
  102. //-----------------------------------------------------------------------------
  103. inline void CDispCollTri::SetIntersect( bool bIntersect )
  104. {
  105. m_bIntersect = bIntersect;
  106. }
  107. //-----------------------------------------------------------------------------
  108. // Purpose:
  109. //-----------------------------------------------------------------------------
  110. inline bool CDispCollTri::IsIntersect( void )
  111. {
  112. return m_bIntersect;
  113. }
  114. //=============================================================================
  115. //
  116. // Displacement Collision Node Functions
  117. //
  118. //-----------------------------------------------------------------------------
  119. // Purpose: constructor
  120. //-----------------------------------------------------------------------------
  121. CDispCollNode::CDispCollNode()
  122. {
  123. m_Bounds[0].x = m_Bounds[0].y = m_Bounds[0].z = 99999.9f;
  124. m_Bounds[1].x = m_Bounds[1].y = m_Bounds[1].z = -99999.9f;
  125. m_Tris[0].Init();
  126. m_Tris[1].Init();
  127. m_bIsLeaf = false;
  128. }
  129. //-----------------------------------------------------------------------------
  130. // Purpose:
  131. //-----------------------------------------------------------------------------
  132. inline bool CDispCollNode::IsLeaf( void )
  133. {
  134. return m_bIsLeaf;
  135. }
  136. //-----------------------------------------------------------------------------
  137. // Purpose:
  138. //-----------------------------------------------------------------------------
  139. inline void CDispCollNode::SetBounds( Vector const &bMin, Vector const &bMax )
  140. {
  141. m_Bounds[0] = bMin;
  142. m_Bounds[1] = bMax;
  143. }
  144. //-----------------------------------------------------------------------------
  145. // Purpose:
  146. //-----------------------------------------------------------------------------
  147. inline void CDispCollNode::GetBounds( Vector &bMin, Vector &bMax )
  148. {
  149. bMin = m_Bounds[0];
  150. bMax = m_Bounds[1];
  151. }
  152. //=============================================================================
  153. //
  154. // Displacement Collision Tree Functions
  155. //
  156. //-----------------------------------------------------------------------------
  157. // Purpose: constructor
  158. //-----------------------------------------------------------------------------
  159. CDispCollTree::CDispCollTree()
  160. {
  161. m_Power = 0;
  162. m_NodeCount = 0;
  163. m_pNodes = NULL;
  164. InitAABBData();
  165. }
  166. //-----------------------------------------------------------------------------
  167. // Purpose: deconstructor
  168. //-----------------------------------------------------------------------------
  169. CDispCollTree::~CDispCollTree()
  170. {
  171. FreeNodes();
  172. }
  173. //-----------------------------------------------------------------------------
  174. // Purpose:
  175. //-----------------------------------------------------------------------------
  176. void CDispCollTree::InitAABBData( void )
  177. {
  178. m_AABBNormals[0].x = -1.0f; m_AABBNormals[0].y = 0.0f; m_AABBNormals[0].z = 0.0f;
  179. m_AABBNormals[1].x = 1.0f; m_AABBNormals[1].y = 0.0f; m_AABBNormals[1].z = 0.0f;
  180. m_AABBNormals[2].x = 0.0f; m_AABBNormals[2].y = -1.0f; m_AABBNormals[2].z = 0.0f;
  181. m_AABBNormals[3].x = 0.0f; m_AABBNormals[3].y = 1.0f; m_AABBNormals[3].z = 0.0f;
  182. m_AABBNormals[4].x = 0.0f; m_AABBNormals[4].y = 0.0f; m_AABBNormals[4].z = -1.0f;
  183. m_AABBNormals[5].x = 0.0f; m_AABBNormals[5].y = 0.0f; m_AABBNormals[5].z = 1.0f;
  184. }
  185. //-----------------------------------------------------------------------------
  186. // Purpose:
  187. //-----------------------------------------------------------------------------
  188. void CDispCollTree::CalcBounds( CDispCollNode *pNode, int nodeIndex )
  189. {
  190. Vector bounds[2];
  191. bounds[0].Init( 99999.9f, 99999.9f, 99999.9f );
  192. bounds[1].Init( -99999.9f, -99999.9f, -99999.9f );
  193. //
  194. // handle leaves differently -- bounding volume defined by triangles
  195. //
  196. if( pNode->IsLeaf() )
  197. {
  198. for( int i = 0; i < 2; i++ )
  199. {
  200. for( int j = 0; j < 3; j++ )
  201. {
  202. //
  203. // minimum
  204. //
  205. if( bounds[0].x > pNode->m_Tris[i].m_Points[j].x ) { bounds[0].x = pNode->m_Tris[i].m_Points[j].x; }
  206. if( bounds[0].y > pNode->m_Tris[i].m_Points[j].y ) { bounds[0].y = pNode->m_Tris[i].m_Points[j].y; }
  207. if( bounds[0].z > pNode->m_Tris[i].m_Points[j].z ) { bounds[0].z = pNode->m_Tris[i].m_Points[j].z; }
  208. //
  209. // maximum
  210. //
  211. if( bounds[1].x < pNode->m_Tris[i].m_Points[j].x ) { bounds[1].x = pNode->m_Tris[i].m_Points[j].x; }
  212. if( bounds[1].y < pNode->m_Tris[i].m_Points[j].y ) { bounds[1].y = pNode->m_Tris[i].m_Points[j].y; }
  213. if( bounds[1].z < pNode->m_Tris[i].m_Points[j].z ) { bounds[1].z = pNode->m_Tris[i].m_Points[j].z; }
  214. }
  215. }
  216. }
  217. //
  218. // bounding volume defined by maxima and minima of children volumes
  219. //
  220. else
  221. {
  222. for( int i = 0; i < 4; i++ )
  223. {
  224. int childIndex = GetChildNode( nodeIndex, i );
  225. CDispCollNode *pChildNode = &m_pNodes[childIndex];
  226. Vector childBounds[2];
  227. pChildNode->GetBounds( childBounds[0], childBounds[1] );
  228. //
  229. // minimum
  230. //
  231. if( bounds[0].x > childBounds[0].x ) { bounds[0].x = childBounds[0].x; }
  232. if( bounds[0].y > childBounds[0].y ) { bounds[0].y = childBounds[0].y; }
  233. if( bounds[0].z > childBounds[0].z ) { bounds[0].z = childBounds[0].z; }
  234. //
  235. // maximum
  236. //
  237. if( bounds[1].x < childBounds[1].x ) { bounds[1].x = childBounds[1].x; }
  238. if( bounds[1].y < childBounds[1].y ) { bounds[1].y = childBounds[1].y; }
  239. if( bounds[1].z < childBounds[1].z ) { bounds[1].z = childBounds[1].z; }
  240. }
  241. }
  242. pNode->SetBounds( bounds[0], bounds[1] );
  243. }
  244. //-----------------------------------------------------------------------------
  245. // Purpose:
  246. //-----------------------------------------------------------------------------
  247. void CDispCollTree::CreateNodes_r( CCoreDispInfo *pDisp, int nodeIndex, int termLevel )
  248. {
  249. int nodeLevel = GetNodeLevel( nodeIndex );
  250. //
  251. // terminating condition -- set node info (leaf or otherwise)
  252. //
  253. if( nodeLevel == termLevel )
  254. {
  255. CDispCollNode *pNode = &m_pNodes[nodeIndex];
  256. CalcBounds( pNode, nodeIndex );
  257. return;
  258. }
  259. //
  260. // recurse into children
  261. //
  262. for( int i = 0; i < 4; i++ )
  263. {
  264. CreateNodes_r( pDisp, GetChildNode( nodeIndex, i ), termLevel );
  265. }
  266. }
  267. //-----------------------------------------------------------------------------
  268. // Purpose:
  269. //-----------------------------------------------------------------------------
  270. void CDispCollTree::CreateNodes( CCoreDispInfo *pDisp )
  271. {
  272. //
  273. // create all nodes in tree
  274. //
  275. int power = pDisp->GetPower() + 1;
  276. for( int level = power; level > 0; level-- )
  277. {
  278. CreateNodes_r( pDisp, 0 /* rootIndex */, level );
  279. }
  280. }
  281. //-----------------------------------------------------------------------------
  282. //-----------------------------------------------------------------------------
  283. int CDispCollTree::GetNodeIndexFromComponents( int x, int y )
  284. {
  285. int index = 0;
  286. // Interleave bits from the x and y values to create the index:
  287. for( int shift = 0; x != 0; shift += 2, x >>= 1 )
  288. {
  289. index |= ( x & 1 ) << shift;
  290. }
  291. for( shift = 1; y != 0; shift += 2, y >>= 1 )
  292. {
  293. index |= ( y & 1 ) << shift;
  294. }
  295. return index;
  296. }
  297. //-----------------------------------------------------------------------------
  298. // Purpose:
  299. //-----------------------------------------------------------------------------
  300. void CDispCollTree::InitLeaves( CCoreDispInfo *pDisp )
  301. {
  302. //
  303. // get power and width and displacement surface
  304. //
  305. int power = pDisp->GetPower();
  306. int width = pDisp->GetWidth();
  307. //
  308. // get leaf indices
  309. //
  310. int startIndex = CalcNodeCount( power - 1 );
  311. int endIndex = CalcNodeCount( power );
  312. for( int index = startIndex; index < endIndex; index++ )
  313. {
  314. //
  315. // create triangles at leaves
  316. //
  317. int x = ( index - startIndex ) % ( width - 1 );
  318. int y = ( index - startIndex ) / ( width - 1 );
  319. int nodeIndex = GetNodeIndexFromComponents( x, y );
  320. nodeIndex += startIndex;
  321. Vector vert;
  322. Vector normal;
  323. //
  324. // tri 1
  325. //
  326. pDisp->GetVert( x + ( y * width ), vert );
  327. pDisp->GetNormal( x + ( y * width ), normal );
  328. m_pNodes[nodeIndex].m_Tris[0].SetPoint( 0, vert );
  329. m_pNodes[nodeIndex].m_Tris[0].SetPointNormal( 0, normal );
  330. pDisp->GetVert( x + ( ( y + 1 ) * width ), vert );
  331. pDisp->GetNormal( x + ( ( y + 1 ) * width ), normal );
  332. m_pNodes[nodeIndex].m_Tris[0].SetPoint( 1, vert );
  333. m_pNodes[nodeIndex].m_Tris[0].SetPointNormal( 1, normal );
  334. pDisp->GetVert( ( x + 1 ) + ( y * width ), vert );
  335. pDisp->GetNormal( ( x + 1 ) + ( y * width ), normal );
  336. m_pNodes[nodeIndex].m_Tris[0].SetPoint( 2, vert );
  337. m_pNodes[nodeIndex].m_Tris[0].SetPointNormal( 2, normal );
  338. m_pNodes[nodeIndex].m_Tris[0].CalcPlane();
  339. //
  340. // tri 2
  341. //
  342. pDisp->GetVert( ( x + 1 ) + ( y * width ), vert );
  343. pDisp->GetNormal( ( x + 1 ) + ( y * width ), normal );
  344. m_pNodes[nodeIndex].m_Tris[1].SetPoint( 0, vert );
  345. m_pNodes[nodeIndex].m_Tris[1].SetPointNormal( 0, normal );
  346. pDisp->GetVert( x + ( ( y + 1 ) * width ), vert );
  347. pDisp->GetNormal( x + ( ( y + 1 ) * width ), normal );
  348. m_pNodes[nodeIndex].m_Tris[1].SetPoint( 1, vert );
  349. m_pNodes[nodeIndex].m_Tris[1].SetPointNormal( 1, normal );
  350. pDisp->GetVert( ( x + 1 ) + ( ( y + 1 ) * width ), vert );
  351. pDisp->GetNormal( ( x + 1 ) + ( ( y + 1 ) * width ), normal );
  352. m_pNodes[nodeIndex].m_Tris[1].SetPoint( 2, vert );
  353. m_pNodes[nodeIndex].m_Tris[1].SetPointNormal( 2, normal );
  354. m_pNodes[nodeIndex].m_Tris[1].CalcPlane();
  355. // set node as leaf
  356. m_pNodes[nodeIndex].m_bIsLeaf = true;
  357. }
  358. }
  359. //-----------------------------------------------------------------------------
  360. // Purpose: allocate and initialize the displacement collision tree
  361. // Input: power - size of the displacement surface
  362. // Output: bool - success? (true/false)
  363. //-----------------------------------------------------------------------------
  364. bool CDispCollTree::Create( CCoreDispInfo *pDisp )
  365. {
  366. //
  367. // calculate the number of nodes needed given the size of the displacement
  368. //
  369. m_Power = pDisp->GetPower();
  370. m_NodeCount = CalcNodeCount( m_Power );
  371. //
  372. // allocate tree space
  373. //
  374. if( !AllocNodes( m_NodeCount ) )
  375. return false;
  376. // initialize leaves
  377. InitLeaves( pDisp );
  378. // create tree nodes
  379. CreateNodes( pDisp );
  380. // tree successfully created!
  381. return true;
  382. }
  383. //-----------------------------------------------------------------------------
  384. // Purpose: allocate memory for the displacement collision tree
  385. // Input: nodeCount - number of nodes to allocate
  386. // Output: bool - success? (true/false)
  387. //-----------------------------------------------------------------------------
  388. bool CDispCollTree::AllocNodes( int nodeCount )
  389. {
  390. // sanity check
  391. Assert( nodeCount != 0 );
  392. m_pNodes = new CDispCollNode[nodeCount];
  393. if( !m_pNodes )
  394. return false;
  395. // tree successfully allocated!
  396. return true;
  397. }
  398. //-----------------------------------------------------------------------------
  399. // Purpose: release allocated memory for displacement collision tree
  400. //-----------------------------------------------------------------------------
  401. void CDispCollTree::FreeNodes( void )
  402. {
  403. if( m_pNodes )
  404. {
  405. delete [] m_pNodes;
  406. m_pNodes = NULL;
  407. }
  408. }
  409. //-----------------------------------------------------------------------------
  410. // Purpose: calculate the number of tree nodes given the size of the
  411. // displacement surface
  412. // Input: power - size of the displacement surface
  413. // Output: int - the number of tree nodes
  414. //-----------------------------------------------------------------------------
  415. inline int CDispCollTree::CalcNodeCount( int power )
  416. {
  417. // power range [2...4]
  418. Assert( power > 0 );
  419. Assert( power < 5 );
  420. return ( ( 1 << ( ( power + 1 ) << 1 ) ) / 3 );
  421. }
  422. //-----------------------------------------------------------------------------
  423. // Purpose: get the parent node index given the current node
  424. // Input: nodeIndex - current node index
  425. // Output: int - the index of the parent node
  426. //-----------------------------------------------------------------------------
  427. inline int CDispCollTree::GetParentNode( int nodeIndex )
  428. {
  429. // node range [0...m_NodeCount)
  430. Assert( nodeIndex >= 0 );
  431. Assert( nodeIndex < m_NodeCount );
  432. // ( nodeIndex - 1 ) / 4
  433. return ( ( nodeIndex - 1 ) >> 2 );
  434. }
  435. //-----------------------------------------------------------------------------
  436. // Purpose: get the child node index given the current node index and direction
  437. // of the child (1 of 4)
  438. // Input: nodeIndex - current node index
  439. // direction - direction of the child ( [0...3] - SW, SE, NW, NE )
  440. // Output: int - the index of the child node
  441. //-----------------------------------------------------------------------------
  442. inline int CDispCollTree::GetChildNode( int nodeIndex, int direction )
  443. {
  444. // node range [0...m_NodeCount)
  445. Assert( nodeIndex >= 0 );
  446. Assert( nodeIndex < m_NodeCount );
  447. // ( nodeIndex * 4 ) + ( direction + 1 )
  448. return ( ( nodeIndex << 2 ) + ( direction + 1 ) );
  449. }
  450. //-----------------------------------------------------------------------------
  451. // Purpose:
  452. //-----------------------------------------------------------------------------
  453. inline int CDispCollTree::GetNodeLevel( int nodeIndex )
  454. {
  455. // node range [0...m_NodeCount)
  456. Assert( nodeIndex >= 0 );
  457. Assert( nodeIndex < m_NodeCount );
  458. // level = 2^n + 1
  459. if( nodeIndex == 0 ) { return 1; }
  460. if( nodeIndex < 5 ) { return 2; }
  461. if( nodeIndex < 21 ) { return 3; }
  462. if( nodeIndex < 85 ) { return 4; }
  463. if( nodeIndex < 341 ) { return 5; }
  464. return -1;
  465. }
  466. //-----------------------------------------------------------------------------
  467. //-----------------------------------------------------------------------------
  468. bool CDispCollTree::RayTriTest( Vector const &rayStart, Vector const &rayDir, float const rayLength,
  469. CDispCollTri const *pTri, float *fraction )
  470. {
  471. const float DET_EPSILON = 0.001f;
  472. const float DIST_EPSILON = 0.001f;
  473. //
  474. // calculate the edges
  475. //
  476. Vector edge1 = pTri->m_Points[1] - pTri->m_Points[0];
  477. Vector edge2 = pTri->m_Points[2] - pTri->m_Points[0];
  478. // Vector faceNormal = edge1.Cross( edge2 );
  479. // Vector normNormal = faceNormal.Normalize();
  480. //
  481. // calculate the triangle's determinant
  482. //
  483. Vector pVec = rayDir.Cross( edge2 );
  484. float det = pVec.Dot( edge1 );
  485. // if determinant is zero -- ray lies in plane
  486. if( ( det > -DET_EPSILON ) && ( det < DET_EPSILON ) )
  487. return false;
  488. //
  489. // utility calculations - inverse determinant and distance from v0 to ray start
  490. //
  491. double invDet = 1.0f / det;
  492. Vector tVec = rayStart - pTri->m_Points[0];
  493. //
  494. // calculate the U parameter and test bounds
  495. //
  496. double u = pVec.Dot( tVec ) * invDet;
  497. if( ( u < 0.0f ) || ( u > 1.0f ) )
  498. return false;
  499. Vector qVec = tVec.Cross( edge1 );
  500. //
  501. // calculate the V parameter and test bounds
  502. //
  503. double v = qVec.Dot( rayDir ) * invDet;
  504. if( ( v < 0.0f ) || ( ( u + v ) > 1.0f ) )
  505. return false;
  506. // calculate where ray intersects triangle
  507. *fraction = qVec.Dot( edge2 ) * invDet;
  508. *fraction /= rayLength;
  509. if( ( *fraction < DIST_EPSILON ) || ( *fraction > ( 1.0f - DIST_EPSILON ) ) )
  510. return false;
  511. return true;
  512. }
  513. //-----------------------------------------------------------------------------
  514. //-----------------------------------------------------------------------------
  515. bool CDispCollTree::RayTriListTest( CDispCollTreeTempData *pTemp, CDispCollData *pData )
  516. {
  517. // save starting fraction -- to test for collision
  518. float startFraction = pData->m_Fraction;
  519. //
  520. // calculate the ray
  521. //
  522. Vector seg = pData->m_EndPos - pData->m_StartPos;
  523. Vector rayDir = seg;
  524. float rayLength = VectorNormalize( rayDir );
  525. //
  526. // test ray against all triangles in list
  527. //
  528. for( int i = 0; i < pTemp->m_TriListCount; i++ )
  529. {
  530. float fraction = 1.0f;
  531. bool bResult = RayTriTest( pData->m_StartPos, rayDir, rayLength, pTemp->m_ppTriList[i], &fraction );
  532. if( !bResult )
  533. continue;
  534. if( pData->m_bOcclude )
  535. {
  536. return true;
  537. }
  538. if( fraction < pData->m_Fraction )
  539. {
  540. pData->m_Fraction = fraction;
  541. pData->m_Normal = pTemp->m_ppTriList[i]->m_Normal;
  542. pData->m_Distance = pTemp->m_ppTriList[i]->m_Distance;
  543. }
  544. }
  545. // collision!
  546. if( pData->m_Fraction < startFraction )
  547. return true;
  548. // no collision!
  549. return false;
  550. }
  551. //-----------------------------------------------------------------------------
  552. // Purpose:
  553. //-----------------------------------------------------------------------------
  554. bool CDispCollTree::RayAABBTest( CDispCollTreeTempData *pTemp, Vector &rayStart, Vector &rayEnd )
  555. {
  556. const float MY_DIST_EPSILON = 0.01f;
  557. for( int i = 0; i < 6; i++ )
  558. {
  559. float dist1 = m_AABBNormals[i].Dot( rayStart ) - pTemp->m_AABBDistances[i];
  560. float dist2 = m_AABBNormals[i].Dot( rayEnd ) - pTemp->m_AABBDistances[i];
  561. //
  562. // entry intersection point - move ray start up to intersection
  563. //
  564. if( ( dist1 > MY_DIST_EPSILON ) && ( dist2 < -MY_DIST_EPSILON ) )
  565. {
  566. float fraction = ( dist1 / ( dist1 - dist2 ) );
  567. Vector segment, increment;
  568. segment = ( rayEnd - rayStart ) * fraction;
  569. increment = segment;
  570. VectorNormalize(increment);
  571. segment += increment;
  572. rayStart += segment;
  573. }
  574. else if( ( dist1 > MY_DIST_EPSILON ) && ( dist2 > MY_DIST_EPSILON ) )
  575. {
  576. return false;
  577. }
  578. }
  579. return true;
  580. }
  581. //-----------------------------------------------------------------------------
  582. // Purpose:
  583. //-----------------------------------------------------------------------------
  584. void CDispCollTree::CreatePlanesFromBounds( CDispCollTreeTempData *pTemp, Vector const &bbMin, Vector const &bbMax )
  585. {
  586. //
  587. // note -- these never change!
  588. //
  589. // m_AABBNormals[0].x = -1;
  590. // m_AABBNormals[1].x = 1;
  591. // m_AABBNormals[2].y = -1;
  592. // m_AABBNormals[3].y = 1;
  593. // m_AABBNormals[4].z = -1;
  594. // m_AABBNormals[5].z = 1;
  595. pTemp->m_AABBDistances[0] = -bbMin.x;
  596. pTemp->m_AABBDistances[1] = bbMax.x;
  597. pTemp->m_AABBDistances[2] = -bbMin.y;
  598. pTemp->m_AABBDistances[3] = bbMax.y;
  599. pTemp->m_AABBDistances[4] = -bbMin.z;
  600. pTemp->m_AABBDistances[5] = bbMax.z;
  601. }
  602. //-----------------------------------------------------------------------------
  603. // Purpose:
  604. //-----------------------------------------------------------------------------
  605. void CDispCollTree::RayNodeTest_r( CDispCollTreeTempData *pTemp, int nodeIndex, Vector rayStart, Vector rayEnd )
  606. {
  607. // get the current node
  608. CDispCollNode *pNode = &m_pNodes[nodeIndex];
  609. //
  610. // get node bounding box and create collision planes
  611. //
  612. Vector bounds[2];
  613. pNode->GetBounds( bounds[0], bounds[1] );
  614. CreatePlanesFromBounds( pTemp, bounds[0], bounds[1] );
  615. bool bIntersect = RayAABBTest( pTemp, rayStart, rayEnd );
  616. if( bIntersect )
  617. {
  618. // done -- add triangles to triangle list
  619. if( pNode->IsLeaf() )
  620. {
  621. // Assert for now -- flush cache later!!!!!
  622. Assert( pTemp->m_TriListCount >= 0 );
  623. Assert( pTemp->m_TriListCount < TRILIST_CACHE_SIZE );
  624. pTemp->m_ppTriList[pTemp->m_TriListCount] = &pNode->m_Tris[0];
  625. pTemp->m_ppTriList[pTemp->m_TriListCount+1] = &pNode->m_Tris[1];
  626. pTemp->m_TriListCount += 2;
  627. }
  628. // continue recursion
  629. else
  630. {
  631. for( int i = 0; i < 4; i++ )
  632. {
  633. RayNodeTest_r( pTemp, GetChildNode( nodeIndex, i ), rayStart, rayEnd );
  634. }
  635. }
  636. }
  637. }
  638. //-----------------------------------------------------------------------------
  639. // Purpose:
  640. //-----------------------------------------------------------------------------
  641. bool CDispCollTree::RayTestAllTris( CDispCollData *pData, int power )
  642. {
  643. //
  644. // get leaf indices
  645. //
  646. int startIndex = CalcNodeCount( power - 1 );
  647. int endIndex = CalcNodeCount( power );
  648. // save incoming fraction
  649. float startFraction = pData->m_Fraction;
  650. float fraction = pData->m_Fraction;
  651. Vector ray = pData->m_EndPos - pData->m_StartPos;
  652. Vector rayDir = ray;
  653. float rayLength = VectorNormalize(rayDir);
  654. //
  655. // test ray against all triangles in list
  656. //
  657. for( int index = startIndex; index < endIndex; index++ )
  658. {
  659. for( int j = 0; j < 2; j++ )
  660. {
  661. bool bResult = RayTriTest( pData->m_StartPos, rayDir, rayLength, &m_pNodes[index].m_Tris[j], &fraction );
  662. if( !bResult )
  663. continue;
  664. if( pData->m_bOcclude )
  665. {
  666. return true;
  667. }
  668. if( fraction < pData->m_Fraction )
  669. {
  670. pData->m_Fraction = fraction;
  671. pData->m_Normal = m_pNodes[index].m_Tris[j].m_Normal;
  672. pData->m_Distance = m_pNodes[index].m_Tris[j].m_Distance;
  673. }
  674. }
  675. }
  676. // collision!
  677. if( pData->m_Fraction < startFraction )
  678. return true;
  679. // no collision!
  680. return false;
  681. }
  682. //-----------------------------------------------------------------------------
  683. // Purpose:
  684. //-----------------------------------------------------------------------------
  685. bool CDispCollTree::RayTest( CDispCollData *pData )
  686. {
  687. // reset the triangle list count
  688. CDispCollTreeTempData tmp;
  689. tmp.m_TriListCount = 0;
  690. // trace against nodes (copy start, end because they change)
  691. RayNodeTest_r( &tmp, 0, pData->m_StartPos, pData->m_EndPos );
  692. //
  693. // trace against tris (if need be)
  694. //
  695. if( tmp.m_TriListCount != 0 )
  696. {
  697. bool result = RayTriListTest( &tmp, pData );
  698. return result;
  699. }
  700. return false;
  701. }
  702. //-----------------------------------------------------------------------------
  703. // Purpose:
  704. //-----------------------------------------------------------------------------
  705. bool CDispCollTree::SweptAABBTriIntersect( Vector &rayStart, Vector &rayEnd, Vector &extents,
  706. CDispCollTri const *pTri, Vector &plNormal, float *plDist,
  707. float *fraction )
  708. {
  709. //
  710. // PUT A COPY HERE OF START AND END -- SINCE I CHANGE THEM!!!!!!
  711. //
  712. int dir, ptIndex;
  713. float closeValue;
  714. float distStart, distEnd;
  715. float t;
  716. Vector rayPt;
  717. // get ray direction
  718. Vector rayDir = rayEnd - rayStart;
  719. // initialize fraction
  720. *fraction = 1.0f;
  721. //
  722. // test for collision with axial planes (x, y, z)
  723. //
  724. for( dir = 0; dir < 3; dir++ )
  725. {
  726. if( rayDir[dir] < 0.0f )
  727. {
  728. closeValue = -99999.9f;
  729. for( ptIndex = 0; ptIndex < 3; ptIndex++ )
  730. {
  731. if( pTri->m_Points[ptIndex][dir] > closeValue )
  732. {
  733. closeValue = pTri->m_Points[ptIndex][dir];
  734. }
  735. }
  736. closeValue += extents[dir];
  737. distStart = rayStart[dir] - closeValue;
  738. distEnd = rayEnd[dir] - closeValue;
  739. }
  740. else
  741. {
  742. closeValue = 99999.9f;
  743. for( ptIndex = 0; ptIndex < 3; ptIndex++ )
  744. {
  745. if( pTri->m_Points[ptIndex][dir] < closeValue )
  746. {
  747. closeValue = pTri->m_Points[ptIndex][dir];
  748. }
  749. }
  750. closeValue -= extents[dir];
  751. distStart = -( rayStart[dir] - closeValue );
  752. distEnd = -( rayEnd[dir] - closeValue );
  753. }
  754. if( ( distStart > COLLISION_EPSILON ) && ( distEnd < -COLLISION_EPSILON ) )
  755. {
  756. t = ( distStart - COLLISION_EPSILON ) / ( distStart - distEnd );
  757. if( t > *fraction )
  758. {
  759. VectorScale( rayDir, t, rayPt );
  760. VectorAdd( rayStart, rayPt, rayStart );
  761. *fraction = t;
  762. plNormal.Init();
  763. plNormal[dir] = 1.0f;
  764. *plDist = closeValue;
  765. }
  766. }
  767. else if( ( distStart < -COLLISION_EPSILON ) && ( distEnd > COLLISION_EPSILON ) )
  768. {
  769. t = ( distStart + COLLISION_EPSILON ) / ( distStart - distEnd );
  770. VectorScale( rayDir, t, rayPt );
  771. VectorAdd( rayStart, rayPt, rayEnd );
  772. }
  773. else if( ( distStart > COLLISION_EPSILON ) && ( distEnd > COLLISION_EPSILON ) )
  774. {
  775. return false;
  776. }
  777. }
  778. //
  779. // check for an early out
  780. //
  781. if( ( pTri->m_Normal[0] > ONE_MINUS_COLLISION_EPSILON ) ||
  782. ( pTri->m_Normal[1] > ONE_MINUS_COLLISION_EPSILON ) ||
  783. ( pTri->m_Normal[2] > ONE_MINUS_COLLISION_EPSILON ) )
  784. {
  785. if( *fraction == 1.0f )
  786. return false;
  787. return true;
  788. }
  789. //
  790. // handle 9 edge tests
  791. //
  792. Vector normal;
  793. Vector edge;
  794. float dist;
  795. // find the closest box point
  796. Vector boxPt( 0.0f, 0.0f, 0.0f );
  797. for( dir = 0; dir < 3; dir++ )
  798. {
  799. if( rayDir[dir] < 0.0f )
  800. {
  801. boxPt[dir] = extents[dir];
  802. }
  803. else
  804. {
  805. boxPt[dir] = -extents[dir];
  806. }
  807. }
  808. //
  809. // edge 0
  810. //
  811. edge = pTri->m_Points[1] - pTri->m_Points[0];
  812. // cross x-edge
  813. normal.x = 0.0f;
  814. normal.y = -edge.z;
  815. normal.z = edge.y;
  816. // extents adjusted dist
  817. dist = ( normal.y * ( boxPt.y - pTri->m_Points[0].y ) ) + ( normal.z * ( boxPt.z - pTri->m_Points[0].z ) );
  818. // find distances from plane (start, end)
  819. distStart = ( normal.y * rayStart.y ) + ( normal.z * rayStart.z ) - dist;
  820. distEnd = ( normal.y * rayEnd.y ) + ( normal.z * rayEnd.z ) - dist;
  821. if( ( distStart > COLLISION_EPSILON ) && ( distEnd < -COLLISION_EPSILON ) )
  822. {
  823. t = ( distStart - COLLISION_EPSILON ) / ( distStart - distEnd );
  824. if( t > *fraction )
  825. {
  826. VectorScale( rayDir, t, rayPt );
  827. VectorAdd( rayStart, rayPt, rayStart );
  828. *fraction = t;
  829. plNormal = normal;
  830. *plDist = dist;
  831. }
  832. }
  833. else if( ( distStart < -COLLISION_EPSILON ) && ( distEnd > COLLISION_EPSILON ) )
  834. {
  835. t = ( distStart + COLLISION_EPSILON ) / ( distStart - distEnd );
  836. VectorScale( rayDir, t, rayPt );
  837. VectorAdd( rayStart, rayPt, rayEnd );
  838. }
  839. else if( ( distStart > COLLISION_EPSILON ) && ( distEnd > COLLISION_EPSILON ) )
  840. {
  841. return false;
  842. }
  843. // cross y-edge
  844. normal.x = edge.z;
  845. normal.y = 0.0f;
  846. normal.z = edge.y;
  847. // extents adjusted dist
  848. dist = ( normal.x * ( boxPt.x - pTri->m_Points[0].x ) ) + ( normal.z * ( boxPt.z - pTri->m_Points[0].z ) );
  849. // find distances from plane (start, end)
  850. distStart = ( normal.x * rayStart.x ) + ( normal.z * rayStart.z ) - dist;
  851. distEnd = ( normal.x * rayEnd.x ) + ( normal.z * rayEnd.z ) - dist;
  852. if( ( distStart > COLLISION_EPSILON ) && ( distEnd < -COLLISION_EPSILON ) )
  853. {
  854. t = ( distStart - COLLISION_EPSILON ) / ( distStart - distEnd );
  855. if( t > *fraction )
  856. {
  857. VectorScale( rayDir, t, rayPt );
  858. VectorAdd( rayStart, rayPt, rayStart );
  859. *fraction = t;
  860. plNormal = normal;
  861. *plDist = dist;
  862. }
  863. }
  864. else if( ( distStart < -COLLISION_EPSILON ) && ( distEnd > COLLISION_EPSILON ) )
  865. {
  866. t = ( distStart + COLLISION_EPSILON ) / ( distStart - distEnd );
  867. VectorScale( rayDir, t, rayPt );
  868. VectorAdd( rayStart, rayPt, rayEnd );
  869. }
  870. else if( ( distStart > COLLISION_EPSILON ) && ( distEnd > COLLISION_EPSILON ) )
  871. {
  872. return false;
  873. }
  874. // cross z-edge
  875. normal.x = -edge.y;
  876. normal.y = edge.x;
  877. normal.z = 0.0f;
  878. // extents adjusted dist
  879. dist = ( normal.x * ( boxPt.x - pTri->m_Points[0].x ) ) + ( normal.y * ( boxPt.y - pTri->m_Points[0].y ) );
  880. // find distances from plane (start, end)
  881. distStart = ( normal.x * rayStart.x ) + ( normal.y * rayStart.y ) - dist;
  882. distEnd = ( normal.x * rayEnd.x ) + ( normal.y * rayEnd.y ) - dist;
  883. if( ( distStart > COLLISION_EPSILON ) && ( distEnd < -COLLISION_EPSILON ) )
  884. {
  885. t = ( distStart - COLLISION_EPSILON ) / ( distStart - distEnd );
  886. if( t > *fraction )
  887. {
  888. VectorScale( rayDir, t, rayPt );
  889. VectorAdd( rayStart, rayPt, rayStart );
  890. *fraction = t;
  891. plNormal = normal;
  892. *plDist = dist;
  893. }
  894. }
  895. else if( ( distStart < -COLLISION_EPSILON ) && ( distEnd > COLLISION_EPSILON ) )
  896. {
  897. t = ( distStart + COLLISION_EPSILON ) / ( distStart - distEnd );
  898. VectorScale( rayDir, t, rayPt );
  899. VectorAdd( rayStart, rayPt, rayEnd );
  900. }
  901. else if( ( distStart > COLLISION_EPSILON ) && ( distEnd > COLLISION_EPSILON ) )
  902. {
  903. return false;
  904. }
  905. //
  906. // edge 1
  907. //
  908. edge = pTri->m_Points[2] - pTri->m_Points[1];
  909. // cross x-edge
  910. normal.x = 0.0f;
  911. normal.y = -edge.z;
  912. normal.z = edge.y;
  913. // extents adjusted dist
  914. dist = ( normal.y * ( boxPt.y - pTri->m_Points[0].y ) ) + ( normal.z * ( boxPt.z - pTri->m_Points[0].z ) );
  915. // find distances from plane (start, end)
  916. distStart = ( normal.y * rayStart.y ) + ( normal.z * rayStart.z ) - dist;
  917. distEnd = ( normal.y * rayEnd.y ) + ( normal.z * rayEnd.z ) - dist;
  918. if( ( distStart > COLLISION_EPSILON ) && ( distEnd < -COLLISION_EPSILON ) )
  919. {
  920. t = ( distStart - COLLISION_EPSILON ) / ( distStart - distEnd );
  921. if( t > *fraction )
  922. {
  923. VectorScale( rayDir, t, rayPt );
  924. VectorAdd( rayStart, rayPt, rayStart );
  925. *fraction = t;
  926. plNormal = normal;
  927. *plDist = dist;
  928. }
  929. }
  930. else if( ( distStart < -COLLISION_EPSILON ) && ( distEnd > COLLISION_EPSILON ) )
  931. {
  932. t = ( distStart + COLLISION_EPSILON ) / ( distStart - distEnd );
  933. VectorScale( rayDir, t, rayPt );
  934. VectorAdd( rayStart, rayPt, rayEnd );
  935. }
  936. else if( ( distStart > COLLISION_EPSILON ) && ( distEnd > COLLISION_EPSILON ) )
  937. {
  938. return false;
  939. }
  940. // cross y-edge
  941. normal.x = edge.z;
  942. normal.y = 0.0f;
  943. normal.z = edge.y;
  944. // extents adjusted dist
  945. dist = ( normal.x * ( boxPt.x - pTri->m_Points[0].x ) ) + ( normal.z * ( boxPt.z - pTri->m_Points[0].z ) );
  946. // find distances from plane (start, end)
  947. distStart = ( normal.x * rayStart.x ) + ( normal.z * rayStart.z ) - dist;
  948. distEnd = ( normal.x * rayEnd.x ) + ( normal.z * rayEnd.z ) - dist;
  949. if( ( distStart > COLLISION_EPSILON ) && ( distEnd < -COLLISION_EPSILON ) )
  950. {
  951. t = ( distStart - COLLISION_EPSILON ) / ( distStart - distEnd );
  952. if( t > *fraction )
  953. {
  954. VectorScale( rayDir, t, rayPt );
  955. VectorAdd( rayStart, rayPt, rayStart );
  956. *fraction = t;
  957. plNormal = normal;
  958. *plDist = dist;
  959. }
  960. }
  961. else if( ( distStart < -COLLISION_EPSILON ) && ( distEnd > COLLISION_EPSILON ) )
  962. {
  963. t = ( distStart + COLLISION_EPSILON ) / ( distStart - distEnd );
  964. VectorScale( rayDir, t, rayPt );
  965. VectorAdd( rayStart, rayPt, rayEnd );
  966. }
  967. else if( ( distStart > COLLISION_EPSILON ) && ( distEnd > COLLISION_EPSILON ) )
  968. {
  969. return false;
  970. }
  971. // cross z-edge
  972. normal.x = -edge.y;
  973. normal.y = edge.x;
  974. normal.z = 0.0f;
  975. // extents adjusted dist
  976. dist = ( normal.x * ( boxPt.x - pTri->m_Points[0].x ) ) + ( normal.y * ( boxPt.y - pTri->m_Points[0].y ) );
  977. // find distances from plane (start, end)
  978. distStart = ( normal.x * rayStart.x ) + ( normal.y * rayStart.y ) - dist;
  979. distEnd = ( normal.x * rayEnd.x ) + ( normal.y * rayEnd.y ) - dist;
  980. if( ( distStart > COLLISION_EPSILON ) && ( distEnd < -COLLISION_EPSILON ) )
  981. {
  982. t = ( distStart - COLLISION_EPSILON ) / ( distStart - distEnd );
  983. if( t > *fraction )
  984. {
  985. VectorScale( rayDir, t, rayPt );
  986. VectorAdd( rayStart, rayPt, rayStart );
  987. *fraction = t;
  988. plNormal = normal;
  989. *plDist = dist;
  990. }
  991. }
  992. else if( ( distStart < -COLLISION_EPSILON ) && ( distEnd > COLLISION_EPSILON ) )
  993. {
  994. t = ( distStart + COLLISION_EPSILON ) / ( distStart - distEnd );
  995. VectorScale( rayDir, t, rayPt );
  996. VectorAdd( rayStart, rayPt, rayEnd );
  997. }
  998. else if( ( distStart > COLLISION_EPSILON ) && ( distEnd > COLLISION_EPSILON ) )
  999. {
  1000. return false;
  1001. }
  1002. //
  1003. // edge 2
  1004. //
  1005. edge = pTri->m_Points[0] - pTri->m_Points[2];
  1006. // cross x-edge
  1007. normal.x = 0.0f;
  1008. normal.y = -edge.z;
  1009. normal.z = edge.y;
  1010. // extents adjusted dist
  1011. dist = ( normal.y * ( boxPt.y - pTri->m_Points[0].y ) ) + ( normal.z * ( boxPt.z - pTri->m_Points[0].z ) );
  1012. // find distances from plane (start, end)
  1013. distStart = ( normal.y * rayStart.y ) + ( normal.z * rayStart.z ) - dist;
  1014. distEnd = ( normal.y * rayEnd.y ) + ( normal.z * rayEnd.z ) - dist;
  1015. if( ( distStart > COLLISION_EPSILON ) && ( distEnd < -COLLISION_EPSILON ) )
  1016. {
  1017. t = ( distStart - COLLISION_EPSILON ) / ( distStart - distEnd );
  1018. if( t > *fraction )
  1019. {
  1020. VectorScale( rayDir, t, rayPt );
  1021. VectorAdd( rayStart, rayPt, rayStart );
  1022. *fraction = t;
  1023. plNormal = normal;
  1024. *plDist = dist;
  1025. }
  1026. }
  1027. else if( ( distStart < -COLLISION_EPSILON ) && ( distEnd > COLLISION_EPSILON ) )
  1028. {
  1029. t = ( distStart + COLLISION_EPSILON ) / ( distStart - distEnd );
  1030. VectorScale( rayDir, t, rayPt );
  1031. VectorAdd( rayStart, rayPt, rayEnd );
  1032. }
  1033. else if( ( distStart > COLLISION_EPSILON ) && ( distEnd > COLLISION_EPSILON ) )
  1034. {
  1035. return false;
  1036. }
  1037. // cross y-edge
  1038. normal.x = edge.z;
  1039. normal.y = 0.0f;
  1040. normal.z = edge.y;
  1041. // extents adjusted dist
  1042. dist = ( normal.x * ( boxPt.x - pTri->m_Points[0].x ) ) + ( normal.z * ( boxPt.z - pTri->m_Points[0].z ) );
  1043. // find distances from plane (start, end)
  1044. distStart = ( normal.x * rayStart.x ) + ( normal.z * rayStart.z ) - dist;
  1045. distEnd = ( normal.x * rayEnd.x ) + ( normal.z * rayEnd.z ) - dist;
  1046. if( ( distStart > COLLISION_EPSILON ) && ( distEnd < -COLLISION_EPSILON ) )
  1047. {
  1048. t = ( distStart - COLLISION_EPSILON ) / ( distStart - distEnd );
  1049. if( t > *fraction )
  1050. {
  1051. VectorScale( rayDir, t, rayPt );
  1052. VectorAdd( rayStart, rayPt, rayStart );
  1053. *fraction = t;
  1054. plNormal = normal;
  1055. *plDist = dist;
  1056. }
  1057. }
  1058. else if( ( distStart < -COLLISION_EPSILON ) && ( distEnd > COLLISION_EPSILON ) )
  1059. {
  1060. t = ( distStart + COLLISION_EPSILON ) / ( distStart - distEnd );
  1061. VectorScale( rayDir, t, rayPt );
  1062. VectorAdd( rayStart, rayPt, rayEnd );
  1063. }
  1064. else if( ( distStart > COLLISION_EPSILON ) && ( distEnd > COLLISION_EPSILON ) )
  1065. {
  1066. return false;
  1067. }
  1068. // cross z-edge
  1069. normal.x = -edge.y;
  1070. normal.y = edge.x;
  1071. normal.z = 0.0f;
  1072. // extents adjusted dist
  1073. dist = ( normal.x * ( boxPt.x - pTri->m_Points[0].x ) ) + ( normal.y * ( boxPt.y - pTri->m_Points[0].y ) );
  1074. // find distances from plane (start, end)
  1075. distStart = ( normal.x * rayStart.x ) + ( normal.y * rayStart.y ) - dist;
  1076. distEnd = ( normal.x * rayEnd.x ) + ( normal.y * rayEnd.y ) - dist;
  1077. if( ( distStart > COLLISION_EPSILON ) && ( distEnd < -COLLISION_EPSILON ) )
  1078. {
  1079. t = ( distStart - COLLISION_EPSILON ) / ( distStart - distEnd );
  1080. if( t > *fraction )
  1081. {
  1082. VectorScale( rayDir, t, rayPt );
  1083. VectorAdd( rayStart, rayPt, rayStart );
  1084. *fraction = t;
  1085. plNormal = normal;
  1086. *plDist = dist;
  1087. }
  1088. }
  1089. else if( ( distStart < -COLLISION_EPSILON ) && ( distEnd > COLLISION_EPSILON ) )
  1090. {
  1091. t = ( distStart + COLLISION_EPSILON ) / ( distStart - distEnd );
  1092. VectorScale( rayDir, t, rayPt );
  1093. VectorAdd( rayStart, rayPt, rayEnd );
  1094. }
  1095. else if( ( distStart > COLLISION_EPSILON ) && ( distEnd > COLLISION_EPSILON ) )
  1096. {
  1097. return false;
  1098. }
  1099. //
  1100. // test face plane
  1101. //
  1102. dist = ( pTri->m_Normal.x * ( boxPt.x - pTri->m_Points[0].x ) ) +
  1103. ( pTri->m_Normal.y * ( boxPt.y - pTri->m_Points[0].y ) ) +
  1104. ( pTri->m_Normal.z * ( boxPt.z - pTri->m_Points[0].z ) );
  1105. distStart = pTri->m_Normal.Dot( rayStart ) - dist;
  1106. distEnd = pTri->m_Normal.Dot( rayEnd ) - dist;
  1107. if( ( distStart > COLLISION_EPSILON ) && ( distEnd < -COLLISION_EPSILON ) )
  1108. {
  1109. t = ( distStart - COLLISION_EPSILON ) / ( distStart - distEnd );
  1110. if( t > *fraction )
  1111. {
  1112. VectorScale( rayDir, t, rayPt );
  1113. VectorAdd( rayStart, rayPt, rayStart );
  1114. *fraction = t;
  1115. plNormal = normal;
  1116. *plDist = dist;
  1117. }
  1118. }
  1119. else if( ( distStart < -COLLISION_EPSILON ) && ( distEnd > COLLISION_EPSILON ) )
  1120. {
  1121. t = ( distStart + COLLISION_EPSILON ) / ( distStart - distEnd );
  1122. VectorScale( rayDir, t, rayPt );
  1123. VectorAdd( rayStart, rayPt, rayEnd );
  1124. }
  1125. else if( ( distStart > COLLISION_EPSILON ) && ( distEnd > COLLISION_EPSILON ) )
  1126. {
  1127. return false;
  1128. }
  1129. if( *fraction == 1.0f )
  1130. return false;
  1131. return true;
  1132. }
  1133. //-----------------------------------------------------------------------------
  1134. // Purpose:
  1135. //-----------------------------------------------------------------------------
  1136. bool CDispCollTree::AABBTriIntersect( CDispCollTreeTempData *pTemp, CDispCollData *pData )
  1137. {
  1138. bool bResult = false;
  1139. Vector normal;
  1140. float fraction, dist;
  1141. //
  1142. // sweep ABB against all triangles in list
  1143. //
  1144. for( int i = 0; i < pTemp->m_TriListCount; i++ )
  1145. {
  1146. if( pTemp->m_ppTriList[i]->IsIntersect() )
  1147. {
  1148. bResult = SweptAABBTriIntersect( pData->m_StartPos, pData->m_EndPos, pData->m_Extents,
  1149. pTemp->m_ppTriList[i], normal, &dist, &fraction );
  1150. if( bResult )
  1151. {
  1152. if( fraction < pData->m_Fraction )
  1153. {
  1154. pData->m_Fraction = fraction;
  1155. pData->m_Normal = normal;
  1156. pData->m_Distance = dist;
  1157. }
  1158. }
  1159. }
  1160. }
  1161. return bResult;
  1162. }
  1163. //-----------------------------------------------------------------------------
  1164. // Purpose:
  1165. //-----------------------------------------------------------------------------
  1166. bool CDispCollTree::IntersectAABBTriTest( Vector &rayStart, Vector &extents,
  1167. CDispCollTri const *pTri )
  1168. {
  1169. int dir, ptIndex;
  1170. float dist;
  1171. //
  1172. // test axail planes (x, y, z)
  1173. //
  1174. for( dir = 0; dir < 3; dir++ )
  1175. {
  1176. //
  1177. // negative axial plane, component = dir
  1178. //
  1179. dist = rayStart[dir] - extents[dir];
  1180. for( ptIndex = 0; ptIndex < 3; ptIndex++ )
  1181. {
  1182. if( pTri->m_Points[ptIndex][dir] > dist )
  1183. break;
  1184. }
  1185. if( ptIndex == 3 )
  1186. return false;
  1187. //
  1188. // positive axial plane, component = dir
  1189. //
  1190. dist = rayStart[dir] + extents[dir];
  1191. for( ptIndex = 0; ptIndex < 3; ptIndex++ )
  1192. {
  1193. if( pTri->m_Points[ptIndex][dir] < dist )
  1194. break;
  1195. }
  1196. if( ptIndex == 3 )
  1197. return false;
  1198. }
  1199. //
  1200. // add a test here to see if triangle face normal is close to axial -- done if so!!!
  1201. //
  1202. if( ( pTri->m_Normal[0] > ONE_MINUS_COLLISION_EPSILON ) ||
  1203. ( pTri->m_Normal[1] > ONE_MINUS_COLLISION_EPSILON ) ||
  1204. ( pTri->m_Normal[2] > ONE_MINUS_COLLISION_EPSILON ) )
  1205. return true;
  1206. // find the closest point on the box (use negated tri face noraml)
  1207. Vector boxPt( 0.0f, 0.0f, 0.0f );
  1208. for( dir = 0; dir < 3; dir++ )
  1209. {
  1210. if( pTri->m_Normal[dir] < 0.0f )
  1211. {
  1212. boxPt[dir] = extents[dir];
  1213. }
  1214. else
  1215. {
  1216. boxPt[dir] = -extents[dir];
  1217. }
  1218. }
  1219. //
  1220. // triangle plane test
  1221. //
  1222. // do the opposite because the ray has been negated
  1223. if( ( ( pTri->m_Normal.x * ( boxPt.x - pTri->m_Points[0].x ) ) +
  1224. ( pTri->m_Normal.y * ( boxPt.y - pTri->m_Points[0].y ) ) +
  1225. ( pTri->m_Normal.z * ( boxPt.z - pTri->m_Points[0].z ) ) ) > 0.0f )
  1226. return false;
  1227. //
  1228. // test edge planes - 9 of them
  1229. //
  1230. Vector normal;
  1231. Vector edge;
  1232. //
  1233. // edge 0
  1234. //
  1235. edge = pTri->m_Points[1] - pTri->m_Points[0];
  1236. // cross x
  1237. normal.x = 0.0f;
  1238. normal.y = -edge.z;
  1239. normal.z = edge.y;
  1240. if( ( ( normal.y * ( boxPt.y - pTri->m_Points[0].y ) ) + ( normal.z * ( boxPt.z - pTri->m_Points[0].z ) ) ) > 0.0f )
  1241. return false;
  1242. // cross y
  1243. normal.x = edge.z;
  1244. normal.y = 0.0f;
  1245. normal.z = edge.y;
  1246. if( ( ( normal.x * ( boxPt.x - pTri->m_Points[0].x ) ) + ( normal.z * ( boxPt.z - pTri->m_Points[0].z ) ) ) > 0.0f )
  1247. return false;
  1248. // cross z
  1249. normal.x = -edge.y;
  1250. normal.y = edge.x;
  1251. normal.z = 0.0f;
  1252. if( ( ( normal.x * ( boxPt.x - pTri->m_Points[0].x ) ) + ( normal.y * ( boxPt.y - pTri->m_Points[0].y ) ) ) > 0.0f )
  1253. return false;
  1254. //
  1255. // edge 1
  1256. //
  1257. edge = pTri->m_Points[2] - pTri->m_Points[1];
  1258. // cross x
  1259. normal.x = 0.0f;
  1260. normal.y = -edge.z;
  1261. normal.z = edge.y;
  1262. if( ( ( normal.y * ( boxPt.y - pTri->m_Points[0].y ) ) + ( normal.z * ( boxPt.z - pTri->m_Points[0].z ) ) ) > 0.0f )
  1263. return false;
  1264. // cross y
  1265. normal.x = edge.z;
  1266. normal.y = 0.0f;
  1267. normal.z = edge.y;
  1268. if( ( ( normal.x * ( boxPt.x - pTri->m_Points[0].x ) ) + ( normal.z * ( boxPt.z - pTri->m_Points[0].z ) ) ) > 0.0f )
  1269. return false;
  1270. // cross z
  1271. normal.x = -edge.y;
  1272. normal.y = edge.x;
  1273. normal.z = 0.0f;
  1274. if( ( ( normal.x * ( boxPt.x - pTri->m_Points[0].x ) ) + ( normal.y * ( boxPt.y - pTri->m_Points[0].y ) ) ) > 0.0f )
  1275. return false;
  1276. //
  1277. // edge 2
  1278. //
  1279. edge = pTri->m_Points[0] - pTri->m_Points[2];
  1280. // cross x
  1281. normal.x = 0.0f;
  1282. normal.y = -edge.z;
  1283. normal.z = edge.y;
  1284. if( ( ( normal.y * ( boxPt.y - pTri->m_Points[0].y ) ) + ( normal.z * ( boxPt.z - pTri->m_Points[0].z ) ) ) > 0.0f )
  1285. return false;
  1286. // cross y
  1287. normal.x = edge.z;
  1288. normal.y = 0.0f;
  1289. normal.z = edge.y;
  1290. if( ( ( normal.x * ( boxPt.x - pTri->m_Points[0].x ) ) + ( normal.z * ( boxPt.z - pTri->m_Points[0].z ) ) ) > 0.0f )
  1291. return false;
  1292. // cross z
  1293. normal.x = -edge.y;
  1294. normal.y = edge.x;
  1295. normal.z = 0.0f;
  1296. if( ( ( normal.x * ( boxPt.x - pTri->m_Points[0].x ) ) + ( normal.y * ( boxPt.y - pTri->m_Points[0].y ) ) ) > 0.0f )
  1297. return false;
  1298. return true;
  1299. }
  1300. //-----------------------------------------------------------------------------
  1301. // Purpose:
  1302. //-----------------------------------------------------------------------------
  1303. bool CDispCollTree::SweptAABBTriTest( Vector &rayStart, Vector &rayEnd, Vector &extents,
  1304. CDispCollTri const *pTri )
  1305. {
  1306. // get ray direction
  1307. Vector rayDir = rayEnd - rayStart;
  1308. //
  1309. // quick and dirty test -- test to see if the object is traveling away from triangle surface???
  1310. //
  1311. if( pTri->m_Normal.Dot( rayDir ) > 0.0f )
  1312. return false;
  1313. //
  1314. // calc the swept triangle face (negate the ray -- opposite direction of box travel)
  1315. //
  1316. rayDir.Negate();
  1317. Vector points[3];
  1318. points[0] = pTri->m_Points[0] + rayDir;
  1319. points[1] = pTri->m_Points[1] + rayDir;
  1320. points[2] = pTri->m_Points[2] + rayDir;
  1321. //
  1322. // handle 4 faces tests (3 axial planes and triangle face)
  1323. //
  1324. int dir;
  1325. float dist;
  1326. //
  1327. // axial planes tests (x, y, z)
  1328. //
  1329. for( dir = 0; dir < 3; dir++ )
  1330. {
  1331. bool bOutside = true;
  1332. if( rayDir[dir] < 0.0f )
  1333. {
  1334. dist = rayStart[dir] - extents[dir];
  1335. for( int ptIndex = 0; ptIndex < 3; ptIndex )
  1336. {
  1337. if( points[ptIndex][dir] > dist )
  1338. {
  1339. bOutside = false;
  1340. break;
  1341. }
  1342. }
  1343. }
  1344. else
  1345. {
  1346. dist = rayStart[dir] + extents[dir];
  1347. for( int ptIndex = 0; ptIndex < 3; ptIndex )
  1348. {
  1349. if( pTri->m_Points[ptIndex][dir] < dist )
  1350. {
  1351. bOutside = false;
  1352. break;
  1353. }
  1354. }
  1355. }
  1356. if( bOutside )
  1357. return false;
  1358. }
  1359. //
  1360. // add a test here to see if triangle face normal is close to axial -- done if so!!!
  1361. //
  1362. if( ( pTri->m_Normal[0] > ONE_MINUS_COLLISION_EPSILON ) ||
  1363. ( pTri->m_Normal[1] > ONE_MINUS_COLLISION_EPSILON ) ||
  1364. ( pTri->m_Normal[2] > ONE_MINUS_COLLISION_EPSILON ) )
  1365. return true;
  1366. //
  1367. // handle 9 edge tests - always use the newly swept face for this
  1368. //
  1369. Vector normal;
  1370. Vector edge;
  1371. // find the closest box point - (is written opposite to normal due to negating ray)
  1372. Vector boxPt( 0.0f, 0.0f, 0.0f );
  1373. for( dir = 0; dir < 3; dir++ )
  1374. {
  1375. if( rayDir[dir] < 0.0f )
  1376. {
  1377. boxPt[dir] = rayStart[dir] - extents[dir];
  1378. }
  1379. else
  1380. {
  1381. boxPt[dir] = rayStart[dir] + extents[dir];
  1382. }
  1383. }
  1384. //
  1385. // edge 0
  1386. //
  1387. edge = points[1] - points[0];
  1388. // cross x-edge
  1389. normal.x = 0.0f;
  1390. normal.y = -edge.z;
  1391. normal.z = edge.y;
  1392. if( ( ( normal.y * ( boxPt.y - points[0].y ) ) + ( normal.z * ( boxPt.z - points[0].z ) ) ) > 0.0f )
  1393. return false;
  1394. // cross, y-edge
  1395. normal.x = edge.z;
  1396. normal.y = 0.0f;
  1397. normal.z = edge.y;
  1398. if( ( ( normal.x * ( boxPt.x - points[0].x ) ) + ( normal.z * ( boxPt.z - points[0].z ) ) ) > 0.0f )
  1399. return false;
  1400. // cross z-edge
  1401. normal.x = -edge.y;
  1402. normal.y = edge.x;
  1403. normal.z = 0.0f;
  1404. if( ( ( normal.x * ( boxPt.x - points[0].x ) ) + ( normal.y * ( boxPt.y - points[0].y ) ) ) > 0.0f )
  1405. return false;
  1406. //
  1407. // edge 1
  1408. //
  1409. edge = points[2] - points[1];
  1410. // cross x-edge
  1411. normal.x = 0.0f;
  1412. normal.y = -edge.z;
  1413. normal.z = edge.y;
  1414. if( ( ( normal.y * ( boxPt.y - points[0].y ) ) + ( normal.z * ( boxPt.z - points[0].z ) ) ) > 0.0f )
  1415. return false;
  1416. // cross, y-edge
  1417. normal.x = edge.z;
  1418. normal.y = 0.0f;
  1419. normal.z = edge.y;
  1420. if( ( ( normal.x * ( boxPt.x - points[0].x ) ) + ( normal.z * ( boxPt.z - points[0].z ) ) ) > 0.0f )
  1421. return false;
  1422. // cross z-edge
  1423. normal.x = -edge.y;
  1424. normal.y = edge.x;
  1425. normal.z = 0.0f;
  1426. if( ( ( normal.x * ( boxPt.x - points[0].x ) ) + ( normal.y * ( boxPt.y - points[0].y ) ) ) > 0.0f )
  1427. return false;
  1428. //
  1429. // edge 2
  1430. //
  1431. edge = points[0] - points[2];
  1432. // cross x-edge
  1433. normal.x = 0.0f;
  1434. normal.y = -edge.z;
  1435. normal.z = edge.y;
  1436. if( ( ( normal.y * ( boxPt.y - points[0].y ) ) + ( normal.z * ( boxPt.z - points[0].z ) ) ) > 0.0f )
  1437. return false;
  1438. // cross, y-edge
  1439. normal.x = edge.z;
  1440. normal.y = 0.0f;
  1441. normal.z = edge.y;
  1442. if( ( ( normal.x * ( boxPt.x - points[0].x ) ) + ( normal.z * ( boxPt.z - points[0].z ) ) ) > 0.0f )
  1443. return false;
  1444. // cross z-edge
  1445. normal.x = -edge.y;
  1446. normal.y = edge.x;
  1447. normal.z = 0.0f;
  1448. if( ( ( normal.x * ( boxPt.x - points[0].x ) ) + ( normal.y * ( boxPt.y - points[0].y ) ) ) > 0.0f )
  1449. return false;
  1450. //
  1451. // triangle plane test
  1452. //
  1453. // do the opposite because the ray has been negated
  1454. if( ( ( pTri->m_Normal.x * ( boxPt.x - points[0].x ) ) +
  1455. ( pTri->m_Normal.y * ( boxPt.y - points[0].y ) ) +
  1456. ( pTri->m_Normal.z * ( boxPt.z - points[0].z ) ) ) > 0.0f )
  1457. return false;
  1458. return true;
  1459. }
  1460. //-----------------------------------------------------------------------------
  1461. // Purpose:
  1462. //-----------------------------------------------------------------------------
  1463. bool CDispCollTree::CullTriList( CDispCollTreeTempData *pTemp, Vector &rayStart, Vector &rayEnd, Vector &extents, bool bIntersect )
  1464. {
  1465. //
  1466. // intersect AABB with all triangles in list
  1467. //
  1468. if( bIntersect )
  1469. {
  1470. for( int i = 0; i < pTemp->m_TriListCount; i++ )
  1471. {
  1472. if( IntersectAABBTriTest( rayStart, extents, pTemp->m_ppTriList[i] ) )
  1473. return true;
  1474. }
  1475. return false;
  1476. }
  1477. //
  1478. // sweep AABB against all triangles in list
  1479. //
  1480. else
  1481. {
  1482. bool bResult = false;
  1483. for( int i = 0; i < pTemp->m_TriListCount; i++ )
  1484. {
  1485. if( SweptAABBTriTest( rayStart, rayEnd, extents, pTemp->m_ppTriList[i] ) )
  1486. {
  1487. pTemp->m_ppTriList[i]->SetIntersect( true );
  1488. bResult = true;
  1489. }
  1490. }
  1491. return bResult;
  1492. }
  1493. }
  1494. //-----------------------------------------------------------------------------
  1495. // Purpose:
  1496. //-----------------------------------------------------------------------------
  1497. bool CDispCollTree::IntersectAABBAABBTest( CDispCollTreeTempData *pTemp, const Vector &pos, const Vector &extents )
  1498. {
  1499. float dist;
  1500. for( int dir = 0; dir < 3; dir++ )
  1501. {
  1502. // negative direction
  1503. dist = -( pos[dir] - ( pTemp->m_AABBDistances[(dir>>1)] - extents[dir] ) );
  1504. if( dist > COLLISION_EPSILON )
  1505. return false;
  1506. // positive direction
  1507. dist = pos[dir] - ( pTemp->m_AABBDistances[(dir>>1)+1] + extents[dir] );
  1508. if( dist > COLLISION_EPSILON )
  1509. return false;
  1510. }
  1511. return true;
  1512. }
  1513. //-----------------------------------------------------------------------------
  1514. // Purpose:
  1515. //-----------------------------------------------------------------------------
  1516. bool CDispCollTree::SweptAABBAABBTest( CDispCollTreeTempData *pTemp, const Vector &rayStart, const Vector &rayEnd, const Vector &extents )
  1517. {
  1518. int dir;
  1519. float distStart, distEnd;
  1520. float fraction;
  1521. float deltas[3];
  1522. float scalers[3];
  1523. //
  1524. // enter and exit fractions
  1525. //
  1526. float enterFraction = 0.0f;
  1527. float exitFraction = 0.0f;
  1528. //
  1529. // de-normalize the paramter space so that we don't have to divide
  1530. // to find the fractional amount later (clamped for precision)
  1531. //
  1532. deltas[0] = rayEnd.x - rayStart.x;
  1533. deltas[1] = rayEnd.y - rayStart.y;
  1534. deltas[2] = rayEnd.z - rayStart.z;
  1535. if( ( deltas[0] < COLLISION_EPSILON ) && ( deltas[0] > -COLLISION_EPSILON ) ) { deltas[0] = 1.0f; }
  1536. if( ( deltas[1] < COLLISION_EPSILON ) && ( deltas[1] > -COLLISION_EPSILON ) ) { deltas[0] = 1.0f; }
  1537. if( ( deltas[2] < COLLISION_EPSILON ) && ( deltas[2] > -COLLISION_EPSILON ) ) { deltas[0] = 1.0f; }
  1538. scalers[0] = deltas[1] * deltas[2];
  1539. scalers[1] = deltas[0] * deltas[2];
  1540. scalers[2] = deltas[0] * deltas[1];
  1541. for( dir = 0; dir < 3; dir++ )
  1542. {
  1543. //
  1544. // negative direction
  1545. //
  1546. distStart = -( rayStart[dir] - ( pTemp->m_AABBDistances[(dir>>1)] - extents[dir] ) );
  1547. distEnd = -( rayEnd[dir] - ( pTemp->m_AABBDistances[(dir>>1)] - extents[dir] ) );
  1548. if( ( distStart > COLLISION_EPSILON ) && ( distEnd < -COLLISION_EPSILON ) )
  1549. {
  1550. fraction = distStart * scalers[dir];
  1551. if( fraction > enterFraction )
  1552. {
  1553. enterFraction = fraction;
  1554. }
  1555. }
  1556. else if( ( distStart < -COLLISION_EPSILON ) && ( distEnd > COLLISION_EPSILON ) )
  1557. {
  1558. fraction = distStart * scalers[dir];
  1559. if( fraction < exitFraction )
  1560. {
  1561. exitFraction = fraction;
  1562. }
  1563. }
  1564. else if( ( distStart > COLLISION_EPSILON ) && ( distEnd > COLLISION_EPSILON ) )
  1565. {
  1566. return false;
  1567. }
  1568. //
  1569. // positive direction
  1570. //
  1571. distStart = rayStart[dir] - ( pTemp->m_AABBDistances[(dir>>1)+1] + extents[dir] );
  1572. distEnd = rayEnd[dir] - ( pTemp->m_AABBDistances[(dir>>1)+1] + extents[dir] );
  1573. if( ( distStart > COLLISION_EPSILON ) && ( distEnd < -COLLISION_EPSILON ) )
  1574. {
  1575. fraction = distStart * scalers[dir];
  1576. if( fraction > enterFraction )
  1577. {
  1578. enterFraction = fraction;
  1579. }
  1580. }
  1581. else if( ( distStart < -COLLISION_EPSILON ) && ( distEnd > COLLISION_EPSILON ) )
  1582. {
  1583. fraction = distStart * scalers[dir];
  1584. if( fraction < exitFraction )
  1585. {
  1586. exitFraction = fraction;
  1587. }
  1588. }
  1589. else if( ( distStart > COLLISION_EPSILON ) && ( distEnd > COLLISION_EPSILON ) )
  1590. {
  1591. return false;
  1592. }
  1593. }
  1594. if( exitFraction < enterFraction )
  1595. return false;
  1596. return true;
  1597. }
  1598. //-----------------------------------------------------------------------------
  1599. // Purpose:
  1600. //-----------------------------------------------------------------------------
  1601. void CDispCollTree::BuildTriList_r( CDispCollTreeTempData *pTemp, int nodeIndex, Vector &rayStart, Vector &rayEnd, Vector &extents,
  1602. bool bIntersect )
  1603. {
  1604. //
  1605. // get the current nodes bounds and create collision test planes
  1606. // (saved in the in class cache m_AABBNormals, m_AABBDistances)
  1607. //
  1608. Vector bounds[2];
  1609. CDispCollNode *pNode = &m_pNodes[nodeIndex];
  1610. pNode->GetBounds( bounds[0], bounds[1] );
  1611. CreatePlanesFromBounds( pTemp, bounds[0], bounds[1] );
  1612. //
  1613. // interesect/sweep test
  1614. //
  1615. bool bResult;
  1616. if( bIntersect )
  1617. {
  1618. bResult = IntersectAABBAABBTest( pTemp, rayStart, extents );
  1619. }
  1620. else
  1621. {
  1622. bResult = SweptAABBAABBTest( pTemp, rayStart, rayEnd, extents );
  1623. }
  1624. if( bResult )
  1625. {
  1626. // if leaf node -- add triangles to interstection test list
  1627. if( pNode->IsLeaf() )
  1628. {
  1629. // Assert for now -- flush cache later!!!!!
  1630. Assert( pTemp->m_TriListCount >= 0 );
  1631. Assert( pTemp->m_TriListCount < TRILIST_CACHE_SIZE );
  1632. pTemp->m_ppTriList[pTemp->m_TriListCount] = &pNode->m_Tris[0];
  1633. pTemp->m_ppTriList[pTemp->m_TriListCount+1] = &pNode->m_Tris[1];
  1634. pTemp->m_TriListCount += 2;
  1635. }
  1636. // continue recursion
  1637. else
  1638. {
  1639. BuildTriList_r( pTemp, GetChildNode( nodeIndex, 0 ), rayStart, rayEnd, extents, bIntersect );
  1640. BuildTriList_r( pTemp, GetChildNode( nodeIndex, 1 ), rayStart, rayEnd, extents, bIntersect );
  1641. BuildTriList_r( pTemp, GetChildNode( nodeIndex, 2 ), rayStart, rayEnd, extents, bIntersect );
  1642. BuildTriList_r( pTemp, GetChildNode( nodeIndex, 3 ), rayStart, rayEnd, extents, bIntersect );
  1643. }
  1644. }
  1645. }
  1646. //-----------------------------------------------------------------------------
  1647. // Purpose:
  1648. //-----------------------------------------------------------------------------
  1649. bool CDispCollTree::AABBSweep( CDispCollData *pData )
  1650. {
  1651. // reset the triangle lists counts
  1652. CDispCollTreeTempData tmp;
  1653. tmp.m_TriListCount = 0;
  1654. // sweep the AABB against the tree
  1655. BuildTriList_r( &tmp, 0, pData->m_StartPos, pData->m_EndPos, pData->m_Extents, false );
  1656. // find collision triangles
  1657. if( CullTriList( &tmp, pData->m_StartPos, pData->m_EndPos, pData->m_Extents, false ) )
  1658. {
  1659. // find closest intersection
  1660. return AABBTriIntersect( &tmp, pData );
  1661. }
  1662. return false;
  1663. }
  1664. //-----------------------------------------------------------------------------
  1665. // Purpose:
  1666. //-----------------------------------------------------------------------------
  1667. bool CDispCollTree::AABBIntersect( CDispCollData *pData )
  1668. {
  1669. // reset the triangle lists counts
  1670. CDispCollTreeTempData tmp;
  1671. tmp.m_TriListCount = 0;
  1672. // sweep the AABB against the tree
  1673. BuildTriList_r( &tmp, 0, pData->m_StartPos, pData->m_StartPos, pData->m_Extents, true );
  1674. // find collision triangles
  1675. return CullTriList( &tmp, pData->m_StartPos, pData->m_StartPos, pData->m_Extents, true );
  1676. }