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.

641 lines
17 KiB

  1. //===================== Copyright (c) Valve Corporation. All Rights Reserved. ======================
  2. #include "dynamictree.h"
  3. //--------------------------------------------------------------------------------------------------
  4. // Local utilities
  5. //--------------------------------------------------------------------------------------------------
  6. static inline Vector Clamp( const Vector &v, const Vector &min, const Vector &max )
  7. {
  8. Vector out;
  9. out.x = fpmax( min.x, fpmin( v.x, max.x ) );
  10. out.y = fpmax( min.y, fpmin( v.y, max.y ) );
  11. out.z = fpmax( min.z, fpmin( v.z, max.z ) );
  12. return out;
  13. }
  14. //-------------------------------------------------------------------------------------------------
  15. static inline Vector ClosestPointOnAABB( const Vector &p, const Vector &e, const Vector &q )
  16. {
  17. // Offset vector from center of box to point q
  18. Vector dp = q - p;
  19. // Clamp offset vector to bounds extent
  20. dp = Clamp( dp, -e, e );
  21. // Return closest point
  22. return p + dp;
  23. }
  24. //--------------------------------------------------------------------------------------------------
  25. static inline AABB_t Merge( const AABB_t& bounds1, const AABB_t& bounds2 )
  26. {
  27. AABB_t out;
  28. out.m_vMinBounds = VectorMin( bounds1.m_vMinBounds, bounds2.m_vMinBounds );
  29. out.m_vMaxBounds = VectorMax( bounds1.m_vMaxBounds, bounds2.m_vMaxBounds );
  30. return out;
  31. }
  32. //-------------------------------------------------------------------------------------------------
  33. static inline bool Overlap( const AABB_t& bounds1, const AABB_t& bounds2 )
  34. {
  35. // No intersection if separated along one axis
  36. if ( bounds1.m_vMaxBounds.x < bounds2.m_vMinBounds.x || bounds1.m_vMinBounds.x > bounds2.m_vMaxBounds.x ) return false;
  37. if ( bounds1.m_vMaxBounds.y < bounds2.m_vMinBounds.y || bounds1.m_vMinBounds.y > bounds2.m_vMaxBounds.y ) return false;
  38. if ( bounds1.m_vMaxBounds.z < bounds2.m_vMinBounds.z || bounds1.m_vMinBounds.z > bounds2.m_vMaxBounds.z ) return false;
  39. // Overlapping on all axis means bounds are intersecting
  40. return true;
  41. }
  42. //-------------------------------------------------------------------------------------------------
  43. static inline bool Overlap( const AABB_t& bounds, const Vector& vCenter, float flRadius )
  44. {
  45. Vector vBoundsCenter = 0.5f * ( bounds.m_vMaxBounds + bounds.m_vMinBounds );
  46. Vector vBoundsExtent = 0.5f * ( bounds.m_vMaxBounds - bounds.m_vMinBounds );
  47. Vector vClosestPoint = ClosestPointOnAABB( vBoundsCenter, vBoundsExtent, vCenter );
  48. Vector vOffset = vClosestPoint - vCenter;
  49. return DotProduct( vOffset, vOffset ) <= flRadius * flRadius;
  50. }
  51. //--------------------------------------------------------------------------------------------------
  52. // Dynamic tree
  53. //--------------------------------------------------------------------------------------------------
  54. CDynamicTree::CDynamicTree()
  55. {
  56. m_nRoot = NULL_NODE;
  57. m_nProxyCount = 0;
  58. m_NodePool.Reserve( 32 );
  59. }
  60. //--------------------------------------------------------------------------------------------------
  61. int CDynamicTree::ProxyCount() const
  62. {
  63. return m_nProxyCount;
  64. }
  65. //--------------------------------------------------------------------------------------------------
  66. int32 CDynamicTree::CreateProxy( const AABB_t& bounds, void* pUserData )
  67. {
  68. m_nProxyCount++;
  69. // Allocate a new node and insert into the tree
  70. int32 nProxyId = m_NodePool.Alloc();
  71. m_NodePool[ nProxyId ].m_Bounds = bounds;
  72. m_NodePool[ nProxyId ].m_nParent = NULL_NODE;
  73. m_NodePool[ nProxyId ].m_nChild1 = NULL_NODE;
  74. m_NodePool[ nProxyId ].m_nChild2 = NULL_NODE;
  75. m_NodePool[ nProxyId ].m_nHeight = 0;
  76. m_NodePool[ nProxyId ].m_pUserData = pUserData;
  77. InsertLeaf( nProxyId );
  78. return nProxyId;
  79. }
  80. //--------------------------------------------------------------------------------------------------
  81. void* CDynamicTree::DestroyProxy( int32 nProxyId )
  82. {
  83. AssertDbg( m_NodePool[ nProxyId ].IsLeaf() );
  84. // Grab user data from the node to return it
  85. void* pUserData = m_NodePool[ nProxyId ].m_pUserData;
  86. // Remove node from tree and free it
  87. RemoveLeaf( nProxyId );
  88. m_NodePool.Free( nProxyId );
  89. m_nProxyCount--;
  90. return pUserData;
  91. }
  92. //--------------------------------------------------------------------------------------------------
  93. void CDynamicTree::MoveProxy( int32 nProxyId, const AABB_t& bounds )
  94. {
  95. AssertDbg ( m_NodePool[ nProxyId ].IsLeaf() );
  96. RemoveLeaf( nProxyId );
  97. // Save new bounds
  98. m_NodePool[ nProxyId ].m_Bounds = bounds;
  99. InsertLeaf( nProxyId );
  100. }
  101. //--------------------------------------------------------------------------------------------------
  102. void CDynamicTree::InsertLeaf( int32 nLeaf )
  103. {
  104. if ( m_nRoot == NULL_NODE )
  105. {
  106. m_nRoot = nLeaf;
  107. m_NodePool[ nLeaf ].m_nParent = NULL_NODE;
  108. return;
  109. }
  110. // Find the best sibling
  111. int32 nNode = m_nRoot;
  112. while ( !m_NodePool[ nNode ].IsLeaf() )
  113. {
  114. float flArea = m_NodePool[ nNode ].m_Bounds.GetSurfaceArea();
  115. AABB_t combined = Merge( m_NodePool[ nNode ].m_Bounds, m_NodePool[ nLeaf ].m_Bounds );
  116. float flCombinedArea = combined.GetSurfaceArea();
  117. // Cost of creating a new parent for this node and the new leaf
  118. float flCost = 2.0f * flCombinedArea;
  119. // Minimum cost of pushing the leaf further down the tree (we must inflate the parent if this leaf is not contained)
  120. float flInheritanceCost = 2.0f * ( flCombinedArea - flArea );
  121. // Cost of descending into first child
  122. int32 nChild1 = m_NodePool[ nNode ].m_nChild1;
  123. AABB_t combined1 = Merge( m_NodePool[ nChild1 ].m_Bounds, m_NodePool[ nLeaf ].m_Bounds );
  124. float flCost1 = combined1.GetSurfaceArea() + flInheritanceCost;
  125. if ( !m_NodePool[ nChild1 ].IsLeaf() )
  126. {
  127. flCost1 -= m_NodePool[ nChild1 ].m_Bounds.GetSurfaceArea();
  128. }
  129. // Cost of descending into second child
  130. int32 nChild2 = m_NodePool[ nNode ].m_nChild2;
  131. AABB_t combined2 = Merge( m_NodePool[ nChild2 ].m_Bounds, m_NodePool[ nLeaf ].m_Bounds );
  132. float flCost2 = combined2.GetSurfaceArea() + flInheritanceCost;
  133. if ( !m_NodePool[ nChild2 ].IsLeaf() )
  134. {
  135. flCost2 -= m_NodePool[ nChild2 ].m_Bounds.GetSurfaceArea();
  136. }
  137. // Break if creating a parent results in minimal cost
  138. if ( flCost < flCost1 && flCost < flCost2 )
  139. {
  140. break;
  141. }
  142. // Descend according to the minimum cost
  143. nNode = flCost1 < flCost2 ? nChild1 : nChild2;
  144. }
  145. // Create and insert new parent
  146. int32 nNewParent = m_NodePool.Alloc();
  147. m_NodePool[ nNewParent ].m_Bounds = Merge( m_NodePool[ nNode ].m_Bounds, m_NodePool[ nLeaf ].m_Bounds );
  148. m_NodePool[ nNewParent ].m_nParent = m_NodePool[ nNode ].m_nParent;
  149. m_NodePool[ nNewParent ].m_nChild1 = nNode;
  150. m_NodePool[ nNewParent ].m_nChild2 = nLeaf;
  151. m_NodePool[ nNewParent ].m_nHeight = m_NodePool[ nNode ].m_nHeight + 1;
  152. m_NodePool[ nNewParent ].m_pUserData = NULL;
  153. int32 nOldParent = m_NodePool[ nNode ].m_nParent;
  154. if ( nOldParent != NULL_NODE )
  155. {
  156. // We are not inserting at the root
  157. if ( m_NodePool[ nOldParent ].m_nChild1 == nNode )
  158. {
  159. m_NodePool[ nOldParent ].m_nChild1 = nNewParent;
  160. }
  161. else
  162. {
  163. m_NodePool[ nOldParent ].m_nChild2 = nNewParent;
  164. }
  165. }
  166. else
  167. {
  168. // Inserting at the root
  169. m_nRoot = nNewParent;
  170. }
  171. m_NodePool[ nNode ].m_nParent = nNewParent;
  172. m_NodePool[ nLeaf ].m_nParent = nNewParent;
  173. // Walk back up the tree and fix heights and AABBs
  174. AdjustAncestors( m_NodePool[ nLeaf ].m_nParent );
  175. }
  176. //--------------------------------------------------------------------------------------------------
  177. void CDynamicTree::RemoveLeaf( int32 nLeaf )
  178. {
  179. AssertDbg( m_NodePool[ nLeaf ].IsLeaf() );
  180. if ( nLeaf == m_nRoot )
  181. {
  182. m_nRoot = NULL_NODE;
  183. return;
  184. }
  185. int32 nParent = m_NodePool[ nLeaf ].m_nParent;
  186. int32 nSibling = NULL_NODE;
  187. if ( m_NodePool[ nParent ].m_nChild1 == nLeaf )
  188. {
  189. nSibling = m_NodePool[ nParent ].m_nChild2;
  190. }
  191. else
  192. {
  193. nSibling = m_NodePool[ nParent ].m_nChild1;
  194. }
  195. int nGrandParent = m_NodePool[ nParent ].m_nParent;
  196. if ( nGrandParent != NULL_NODE )
  197. {
  198. // Destroy parent and connect sibling to grandparent
  199. m_NodePool[ nSibling ].m_nParent = nGrandParent;
  200. if ( m_NodePool[ nGrandParent ].m_nChild1 == nParent )
  201. {
  202. m_NodePool[ nGrandParent ].m_nChild1 = nSibling;
  203. }
  204. else
  205. {
  206. m_NodePool[ nGrandParent ].m_nChild2 = nSibling;
  207. }
  208. // Walk back up the tree and fix heights and AABBs
  209. AdjustAncestors( nGrandParent );
  210. }
  211. else
  212. {
  213. m_NodePool[ nSibling ].m_nParent = NULL_NODE;
  214. m_nRoot = nSibling;
  215. }
  216. m_NodePool.Free( nParent );
  217. }
  218. //--------------------------------------------------------------------------------------------------
  219. void CDynamicTree::AdjustAncestors( int32 nNode )
  220. {
  221. while ( nNode != NULL_NODE )
  222. {
  223. nNode = Balance( nNode );
  224. int32 nChild1 = m_NodePool[ nNode ].m_nChild1;
  225. AssertDbg( nChild1 != NULL_NODE );
  226. int32 nChild2 = m_NodePool[ nNode ].m_nChild2;
  227. AssertDbg( nChild2 != NULL_NODE );
  228. m_NodePool[ nNode ].m_nHeight = 1 + MAX( m_NodePool[ nChild1 ].m_nHeight, m_NodePool[ nChild2 ].m_nHeight );
  229. m_NodePool[ nNode ].m_Bounds = Merge( m_NodePool[ nChild1 ].m_Bounds, m_NodePool[ nChild2 ].m_Bounds );
  230. nNode = m_NodePool[ nNode ].m_nParent;
  231. }
  232. }
  233. //--------------------------------------------------------------------------------------------------
  234. int32 CDynamicTree::Balance( int32 nNode )
  235. {
  236. int32 nIndexA = nNode;
  237. Node_t& A = m_NodePool[ nIndexA ];
  238. if ( A.IsLeaf() || A.m_nHeight < 2 )
  239. {
  240. return nNode;
  241. }
  242. int32 nIndexB = A.m_nChild1;
  243. int32 nIndexC = A.m_nChild2;
  244. Node_t& B = m_NodePool[ nIndexB ];
  245. Node_t& C = m_NodePool[ nIndexC ];
  246. int nBalance = C.m_nHeight - B.m_nHeight;
  247. // Rotate C up (left rotation)
  248. if ( nBalance > 1 )
  249. {
  250. int32 nIndexF = C.m_nChild1;
  251. int32 nIndexG = C.m_nChild2;
  252. Node_t& F = m_NodePool[ nIndexF ];
  253. Node_t& G = m_NodePool[ nIndexG ];
  254. // Swap A and C
  255. C.m_nChild1 = nIndexA;
  256. C.m_nParent = A.m_nParent;
  257. A.m_nParent = nIndexC;
  258. // A's old parent should point to C
  259. if ( C.m_nParent != NULL_NODE )
  260. {
  261. if ( m_NodePool[ C.m_nParent ].m_nChild1 == nIndexA )
  262. {
  263. m_NodePool[ C.m_nParent ].m_nChild1 = nIndexC;
  264. }
  265. else
  266. {
  267. AssertDbg( m_NodePool[ C.m_nParent ].m_nChild2 == nIndexA );
  268. m_NodePool[ C.m_nParent ].m_nChild2 = nIndexC;
  269. }
  270. }
  271. else
  272. {
  273. m_nRoot = nIndexC;
  274. }
  275. // Rotate
  276. if ( F.m_nHeight > G.m_nHeight )
  277. {
  278. G.m_nParent = nIndexA;
  279. C.m_nChild2 = nIndexF;
  280. A.m_nChild2 = nIndexG;
  281. A.m_Bounds = Merge( B.m_Bounds, G.m_Bounds );
  282. C.m_Bounds = Merge( A.m_Bounds, F.m_Bounds );
  283. A.m_nHeight = 1 + MAX( B.m_nHeight, G.m_nHeight );
  284. C.m_nHeight = 1 + MAX( A.m_nHeight, F.m_nHeight );
  285. }
  286. else
  287. {
  288. F.m_nParent = nIndexA;
  289. C.m_nChild2 = nIndexG;
  290. A.m_nChild2 = nIndexF;
  291. A.m_Bounds = Merge( B.m_Bounds, F.m_Bounds );
  292. C.m_Bounds = Merge( A.m_Bounds, G.m_Bounds );
  293. A.m_nHeight = 1 + MAX( B.m_nHeight, F.m_nHeight );
  294. C.m_nHeight = 1 + MAX( A.m_nHeight, G.m_nHeight );
  295. }
  296. return nIndexC;
  297. }
  298. // Rotate B up (right rotation)
  299. if ( nBalance < -1 )
  300. {
  301. int32 nIndexD = B.m_nChild1;
  302. int32 nIndexE = B.m_nChild2;
  303. Node_t& D = m_NodePool[ nIndexD ];
  304. Node_t& E = m_NodePool[ nIndexE ];
  305. // Swap A and B
  306. B.m_nChild1 = nIndexA;
  307. B.m_nParent = A.m_nParent;
  308. A.m_nParent = nIndexB;
  309. // A's old parent should point to B
  310. if ( B.m_nParent != NULL_NODE )
  311. {
  312. if ( m_NodePool[ B.m_nParent ].m_nChild1 == nIndexA )
  313. {
  314. m_NodePool[ B.m_nParent ].m_nChild1 = nIndexB;
  315. }
  316. else
  317. {
  318. AssertDbg( m_NodePool[ B.m_nParent ].m_nChild2 == nIndexA );
  319. m_NodePool[ B.m_nParent ].m_nChild2 = nIndexB;
  320. }
  321. }
  322. else
  323. {
  324. m_nRoot = nIndexB;
  325. }
  326. // Rotate
  327. if ( D.m_nHeight > E.m_nHeight )
  328. {
  329. E.m_nParent = nIndexA;
  330. A.m_nChild1 = nIndexE;
  331. B.m_nChild2 = nIndexD;
  332. A.m_Bounds = Merge( C.m_Bounds, E.m_Bounds );
  333. B.m_Bounds = Merge( A.m_Bounds, D.m_Bounds );
  334. A.m_nHeight = 1 + MAX( C.m_nHeight, E.m_nHeight );
  335. B.m_nHeight = 1 + MAX( A.m_nHeight, D.m_nHeight );
  336. }
  337. else
  338. {
  339. D.m_nParent = nIndexA;
  340. A.m_nChild1 = nIndexD;
  341. B.m_nChild2 = nIndexE;
  342. A.m_Bounds = Merge( C.m_Bounds, D.m_Bounds );
  343. B.m_Bounds = Merge( A.m_Bounds, E.m_Bounds );
  344. A.m_nHeight = 1 + MAX( C.m_nHeight, D.m_nHeight );
  345. B.m_nHeight = 1 + MAX( A.m_nHeight, E.m_nHeight );
  346. }
  347. return nIndexB;
  348. }
  349. return nIndexA;
  350. }
  351. //--------------------------------------------------------------------------------------------------
  352. void CDynamicTree::Query( CProxyVector& proxies, const AABB_t& bounds ) const
  353. {
  354. if ( m_nRoot == NULL_NODE )
  355. {
  356. return;
  357. }
  358. int nCount = 0;
  359. int32 stack[ STACK_DEPTH ];
  360. stack[ nCount++ ] = m_nRoot;
  361. while ( nCount > 0 )
  362. {
  363. int32 nNode = stack[ --nCount ];
  364. const Node_t& node = m_NodePool[ nNode ];
  365. if ( Overlap( node.m_Bounds, bounds ) )
  366. {
  367. if ( !node.IsLeaf() )
  368. {
  369. AssertDbg( nCount + 2 <= STACK_DEPTH );
  370. stack[ nCount++ ] = node.m_nChild2;
  371. stack[ nCount++ ] = node.m_nChild1;
  372. }
  373. else
  374. {
  375. proxies.AddToTail( nNode );
  376. }
  377. }
  378. }
  379. }
  380. //--------------------------------------------------------------------------------------------------
  381. void CDynamicTree::Query( CProxyVector& proxies, const Vector& vCenter, float flRadius ) const
  382. {
  383. if ( m_nRoot == NULL_NODE )
  384. {
  385. return;
  386. }
  387. int nCount = 0;
  388. int32 stack[ STACK_DEPTH ];
  389. stack[ nCount++ ] = m_nRoot;
  390. while ( nCount > 0 )
  391. {
  392. int32 nNode = stack[ --nCount ];
  393. const Node_t& node = m_NodePool[ nNode ];
  394. if ( Overlap( node.m_Bounds, vCenter, flRadius ) )
  395. {
  396. if ( !node.IsLeaf() )
  397. {
  398. AssertDbg( nCount + 2 <= STACK_DEPTH );
  399. stack[ nCount++ ] = node.m_nChild2;
  400. stack[ nCount++ ] = node.m_nChild1;
  401. }
  402. else
  403. {
  404. proxies.AddToTail( nNode );
  405. }
  406. }
  407. }
  408. }
  409. //--------------------------------------------------------------------------------------------------
  410. float CDynamicTree::ClosestProxies( CProxyVector& proxies, const Vector &vQuery ) const
  411. {
  412. if ( m_nRoot == NULL_NODE )
  413. {
  414. return FLT_MAX;
  415. }
  416. int nCount = 0;
  417. int32 stack[ STACK_DEPTH ];
  418. stack[ nCount++ ] = m_nRoot;
  419. float bestDistance = FLT_MAX;
  420. while ( nCount > 0 )
  421. {
  422. int32 nNode = stack[ --nCount ];
  423. const Node_t& node = m_NodePool[ nNode ];
  424. float dist = node.m_Bounds.GetMinDistToPoint( vQuery );
  425. if ( dist <= bestDistance )
  426. {
  427. if ( !node.IsLeaf() )
  428. {
  429. AssertDbg( nCount + 2 <= STACK_DEPTH );
  430. stack[ nCount++ ] = node.m_nChild2;
  431. stack[ nCount++ ] = node.m_nChild1;
  432. }
  433. else
  434. {
  435. bestDistance = dist;
  436. proxies.AddToTail( nNode );
  437. }
  438. }
  439. }
  440. // We now have a collection of indices that -- at the time they
  441. // were added -- pointed to the closest proxies. However, as
  442. // 'bestDistance' is updated during processing, this may no longer
  443. // be true. So we do one last scan of all the "best" proxies to
  444. // find the true closest ones
  445. CProxyVector closestProxies;
  446. const uint32 numCandidates = proxies.Count();
  447. for (uint32 ii=0; ii<numCandidates; ++ii)
  448. if ( m_NodePool[ proxies[ii] ].m_Bounds.GetMinDistToPoint( vQuery ) <= bestDistance )
  449. closestProxies.AddToTail( proxies[ii] );
  450. proxies = closestProxies;
  451. return bestDistance;
  452. }
  453. //--------------------------------------------------------------------------------------------------
  454. // Node pool
  455. //--------------------------------------------------------------------------------------------------
  456. CDynamicTree::CNodePool::CNodePool()
  457. {
  458. m_nCapacity = 0;
  459. m_pObjects = NULL;
  460. m_nNext = - 1;
  461. }
  462. //--------------------------------------------------------------------------------------------------
  463. CDynamicTree::CNodePool::~CNodePool()
  464. {
  465. delete m_pObjects;
  466. }
  467. //--------------------------------------------------------------------------------------------------
  468. void CDynamicTree::CNodePool::Clear()
  469. {
  470. delete m_pObjects;
  471. m_nCapacity = 0;
  472. m_pObjects = NULL;
  473. m_nNext = - 1;
  474. }
  475. //--------------------------------------------------------------------------------------------------
  476. void CDynamicTree::CNodePool::Reserve( int nCapacity )
  477. {
  478. if ( nCapacity > m_nCapacity )
  479. {
  480. Node_t* pObjects = m_pObjects;
  481. m_pObjects = new Node_t[ nCapacity ];
  482. V_memcpy( m_pObjects, pObjects, m_nCapacity * sizeof( Node_t ) );
  483. delete pObjects;
  484. pObjects = NULL;
  485. for ( int32 i = m_nCapacity; i < nCapacity - 1; ++i )
  486. {
  487. int32* nNext = (int32*)( m_pObjects + i );
  488. *nNext = i + 1;
  489. }
  490. int32* nNext = (int32*)( m_pObjects + nCapacity - 1 );
  491. *nNext = -1;
  492. m_nNext = m_nCapacity;
  493. m_nCapacity = nCapacity;
  494. }
  495. }
  496. //--------------------------------------------------------------------------------------------------
  497. int32 CDynamicTree::CNodePool::Alloc()
  498. {
  499. // Grow the pool if the free list is empty
  500. if ( m_nNext < 0 )
  501. {
  502. Reserve( MAX( 2, 2 * m_nCapacity ) );
  503. }
  504. // Peel of a node from the free list
  505. int32 id = m_nNext;
  506. m_nNext = *(int32*)( m_pObjects + id );
  507. #if _DEBUG
  508. // Do reuse old objects accidentally
  509. V_memset( m_pObjects + id, 0xcd, sizeof( Node_t ) );
  510. #endif
  511. return id;
  512. }
  513. //--------------------------------------------------------------------------------------------------
  514. void CDynamicTree::CNodePool::Free( int32 id )
  515. {
  516. // Return node to the pool
  517. AssertDbg( 0 <= id && id < m_nCapacity );
  518. *(int32*)( m_pObjects + id ) = m_nNext;
  519. m_nNext = id;
  520. }