17#ifndef BT_DYNAMIC_BOUNDING_VOLUME_TREE_H
18#define BT_DYNAMIC_BOUNDING_VOLUME_TREE_H
29#define DBVT_IMPL_GENERIC 0
30#define DBVT_IMPL_SSE 1
34#if (defined(_MSC_VER) && _MSC_VER >= 1400)
35#define DBVT_USE_TEMPLATE 1
37#define DBVT_USE_TEMPLATE 0
40#define DBVT_USE_TEMPLATE 0
44#define DBVT_USE_INTRINSIC_SSE 1
47#define DBVT_USE_MEMMOVE 1
50#define DBVT_ENABLE_BENCHMARK 0
53#define DBVT_INLINE SIMD_FORCE_INLINE
58#if defined(BT_USE_SSE)
59#define DBVT_SELECT_IMPL DBVT_IMPL_SSE
60#define DBVT_MERGE_IMPL DBVT_IMPL_SSE
61#define DBVT_INT0_IMPL DBVT_IMPL_SSE
63#define DBVT_SELECT_IMPL DBVT_IMPL_GENERIC
64#define DBVT_MERGE_IMPL DBVT_IMPL_GENERIC
65#define DBVT_INT0_IMPL DBVT_IMPL_GENERIC
68#if (DBVT_SELECT_IMPL == DBVT_IMPL_SSE) || \
69 (DBVT_MERGE_IMPL == DBVT_IMPL_SSE) || \
70 (DBVT_INT0_IMPL == DBVT_IMPL_SSE)
80#define DBVT_VIRTUAL_DTOR(a)
81#define DBVT_PREFIX template <typename T>
82#define DBVT_IPOLICY T& policy
83#define DBVT_CHECKTYPE \
84 static const ICollide& typechecker = *(T*)1; \
87#define DBVT_VIRTUAL_DTOR(a) \
89#define DBVT_VIRTUAL virtual
91#define DBVT_IPOLICY ICollide& policy
96#if !defined(__CELLOS_LV2__) && !defined(__MWERKS__)
102#ifndef DBVT_USE_TEMPLATE
103#error "DBVT_USE_TEMPLATE undefined"
106#ifndef DBVT_USE_MEMMOVE
107#error "DBVT_USE_MEMMOVE undefined"
110#ifndef DBVT_ENABLE_BENCHMARK
111#error "DBVT_ENABLE_BENCHMARK undefined"
114#ifndef DBVT_SELECT_IMPL
115#error "DBVT_SELECT_IMPL undefined"
118#ifndef DBVT_MERGE_IMPL
119#error "DBVT_MERGE_IMPL undefined"
122#ifndef DBVT_INT0_IMPL
123#error "DBVT_INT0_IMPL undefined"
325 void write(IWriter* iwriter)
const;
326 void clone(
btDbvt& dest, IClone* iclone = 0)
const;
330#if DBVT_ENABLE_BENCHMARK
398 unsigned int signs[3],
418 bool fullsort =
true);
429 if (a[i[m]].value >= v)
441 if (ifree.
size() > 0)
443 i = ifree[ifree.
size() - 1];
491 box.
mi = box.
mx = pts[0];
492 for (
int i = 1; i < n; ++i)
504 box.
mi = box.
mx = *ppts[0];
505 for (
int i = 1; i < n; ++i)
540 return ((
mi.
x() <= a.
mi.
x()) &&
587 if ((
btDot(n, px) + o) < 0)
return (-1);
588 if ((
btDot(n, pi) + o) >= 0)
return (+1);
596 const btVector3 p(b[(signs >> 0) & 1]->x(),
597 b[(signs >> 1) & 1]->y(),
598 b[(signs >> 2) & 1]->z());
599 return (
btDot(p, v));
605 for (
int i = 0; i < 3; ++i)
624#if DBVT_INT0_IMPL == DBVT_IMPL_SSE
625 const __m128 rt(_mm_or_ps(_mm_cmplt_ps(_mm_load_ps(b.
mx), _mm_load_ps(a.
mi)),
626 _mm_cmplt_ps(_mm_load_ps(a.
mx), _mm_load_ps(b.
mi))));
628 const __int32* pu((
const __int32*)&rt);
630 const int* pu((
const int*)&rt);
632 return ((pu[0] | pu[1] | pu[2]) == 0);
634 return ((a.
mi.
x() <= b.
mx.
x()) &&
647 return ((b.
x() >= a.
mi.
x()) &&
648 (b.
y() >= a.
mi.
y()) &&
649 (b.
z() >= a.
mi.
z()) &&
650 (b.
x() <= a.
mx.
x()) &&
651 (b.
y() <= a.
mx.
y()) &&
652 (b.
z() <= a.
mx.
z()));
670#if DBVT_SELECT_IMPL == DBVT_IMPL_SSE
673 static ATTRIBUTE_ALIGNED16(
const unsigned __int32) mask[] = {0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff};
675 static ATTRIBUTE_ALIGNED16(
const unsigned int) mask[] = {0x7fffffff, 0x7fffffff, 0x7fffffff, 0x00000000 };
678#if DBVT_USE_INTRINSIC_SSE
687 __m128 omi(_mm_load_ps(o.
mi));
688 omi = _mm_add_ps(omi, _mm_load_ps(o.
mx));
689 __m128 ami(_mm_load_ps(a.
mi));
690 ami = _mm_add_ps(ami, _mm_load_ps(a.
mx));
691 ami = _mm_sub_ps(ami, omi);
692 ami = _mm_and_ps(ami, _mm_load_ps((
const float*)mask));
693 __m128 bmi(_mm_load_ps(b.
mi));
694 bmi = _mm_add_ps(bmi, _mm_load_ps(b.
mx));
695 bmi = _mm_sub_ps(bmi, omi);
696 bmi = _mm_and_ps(bmi, _mm_load_ps((
const float*)mask));
697 __m128 t0(_mm_movehl_ps(ami, ami));
698 ami = _mm_add_ps(ami, t0);
699 ami = _mm_add_ss(ami, _mm_shuffle_ps(ami, ami, 1));
700 __m128 t1(_mm_movehl_ps(bmi, bmi));
701 bmi = _mm_add_ps(bmi, t1);
702 bmi = _mm_add_ss(bmi, _mm_shuffle_ps(bmi, bmi, 1));
705 tmp.ssereg = _mm_cmple_ss(bmi, ami);
706 return tmp.ints[0] & 1;
749#if DBVT_MERGE_IMPL == DBVT_IMPL_SSE
750 __m128 ami(_mm_load_ps(a.
mi));
751 __m128 amx(_mm_load_ps(a.
mx));
752 __m128 bmi(_mm_load_ps(b.
mi));
753 __m128 bmx(_mm_load_ps(b.
mx));
754 ami = _mm_min_ps(ami, bmi);
755 amx = _mm_max_ps(amx, bmx);
756 _mm_store_ps(r.
mi, ami);
757 _mm_store_ps(r.
mx, amx);
759 for (
int i = 0; i < 3; ++i)
761 if (a.
mi[i] < b.
mi[i])
765 if (a.
mx[i] > b.
mx[i])
777 return ((a.
mi.
x() != b.
mi.
x()) ||
795 policy.Process(root);
816 policy.Process(root);
833 stkStack[0] =
sStkNN(root0, root1);
836 sStkNN p = stkStack[--depth];
837 if (depth > treshold)
840 treshold = stkStack.
size() - 4;
877 policy.Process(p.
a, p.
b);
897 stkStack[0] =
sStknNN(root, root);
901 if (depth > treshold)
904 treshold = stkStack.
size() - 4;
941 policy.Process(p.
a, p.
b);
961 stkStack[0] =
sStkNN(root, root);
964 sStkNN p = stkStack[--depth];
965 if (depth > treshold)
968 treshold = stkStack.
size() - 4;
1005 policy.Process(p.
a, p.
b);
1030 if (depth > treshold)
1070 policy.Process(p.
a, p.
b);
1093 stkStack[0]=sStkNN(root0,root1);
1095 sStkNN p=stkStack[--depth];
1096 if(
Intersect(p.a->volume,p.b->volume,xform))
1101 treshold=stkStack.
size()-4;
1103 if(p.a->isinternal())
1105 if(p.b->isinternal())
1107 stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[0]);
1108 stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[0]);
1109 stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[1]);
1110 stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[1]);
1114 stkStack[depth++]=sStkNN(p.a->childs[0],p.b);
1115 stkStack[depth++]=sStkNN(p.a->childs[1],p.b);
1120 if(p.b->isinternal())
1122 stkStack[depth++]=sStkNN(p.a,p.b->childs[0]);
1123 stkStack[depth++]=sStkNN(p.a,p.b->childs[1]);
1127 policy.Process(p.a,p.b);
1159#ifndef BT_DISABLE_STACK_TEMP_MEMORY
1183 }
while (stack.
size() > 0);
1218 }
while (stack.
size() > 0);
1227 unsigned int signs[3],
1250 btScalar tmin = 1.f, lambda_min = 0.f;
1251 unsigned int result1 =
false;
1252 result1 =
btRayAabb2(rayFrom, rayDirectionInverse, signs,
bounds, tmin, lambda_min, lambda_max);
1257 if (depth > treshold)
1260 treshold = stack.
size() - 2;
1262 stack[depth++] = node->
childs[0];
1263 stack[depth++] = node->
childs[1];
1267 policy.Process(node);
1292 unsigned int signs[3] = {rayDirectionInverse[0] < 0.0, rayDirectionInverse[1] < 0.0, rayDirectionInverse[2] < 0.0};
1294 btScalar lambda_max = rayDir.
dot(rayTo - rayFrom);
1304#ifndef BT_DISABLE_STACK_TEMP_MEMORY
1318 btScalar tmin = 1.f, lambda_min = 0.f;
1319 unsigned int result1 =
btRayAabb2(rayFrom, rayDirectionInverse, signs,
bounds, tmin, lambda_min, lambda_max);
1321#ifdef COMPARE_BTRAY_AABB2
1331 if (depth > treshold)
1334 treshold = stack.
size() - 2;
1336 stack[depth++] = node->
childs[0];
1337 stack[depth++] = node->
childs[1];
1341 policy.Process(node);
1359 const int inside = (1 << count) - 1;
1361 int signs[
sizeof(unsigned) * 8];
1362 btAssert(count <
int(
sizeof(signs) /
sizeof(signs[0])));
1363 for (
int i = 0; i < count; ++i)
1365 signs[i] = ((normals[i].
x() >= 0) ? 1 : 0) +
1366 ((normals[i].
y() >= 0) ? 2 : 0) +
1367 ((normals[i].
z() >= 0) ? 4 : 0);
1376 for (
int i = 0, j = 1; (!out) && (i < count); ++i, j <<= 1)
1378 if (0 == (se.
mask & j))
1404 }
while (stack.
size());
1421 const unsigned srtsgns = (sortaxis[0] >= 0 ? 1 : 0) +
1422 (sortaxis[1] >= 0 ? 2 : 0) +
1423 (sortaxis[2] >= 0 ? 4 : 0);
1424 const int inside = (1 << count) - 1;
1428 int signs[
sizeof(unsigned) * 8];
1429 btAssert(count <
int(
sizeof(signs) /
sizeof(signs[0])));
1430 for (
int i = 0; i < count; ++i)
1432 signs[i] = ((normals[i].
x() >= 0) ? 1 : 0) +
1433 ((normals[i].
y() >= 0) ? 2 : 0) +
1434 ((normals[i].
z() >= 0) ? 4 : 0);
1442 const int id = stack[stack.
size() - 1];
1446 if (se.
mask != inside)
1449 for (
int i = 0, j = 1; (!out) && (i < count); ++i, j <<= 1)
1451 if (0 == (se.
mask & j))
1467 if (policy.Descent(se.
node))
1474 const int q = nes[0].
value < nes[1].
value ? 1 : 0;
1475 int j = stack.
size();
1476 if (fsort && (j > 0))
1479 j =
nearest(&stack[0], &stock[0], nes[q].value, 0, stack.
size());
1486 int num_items_to_move = stack.
size() - 1 - j;
1487 if (num_items_to_move > 0)
1488 memmove(&stack[j + 1], &stack[j],
sizeof(
int) * num_items_to_move);
1491 for (
int k = stack.
size() - 1; k > j; --k)
1493 stack[k] = stack[k - 1];
1496 stack[j] =
allocate(ifree, stock, nes[q]);
1498 j =
nearest(&stack[0], &stock[0], nes[1 - q].value, j, stack.
size());
1502 int num_items_to_move = stack.
size() - 1 - j;
1503 if (num_items_to_move > 0)
1504 memmove(&stack[j + 1], &stack[j],
sizeof(
int) * num_items_to_move);
1507 for (
int k = stack.
size() - 1; k > j; --k)
1509 stack[k] = stack[k - 1];
1512 stack[j] =
allocate(ifree, stock, nes[1 - q]);
1525 }
while (stack.
size());
1544 if (policy.Descent(n))
1556 }
while (stack.
size() > 0);
1564#undef DBVT_USE_MEMMOVE
1565#undef DBVT_USE_TEMPLATE
1566#undef DBVT_VIRTUAL_DTOR
1570#undef DBVT_CHECKTYPE
1571#undef DBVT_IMPL_GENERIC
1573#undef DBVT_USE_INTRINSIC_SSE
1574#undef DBVT_SELECT_IMPL
1575#undef DBVT_MERGE_IMPL
1576#undef DBVT_INT0_IMPL
bool btRayAabb(const btVector3 &rayFrom, const btVector3 &rayTo, const btVector3 &aabbMin, const btVector3 &aabbMax, btScalar ¶m, btVector3 &normal)
bool btRayAabb2(const btVector3 &rayFrom, const btVector3 &rayInvDirection, const unsigned int raySign[3], const btVector3 bounds[2], btScalar &tmin, btScalar lambda_min, btScalar lambda_max)
static btDbvtVolume bounds(btDbvtNode **leaves, int count)
#define DBVT_VIRTUAL_DTOR(a)
DBVT_INLINE bool Intersect(const btDbvtAabbMm &a, const btDbvtAabbMm &b)
btDbvtAabbMm btDbvtVolume
DBVT_INLINE void Merge(const btDbvtAabbMm &a, const btDbvtAabbMm &b, btDbvtAabbMm &r)
DBVT_INLINE bool NotEqual(const btDbvtAabbMm &a, const btDbvtAabbMm &b)
DBVT_INLINE btScalar Proximity(const btDbvtAabbMm &a, const btDbvtAabbMm &b)
btAlignedObjectArray< const btDbvtNode * > btNodeStack
DBVT_INLINE int Select(const btDbvtAabbMm &o, const btDbvtAabbMm &a, const btDbvtAabbMm &b)
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
#define ATTRIBUTE_ALIGNED16(a)
btScalar btFabs(btScalar x)
btScalar btDot(const btVector3 &v1, const btVector3 &v2)
Return the dot product between two vectors.
int size() const
return the number of elements in the array
void resize(int newsize, const T &fillData=T())
void push_back(const T &_Val)
void initializeFromBuffer(void *buffer, int size, int capacity)
btVector3 can be used to represent 3D points and vectors.
void setMax(const btVector3 &other)
Set each element to the max of the current values and the values of another btVector3.
void setZ(btScalar _z)
Set the z value.
const btScalar & z() const
Return the z value.
btScalar dot(const btVector3 &v) const
Return the dot product.
void setY(btScalar _y)
Set the y value.
void setX(btScalar _x)
Set the x value.
const btScalar & x() const
Return the x value.
void setMin(const btVector3 &other)
Set each element to the min of the current values and the values of another btVector3.
btVector3 & normalize()
Normalize this vector x^2 + y^2 + z^2 = 1.
const btScalar & y() const
Return the y value.
btDbvntNode(const btDbvtNode *n)
DBVT_INLINE bool isinternal() const
DBVT_INLINE bool isleaf() const
DBVT_INLINE btScalar ProjectMinimum(const btVector3 &v, unsigned signs) const
DBVT_INLINE bool Contain(const btDbvtAabbMm &a) const
DBVT_INLINE void SignedExpand(const btVector3 &e)
DBVT_INLINE btDbvtAabbMm()
DBVT_INLINE btVector3 & tMaxs()
static btDbvtAabbMm FromMM(const btVector3 &mi, const btVector3 &mx)
DBVT_INLINE const btVector3 & Mins() const
DBVT_INLINE friend bool NotEqual(const btDbvtAabbMm &a, const btDbvtAabbMm &b)
static btDbvtAabbMm FromCE(const btVector3 &c, const btVector3 &e)
DBVT_INLINE friend int Select(const btDbvtAabbMm &o, const btDbvtAabbMm &a, const btDbvtAabbMm &b)
DBVT_INLINE friend bool Intersect(const btDbvtAabbMm &a, const btDbvtAabbMm &b)
DBVT_INLINE btVector3 & tMins()
DBVT_INLINE friend void Merge(const btDbvtAabbMm &a, const btDbvtAabbMm &b, btDbvtAabbMm &r)
static btDbvtAabbMm FromCR(const btVector3 &c, btScalar r)
DBVT_INLINE const btVector3 & Maxs() const
DBVT_INLINE btVector3 Extents() const
static btDbvtAabbMm FromPoints(const btVector3 *pts, int n)
DBVT_INLINE int Classify(const btVector3 &n, btScalar o, int s) const
DBVT_INLINE void Expand(const btVector3 &e)
DBVT_INLINE btVector3 Center() const
DBVT_INLINE friend btScalar Proximity(const btDbvtAabbMm &a, const btDbvtAabbMm &b)
DBVT_INLINE btVector3 Lengths() const
DBVT_INLINE void AddSpan(const btVector3 &d, btScalar &smi, btScalar &smx) const
DBVT_INLINE bool isinternal() const
DBVT_INLINE bool isleaf() const
virtual void CloneLeaf(btDbvtNode *)
DBVT_VIRTUAL bool AllLeaves(const btDbvtNode *)
DBVT_VIRTUAL void Process(const btDbvtNode *)
DBVT_VIRTUAL void Process(const btDbvntNode *, const btDbvntNode *)
DBVT_VIRTUAL void Process(const btDbvtNode *n, btScalar)
DBVT_VIRTUAL bool Descent(const btDbvtNode *)
DBVT_VIRTUAL void Process(const btDbvtNode *, const btDbvtNode *)
virtual void WriteLeaf(const btDbvtNode *, int index, int parent)=0
virtual void Prepare(const btDbvtNode *root, int numnodes)=0
virtual void WriteNode(const btDbvtNode *, int index, int parent, int child0, int child1)=0
sStkCLN(const btDbvtNode *n, btDbvtNode *p)
sStkNN(const btDbvtNode *na, const btDbvtNode *nb)
sStkNPS(const btDbvtNode *n, unsigned m, btScalar v)
sStkNP(const btDbvtNode *n, unsigned m)
sStknNN(const btDbvntNode *na, const btDbvntNode *nb)
The btDbvt class implements a fast dynamic bounding volume tree based on axis aligned bounding boxes ...
static DBVT_INLINE int nearest(const int *i, const btDbvt::sStkNPS *a, btScalar v, int l, int h)
btDbvtNode * insert(const btDbvtVolume &box, void *data)
static DBVT_INLINE int allocate(btAlignedObjectArray< int > &ifree, btAlignedObjectArray< sStkNPS > &stock, const sStkNPS &value)
void optimizeIncremental(int passes)
DBVT_PREFIX void selfCollideTT(const btDbvtNode *root, DBVT_IPOLICY)
void optimizeTopDown(int bu_treshold=128)
static DBVT_PREFIX void collideOCL(const btDbvtNode *root, const btVector3 *normals, const btScalar *offsets, const btVector3 &sortaxis, int count, DBVT_IPOLICY, bool fullsort=true)
static DBVT_PREFIX void enumNodes(const btDbvtNode *root, DBVT_IPOLICY)
void write(IWriter *iwriter) const
static DBVT_PREFIX void collideTU(const btDbvtNode *root, DBVT_IPOLICY)
void update(btDbvtNode *leaf, int lookahead=-1)
btAlignedObjectArray< sStkNN > m_stkStack
DBVT_PREFIX void collideTV(const btDbvtNode *root, const btDbvtVolume &volume, DBVT_IPOLICY) const
void clone(btDbvt &dest, IClone *iclone=0) const
static DBVT_PREFIX void rayTest(const btDbvtNode *root, const btVector3 &rayFrom, const btVector3 &rayTo, DBVT_IPOLICY)
rayTest is a re-entrant ray test, and can be called in parallel as long as the btAlignedAlloc is thre...
DBVT_PREFIX void rayTestInternal(const btDbvtNode *root, const btVector3 &rayFrom, const btVector3 &rayTo, const btVector3 &rayDirectionInverse, unsigned int signs[3], btScalar lambda_max, const btVector3 &aabbMin, const btVector3 &aabbMax, btAlignedObjectArray< const btDbvtNode * > &stack, DBVT_IPOLICY) const
rayTestInternal is faster than rayTest, because it uses a persistent stack (to reduce dynamic memory ...
static DBVT_PREFIX void collideKDOP(const btDbvtNode *root, const btVector3 *normals, const btScalar *offsets, int count, DBVT_IPOLICY)
static void extractLeaves(const btDbvtNode *node, btAlignedObjectArray< const btDbvtNode * > &leaves)
static DBVT_PREFIX void enumLeaves(const btDbvtNode *root, DBVT_IPOLICY)
DBVT_PREFIX void collideTVNoStackAlloc(const btDbvtNode *root, const btDbvtVolume &volume, btNodeStack &stack, DBVT_IPOLICY) const
static int countLeaves(const btDbvtNode *node)
DBVT_PREFIX void collideTTpersistentStack(const btDbvtNode *root0, const btDbvtNode *root1, DBVT_IPOLICY)
void remove(btDbvtNode *leaf)
DBVT_PREFIX void collideTT(const btDbvtNode *root0, const btDbvtNode *root1, DBVT_IPOLICY)
static int maxdepth(const btDbvtNode *node)
DBVT_PREFIX void selfCollideT(const btDbvntNode *root, DBVT_IPOLICY)