b3DynamicBvhBroadphase.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808
  1. /*
  2. Bullet Continuous Collision Detection and Physics Library
  3. Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org
  4. This software is provided 'as-is', without any express or implied warranty.
  5. In no event will the authors be held liable for any damages arising from the use of this software.
  6. Permission is granted to anyone to use this software for any purpose,
  7. including commercial applications, and to alter it and redistribute it freely,
  8. subject to the following restrictions:
  9. 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
  10. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
  11. 3. This notice may not be removed or altered from any source distribution.
  12. */
  13. ///b3DynamicBvhBroadphase implementation by Nathanael Presson
  14. #include "b3DynamicBvhBroadphase.h"
  15. #include "b3OverlappingPair.h"
  16. //
  17. // Profiling
  18. //
  19. #if B3_DBVT_BP_PROFILE || B3_DBVT_BP_ENABLE_BENCHMARK
  20. #include <stdio.h>
  21. #endif
  22. #if B3_DBVT_BP_PROFILE
  23. struct b3ProfileScope
  24. {
  25. __forceinline b3ProfileScope(b3Clock& clock, unsigned long& value) : m_clock(&clock), m_value(&value), m_base(clock.getTimeMicroseconds())
  26. {
  27. }
  28. __forceinline ~b3ProfileScope()
  29. {
  30. (*m_value) += m_clock->getTimeMicroseconds() - m_base;
  31. }
  32. b3Clock* m_clock;
  33. unsigned long* m_value;
  34. unsigned long m_base;
  35. };
  36. #define b3SPC(_value_) b3ProfileScope spc_scope(m_clock, _value_)
  37. #else
  38. #define b3SPC(_value_)
  39. #endif
  40. //
  41. // Helpers
  42. //
  43. //
  44. template <typename T>
  45. static inline void b3ListAppend(T* item, T*& list)
  46. {
  47. item->links[0] = 0;
  48. item->links[1] = list;
  49. if (list) list->links[0] = item;
  50. list = item;
  51. }
  52. //
  53. template <typename T>
  54. static inline void b3ListRemove(T* item, T*& list)
  55. {
  56. if (item->links[0])
  57. item->links[0]->links[1] = item->links[1];
  58. else
  59. list = item->links[1];
  60. if (item->links[1]) item->links[1]->links[0] = item->links[0];
  61. }
  62. //
  63. template <typename T>
  64. static inline int b3ListCount(T* root)
  65. {
  66. int n = 0;
  67. while (root)
  68. {
  69. ++n;
  70. root = root->links[1];
  71. }
  72. return (n);
  73. }
  74. //
  75. template <typename T>
  76. static inline void b3Clear(T& value)
  77. {
  78. static const struct ZeroDummy : T
  79. {
  80. } zerodummy;
  81. value = zerodummy;
  82. }
  83. //
  84. // Colliders
  85. //
  86. /* Tree collider */
  87. struct b3DbvtTreeCollider : b3DynamicBvh::ICollide
  88. {
  89. b3DynamicBvhBroadphase* pbp;
  90. b3DbvtProxy* proxy;
  91. b3DbvtTreeCollider(b3DynamicBvhBroadphase* p) : pbp(p) {}
  92. void Process(const b3DbvtNode* na, const b3DbvtNode* nb)
  93. {
  94. if (na != nb)
  95. {
  96. b3DbvtProxy* pa = (b3DbvtProxy*)na->data;
  97. b3DbvtProxy* pb = (b3DbvtProxy*)nb->data;
  98. #if B3_DBVT_BP_SORTPAIRS
  99. if (pa->m_uniqueId > pb->m_uniqueId)
  100. b3Swap(pa, pb);
  101. #endif
  102. pbp->m_paircache->addOverlappingPair(pa->getUid(), pb->getUid());
  103. ++pbp->m_newpairs;
  104. }
  105. }
  106. void Process(const b3DbvtNode* n)
  107. {
  108. Process(n, proxy->leaf);
  109. }
  110. };
  111. //
  112. // b3DynamicBvhBroadphase
  113. //
  114. //
  115. b3DynamicBvhBroadphase::b3DynamicBvhBroadphase(int proxyCapacity, b3OverlappingPairCache* paircache)
  116. {
  117. m_deferedcollide = false;
  118. m_needcleanup = true;
  119. m_releasepaircache = (paircache != 0) ? false : true;
  120. m_prediction = 0;
  121. m_stageCurrent = 0;
  122. m_fixedleft = 0;
  123. m_fupdates = 1;
  124. m_dupdates = 0;
  125. m_cupdates = 10;
  126. m_newpairs = 1;
  127. m_updates_call = 0;
  128. m_updates_done = 0;
  129. m_updates_ratio = 0;
  130. m_paircache = paircache ? paircache : new (b3AlignedAlloc(sizeof(b3HashedOverlappingPairCache), 16)) b3HashedOverlappingPairCache();
  131. m_pid = 0;
  132. m_cid = 0;
  133. for (int i = 0; i <= STAGECOUNT; ++i)
  134. {
  135. m_stageRoots[i] = 0;
  136. }
  137. #if B3_DBVT_BP_PROFILE
  138. b3Clear(m_profiling);
  139. #endif
  140. m_proxies.resize(proxyCapacity);
  141. }
  142. //
  143. b3DynamicBvhBroadphase::~b3DynamicBvhBroadphase()
  144. {
  145. if (m_releasepaircache)
  146. {
  147. m_paircache->~b3OverlappingPairCache();
  148. b3AlignedFree(m_paircache);
  149. }
  150. }
  151. //
  152. b3BroadphaseProxy* b3DynamicBvhBroadphase::createProxy(const b3Vector3& aabbMin,
  153. const b3Vector3& aabbMax,
  154. int objectId,
  155. void* userPtr,
  156. int collisionFilterGroup,
  157. int collisionFilterMask)
  158. {
  159. b3DbvtProxy* mem = &m_proxies[objectId];
  160. b3DbvtProxy* proxy = new (mem) b3DbvtProxy(aabbMin, aabbMax, userPtr,
  161. collisionFilterGroup,
  162. collisionFilterMask);
  163. b3DbvtAabbMm aabb = b3DbvtVolume::FromMM(aabbMin, aabbMax);
  164. //bproxy->aabb = b3DbvtVolume::FromMM(aabbMin,aabbMax);
  165. proxy->stage = m_stageCurrent;
  166. proxy->m_uniqueId = objectId;
  167. proxy->leaf = m_sets[0].insert(aabb, proxy);
  168. b3ListAppend(proxy, m_stageRoots[m_stageCurrent]);
  169. if (!m_deferedcollide)
  170. {
  171. b3DbvtTreeCollider collider(this);
  172. collider.proxy = proxy;
  173. m_sets[0].collideTV(m_sets[0].m_root, aabb, collider);
  174. m_sets[1].collideTV(m_sets[1].m_root, aabb, collider);
  175. }
  176. return (proxy);
  177. }
  178. //
  179. void b3DynamicBvhBroadphase::destroyProxy(b3BroadphaseProxy* absproxy,
  180. b3Dispatcher* dispatcher)
  181. {
  182. b3DbvtProxy* proxy = (b3DbvtProxy*)absproxy;
  183. if (proxy->stage == STAGECOUNT)
  184. m_sets[1].remove(proxy->leaf);
  185. else
  186. m_sets[0].remove(proxy->leaf);
  187. b3ListRemove(proxy, m_stageRoots[proxy->stage]);
  188. m_paircache->removeOverlappingPairsContainingProxy(proxy->getUid(), dispatcher);
  189. m_needcleanup = true;
  190. }
  191. void b3DynamicBvhBroadphase::getAabb(int objectId, b3Vector3& aabbMin, b3Vector3& aabbMax) const
  192. {
  193. const b3DbvtProxy* proxy = &m_proxies[objectId];
  194. aabbMin = proxy->m_aabbMin;
  195. aabbMax = proxy->m_aabbMax;
  196. }
  197. /*
  198. void b3DynamicBvhBroadphase::getAabb(b3BroadphaseProxy* absproxy,b3Vector3& aabbMin, b3Vector3& aabbMax ) const
  199. {
  200. b3DbvtProxy* proxy=(b3DbvtProxy*)absproxy;
  201. aabbMin = proxy->m_aabbMin;
  202. aabbMax = proxy->m_aabbMax;
  203. }
  204. */
  205. struct BroadphaseRayTester : b3DynamicBvh::ICollide
  206. {
  207. b3BroadphaseRayCallback& m_rayCallback;
  208. BroadphaseRayTester(b3BroadphaseRayCallback& orgCallback)
  209. : m_rayCallback(orgCallback)
  210. {
  211. }
  212. void Process(const b3DbvtNode* leaf)
  213. {
  214. b3DbvtProxy* proxy = (b3DbvtProxy*)leaf->data;
  215. m_rayCallback.process(proxy);
  216. }
  217. };
  218. void b3DynamicBvhBroadphase::rayTest(const b3Vector3& rayFrom, const b3Vector3& rayTo, b3BroadphaseRayCallback& rayCallback, const b3Vector3& aabbMin, const b3Vector3& aabbMax)
  219. {
  220. BroadphaseRayTester callback(rayCallback);
  221. m_sets[0].rayTestInternal(m_sets[0].m_root,
  222. rayFrom,
  223. rayTo,
  224. rayCallback.m_rayDirectionInverse,
  225. rayCallback.m_signs,
  226. rayCallback.m_lambda_max,
  227. aabbMin,
  228. aabbMax,
  229. callback);
  230. m_sets[1].rayTestInternal(m_sets[1].m_root,
  231. rayFrom,
  232. rayTo,
  233. rayCallback.m_rayDirectionInverse,
  234. rayCallback.m_signs,
  235. rayCallback.m_lambda_max,
  236. aabbMin,
  237. aabbMax,
  238. callback);
  239. }
  240. struct BroadphaseAabbTester : b3DynamicBvh::ICollide
  241. {
  242. b3BroadphaseAabbCallback& m_aabbCallback;
  243. BroadphaseAabbTester(b3BroadphaseAabbCallback& orgCallback)
  244. : m_aabbCallback(orgCallback)
  245. {
  246. }
  247. void Process(const b3DbvtNode* leaf)
  248. {
  249. b3DbvtProxy* proxy = (b3DbvtProxy*)leaf->data;
  250. m_aabbCallback.process(proxy);
  251. }
  252. };
  253. void b3DynamicBvhBroadphase::aabbTest(const b3Vector3& aabbMin, const b3Vector3& aabbMax, b3BroadphaseAabbCallback& aabbCallback)
  254. {
  255. BroadphaseAabbTester callback(aabbCallback);
  256. const B3_ATTRIBUTE_ALIGNED16(b3DbvtVolume) bounds = b3DbvtVolume::FromMM(aabbMin, aabbMax);
  257. //process all children, that overlap with the given AABB bounds
  258. m_sets[0].collideTV(m_sets[0].m_root, bounds, callback);
  259. m_sets[1].collideTV(m_sets[1].m_root, bounds, callback);
  260. }
  261. //
  262. void b3DynamicBvhBroadphase::setAabb(int objectId,
  263. const b3Vector3& aabbMin,
  264. const b3Vector3& aabbMax,
  265. b3Dispatcher* /*dispatcher*/)
  266. {
  267. b3DbvtProxy* proxy = &m_proxies[objectId];
  268. // b3DbvtProxy* proxy=(b3DbvtProxy*)absproxy;
  269. B3_ATTRIBUTE_ALIGNED16(b3DbvtVolume)
  270. aabb = b3DbvtVolume::FromMM(aabbMin, aabbMax);
  271. #if B3_DBVT_BP_PREVENTFALSEUPDATE
  272. if (b3NotEqual(aabb, proxy->leaf->volume))
  273. #endif
  274. {
  275. bool docollide = false;
  276. if (proxy->stage == STAGECOUNT)
  277. { /* fixed -> dynamic set */
  278. m_sets[1].remove(proxy->leaf);
  279. proxy->leaf = m_sets[0].insert(aabb, proxy);
  280. docollide = true;
  281. }
  282. else
  283. { /* dynamic set */
  284. ++m_updates_call;
  285. if (b3Intersect(proxy->leaf->volume, aabb))
  286. { /* Moving */
  287. const b3Vector3 delta = aabbMin - proxy->m_aabbMin;
  288. b3Vector3 velocity(((proxy->m_aabbMax - proxy->m_aabbMin) / 2) * m_prediction);
  289. if (delta[0] < 0) velocity[0] = -velocity[0];
  290. if (delta[1] < 0) velocity[1] = -velocity[1];
  291. if (delta[2] < 0) velocity[2] = -velocity[2];
  292. if (
  293. #ifdef B3_DBVT_BP_MARGIN
  294. m_sets[0].update(proxy->leaf, aabb, velocity, B3_DBVT_BP_MARGIN)
  295. #else
  296. m_sets[0].update(proxy->leaf, aabb, velocity)
  297. #endif
  298. )
  299. {
  300. ++m_updates_done;
  301. docollide = true;
  302. }
  303. }
  304. else
  305. { /* Teleporting */
  306. m_sets[0].update(proxy->leaf, aabb);
  307. ++m_updates_done;
  308. docollide = true;
  309. }
  310. }
  311. b3ListRemove(proxy, m_stageRoots[proxy->stage]);
  312. proxy->m_aabbMin = aabbMin;
  313. proxy->m_aabbMax = aabbMax;
  314. proxy->stage = m_stageCurrent;
  315. b3ListAppend(proxy, m_stageRoots[m_stageCurrent]);
  316. if (docollide)
  317. {
  318. m_needcleanup = true;
  319. if (!m_deferedcollide)
  320. {
  321. b3DbvtTreeCollider collider(this);
  322. m_sets[1].collideTTpersistentStack(m_sets[1].m_root, proxy->leaf, collider);
  323. m_sets[0].collideTTpersistentStack(m_sets[0].m_root, proxy->leaf, collider);
  324. }
  325. }
  326. }
  327. }
  328. //
  329. void b3DynamicBvhBroadphase::setAabbForceUpdate(b3BroadphaseProxy* absproxy,
  330. const b3Vector3& aabbMin,
  331. const b3Vector3& aabbMax,
  332. b3Dispatcher* /*dispatcher*/)
  333. {
  334. b3DbvtProxy* proxy = (b3DbvtProxy*)absproxy;
  335. B3_ATTRIBUTE_ALIGNED16(b3DbvtVolume)
  336. aabb = b3DbvtVolume::FromMM(aabbMin, aabbMax);
  337. bool docollide = false;
  338. if (proxy->stage == STAGECOUNT)
  339. { /* fixed -> dynamic set */
  340. m_sets[1].remove(proxy->leaf);
  341. proxy->leaf = m_sets[0].insert(aabb, proxy);
  342. docollide = true;
  343. }
  344. else
  345. { /* dynamic set */
  346. ++m_updates_call;
  347. /* Teleporting */
  348. m_sets[0].update(proxy->leaf, aabb);
  349. ++m_updates_done;
  350. docollide = true;
  351. }
  352. b3ListRemove(proxy, m_stageRoots[proxy->stage]);
  353. proxy->m_aabbMin = aabbMin;
  354. proxy->m_aabbMax = aabbMax;
  355. proxy->stage = m_stageCurrent;
  356. b3ListAppend(proxy, m_stageRoots[m_stageCurrent]);
  357. if (docollide)
  358. {
  359. m_needcleanup = true;
  360. if (!m_deferedcollide)
  361. {
  362. b3DbvtTreeCollider collider(this);
  363. m_sets[1].collideTTpersistentStack(m_sets[1].m_root, proxy->leaf, collider);
  364. m_sets[0].collideTTpersistentStack(m_sets[0].m_root, proxy->leaf, collider);
  365. }
  366. }
  367. }
  368. //
  369. void b3DynamicBvhBroadphase::calculateOverlappingPairs(b3Dispatcher* dispatcher)
  370. {
  371. collide(dispatcher);
  372. #if B3_DBVT_BP_PROFILE
  373. if (0 == (m_pid % B3_DBVT_BP_PROFILING_RATE))
  374. {
  375. printf("fixed(%u) dynamics(%u) pairs(%u)\r\n", m_sets[1].m_leaves, m_sets[0].m_leaves, m_paircache->getNumOverlappingPairs());
  376. unsigned int total = m_profiling.m_total;
  377. if (total <= 0) total = 1;
  378. printf("ddcollide: %u%% (%uus)\r\n", (50 + m_profiling.m_ddcollide * 100) / total, m_profiling.m_ddcollide / B3_DBVT_BP_PROFILING_RATE);
  379. printf("fdcollide: %u%% (%uus)\r\n", (50 + m_profiling.m_fdcollide * 100) / total, m_profiling.m_fdcollide / B3_DBVT_BP_PROFILING_RATE);
  380. printf("cleanup: %u%% (%uus)\r\n", (50 + m_profiling.m_cleanup * 100) / total, m_profiling.m_cleanup / B3_DBVT_BP_PROFILING_RATE);
  381. printf("total: %uus\r\n", total / B3_DBVT_BP_PROFILING_RATE);
  382. const unsigned long sum = m_profiling.m_ddcollide +
  383. m_profiling.m_fdcollide +
  384. m_profiling.m_cleanup;
  385. printf("leaked: %u%% (%uus)\r\n", 100 - ((50 + sum * 100) / total), (total - sum) / B3_DBVT_BP_PROFILING_RATE);
  386. printf("job counts: %u%%\r\n", (m_profiling.m_jobcount * 100) / ((m_sets[0].m_leaves + m_sets[1].m_leaves) * B3_DBVT_BP_PROFILING_RATE));
  387. b3Clear(m_profiling);
  388. m_clock.reset();
  389. }
  390. #endif
  391. performDeferredRemoval(dispatcher);
  392. }
  393. void b3DynamicBvhBroadphase::performDeferredRemoval(b3Dispatcher* dispatcher)
  394. {
  395. if (m_paircache->hasDeferredRemoval())
  396. {
  397. b3BroadphasePairArray& overlappingPairArray = m_paircache->getOverlappingPairArray();
  398. //perform a sort, to find duplicates and to sort 'invalid' pairs to the end
  399. overlappingPairArray.quickSort(b3BroadphasePairSortPredicate());
  400. int invalidPair = 0;
  401. int i;
  402. b3BroadphasePair previousPair = b3MakeBroadphasePair(-1, -1);
  403. for (i = 0; i < overlappingPairArray.size(); i++)
  404. {
  405. b3BroadphasePair& pair = overlappingPairArray[i];
  406. bool isDuplicate = (pair == previousPair);
  407. previousPair = pair;
  408. bool needsRemoval = false;
  409. if (!isDuplicate)
  410. {
  411. //important to perform AABB check that is consistent with the broadphase
  412. b3DbvtProxy* pa = &m_proxies[pair.x];
  413. b3DbvtProxy* pb = &m_proxies[pair.y];
  414. bool hasOverlap = b3Intersect(pa->leaf->volume, pb->leaf->volume);
  415. if (hasOverlap)
  416. {
  417. needsRemoval = false;
  418. }
  419. else
  420. {
  421. needsRemoval = true;
  422. }
  423. }
  424. else
  425. {
  426. //remove duplicate
  427. needsRemoval = true;
  428. //should have no algorithm
  429. }
  430. if (needsRemoval)
  431. {
  432. m_paircache->cleanOverlappingPair(pair, dispatcher);
  433. pair.x = -1;
  434. pair.y = -1;
  435. invalidPair++;
  436. }
  437. }
  438. //perform a sort, to sort 'invalid' pairs to the end
  439. overlappingPairArray.quickSort(b3BroadphasePairSortPredicate());
  440. overlappingPairArray.resize(overlappingPairArray.size() - invalidPair);
  441. }
  442. }
  443. //
  444. void b3DynamicBvhBroadphase::collide(b3Dispatcher* dispatcher)
  445. {
  446. /*printf("---------------------------------------------------------\n");
  447. printf("m_sets[0].m_leaves=%d\n",m_sets[0].m_leaves);
  448. printf("m_sets[1].m_leaves=%d\n",m_sets[1].m_leaves);
  449. printf("numPairs = %d\n",getOverlappingPairCache()->getNumOverlappingPairs());
  450. {
  451. int i;
  452. for (i=0;i<getOverlappingPairCache()->getNumOverlappingPairs();i++)
  453. {
  454. printf("pair[%d]=(%d,%d),",i,getOverlappingPairCache()->getOverlappingPairArray()[i].m_pProxy0->getUid(),
  455. getOverlappingPairCache()->getOverlappingPairArray()[i].m_pProxy1->getUid());
  456. }
  457. printf("\n");
  458. }
  459. */
  460. b3SPC(m_profiling.m_total);
  461. /* optimize */
  462. m_sets[0].optimizeIncremental(1 + (m_sets[0].m_leaves * m_dupdates) / 100);
  463. if (m_fixedleft)
  464. {
  465. const int count = 1 + (m_sets[1].m_leaves * m_fupdates) / 100;
  466. m_sets[1].optimizeIncremental(1 + (m_sets[1].m_leaves * m_fupdates) / 100);
  467. m_fixedleft = b3Max<int>(0, m_fixedleft - count);
  468. }
  469. /* dynamic -> fixed set */
  470. m_stageCurrent = (m_stageCurrent + 1) % STAGECOUNT;
  471. b3DbvtProxy* current = m_stageRoots[m_stageCurrent];
  472. if (current)
  473. {
  474. b3DbvtTreeCollider collider(this);
  475. do
  476. {
  477. b3DbvtProxy* next = current->links[1];
  478. b3ListRemove(current, m_stageRoots[current->stage]);
  479. b3ListAppend(current, m_stageRoots[STAGECOUNT]);
  480. #if B3_DBVT_BP_ACCURATESLEEPING
  481. m_paircache->removeOverlappingPairsContainingProxy(current, dispatcher);
  482. collider.proxy = current;
  483. b3DynamicBvh::collideTV(m_sets[0].m_root, current->aabb, collider);
  484. b3DynamicBvh::collideTV(m_sets[1].m_root, current->aabb, collider);
  485. #endif
  486. m_sets[0].remove(current->leaf);
  487. B3_ATTRIBUTE_ALIGNED16(b3DbvtVolume)
  488. curAabb = b3DbvtVolume::FromMM(current->m_aabbMin, current->m_aabbMax);
  489. current->leaf = m_sets[1].insert(curAabb, current);
  490. current->stage = STAGECOUNT;
  491. current = next;
  492. } while (current);
  493. m_fixedleft = m_sets[1].m_leaves;
  494. m_needcleanup = true;
  495. }
  496. /* collide dynamics */
  497. {
  498. b3DbvtTreeCollider collider(this);
  499. if (m_deferedcollide)
  500. {
  501. b3SPC(m_profiling.m_fdcollide);
  502. m_sets[0].collideTTpersistentStack(m_sets[0].m_root, m_sets[1].m_root, collider);
  503. }
  504. if (m_deferedcollide)
  505. {
  506. b3SPC(m_profiling.m_ddcollide);
  507. m_sets[0].collideTTpersistentStack(m_sets[0].m_root, m_sets[0].m_root, collider);
  508. }
  509. }
  510. /* clean up */
  511. if (m_needcleanup)
  512. {
  513. b3SPC(m_profiling.m_cleanup);
  514. b3BroadphasePairArray& pairs = m_paircache->getOverlappingPairArray();
  515. if (pairs.size() > 0)
  516. {
  517. int ni = b3Min(pairs.size(), b3Max<int>(m_newpairs, (pairs.size() * m_cupdates) / 100));
  518. for (int i = 0; i < ni; ++i)
  519. {
  520. b3BroadphasePair& p = pairs[(m_cid + i) % pairs.size()];
  521. b3DbvtProxy* pa = &m_proxies[p.x];
  522. b3DbvtProxy* pb = &m_proxies[p.y];
  523. if (!b3Intersect(pa->leaf->volume, pb->leaf->volume))
  524. {
  525. #if B3_DBVT_BP_SORTPAIRS
  526. if (pa->m_uniqueId > pb->m_uniqueId)
  527. b3Swap(pa, pb);
  528. #endif
  529. m_paircache->removeOverlappingPair(pa->getUid(), pb->getUid(), dispatcher);
  530. --ni;
  531. --i;
  532. }
  533. }
  534. if (pairs.size() > 0)
  535. m_cid = (m_cid + ni) % pairs.size();
  536. else
  537. m_cid = 0;
  538. }
  539. }
  540. ++m_pid;
  541. m_newpairs = 1;
  542. m_needcleanup = false;
  543. if (m_updates_call > 0)
  544. {
  545. m_updates_ratio = m_updates_done / (b3Scalar)m_updates_call;
  546. }
  547. else
  548. {
  549. m_updates_ratio = 0;
  550. }
  551. m_updates_done /= 2;
  552. m_updates_call /= 2;
  553. }
  554. //
  555. void b3DynamicBvhBroadphase::optimize()
  556. {
  557. m_sets[0].optimizeTopDown();
  558. m_sets[1].optimizeTopDown();
  559. }
  560. //
  561. b3OverlappingPairCache* b3DynamicBvhBroadphase::getOverlappingPairCache()
  562. {
  563. return (m_paircache);
  564. }
  565. //
  566. const b3OverlappingPairCache* b3DynamicBvhBroadphase::getOverlappingPairCache() const
  567. {
  568. return (m_paircache);
  569. }
  570. //
  571. void b3DynamicBvhBroadphase::getBroadphaseAabb(b3Vector3& aabbMin, b3Vector3& aabbMax) const
  572. {
  573. B3_ATTRIBUTE_ALIGNED16(b3DbvtVolume)
  574. bounds;
  575. if (!m_sets[0].empty())
  576. if (!m_sets[1].empty())
  577. b3Merge(m_sets[0].m_root->volume,
  578. m_sets[1].m_root->volume, bounds);
  579. else
  580. bounds = m_sets[0].m_root->volume;
  581. else if (!m_sets[1].empty())
  582. bounds = m_sets[1].m_root->volume;
  583. else
  584. bounds = b3DbvtVolume::FromCR(b3MakeVector3(0, 0, 0), 0);
  585. aabbMin = bounds.Mins();
  586. aabbMax = bounds.Maxs();
  587. }
  588. void b3DynamicBvhBroadphase::resetPool(b3Dispatcher* dispatcher)
  589. {
  590. int totalObjects = m_sets[0].m_leaves + m_sets[1].m_leaves;
  591. if (!totalObjects)
  592. {
  593. //reset internal dynamic tree data structures
  594. m_sets[0].clear();
  595. m_sets[1].clear();
  596. m_deferedcollide = false;
  597. m_needcleanup = true;
  598. m_stageCurrent = 0;
  599. m_fixedleft = 0;
  600. m_fupdates = 1;
  601. m_dupdates = 0;
  602. m_cupdates = 10;
  603. m_newpairs = 1;
  604. m_updates_call = 0;
  605. m_updates_done = 0;
  606. m_updates_ratio = 0;
  607. m_pid = 0;
  608. m_cid = 0;
  609. for (int i = 0; i <= STAGECOUNT; ++i)
  610. {
  611. m_stageRoots[i] = 0;
  612. }
  613. }
  614. }
  615. //
  616. void b3DynamicBvhBroadphase::printStats()
  617. {
  618. }
  619. //
  620. #if B3_DBVT_BP_ENABLE_BENCHMARK
  621. struct b3BroadphaseBenchmark
  622. {
  623. struct Experiment
  624. {
  625. const char* name;
  626. int object_count;
  627. int update_count;
  628. int spawn_count;
  629. int iterations;
  630. b3Scalar speed;
  631. b3Scalar amplitude;
  632. };
  633. struct Object
  634. {
  635. b3Vector3 center;
  636. b3Vector3 extents;
  637. b3BroadphaseProxy* proxy;
  638. b3Scalar time;
  639. void update(b3Scalar speed, b3Scalar amplitude, b3BroadphaseInterface* pbi)
  640. {
  641. time += speed;
  642. center[0] = b3Cos(time * (b3Scalar)2.17) * amplitude +
  643. b3Sin(time) * amplitude / 2;
  644. center[1] = b3Cos(time * (b3Scalar)1.38) * amplitude +
  645. b3Sin(time) * amplitude;
  646. center[2] = b3Sin(time * (b3Scalar)0.777) * amplitude;
  647. pbi->setAabb(proxy, center - extents, center + extents, 0);
  648. }
  649. };
  650. static int UnsignedRand(int range = RAND_MAX - 1) { return (rand() % (range + 1)); }
  651. static b3Scalar UnitRand() { return (UnsignedRand(16384) / (b3Scalar)16384); }
  652. static void OutputTime(const char* name, b3Clock& c, unsigned count = 0)
  653. {
  654. const unsigned long us = c.getTimeMicroseconds();
  655. const unsigned long ms = (us + 500) / 1000;
  656. const b3Scalar sec = us / (b3Scalar)(1000 * 1000);
  657. if (count > 0)
  658. printf("%s : %u us (%u ms), %.2f/s\r\n", name, us, ms, count / sec);
  659. else
  660. printf("%s : %u us (%u ms)\r\n", name, us, ms);
  661. }
  662. };
  663. void b3DynamicBvhBroadphase::benchmark(b3BroadphaseInterface* pbi)
  664. {
  665. static const b3BroadphaseBenchmark::Experiment experiments[] =
  666. {
  667. {"1024o.10%", 1024, 10, 0, 8192, (b3Scalar)0.005, (b3Scalar)100},
  668. /*{"4096o.10%",4096,10,0,8192,(b3Scalar)0.005,(b3Scalar)100},
  669. {"8192o.10%",8192,10,0,8192,(b3Scalar)0.005,(b3Scalar)100},*/
  670. };
  671. static const int nexperiments = sizeof(experiments) / sizeof(experiments[0]);
  672. b3AlignedObjectArray<b3BroadphaseBenchmark::Object*> objects;
  673. b3Clock wallclock;
  674. /* Begin */
  675. for (int iexp = 0; iexp < nexperiments; ++iexp)
  676. {
  677. const b3BroadphaseBenchmark::Experiment& experiment = experiments[iexp];
  678. const int object_count = experiment.object_count;
  679. const int update_count = (object_count * experiment.update_count) / 100;
  680. const int spawn_count = (object_count * experiment.spawn_count) / 100;
  681. const b3Scalar speed = experiment.speed;
  682. const b3Scalar amplitude = experiment.amplitude;
  683. printf("Experiment #%u '%s':\r\n", iexp, experiment.name);
  684. printf("\tObjects: %u\r\n", object_count);
  685. printf("\tUpdate: %u\r\n", update_count);
  686. printf("\tSpawn: %u\r\n", spawn_count);
  687. printf("\tSpeed: %f\r\n", speed);
  688. printf("\tAmplitude: %f\r\n", amplitude);
  689. srand(180673);
  690. /* Create objects */
  691. wallclock.reset();
  692. objects.reserve(object_count);
  693. for (int i = 0; i < object_count; ++i)
  694. {
  695. b3BroadphaseBenchmark::Object* po = new b3BroadphaseBenchmark::Object();
  696. po->center[0] = b3BroadphaseBenchmark::UnitRand() * 50;
  697. po->center[1] = b3BroadphaseBenchmark::UnitRand() * 50;
  698. po->center[2] = b3BroadphaseBenchmark::UnitRand() * 50;
  699. po->extents[0] = b3BroadphaseBenchmark::UnitRand() * 2 + 2;
  700. po->extents[1] = b3BroadphaseBenchmark::UnitRand() * 2 + 2;
  701. po->extents[2] = b3BroadphaseBenchmark::UnitRand() * 2 + 2;
  702. po->time = b3BroadphaseBenchmark::UnitRand() * 2000;
  703. po->proxy = pbi->createProxy(po->center - po->extents, po->center + po->extents, 0, po, 1, 1, 0, 0);
  704. objects.push_back(po);
  705. }
  706. b3BroadphaseBenchmark::OutputTime("\tInitialization", wallclock);
  707. /* First update */
  708. wallclock.reset();
  709. for (int i = 0; i < objects.size(); ++i)
  710. {
  711. objects[i]->update(speed, amplitude, pbi);
  712. }
  713. b3BroadphaseBenchmark::OutputTime("\tFirst update", wallclock);
  714. /* Updates */
  715. wallclock.reset();
  716. for (int i = 0; i < experiment.iterations; ++i)
  717. {
  718. for (int j = 0; j < update_count; ++j)
  719. {
  720. objects[j]->update(speed, amplitude, pbi);
  721. }
  722. pbi->calculateOverlappingPairs(0);
  723. }
  724. b3BroadphaseBenchmark::OutputTime("\tUpdate", wallclock, experiment.iterations);
  725. /* Clean up */
  726. wallclock.reset();
  727. for (int i = 0; i < objects.size(); ++i)
  728. {
  729. pbi->destroyProxy(objects[i]->proxy, 0);
  730. delete objects[i];
  731. }
  732. objects.resize(0);
  733. b3BroadphaseBenchmark::OutputTime("\tRelease", wallclock);
  734. }
  735. }
  736. #else
  737. /*void b3DynamicBvhBroadphase::benchmark(b3BroadphaseInterface*)
  738. {}
  739. */
  740. #endif
  741. #if B3_DBVT_BP_PROFILE
  742. #undef b3SPC
  743. #endif