123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829 |
- /*
- Bullet Continuous Collision Detection and Physics Library
- Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
- This software is provided 'as-is', without any express or implied warranty.
- In no event will the authors be held liable for any damages arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it freely,
- subject to the following restrictions:
- 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.
- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
- ///btDbvtBroadphase implementation by Nathanael Presson
- #include "btDbvtBroadphase.h"
- #include "LinearMath/btThreads.h"
- btScalar gDbvtMargin = btScalar(0.05);
- //
- // Profiling
- //
- #if DBVT_BP_PROFILE || DBVT_BP_ENABLE_BENCHMARK
- #include <stdio.h>
- #endif
- #if DBVT_BP_PROFILE
- struct ProfileScope
- {
- __forceinline ProfileScope(btClock& clock, unsigned long& value) : m_clock(&clock), m_value(&value), m_base(clock.getTimeMicroseconds())
- {
- }
- __forceinline ~ProfileScope()
- {
- (*m_value) += m_clock->getTimeMicroseconds() - m_base;
- }
- btClock* m_clock;
- unsigned long* m_value;
- unsigned long m_base;
- };
- #define SPC(_value_) ProfileScope spc_scope(m_clock, _value_)
- #else
- #define SPC(_value_)
- #endif
- //
- // Helpers
- //
- //
- template <typename T>
- static inline void listappend(T* item, T*& list)
- {
- item->links[0] = 0;
- item->links[1] = list;
- if (list) list->links[0] = item;
- list = item;
- }
- //
- template <typename T>
- static inline void listremove(T* item, T*& list)
- {
- if (item->links[0])
- item->links[0]->links[1] = item->links[1];
- else
- list = item->links[1];
- if (item->links[1]) item->links[1]->links[0] = item->links[0];
- }
- //
- template <typename T>
- static inline int listcount(T* root)
- {
- int n = 0;
- while (root)
- {
- ++n;
- root = root->links[1];
- }
- return (n);
- }
- //
- template <typename T>
- static inline void clear(T& value)
- {
- static const struct ZeroDummy : T
- {
- } zerodummy;
- value = zerodummy;
- }
- //
- // Colliders
- //
- /* Tree collider */
- struct btDbvtTreeCollider : btDbvt::ICollide
- {
- btDbvtBroadphase* pbp;
- btDbvtProxy* proxy;
- btDbvtTreeCollider(btDbvtBroadphase* p) : pbp(p) {}
- void Process(const btDbvtNode* na, const btDbvtNode* nb)
- {
- if (na != nb)
- {
- btDbvtProxy* pa = (btDbvtProxy*)na->data;
- btDbvtProxy* pb = (btDbvtProxy*)nb->data;
- #if DBVT_BP_SORTPAIRS
- if (pa->m_uniqueId > pb->m_uniqueId)
- btSwap(pa, pb);
- #endif
- pbp->m_paircache->addOverlappingPair(pa, pb);
- ++pbp->m_newpairs;
- }
- }
- void Process(const btDbvtNode* n)
- {
- Process(n, proxy->leaf);
- }
- };
- //
- // btDbvtBroadphase
- //
- //
- btDbvtBroadphase::btDbvtBroadphase(btOverlappingPairCache* paircache)
- {
- m_deferedcollide = false;
- m_needcleanup = true;
- m_releasepaircache = (paircache != 0) ? false : true;
- m_prediction = 0;
- m_stageCurrent = 0;
- m_fixedleft = 0;
- m_fupdates = 1;
- m_dupdates = 0;
- m_cupdates = 10;
- m_newpairs = 1;
- m_updates_call = 0;
- m_updates_done = 0;
- m_updates_ratio = 0;
- m_paircache = paircache ? paircache : new (btAlignedAlloc(sizeof(btHashedOverlappingPairCache), 16)) btHashedOverlappingPairCache();
- m_gid = 0;
- m_pid = 0;
- m_cid = 0;
- for (int i = 0; i <= STAGECOUNT; ++i)
- {
- m_stageRoots[i] = 0;
- }
- #if BT_THREADSAFE
- m_rayTestStacks.resize(BT_MAX_THREAD_COUNT);
- #else
- m_rayTestStacks.resize(1);
- #endif
- #if DBVT_BP_PROFILE
- clear(m_profiling);
- #endif
- }
- //
- btDbvtBroadphase::~btDbvtBroadphase()
- {
- if (m_releasepaircache)
- {
- m_paircache->~btOverlappingPairCache();
- btAlignedFree(m_paircache);
- }
- }
- //
- btBroadphaseProxy* btDbvtBroadphase::createProxy(const btVector3& aabbMin,
- const btVector3& aabbMax,
- int /*shapeType*/,
- void* userPtr,
- int collisionFilterGroup,
- int collisionFilterMask,
- btDispatcher* /*dispatcher*/)
- {
- btDbvtProxy* proxy = new (btAlignedAlloc(sizeof(btDbvtProxy), 16)) btDbvtProxy(aabbMin, aabbMax, userPtr,
- collisionFilterGroup,
- collisionFilterMask);
- btDbvtAabbMm aabb = btDbvtVolume::FromMM(aabbMin, aabbMax);
- //bproxy->aabb = btDbvtVolume::FromMM(aabbMin,aabbMax);
- proxy->stage = m_stageCurrent;
- proxy->m_uniqueId = ++m_gid;
- proxy->leaf = m_sets[0].insert(aabb, proxy);
- listappend(proxy, m_stageRoots[m_stageCurrent]);
- if (!m_deferedcollide)
- {
- btDbvtTreeCollider collider(this);
- collider.proxy = proxy;
- m_sets[0].collideTV(m_sets[0].m_root, aabb, collider);
- m_sets[1].collideTV(m_sets[1].m_root, aabb, collider);
- }
- return (proxy);
- }
- //
- void btDbvtBroadphase::destroyProxy(btBroadphaseProxy* absproxy,
- btDispatcher* dispatcher)
- {
- btDbvtProxy* proxy = (btDbvtProxy*)absproxy;
- if (proxy->stage == STAGECOUNT)
- m_sets[1].remove(proxy->leaf);
- else
- m_sets[0].remove(proxy->leaf);
- listremove(proxy, m_stageRoots[proxy->stage]);
- m_paircache->removeOverlappingPairsContainingProxy(proxy, dispatcher);
- btAlignedFree(proxy);
- m_needcleanup = true;
- }
- void btDbvtBroadphase::getAabb(btBroadphaseProxy* absproxy, btVector3& aabbMin, btVector3& aabbMax) const
- {
- btDbvtProxy* proxy = (btDbvtProxy*)absproxy;
- aabbMin = proxy->m_aabbMin;
- aabbMax = proxy->m_aabbMax;
- }
- struct BroadphaseRayTester : btDbvt::ICollide
- {
- btBroadphaseRayCallback& m_rayCallback;
- BroadphaseRayTester(btBroadphaseRayCallback& orgCallback)
- : m_rayCallback(orgCallback)
- {
- }
- void Process(const btDbvtNode* leaf)
- {
- btDbvtProxy* proxy = (btDbvtProxy*)leaf->data;
- m_rayCallback.process(proxy);
- }
- };
- void btDbvtBroadphase::rayTest(const btVector3& rayFrom, const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin, const btVector3& aabbMax)
- {
- BroadphaseRayTester callback(rayCallback);
- btAlignedObjectArray<const btDbvtNode*>* stack = &m_rayTestStacks[0];
- #if BT_THREADSAFE
- // for this function to be threadsafe, each thread must have a separate copy
- // of this stack. This could be thread-local static to avoid dynamic allocations,
- // instead of just a local.
- int threadIndex = btGetCurrentThreadIndex();
- btAlignedObjectArray<const btDbvtNode*> localStack;
- //todo(erwincoumans, "why do we get tsan issue here?")
- if (0)//threadIndex < m_rayTestStacks.size())
- //if (threadIndex < m_rayTestStacks.size())
- {
- // use per-thread preallocated stack if possible to avoid dynamic allocations
- stack = &m_rayTestStacks[threadIndex];
- }
- else
- {
- stack = &localStack;
- }
- #endif
- m_sets[0].rayTestInternal(m_sets[0].m_root,
- rayFrom,
- rayTo,
- rayCallback.m_rayDirectionInverse,
- rayCallback.m_signs,
- rayCallback.m_lambda_max,
- aabbMin,
- aabbMax,
- *stack,
- callback);
- m_sets[1].rayTestInternal(m_sets[1].m_root,
- rayFrom,
- rayTo,
- rayCallback.m_rayDirectionInverse,
- rayCallback.m_signs,
- rayCallback.m_lambda_max,
- aabbMin,
- aabbMax,
- *stack,
- callback);
- }
- struct BroadphaseAabbTester : btDbvt::ICollide
- {
- btBroadphaseAabbCallback& m_aabbCallback;
- BroadphaseAabbTester(btBroadphaseAabbCallback& orgCallback)
- : m_aabbCallback(orgCallback)
- {
- }
- void Process(const btDbvtNode* leaf)
- {
- btDbvtProxy* proxy = (btDbvtProxy*)leaf->data;
- m_aabbCallback.process(proxy);
- }
- };
- void btDbvtBroadphase::aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& aabbCallback)
- {
- BroadphaseAabbTester callback(aabbCallback);
- const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds = btDbvtVolume::FromMM(aabbMin, aabbMax);
- //process all children, that overlap with the given AABB bounds
- m_sets[0].collideTV(m_sets[0].m_root, bounds, callback);
- m_sets[1].collideTV(m_sets[1].m_root, bounds, callback);
- }
- //
- void btDbvtBroadphase::setAabb(btBroadphaseProxy* absproxy,
- const btVector3& aabbMin,
- const btVector3& aabbMax,
- btDispatcher* /*dispatcher*/)
- {
- btDbvtProxy* proxy = (btDbvtProxy*)absproxy;
- ATTRIBUTE_ALIGNED16(btDbvtVolume)
- aabb = btDbvtVolume::FromMM(aabbMin, aabbMax);
- #if DBVT_BP_PREVENTFALSEUPDATE
- if (NotEqual(aabb, proxy->leaf->volume))
- #endif
- {
- bool docollide = false;
- if (proxy->stage == STAGECOUNT)
- { /* fixed -> dynamic set */
- m_sets[1].remove(proxy->leaf);
- proxy->leaf = m_sets[0].insert(aabb, proxy);
- docollide = true;
- }
- else
- { /* dynamic set */
- ++m_updates_call;
- if (Intersect(proxy->leaf->volume, aabb))
- { /* Moving */
- const btVector3 delta = aabbMin - proxy->m_aabbMin;
- btVector3 velocity(((proxy->m_aabbMax - proxy->m_aabbMin) / 2) * m_prediction);
- if (delta[0] < 0) velocity[0] = -velocity[0];
- if (delta[1] < 0) velocity[1] = -velocity[1];
- if (delta[2] < 0) velocity[2] = -velocity[2];
- if (
- m_sets[0].update(proxy->leaf, aabb, velocity, gDbvtMargin)
- )
- {
- ++m_updates_done;
- docollide = true;
- }
- }
- else
- { /* Teleporting */
- m_sets[0].update(proxy->leaf, aabb);
- ++m_updates_done;
- docollide = true;
- }
- }
- listremove(proxy, m_stageRoots[proxy->stage]);
- proxy->m_aabbMin = aabbMin;
- proxy->m_aabbMax = aabbMax;
- proxy->stage = m_stageCurrent;
- listappend(proxy, m_stageRoots[m_stageCurrent]);
- if (docollide)
- {
- m_needcleanup = true;
- if (!m_deferedcollide)
- {
- btDbvtTreeCollider collider(this);
- m_sets[1].collideTTpersistentStack(m_sets[1].m_root, proxy->leaf, collider);
- m_sets[0].collideTTpersistentStack(m_sets[0].m_root, proxy->leaf, collider);
- }
- }
- }
- }
- //
- void btDbvtBroadphase::setAabbForceUpdate(btBroadphaseProxy* absproxy,
- const btVector3& aabbMin,
- const btVector3& aabbMax,
- btDispatcher* /*dispatcher*/)
- {
- btDbvtProxy* proxy = (btDbvtProxy*)absproxy;
- ATTRIBUTE_ALIGNED16(btDbvtVolume)
- aabb = btDbvtVolume::FromMM(aabbMin, aabbMax);
- bool docollide = false;
- if (proxy->stage == STAGECOUNT)
- { /* fixed -> dynamic set */
- m_sets[1].remove(proxy->leaf);
- proxy->leaf = m_sets[0].insert(aabb, proxy);
- docollide = true;
- }
- else
- { /* dynamic set */
- ++m_updates_call;
- /* Teleporting */
- m_sets[0].update(proxy->leaf, aabb);
- ++m_updates_done;
- docollide = true;
- }
- listremove(proxy, m_stageRoots[proxy->stage]);
- proxy->m_aabbMin = aabbMin;
- proxy->m_aabbMax = aabbMax;
- proxy->stage = m_stageCurrent;
- listappend(proxy, m_stageRoots[m_stageCurrent]);
- if (docollide)
- {
- m_needcleanup = true;
- if (!m_deferedcollide)
- {
- btDbvtTreeCollider collider(this);
- m_sets[1].collideTTpersistentStack(m_sets[1].m_root, proxy->leaf, collider);
- m_sets[0].collideTTpersistentStack(m_sets[0].m_root, proxy->leaf, collider);
- }
- }
- }
- //
- void btDbvtBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
- {
- collide(dispatcher);
- #if DBVT_BP_PROFILE
- if (0 == (m_pid % DBVT_BP_PROFILING_RATE))
- {
- printf("fixed(%u) dynamics(%u) pairs(%u)\r\n", m_sets[1].m_leaves, m_sets[0].m_leaves, m_paircache->getNumOverlappingPairs());
- unsigned int total = m_profiling.m_total;
- if (total <= 0) total = 1;
- printf("ddcollide: %u%% (%uus)\r\n", (50 + m_profiling.m_ddcollide * 100) / total, m_profiling.m_ddcollide / DBVT_BP_PROFILING_RATE);
- printf("fdcollide: %u%% (%uus)\r\n", (50 + m_profiling.m_fdcollide * 100) / total, m_profiling.m_fdcollide / DBVT_BP_PROFILING_RATE);
- printf("cleanup: %u%% (%uus)\r\n", (50 + m_profiling.m_cleanup * 100) / total, m_profiling.m_cleanup / DBVT_BP_PROFILING_RATE);
- printf("total: %uus\r\n", total / DBVT_BP_PROFILING_RATE);
- const unsigned long sum = m_profiling.m_ddcollide +
- m_profiling.m_fdcollide +
- m_profiling.m_cleanup;
- printf("leaked: %u%% (%uus)\r\n", 100 - ((50 + sum * 100) / total), (total - sum) / DBVT_BP_PROFILING_RATE);
- printf("job counts: %u%%\r\n", (m_profiling.m_jobcount * 100) / ((m_sets[0].m_leaves + m_sets[1].m_leaves) * DBVT_BP_PROFILING_RATE));
- clear(m_profiling);
- m_clock.reset();
- }
- #endif
- performDeferredRemoval(dispatcher);
- }
- void btDbvtBroadphase::performDeferredRemoval(btDispatcher* dispatcher)
- {
- if (m_paircache->hasDeferredRemoval())
- {
- btBroadphasePairArray& overlappingPairArray = m_paircache->getOverlappingPairArray();
- //perform a sort, to find duplicates and to sort 'invalid' pairs to the end
- overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
- int invalidPair = 0;
- int i;
- btBroadphasePair previousPair;
- previousPair.m_pProxy0 = 0;
- previousPair.m_pProxy1 = 0;
- previousPair.m_algorithm = 0;
- for (i = 0; i < overlappingPairArray.size(); i++)
- {
- btBroadphasePair& pair = overlappingPairArray[i];
- bool isDuplicate = (pair == previousPair);
- previousPair = pair;
- bool needsRemoval = false;
- if (!isDuplicate)
- {
- //important to perform AABB check that is consistent with the broadphase
- btDbvtProxy* pa = (btDbvtProxy*)pair.m_pProxy0;
- btDbvtProxy* pb = (btDbvtProxy*)pair.m_pProxy1;
- bool hasOverlap = Intersect(pa->leaf->volume, pb->leaf->volume);
- if (hasOverlap)
- {
- needsRemoval = false;
- }
- else
- {
- needsRemoval = true;
- }
- }
- else
- {
- //remove duplicate
- needsRemoval = true;
- //should have no algorithm
- btAssert(!pair.m_algorithm);
- }
- if (needsRemoval)
- {
- m_paircache->cleanOverlappingPair(pair, dispatcher);
- pair.m_pProxy0 = 0;
- pair.m_pProxy1 = 0;
- invalidPair++;
- }
- }
- //perform a sort, to sort 'invalid' pairs to the end
- overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
- overlappingPairArray.resize(overlappingPairArray.size() - invalidPair);
- }
- }
- //
- void btDbvtBroadphase::collide(btDispatcher* dispatcher)
- {
- /*printf("---------------------------------------------------------\n");
- printf("m_sets[0].m_leaves=%d\n",m_sets[0].m_leaves);
- printf("m_sets[1].m_leaves=%d\n",m_sets[1].m_leaves);
- printf("numPairs = %d\n",getOverlappingPairCache()->getNumOverlappingPairs());
- {
- int i;
- for (i=0;i<getOverlappingPairCache()->getNumOverlappingPairs();i++)
- {
- printf("pair[%d]=(%d,%d),",i,getOverlappingPairCache()->getOverlappingPairArray()[i].m_pProxy0->getUid(),
- getOverlappingPairCache()->getOverlappingPairArray()[i].m_pProxy1->getUid());
- }
- printf("\n");
- }
- */
- SPC(m_profiling.m_total);
- /* optimize */
- m_sets[0].optimizeIncremental(1 + (m_sets[0].m_leaves * m_dupdates) / 100);
- if (m_fixedleft)
- {
- const int count = 1 + (m_sets[1].m_leaves * m_fupdates) / 100;
- m_sets[1].optimizeIncremental(1 + (m_sets[1].m_leaves * m_fupdates) / 100);
- m_fixedleft = btMax<int>(0, m_fixedleft - count);
- }
- /* dynamic -> fixed set */
- m_stageCurrent = (m_stageCurrent + 1) % STAGECOUNT;
- btDbvtProxy* current = m_stageRoots[m_stageCurrent];
- if (current)
- {
- #if DBVT_BP_ACCURATESLEEPING
- btDbvtTreeCollider collider(this);
- #endif
- do
- {
- btDbvtProxy* next = current->links[1];
- listremove(current, m_stageRoots[current->stage]);
- listappend(current, m_stageRoots[STAGECOUNT]);
- #if DBVT_BP_ACCURATESLEEPING
- m_paircache->removeOverlappingPairsContainingProxy(current, dispatcher);
- collider.proxy = current;
- btDbvt::collideTV(m_sets[0].m_root, current->aabb, collider);
- btDbvt::collideTV(m_sets[1].m_root, current->aabb, collider);
- #endif
- m_sets[0].remove(current->leaf);
- ATTRIBUTE_ALIGNED16(btDbvtVolume)
- curAabb = btDbvtVolume::FromMM(current->m_aabbMin, current->m_aabbMax);
- current->leaf = m_sets[1].insert(curAabb, current);
- current->stage = STAGECOUNT;
- current = next;
- } while (current);
- m_fixedleft = m_sets[1].m_leaves;
- m_needcleanup = true;
- }
- /* collide dynamics */
- {
- btDbvtTreeCollider collider(this);
- if (m_deferedcollide)
- {
- SPC(m_profiling.m_fdcollide);
- m_sets[0].collideTTpersistentStack(m_sets[0].m_root, m_sets[1].m_root, collider);
- }
- if (m_deferedcollide)
- {
- SPC(m_profiling.m_ddcollide);
- m_sets[0].collideTTpersistentStack(m_sets[0].m_root, m_sets[0].m_root, collider);
- }
- }
- /* clean up */
- if (m_needcleanup)
- {
- SPC(m_profiling.m_cleanup);
- btBroadphasePairArray& pairs = m_paircache->getOverlappingPairArray();
- if (pairs.size() > 0)
- {
- int ni = btMin(pairs.size(), btMax<int>(m_newpairs, (pairs.size() * m_cupdates) / 100));
- for (int i = 0; i < ni; ++i)
- {
- btBroadphasePair& p = pairs[(m_cid + i) % pairs.size()];
- btDbvtProxy* pa = (btDbvtProxy*)p.m_pProxy0;
- btDbvtProxy* pb = (btDbvtProxy*)p.m_pProxy1;
- if (!Intersect(pa->leaf->volume, pb->leaf->volume))
- {
- #if DBVT_BP_SORTPAIRS
- if (pa->m_uniqueId > pb->m_uniqueId)
- btSwap(pa, pb);
- #endif
- m_paircache->removeOverlappingPair(pa, pb, dispatcher);
- --ni;
- --i;
- }
- }
- if (pairs.size() > 0)
- m_cid = (m_cid + ni) % pairs.size();
- else
- m_cid = 0;
- }
- }
- ++m_pid;
- m_newpairs = 1;
- m_needcleanup = false;
- if (m_updates_call > 0)
- {
- m_updates_ratio = m_updates_done / (btScalar)m_updates_call;
- }
- else
- {
- m_updates_ratio = 0;
- }
- m_updates_done /= 2;
- m_updates_call /= 2;
- }
- //
- void btDbvtBroadphase::optimize()
- {
- m_sets[0].optimizeTopDown();
- m_sets[1].optimizeTopDown();
- }
- //
- btOverlappingPairCache* btDbvtBroadphase::getOverlappingPairCache()
- {
- return (m_paircache);
- }
- //
- const btOverlappingPairCache* btDbvtBroadphase::getOverlappingPairCache() const
- {
- return (m_paircache);
- }
- //
- void btDbvtBroadphase::getBroadphaseAabb(btVector3& aabbMin, btVector3& aabbMax) const
- {
- ATTRIBUTE_ALIGNED16(btDbvtVolume)
- bounds;
- if (!m_sets[0].empty())
- if (!m_sets[1].empty())
- Merge(m_sets[0].m_root->volume,
- m_sets[1].m_root->volume, bounds);
- else
- bounds = m_sets[0].m_root->volume;
- else if (!m_sets[1].empty())
- bounds = m_sets[1].m_root->volume;
- else
- bounds = btDbvtVolume::FromCR(btVector3(0, 0, 0), 0);
- aabbMin = bounds.Mins();
- aabbMax = bounds.Maxs();
- }
- void btDbvtBroadphase::resetPool(btDispatcher* dispatcher)
- {
- int totalObjects = m_sets[0].m_leaves + m_sets[1].m_leaves;
- if (!totalObjects)
- {
- //reset internal dynamic tree data structures
- m_sets[0].clear();
- m_sets[1].clear();
- m_deferedcollide = false;
- m_needcleanup = true;
- m_stageCurrent = 0;
- m_fixedleft = 0;
- m_fupdates = 1;
- m_dupdates = 0;
- m_cupdates = 10;
- m_newpairs = 1;
- m_updates_call = 0;
- m_updates_done = 0;
- m_updates_ratio = 0;
- m_gid = 0;
- m_pid = 0;
- m_cid = 0;
- for (int i = 0; i <= STAGECOUNT; ++i)
- {
- m_stageRoots[i] = 0;
- }
- }
- }
- //
- void btDbvtBroadphase::printStats()
- {
- }
- //
- #if DBVT_BP_ENABLE_BENCHMARK
- struct btBroadphaseBenchmark
- {
- struct Experiment
- {
- const char* name;
- int object_count;
- int update_count;
- int spawn_count;
- int iterations;
- btScalar speed;
- btScalar amplitude;
- };
- struct Object
- {
- btVector3 center;
- btVector3 extents;
- btBroadphaseProxy* proxy;
- btScalar time;
- void update(btScalar speed, btScalar amplitude, btBroadphaseInterface* pbi)
- {
- time += speed;
- center[0] = btCos(time * (btScalar)2.17) * amplitude +
- btSin(time) * amplitude / 2;
- center[1] = btCos(time * (btScalar)1.38) * amplitude +
- btSin(time) * amplitude;
- center[2] = btSin(time * (btScalar)0.777) * amplitude;
- pbi->setAabb(proxy, center - extents, center + extents, 0);
- }
- };
- static int UnsignedRand(int range = RAND_MAX - 1) { return (rand() % (range + 1)); }
- static btScalar UnitRand() { return (UnsignedRand(16384) / (btScalar)16384); }
- static void OutputTime(const char* name, btClock& c, unsigned count = 0)
- {
- const unsigned long us = c.getTimeMicroseconds();
- const unsigned long ms = (us + 500) / 1000;
- const btScalar sec = us / (btScalar)(1000 * 1000);
- if (count > 0)
- printf("%s : %u us (%u ms), %.2f/s\r\n", name, us, ms, count / sec);
- else
- printf("%s : %u us (%u ms)\r\n", name, us, ms);
- }
- };
- void btDbvtBroadphase::benchmark(btBroadphaseInterface* pbi)
- {
- static const btBroadphaseBenchmark::Experiment experiments[] =
- {
- {"1024o.10%", 1024, 10, 0, 8192, (btScalar)0.005, (btScalar)100},
- /*{"4096o.10%",4096,10,0,8192,(btScalar)0.005,(btScalar)100},
- {"8192o.10%",8192,10,0,8192,(btScalar)0.005,(btScalar)100},*/
- };
- static const int nexperiments = sizeof(experiments) / sizeof(experiments[0]);
- btAlignedObjectArray<btBroadphaseBenchmark::Object*> objects;
- btClock wallclock;
- /* Begin */
- for (int iexp = 0; iexp < nexperiments; ++iexp)
- {
- const btBroadphaseBenchmark::Experiment& experiment = experiments[iexp];
- const int object_count = experiment.object_count;
- const int update_count = (object_count * experiment.update_count) / 100;
- const int spawn_count = (object_count * experiment.spawn_count) / 100;
- const btScalar speed = experiment.speed;
- const btScalar amplitude = experiment.amplitude;
- printf("Experiment #%u '%s':\r\n", iexp, experiment.name);
- printf("\tObjects: %u\r\n", object_count);
- printf("\tUpdate: %u\r\n", update_count);
- printf("\tSpawn: %u\r\n", spawn_count);
- printf("\tSpeed: %f\r\n", speed);
- printf("\tAmplitude: %f\r\n", amplitude);
- srand(180673);
- /* Create objects */
- wallclock.reset();
- objects.reserve(object_count);
- for (int i = 0; i < object_count; ++i)
- {
- btBroadphaseBenchmark::Object* po = new btBroadphaseBenchmark::Object();
- po->center[0] = btBroadphaseBenchmark::UnitRand() * 50;
- po->center[1] = btBroadphaseBenchmark::UnitRand() * 50;
- po->center[2] = btBroadphaseBenchmark::UnitRand() * 50;
- po->extents[0] = btBroadphaseBenchmark::UnitRand() * 2 + 2;
- po->extents[1] = btBroadphaseBenchmark::UnitRand() * 2 + 2;
- po->extents[2] = btBroadphaseBenchmark::UnitRand() * 2 + 2;
- po->time = btBroadphaseBenchmark::UnitRand() * 2000;
- po->proxy = pbi->createProxy(po->center - po->extents, po->center + po->extents, 0, po, 1, 1, 0, 0);
- objects.push_back(po);
- }
- btBroadphaseBenchmark::OutputTime("\tInitialization", wallclock);
- /* First update */
- wallclock.reset();
- for (int i = 0; i < objects.size(); ++i)
- {
- objects[i]->update(speed, amplitude, pbi);
- }
- btBroadphaseBenchmark::OutputTime("\tFirst update", wallclock);
- /* Updates */
- wallclock.reset();
- for (int i = 0; i < experiment.iterations; ++i)
- {
- for (int j = 0; j < update_count; ++j)
- {
- objects[j]->update(speed, amplitude, pbi);
- }
- pbi->calculateOverlappingPairs(0);
- }
- btBroadphaseBenchmark::OutputTime("\tUpdate", wallclock, experiment.iterations);
- /* Clean up */
- wallclock.reset();
- for (int i = 0; i < objects.size(); ++i)
- {
- pbi->destroyProxy(objects[i]->proxy, 0);
- delete objects[i];
- }
- objects.resize(0);
- btBroadphaseBenchmark::OutputTime("\tRelease", wallclock);
- }
- }
- #else
- void btDbvtBroadphase::benchmark(btBroadphaseInterface*)
- {
- }
- #endif
- #if DBVT_BP_PROFILE
- #undef SPC
- #endif
|