25 #if DBVT_BP_PROFILE || DBVT_BP_ENABLE_BENCHMARK 32 __forceinline ProfileScope(
btClock& clock,
unsigned long& value) : m_clock(&clock), m_value(&value), m_base(clock.getTimeMicroseconds())
35 __forceinline ~ProfileScope()
37 (*m_value) += m_clock->getTimeMicroseconds() - m_base;
40 unsigned long* m_value;
43 #define SPC(_value_) ProfileScope spc_scope(m_clock, _value_) 57 item->links[1] = list;
58 if (list) list->links[0] = item;
67 item->links[0]->links[1] = item->links[1];
69 list = item->links[1];
70 if (item->links[1]) item->links[1]->links[0] = item->links[0];
81 root = root->links[1];
88 static inline void clear(T& value)
90 static const struct ZeroDummy : T
112 #if DBVT_BP_SORTPAIRS 122 Process(n, proxy->
leaf);
133 m_deferedcollide =
false;
134 m_needcleanup =
true;
135 m_releasepaircache = (paircache != 0) ?
false :
true;
150 for (
int i = 0; i <= STAGECOUNT; ++i)
157 m_rayTestStacks.resize(1);
167 if (m_releasepaircache)
169 m_paircache->~btOverlappingPairCache();
179 int collisionFilterGroup,
180 int collisionFilterMask,
184 collisionFilterGroup,
185 collisionFilterMask);
190 proxy->
stage = m_stageCurrent;
192 proxy->
leaf = m_sets[0].insert(aabb, proxy);
193 listappend(proxy, m_stageRoots[m_stageCurrent]);
194 if (!m_deferedcollide)
197 collider.
proxy = proxy;
198 m_sets[0].collideTV(m_sets[0].m_root, aabb, collider);
199 m_sets[1].collideTV(m_sets[1].m_root, aabb, collider);
209 if (proxy->
stage == STAGECOUNT)
210 m_sets[1].remove(proxy->
leaf);
212 m_sets[0].remove(proxy->
leaf);
214 m_paircache->removeOverlappingPairsContainingProxy(proxy, dispatcher);
216 m_needcleanup =
true;
230 : m_rayCallback(orgCallback)
255 stack = &m_rayTestStacks[threadIndex];
263 m_sets[0].rayTestInternal(m_sets[0].m_root,
274 m_sets[1].rayTestInternal(m_sets[1].m_root,
290 : m_aabbCallback(orgCallback)
306 m_sets[0].collideTV(m_sets[0].m_root,
bounds, callback);
307 m_sets[1].collideTV(m_sets[1].m_root,
bounds, callback);
319 #if DBVT_BP_PREVENTFALSEUPDATE 323 bool docollide =
false;
324 if (proxy->
stage == STAGECOUNT)
326 m_sets[1].remove(proxy->
leaf);
327 proxy->
leaf = m_sets[0].insert(aabb, proxy);
338 if (delta[0] < 0) velocity[0] = -velocity[0];
339 if (delta[1] < 0) velocity[1] = -velocity[1];
340 if (delta[2] < 0) velocity[2] = -velocity[2];
352 m_sets[0].update(proxy->
leaf, aabb);
360 proxy->
stage = m_stageCurrent;
361 listappend(proxy, m_stageRoots[m_stageCurrent]);
364 m_needcleanup =
true;
365 if (!m_deferedcollide)
368 m_sets[1].collideTTpersistentStack(m_sets[1].m_root, proxy->
leaf, collider);
369 m_sets[0].collideTTpersistentStack(m_sets[0].m_root, proxy->
leaf, collider);
384 bool docollide =
false;
385 if (proxy->
stage == STAGECOUNT)
387 m_sets[1].remove(proxy->
leaf);
388 proxy->
leaf = m_sets[0].insert(aabb, proxy);
395 m_sets[0].update(proxy->
leaf, aabb);
402 proxy->
stage = m_stageCurrent;
403 listappend(proxy, m_stageRoots[m_stageCurrent]);
406 m_needcleanup =
true;
407 if (!m_deferedcollide)
410 m_sets[1].collideTTpersistentStack(m_sets[1].m_root, proxy->
leaf, collider);
411 m_sets[0].collideTTpersistentStack(m_sets[0].m_root, proxy->
leaf, collider);
421 if (0 == (m_pid % DBVT_BP_PROFILING_RATE))
423 printf(
"fixed(%u) dynamics(%u) pairs(%u)\r\n", m_sets[1].m_leaves, m_sets[0].m_leaves, m_paircache->getNumOverlappingPairs());
424 unsigned int total = m_profiling.m_total;
425 if (total <= 0) total = 1;
426 printf(
"ddcollide: %u%% (%uus)\r\n", (50 + m_profiling.m_ddcollide * 100) / total, m_profiling.m_ddcollide / DBVT_BP_PROFILING_RATE);
427 printf(
"fdcollide: %u%% (%uus)\r\n", (50 + m_profiling.m_fdcollide * 100) / total, m_profiling.m_fdcollide / DBVT_BP_PROFILING_RATE);
428 printf(
"cleanup: %u%% (%uus)\r\n", (50 + m_profiling.m_cleanup * 100) / total, m_profiling.m_cleanup / DBVT_BP_PROFILING_RATE);
429 printf(
"total: %uus\r\n", total / DBVT_BP_PROFILING_RATE);
430 const unsigned long sum = m_profiling.m_ddcollide +
431 m_profiling.m_fdcollide +
432 m_profiling.m_cleanup;
433 printf(
"leaked: %u%% (%uus)\r\n", 100 - ((50 + sum * 100) / total), (total - sum) / DBVT_BP_PROFILING_RATE);
434 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));
440 performDeferredRemoval(dispatcher);
445 if (m_paircache->hasDeferredRemoval())
461 for (i = 0; i < overlappingPairArray.
size(); i++)
465 bool isDuplicate = (pair == previousPair);
469 bool needsRemoval =
false;
480 needsRemoval =
false;
497 m_paircache->cleanOverlappingPair(pair, dispatcher);
507 overlappingPairArray.
resize(overlappingPairArray.
size() - invalidPair);
529 SPC(m_profiling.m_total);
531 m_sets[0].optimizeIncremental(1 + (m_sets[0].m_leaves * m_dupdates) / 100);
534 const int count = 1 + (m_sets[1].m_leaves * m_fupdates) / 100;
535 m_sets[1].optimizeIncremental(1 + (m_sets[1].m_leaves * m_fupdates) / 100);
536 m_fixedleft = btMax<int>(0, m_fixedleft - count);
539 m_stageCurrent = (m_stageCurrent + 1) % STAGECOUNT;
540 btDbvtProxy* current = m_stageRoots[m_stageCurrent];
543 #if DBVT_BP_ACCURATESLEEPING 550 listappend(current, m_stageRoots[STAGECOUNT]);
551 #if DBVT_BP_ACCURATESLEEPING 552 m_paircache->removeOverlappingPairsContainingProxy(current, dispatcher);
553 collider.
proxy = current;
557 m_sets[0].remove(current->
leaf);
560 current->
leaf = m_sets[1].insert(curAabb, current);
561 current->
stage = STAGECOUNT;
564 m_fixedleft = m_sets[1].m_leaves;
565 m_needcleanup =
true;
570 if (m_deferedcollide)
572 SPC(m_profiling.m_fdcollide);
573 m_sets[0].collideTTpersistentStack(m_sets[0].m_root, m_sets[1].m_root, collider);
575 if (m_deferedcollide)
577 SPC(m_profiling.m_ddcollide);
578 m_sets[0].collideTTpersistentStack(m_sets[0].m_root, m_sets[0].m_root, collider);
584 SPC(m_profiling.m_cleanup);
586 if (pairs.
size() > 0)
588 int ni =
btMin(pairs.
size(), btMax<int>(m_newpairs, (pairs.
size() * m_cupdates) / 100));
589 for (
int i = 0; i < ni; ++i)
596 #if DBVT_BP_SORTPAIRS 600 m_paircache->removeOverlappingPair(pa, pb, dispatcher);
605 if (pairs.
size() > 0)
606 m_cid = (m_cid + ni) % pairs.
size();
613 m_needcleanup =
false;
614 if (m_updates_call > 0)
616 m_updates_ratio = m_updates_done / (
btScalar)m_updates_call;
629 m_sets[0].optimizeTopDown();
630 m_sets[1].optimizeTopDown();
636 return (m_paircache);
642 return (m_paircache);
651 if (!m_sets[0].empty())
652 if (!m_sets[1].empty())
653 Merge(m_sets[0].m_root->volume,
654 m_sets[1].m_root->volume,
bounds);
656 bounds = m_sets[0].m_root->volume;
657 else if (!m_sets[1].empty())
658 bounds = m_sets[1].m_root->volume;
667 int totalObjects = m_sets[0].m_leaves + m_sets[1].m_leaves;
674 m_deferedcollide =
false;
675 m_needcleanup =
true;
689 for (
int i = 0; i <= STAGECOUNT; ++i)
702 #if DBVT_BP_ENABLE_BENCHMARK 704 struct btBroadphaseBenchmark
726 btSin(time) * amplitude / 2;
728 btSin(time) * amplitude;
730 pbi->
setAabb(proxy, center - extents, center + extents, 0);
733 static int UnsignedRand(
int range = RAND_MAX - 1) {
return (rand() % (range + 1)); }
734 static btScalar UnitRand() {
return (UnsignedRand(16384) / (
btScalar)16384); }
735 static void OutputTime(
const char* name,
btClock& c,
unsigned count = 0)
738 const unsigned long ms = (us + 500) / 1000;
741 printf(
"%s : %u us (%u ms), %.2f/s\r\n", name, us, ms, count / sec);
743 printf(
"%s : %u us (%u ms)\r\n", name, us, ms);
749 static const btBroadphaseBenchmark::Experiment experiments[] =
755 static const int nexperiments =
sizeof(experiments) /
sizeof(experiments[0]);
759 for (
int iexp = 0; iexp < nexperiments; ++iexp)
761 const btBroadphaseBenchmark::Experiment& experiment = experiments[iexp];
762 const int object_count = experiment.object_count;
763 const int update_count = (object_count * experiment.update_count) / 100;
764 const int spawn_count = (object_count * experiment.spawn_count) / 100;
765 const btScalar speed = experiment.speed;
766 const btScalar amplitude = experiment.amplitude;
767 printf(
"Experiment #%u '%s':\r\n", iexp, experiment.name);
768 printf(
"\tObjects: %u\r\n", object_count);
769 printf(
"\tUpdate: %u\r\n", update_count);
770 printf(
"\tSpawn: %u\r\n", spawn_count);
771 printf(
"\tSpeed: %f\r\n", speed);
772 printf(
"\tAmplitude: %f\r\n", amplitude);
777 for (
int i = 0; i < object_count; ++i)
779 btBroadphaseBenchmark::Object* po =
new btBroadphaseBenchmark::Object();
780 po->center[0] = btBroadphaseBenchmark::UnitRand() * 50;
781 po->center[1] = btBroadphaseBenchmark::UnitRand() * 50;
782 po->center[2] = btBroadphaseBenchmark::UnitRand() * 50;
783 po->extents[0] = btBroadphaseBenchmark::UnitRand() * 2 + 2;
784 po->extents[1] = btBroadphaseBenchmark::UnitRand() * 2 + 2;
785 po->extents[2] = btBroadphaseBenchmark::UnitRand() * 2 + 2;
786 po->time = btBroadphaseBenchmark::UnitRand() * 2000;
787 po->proxy = pbi->
createProxy(po->center - po->extents, po->center + po->extents, 0, po, 1, 1, 0, 0);
790 btBroadphaseBenchmark::OutputTime(
"\tInitialization", wallclock);
793 for (
int i = 0; i < objects.
size(); ++i)
795 objects[i]->update(speed, amplitude, pbi);
797 btBroadphaseBenchmark::OutputTime(
"\tFirst update", wallclock);
800 for (
int i = 0; i < experiment.iterations; ++i)
802 for (
int j = 0; j < update_count; ++j)
804 objects[j]->update(speed, amplitude, pbi);
808 btBroadphaseBenchmark::OutputTime(
"\tUpdate", wallclock, experiment.iterations);
811 for (
int i = 0; i < objects.
size(); ++i)
817 btBroadphaseBenchmark::OutputTime(
"\tRelease", wallclock);
virtual void aabbTest(const btVector3 &aabbMin, const btVector3 &aabbMax, btBroadphaseAabbCallback &callback)
static T sum(const btAlignedObjectArray< T > &items)
DBVT_INLINE void Merge(const btDbvtAabbMm &a, const btDbvtAabbMm &b, btDbvtAabbMm &r)
void push_back(const T &_Val)
static void benchmark(btBroadphaseInterface *)
virtual void getBroadphaseAabb(btVector3 &aabbMin, btVector3 &aabbMax) const
getAabb returns the axis aligned bounding box in the 'global' coordinate frame will add some transfor...
DBVT_INLINE const btVector3 & Mins() const
btBroadphaseRayCallback & m_rayCallback
static void listappend(T *item, T *&list)
virtual void resetPool(btDispatcher *dispatcher)
reset broadphase internal structures, to ensure determinism/reproducability
btScalar btSin(btScalar x)
btOverlappingPairCache * m_paircache
void Process(const btDbvtNode *na, const btDbvtNode *nb)
The btClock is a portable basic clock that measures accurate time in seconds, use for profiling...
The btDbvtBroadphase implements a broadphase using two dynamic AABB bounding volume hierarchies/trees...
void reset()
Resets the initial reference time.
void performDeferredRemoval(btDispatcher *dispatcher)
void collide(btDispatcher *dispatcher)
const unsigned int BT_MAX_THREAD_COUNT
DBVT_INLINE const btVector3 & Maxs() const
The btOverlappingPairCache provides an interface for overlapping pair management (add, remove, storage), used by the btBroadphaseInterface broadphases.
void Process(const btDbvtNode *leaf)
btDbvtBroadphase(btOverlappingPairCache *paircache=0)
void Process(const btDbvtNode *n)
virtual void setAabb(btBroadphaseProxy *proxy, const btVector3 &aabbMin, const btVector3 &aabbMax, btDispatcher *dispatcher)
virtual btOverlappingPairCache * getOverlappingPairCache()
static btDbvtAabbMm FromMM(const btVector3 &mi, const btVector3 &mx)
virtual void destroyProxy(btBroadphaseProxy *proxy, btDispatcher *dispatcher)
virtual void rayTest(const btVector3 &rayFrom, const btVector3 &rayTo, btBroadphaseRayCallback &rayCallback, const btVector3 &aabbMin=btVector3(0, 0, 0), const btVector3 &aabbMax=btVector3(0, 0, 0))
static void listremove(T *item, T *&list)
#define btAlignedFree(ptr)
virtual btBroadphaseProxy * createProxy(const btVector3 &aabbMin, const btVector3 &aabbMax, int shapeType, void *userPtr, int collisionFilterGroup, int collisionFilterMask, btDispatcher *dispatcher)=0
unsigned long long int getTimeMicroseconds()
Returns the time in us since the last call to reset or since the Clock was created.
DBVT_PREFIX void collideTV(const btDbvtNode *root, const btDbvtVolume &volume, DBVT_IPOLICY) const
static int listcount(T *root)
virtual void printStats()
static btDbvtAabbMm FromCR(const btVector3 &c, btScalar r)
The btBroadphaseInterface class provides an interface to detect aabb-overlapping object pairs...
The btBroadphaseProxy is the main class that can be used with the Bullet broadphases.
btBroadphaseProxy * m_pProxy1
btCollisionAlgorithm * m_algorithm
btVector3 can be used to represent 3D points and vectors.
#define ATTRIBUTE_ALIGNED16(a)
virtual bool process(const btBroadphaseProxy *proxy)=0
int size() const
return the number of elements in the array
btBroadphaseAabbCallback & m_aabbCallback
btBroadphaseProxy * m_pProxy0
void setAabbForceUpdate(btBroadphaseProxy *absproxy, const btVector3 &aabbMin, const btVector3 &aabbMax, btDispatcher *)
this setAabbForceUpdate is similar to setAabb but always forces the aabb update.
btDbvtTreeCollider(btDbvtBroadphase *p)
BroadphaseRayTester(btBroadphaseRayCallback &orgCallback)
virtual btBroadphasePair * addOverlappingPair(btBroadphaseProxy *proxy0, btBroadphaseProxy *proxy1)=0
static void clear(T &value)
void resize(int newsize, const T &fillData=T())
btVector3 m_rayDirectionInverse
added some cached data to accelerate ray-AABB tests
DBVT_INLINE bool Intersect(const btDbvtAabbMm &a, const btDbvtAabbMm &b)
virtual void setAabb(btBroadphaseProxy *proxy, const btVector3 &aabbMin, const btVector3 &aabbMax, btDispatcher *dispatcher)=0
#define btAlignedAlloc(size, alignment)
static btDbvtVolume bounds(btDbvtNode **leaves, int count)
virtual void calculateOverlappingPairs(btDispatcher *dispatcher)
calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during th...
unsigned int btGetCurrentThreadIndex()
btScalar gDbvtMargin
btDbvtBroadphase implementation by Nathanael Presson
The btDispatcher interface class can be used in combination with broadphase to dispatch calculations ...
const T & btMin(const T &a, const T &b)
BroadphaseAabbTester(btBroadphaseAabbCallback &orgCallback)
virtual void destroyProxy(btBroadphaseProxy *proxy, btDispatcher *dispatcher)=0
btBroadphaseProxy * createProxy(const btVector3 &aabbMin, const btVector3 &aabbMax, int shapeType, void *userPtr, int collisionFilterGroup, int collisionFilterMask, btDispatcher *dispatcher)
Hash-space based Pair Cache, thanks to Erin Catto, Box2D, http://www.box2d.org, and Pierre Terdiman...
virtual void calculateOverlappingPairs(btDispatcher *dispatcher)=0
calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during th...
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
void quickSort(const L &CompareFunc)
btScalar btCos(btScalar x)
DBVT_INLINE bool NotEqual(const btDbvtAabbMm &a, const btDbvtAabbMm &b)
void Process(const btDbvtNode *leaf)
virtual void getAabb(btBroadphaseProxy *proxy, btVector3 &aabbMin, btVector3 &aabbMax) const
The btBroadphasePair class contains a pair of aabb-overlapping objects.