soc-2008-mxcurioni: FRS_glBlendEquation files
authorMaxime Curioni <maxime.curioni@gmail.com>
Sun, 28 Sep 2008 18:43:51 +0000 (18:43 +0000)
committerMaxime Curioni <maxime.curioni@gmail.com>
Sun, 28 Sep 2008 18:43:51 +0000 (18:43 +0000)
67 files changed:
extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.cpp [new file with mode: 0644]
extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.h [new file with mode: 0644]
extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp [new file with mode: 0644]
extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h [new file with mode: 0644]
extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp [new file with mode: 0644]
extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h [new file with mode: 0644]
extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h [new file with mode: 0644]
extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp [new file with mode: 0644]
extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h [new file with mode: 0644]
extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp [new file with mode: 0644]
extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h [new file with mode: 0644]
extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp [new file with mode: 0644]
extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h [new file with mode: 0644]
extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h [new file with mode: 0644]
extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp [new file with mode: 0644]
extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h [new file with mode: 0644]
extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp [new file with mode: 0644]
extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h [new file with mode: 0644]
extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp [new file with mode: 0644]
extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.h [new file with mode: 0644]
extern/bullet2/src/BulletCollision/CollisionShapes/btMaterial.h [new file with mode: 0644]
extern/bullet2/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp [new file with mode: 0644]
extern/bullet2/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h [new file with mode: 0644]
extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp [new file with mode: 0644]
extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h [new file with mode: 0644]
extern/bullet2/src/BulletCollision/CollisionShapes/btShapeHull.cpp [new file with mode: 0644]
extern/bullet2/src/BulletCollision/CollisionShapes/btShapeHull.h [new file with mode: 0644]
extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp [new file with mode: 0644]
extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h [new file with mode: 0644]
extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.cpp [new file with mode: 0644]
extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.h [new file with mode: 0644]
extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp [new file with mode: 0644]
extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h [new file with mode: 0644]
extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp [new file with mode: 0644]
extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h [new file with mode: 0644]
extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.cpp [new file with mode: 0644]
extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.h [new file with mode: 0644]
extern/bullet2/src/LinearMath/btConvexHull.cpp [new file with mode: 0644]
extern/bullet2/src/LinearMath/btConvexHull.h [new file with mode: 0644]
extern/bullet2/src/LinearMath/btHashMap.h [new file with mode: 0644]
extern/bullet2/src/LinearMath/btPoolAllocator.h [new file with mode: 0644]
intern/elbeem/intern/controlparticles.cpp [new file with mode: 0644]
intern/elbeem/intern/controlparticles.h [new file with mode: 0644]
intern/elbeem/intern/elbeem_control.cpp [new file with mode: 0644]
intern/elbeem/intern/elbeem_control.h [new file with mode: 0644]
intern/elbeem/intern/mvmcoords.cpp [new file with mode: 0644]
intern/elbeem/intern/mvmcoords.h [new file with mode: 0644]
intern/elbeem/intern/solver_control.cpp [new file with mode: 0644]
intern/elbeem/intern/solver_control.h [new file with mode: 0644]
intern/guardedalloc/intern/mmap_win.c
intern/guardedalloc/mmap_win.h
release/Makefile
release/scripts/bpymodules/BPyAddMesh.py
release/scripts/ms3d_import_ascii.py [new file with mode: 0644]
release/scripts/scripttemplate_gamelogic.py [new file with mode: 0644]
release/scripts/scripttemplate_gamelogic_basic.py [new file with mode: 0644]
release/scripts/scripttemplate_ipo_gen.py [new file with mode: 0644]
source/blender/blenkernel/BKE_bullet.h [new file with mode: 0644]
source/blender/blenkernel/BKE_fluidsim.h [new file with mode: 0644]
source/blender/blenkernel/BKE_simple_deform.h [new file with mode: 0644]
source/blender/blenkernel/intern/bullet.c [new file with mode: 0644]
source/blender/blenkernel/intern/fluidsim.c [new file with mode: 0644]
source/blender/blenkernel/intern/simple_deform.c [new file with mode: 0644]
source/blender/freestyle/intern/rendering/GLBlendEquation.cpp [new file with mode: 0644]
source/blender/freestyle/intern/rendering/GLBlendEquation.h [new file with mode: 0644]
source/blender/include/BIF_keyframing.h [new file with mode: 0644]
source/blender/src/keyframing.c [new file with mode: 0644]

diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.cpp
new file mode 100644 (file)
index 0000000..7c41c8d
--- /dev/null
@@ -0,0 +1,1289 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+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.
+*/
+///btDbvt implementation by Nathanael Presson
+
+#include "btDbvt.h"
+
+//
+typedef btAlignedObjectArray<btDbvtNode*>                      tNodeArray;
+typedef btAlignedObjectArray<const btDbvtNode*>        tConstNodeArray;
+
+//
+struct btDbvtNodeEnumerator : btDbvt::ICollide
+{
+tConstNodeArray        nodes;
+void Process(const btDbvtNode* n) { nodes.push_back(n); }
+};
+
+//
+static DBVT_INLINE int                 indexof(const btDbvtNode* node)
+{
+return(node->parent->childs[1]==node);
+}
+
+//
+static DBVT_INLINE btDbvtVolume        merge(  const btDbvtVolume& a,
+                                                                               const btDbvtVolume& b)
+{
+#if DBVT_MERGE_IMPL==DBVT_IMPL_SSE
+DBVT_ALIGN char locals[sizeof(btDbvtAabbMm)];
+btDbvtVolume&  res=*(btDbvtVolume*)locals;
+#else
+btDbvtVolume   res;
+#endif
+Merge(a,b,res);
+return(res);
+}
+
+// volume+edge lengths
+static DBVT_INLINE btScalar            size(const btDbvtVolume& a)
+{
+const btVector3        edges=a.Lengths();
+return(        edges.x()*edges.y()*edges.z()+
+               edges.x()+edges.y()+edges.z());
+}
+
+//
+static void                                            getmaxdepth(const btDbvtNode* node,int depth,int& maxdepth)
+{
+if(node->isinternal())
+       {
+       getmaxdepth(node->childs[0],depth+1,maxdepth);
+       getmaxdepth(node->childs[0],depth+1,maxdepth);
+       } else maxdepth=btMax(maxdepth,depth);
+}
+
+//
+static DBVT_INLINE void                        deletenode(     btDbvt* pdbvt,
+                                                                                       btDbvtNode* node)
+{
+btAlignedFree(pdbvt->m_free);
+pdbvt->m_free=node;
+}
+       
+//
+static void                                            recursedeletenode(      btDbvt* pdbvt,
+                                                                                                       btDbvtNode* node)
+{
+if(!node->isleaf())
+       {
+       recursedeletenode(pdbvt,node->childs[0]);
+       recursedeletenode(pdbvt,node->childs[1]);
+       }
+if(node==pdbvt->m_root) pdbvt->m_root=0;
+deletenode(pdbvt,node);
+}
+
+//
+static DBVT_INLINE btDbvtNode* createnode(     btDbvt* pdbvt,
+                                                                                       btDbvtNode* parent,
+                                                                                       void* data)
+{
+btDbvtNode*    node;
+if(pdbvt->m_free)
+       { node=pdbvt->m_free;pdbvt->m_free=0; }
+       else
+       { node=new(btAlignedAlloc(sizeof(btDbvtNode),16)) btDbvtNode(); }
+node->parent   =       parent;
+node->data             =       data;
+node->childs[1]        =       0;
+return(node);
+}
+
+//
+static DBVT_INLINE btDbvtNode* createnode(     btDbvt* pdbvt,
+                                                                                       btDbvtNode* parent,
+                                                                                       const btDbvtVolume& volume,
+                                                                                       void* data)
+{
+btDbvtNode*    node=createnode(pdbvt,parent,data);
+node->volume=volume;
+return(node);
+}
+
+//
+static DBVT_INLINE btDbvtNode* createnode(     btDbvt* pdbvt,
+                                                                                       btDbvtNode* parent,
+                                                                                       const btDbvtVolume& volume0,
+                                                                                       const btDbvtVolume& volume1,
+                                                                                       void* data)
+{
+btDbvtNode*    node=createnode(pdbvt,parent,data);
+Merge(volume0,volume1,node->volume);
+return(node);
+}
+
+//
+static void                                            insertleaf(     btDbvt* pdbvt,
+                                                                                       btDbvtNode* root,
+                                                                                       btDbvtNode* leaf)
+{
+if(!pdbvt->m_root)
+       {
+       pdbvt->m_root   =       leaf;
+       leaf->parent    =       0;
+       }
+       else
+       {
+       if(!root->isleaf())
+               {
+               do      {
+                       root=root->childs[Select(       leaf->volume,
+                                                                               root->childs[0]->volume,
+                                                                               root->childs[1]->volume)];
+                       } while(!root->isleaf());
+               }
+       btDbvtNode*     prev=root->parent;
+       btDbvtNode*     node=createnode(pdbvt,prev,leaf->volume,root->volume,0);
+       if(prev)
+               {
+               prev->childs[indexof(root)]     =       node;
+               node->childs[0]                         =       root;root->parent=node;
+               node->childs[1]                         =       leaf;leaf->parent=node;
+               do      {
+                       if(!prev->volume.Contain(node->volume))
+                               Merge(prev->childs[0]->volume,prev->childs[1]->volume,prev->volume);
+                               else
+                               break;
+                       node=prev;
+                       } while(0!=(prev=node->parent));
+               }
+               else
+               {
+               node->childs[0] =       root;root->parent=node;
+               node->childs[1] =       leaf;leaf->parent=node;
+               pdbvt->m_root   =       node;
+               }
+       }
+}
+       
+//
+static btDbvtNode*                             removeleaf(     btDbvt* pdbvt,
+                                                                                       btDbvtNode* leaf)
+{
+if(leaf==pdbvt->m_root)
+       {
+       pdbvt->m_root=0;
+       return(0);
+       }
+       else
+       {
+       btDbvtNode*     parent=leaf->parent;
+       btDbvtNode*     prev=parent->parent;
+       btDbvtNode*     sibling=parent->childs[1-indexof(leaf)];                        
+       if(prev)
+               {
+               prev->childs[indexof(parent)]=sibling;
+               sibling->parent=prev;
+               deletenode(pdbvt,parent);
+               while(prev)
+                       {
+                       const btDbvtVolume      pb=prev->volume;
+                       Merge(prev->childs[0]->volume,prev->childs[1]->volume,prev->volume);
+                       if(NotEqual(pb,prev->volume))
+                               {
+                               prev=prev->parent;
+                               } else break;
+                       }
+               return(prev?prev:pdbvt->m_root);
+               }
+               else
+               {                                                               
+               pdbvt->m_root=sibling;
+               sibling->parent=0;
+               deletenode(pdbvt,parent);
+               return(pdbvt->m_root);
+               }                       
+       }
+}
+
+//
+static void                                            fetchleaves(btDbvt* pdbvt,
+                                                                                       btDbvtNode* root,
+                                                                                       tNodeArray& leaves,
+                                                                                       int depth=-1)
+{
+if(root->isinternal()&&depth)
+       {
+       fetchleaves(pdbvt,root->childs[0],leaves,depth-1);
+       fetchleaves(pdbvt,root->childs[1],leaves,depth-1);
+       deletenode(pdbvt,root);
+       }
+       else
+       {
+       leaves.push_back(root);
+       }
+}
+
+//
+static void                                            split(  const tNodeArray& leaves,
+                                                                               tNodeArray& left,
+                                                                               tNodeArray& right,
+                                                                               const btVector3& org,
+                                                                               const btVector3& axis)
+{
+left.resize(0);
+right.resize(0);
+for(int i=0,ni=leaves.size();i<ni;++i)
+       {
+       if(dot(axis,leaves[i]->volume.Center()-org)<0)
+               left.push_back(leaves[i]);
+               else
+               right.push_back(leaves[i]);
+       }
+}
+
+//
+static btDbvtVolume                            bounds( const tNodeArray& leaves)
+{
+#if DBVT_MERGE_IMPL==DBVT_IMPL_SSE
+DBVT_ALIGN char        locals[sizeof(btDbvtVolume)];
+btDbvtVolume&  volume=*(btDbvtVolume*)locals;
+volume=leaves[0]->volume;
+#else
+btDbvtVolume volume=leaves[0]->volume;
+#endif
+for(int i=1,ni=leaves.size();i<ni;++i)
+       {
+       Merge(volume,leaves[i]->volume,volume);
+       }
+return(volume);
+}
+
+//
+static void                                            bottomup(       btDbvt* pdbvt,
+                                                                                       tNodeArray& leaves)
+{
+while(leaves.size()>1)
+       {
+       btScalar        minsize=SIMD_INFINITY;
+       int                     minidx[2]={-1,-1};
+       for(int i=0;i<leaves.size();++i)
+               {
+               for(int j=i+1;j<leaves.size();++j)
+                       {
+                       const btScalar  sz=size(merge(leaves[i]->volume,leaves[j]->volume));
+                       if(sz<minsize)
+                               {
+                               minsize         =       sz;
+                               minidx[0]       =       i;
+                               minidx[1]       =       j;
+                               }
+                       }
+               }
+       btDbvtNode*     n[]     =       {leaves[minidx[0]],leaves[minidx[1]]};
+       btDbvtNode*     p       =       createnode(pdbvt,0,n[0]->volume,n[1]->volume,0);
+       p->childs[0]            =       n[0];
+       p->childs[1]            =       n[1];
+       n[0]->parent            =       p;
+       n[1]->parent            =       p;
+       leaves[minidx[0]]       =       p;
+       leaves.swap(minidx[1],leaves.size()-1);
+       leaves.pop_back();
+       }
+}
+
+//
+static btDbvtNode*                     topdown(btDbvt* pdbvt,
+                                                                       tNodeArray& leaves,
+                                                                       int bu_treshold)
+{
+static const btVector3 axis[]={btVector3(1,0,0),
+                                                               btVector3(0,1,0),
+                                                               btVector3(0,0,1)};
+if(leaves.size()>1)
+       {
+       if(leaves.size()>bu_treshold)
+               {
+               const btDbvtVolume      vol=bounds(leaves);
+               const btVector3                 org=vol.Center();
+               tNodeArray                              sets[2];
+               int                                             bestaxis=-1;
+               int                                             bestmidp=leaves.size();
+               int                                             splitcount[3][2]={{0,0},{0,0},{0,0}};
+               int i;
+               for( i=0;i<leaves.size();++i)
+                       {
+                       const btVector3 x=leaves[i]->volume.Center()-org;
+                       for(int j=0;j<3;++j)
+                               {
+                               ++splitcount[j][dot(x,axis[j])>0?1:0];
+                               }
+                       }
+               for( i=0;i<3;++i)
+                       {
+                       if((splitcount[i][0]>0)&&(splitcount[i][1]>0))
+                               {
+                               const int       midp=(int)btFabs(btScalar(splitcount[i][0]-splitcount[i][1]));
+                               if(midp<bestmidp)
+                                       {
+                                       bestaxis=i;
+                                       bestmidp=midp;
+                                       }
+                               }
+                       }
+               if(bestaxis>=0)
+                       {
+                       sets[0].reserve(splitcount[bestaxis][0]);
+                       sets[1].reserve(splitcount[bestaxis][1]);
+                       split(leaves,sets[0],sets[1],org,axis[bestaxis]);
+                       }
+                       else
+                       {
+                       sets[0].reserve(leaves.size()/2+1);
+                       sets[1].reserve(leaves.size()/2);
+                       for(int i=0,ni=leaves.size();i<ni;++i)
+                               {
+                               sets[i&1].push_back(leaves[i]);
+                               }
+                       }
+               btDbvtNode*     node=createnode(pdbvt,0,vol,0);
+               node->childs[0]=topdown(pdbvt,sets[0],bu_treshold);
+               node->childs[1]=topdown(pdbvt,sets[1],bu_treshold);
+               node->childs[0]->parent=node;
+               node->childs[1]->parent=node;
+               return(node);
+               }
+               else
+               {
+               bottomup(pdbvt,leaves);
+               return(leaves[0]);
+               }
+       }
+return(leaves[0]);
+}
+
+//
+static DBVT_INLINE btDbvtNode* sort(btDbvtNode* n,btDbvtNode*& r)
+{
+btDbvtNode*    p=n->parent;
+btAssert(n->isinternal());
+if(p>n)
+       {
+       const int               i=indexof(n);
+       const int               j=1-i;
+       btDbvtNode*     s=p->childs[j];
+       btDbvtNode*     q=p->parent;
+       btAssert(n==p->childs[i]);
+       if(q) q->childs[indexof(p)]=n; else r=n;
+       s->parent=n;
+       p->parent=n;
+       n->parent=q;
+       p->childs[0]=n->childs[0];
+       p->childs[1]=n->childs[1];
+       n->childs[0]->parent=p;
+       n->childs[1]->parent=p;
+       n->childs[i]=p;
+       n->childs[j]=s;
+       btSwap(p->volume,n->volume);
+       return(p);
+       }
+return(n);
+}
+
+//
+static DBVT_INLINE btDbvtNode* walkup(btDbvtNode* n,int count)
+{
+while(n&&(count--)) n=n->parent;
+return(n);
+}
+
+//
+// Api
+//
+
+//
+                               btDbvt::btDbvt()
+{
+m_root         =       0;
+m_free         =       0;
+m_lkhd         =       -1;
+m_leaves       =       0;
+m_opath                =       0;
+}
+
+//
+                               btDbvt::~btDbvt()
+{
+clear();
+}
+
+//
+void                   btDbvt::clear()
+{
+if(m_root)     recursedeletenode(this,m_root);
+btAlignedFree(m_free);
+m_free=0;
+}
+
+//
+void                   btDbvt::optimizeBottomUp()
+{
+if(m_root)
+       {
+       tNodeArray leaves;
+       leaves.reserve(m_leaves);
+       fetchleaves(this,m_root,leaves);
+       bottomup(this,leaves);
+       m_root=leaves[0];
+       }
+}
+
+//
+void                   btDbvt::optimizeTopDown(int bu_treshold)
+{
+if(m_root)
+       {
+       tNodeArray      leaves;
+       leaves.reserve(m_leaves);
+       fetchleaves(this,m_root,leaves);
+       m_root=topdown(this,leaves,bu_treshold);
+       }
+}
+
+//
+void                   btDbvt::optimizeIncremental(int passes)
+{
+if(passes<0) passes=m_leaves;
+if(m_root&&(passes>0))
+       {
+       do      {
+               btDbvtNode*             node=m_root;
+               unsigned        bit=0;
+               while(node->isinternal())
+                       {
+                       node=sort(node,m_root)->childs[(m_opath>>bit)&1];
+                       bit=(bit+1)&(sizeof(unsigned)*8-1);
+                       }
+               update(node);
+               ++m_opath;
+               } while(--passes);
+       }
+}
+
+//
+btDbvtNode*    btDbvt::insert(const btDbvtVolume& volume,void* data)
+{
+btDbvtNode*    leaf=createnode(this,0,volume,data);
+insertleaf(this,m_root,leaf);
+++m_leaves;
+return(leaf);
+}
+
+//
+void                   btDbvt::update(btDbvtNode* leaf,int lookahead)
+{
+btDbvtNode*    root=removeleaf(this,leaf);
+if(root)
+       {
+       if(lookahead>=0)
+               {
+               for(int i=0;(i<lookahead)&&root->parent;++i)
+                       {
+                       root=root->parent;
+                       }
+               } else root=m_root;
+       }
+insertleaf(this,root,leaf);
+}
+
+//
+void                   btDbvt::update(btDbvtNode* leaf,const btDbvtVolume& volume)
+{
+btDbvtNode*    root=removeleaf(this,leaf);
+if(root)
+       {
+       if(m_lkhd>=0)
+               {
+               for(int i=0;(i<m_lkhd)&&root->parent;++i)
+                       {
+                       root=root->parent;
+                       }
+               } else root=m_root;
+       }
+leaf->volume=volume;
+insertleaf(this,root,leaf);
+}
+
+//
+bool                   btDbvt::update(btDbvtNode* leaf,btDbvtVolume volume,const btVector3& velocity,btScalar margin)
+{
+if(leaf->volume.Contain(volume)) return(false);
+volume.Expand(btVector3(margin,margin,margin));
+volume.SignedExpand(velocity);
+update(leaf,volume);
+return(true);
+}
+
+//
+bool                   btDbvt::update(btDbvtNode* leaf,btDbvtVolume volume,const btVector3& velocity)
+{
+if(leaf->volume.Contain(volume)) return(false);
+volume.SignedExpand(velocity);
+update(leaf,volume);
+return(true);
+}
+
+//
+bool                   btDbvt::update(btDbvtNode* leaf,btDbvtVolume volume,btScalar margin)
+{
+if(leaf->volume.Contain(volume)) return(false);
+volume.Expand(btVector3(margin,margin,margin));
+update(leaf,volume);
+return(true);
+}
+
+//
+void                   btDbvt::remove(btDbvtNode* leaf)
+{
+removeleaf(this,leaf);
+deletenode(this,leaf);
+--m_leaves;
+}
+
+//
+void                   btDbvt::write(IWriter* iwriter) const
+{
+btDbvtNodeEnumerator   nodes;
+nodes.nodes.reserve(m_leaves*2);
+enumNodes(m_root,nodes);
+iwriter->Prepare(m_root,nodes.nodes.size());
+for(int i=0;i<nodes.nodes.size();++i)
+       {
+       const btDbvtNode* n=nodes.nodes[i];
+       int                     p=-1;
+       if(n->parent) p=nodes.nodes.findLinearSearch(n->parent);
+       if(n->isinternal())
+               {
+               const int       c0=nodes.nodes.findLinearSearch(n->childs[0]);
+               const int       c1=nodes.nodes.findLinearSearch(n->childs[1]);
+               iwriter->WriteNode(n,i,p,c0,c1);
+               }
+               else
+               {
+               iwriter->WriteLeaf(n,i,p);
+               }       
+       }
+}
+
+//
+void                   btDbvt::clone(btDbvt& dest,IClone* iclone) const
+{
+dest.clear();
+if(m_root!=0)
+       {       
+       btAlignedObjectArray<sStkCLN>   stack;
+       stack.reserve(m_leaves);
+       stack.push_back(sStkCLN(m_root,0));
+       do      {
+               const int               i=stack.size()-1;
+               const sStkCLN   e=stack[i];
+               btDbvtNode*                     n=createnode(&dest,e.parent,e.node->volume,e.node->data);
+               stack.pop_back();
+               if(e.parent!=0)
+                       e.parent->childs[i&1]=n;
+                       else
+                       dest.m_root=n;
+               if(e.node->isinternal())
+                       {
+                       stack.push_back(sStkCLN(e.node->childs[0],n));
+                       stack.push_back(sStkCLN(e.node->childs[1],n));
+                       }
+                       else
+                       {
+                       iclone->CloneLeaf(n);
+                       }
+               } while(stack.size()>0);
+       }
+}
+
+//
+int                            btDbvt::maxdepth(const btDbvtNode* node)
+{
+int    depth=0;
+if(node) getmaxdepth(node,1,depth);
+return(depth);
+}
+
+//
+int                            btDbvt::countLeaves(const btDbvtNode* node)
+{
+if(node->isinternal())
+       return(countLeaves(node->childs[0])+countLeaves(node->childs[1]));
+       else
+       return(1);
+}
+
+//
+void                   btDbvt::extractLeaves(const btDbvtNode* node,btAlignedObjectArray<const btDbvtNode*>& leaves)
+{
+if(node->isinternal())
+       {
+       extractLeaves(node->childs[0],leaves);
+       extractLeaves(node->childs[1],leaves);
+       }
+       else
+       {
+       leaves.push_back(node);
+       }       
+}
+
+//
+#if DBVT_ENABLE_BENCHMARK
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "LinearMath/btQuickProf.h"
+
+/*
+q6600,2.4ghz
+
+/Ox /Ob2 /Oi /Ot /I "." /I "..\.." /I "..\..\src" /D "NDEBUG" /D "_LIB" /D "_WINDOWS" /D "_CRT_SECURE_NO_DEPRECATE" /D "_CRT_NONSTDC_NO_DEPRECATE" /D "WIN32"
+/GF /FD /MT /GS- /Gy /arch:SSE2 /Zc:wchar_t- /Fp"..\..\out\release8\build\libbulletcollision\libbulletcollision.pch"
+/Fo"..\..\out\release8\build\libbulletcollision\\"
+/Fd"..\..\out\release8\build\libbulletcollision\bulletcollision.pdb"
+/W3 /nologo /c /Wp64 /Zi /errorReport:prompt
+
+Benchmarking dbvt...
+        World scale: 100.000000
+        Extents base: 1.000000
+        Extents range: 4.000000
+        Leaves: 8192
+        sizeof(btDbvtVolume): 32 bytes
+        sizeof(btDbvtNode):   44 bytes
+[1] btDbvtVolume intersections: 3499 ms (-1%)
+[2] btDbvtVolume merges: 1934 ms (0%)
+[3] btDbvt::collideTT: 5485 ms (-21%)
+[4] btDbvt::collideTT self: 2814 ms (-20%)
+[5] btDbvt::collideTT xform: 7379 ms (-1%)
+[6] btDbvt::collideTT xform,self: 7270 ms (-2%)
+[7] btDbvt::collideRAY: 6314 ms (0%),(332143 r/s)
+[8] insert/remove: 2093 ms (0%),(1001983 ir/s)
+[9] updates (teleport): 1879 ms (-3%),(1116100 u/s)
+[10] updates (jitter): 1244 ms (-4%),(1685813 u/s)
+[11] optimize (incremental): 2514 ms (0%),(1668000 o/s)
+[12] btDbvtVolume notequal: 3659 ms (0%)
+[13] culling(OCL+fullsort): 2218 ms (0%),(461 t/s)
+[14] culling(OCL+qsort): 3688 ms (5%),(2221 t/s)
+[15] culling(KDOP+qsort): 1139 ms (-1%),(7192 t/s)
+[16] insert/remove batch(256): 5092 ms (0%),(823704 bir/s)
+[17] btDbvtVolume select: 3419 ms (0%)
+*/
+
+struct btDbvtBenchmark
+{
+struct NilPolicy : btDbvt::ICollide
+       {
+       NilPolicy() : m_pcount(0),m_depth(-SIMD_INFINITY),m_checksort(true)             {}
+       void    Process(const btDbvtNode*,const btDbvtNode*)                            { ++m_pcount; }
+       void    Process(const btDbvtNode*)                                                                      { ++m_pcount; }
+       void    Process(const btDbvtNode*,btScalar depth)
+               {
+               ++m_pcount;
+               if(m_checksort)
+                       { if(depth>=m_depth) m_depth=depth; else printf("wrong depth: %f (should be >= %f)\r\n",depth,m_depth); }
+               }
+       int                     m_pcount;
+       btScalar        m_depth;
+       bool            m_checksort;
+       };
+struct P14 : btDbvt::ICollide
+       {
+       struct Node
+               {
+               const btDbvtNode*       leaf;
+               btScalar                        depth;
+               };
+       void Process(const btDbvtNode* leaf,btScalar depth)
+               {
+               Node    n;
+               n.leaf  =       leaf;
+               n.depth =       depth;
+               }
+       static int sortfnc(const Node& a,const Node& b)
+               {
+               if(a.depth<b.depth) return(+1);
+               if(a.depth>b.depth) return(-1);
+               return(0);
+               }
+       btAlignedObjectArray<Node>              m_nodes;
+       };
+struct P15 : btDbvt::ICollide
+       {
+       struct Node
+               {
+               const btDbvtNode*       leaf;
+               btScalar                        depth;
+               };
+       void Process(const btDbvtNode* leaf)
+               {
+               Node    n;
+               n.leaf  =       leaf;
+               n.depth =       dot(leaf->volume.Center(),m_axis);
+               }
+       static int sortfnc(const Node& a,const Node& b)
+               {
+               if(a.depth<b.depth) return(+1);
+               if(a.depth>b.depth) return(-1);
+               return(0);
+               }
+       btAlignedObjectArray<Node>              m_nodes;
+       btVector3                                               m_axis;
+       };
+static btScalar                        RandUnit()
+       {
+       return(rand()/(btScalar)RAND_MAX);
+       }
+static btVector3               RandVector3()
+       {
+       return(btVector3(RandUnit(),RandUnit(),RandUnit()));
+       }
+static btVector3               RandVector3(btScalar cs)
+       {
+       return(RandVector3()*cs-btVector3(cs,cs,cs)/2);
+       }
+static btDbvtVolume    RandVolume(btScalar cs,btScalar eb,btScalar es)
+       {
+       return(btDbvtVolume::FromCE(RandVector3(cs),btVector3(eb,eb,eb)+RandVector3()*es));
+       }
+static btTransform             RandTransform(btScalar cs)
+       {
+       btTransform     t;
+       t.setOrigin(RandVector3(cs));
+       t.setRotation(btQuaternion(RandUnit()*SIMD_PI*2,RandUnit()*SIMD_PI*2,RandUnit()*SIMD_PI*2).normalized());
+       return(t);
+       }
+static void                            RandTree(btScalar cs,btScalar eb,btScalar es,int leaves,btDbvt& dbvt)
+       {
+       dbvt.clear();
+       for(int i=0;i<leaves;++i)
+               {
+               dbvt.insert(RandVolume(cs,eb,es),0);
+               }
+       }
+};
+
+void                   btDbvt::benchmark()
+{
+static const btScalar  cfgVolumeCenterScale            =       100;
+static const btScalar  cfgVolumeExentsBase                     =       1;
+static const btScalar  cfgVolumeExentsScale            =       4;
+static const int               cfgLeaves                                       =       8192;
+static const bool              cfgEnable                                       =       true;
+
+//[1] btDbvtVolume intersections
+bool                                   cfgBenchmark1_Enable            =       cfgEnable;
+static const int               cfgBenchmark1_Iterations        =       8;
+static const int               cfgBenchmark1_Reference         =       3499;
+//[2] btDbvtVolume merges
+bool                                   cfgBenchmark2_Enable            =       cfgEnable;
+static const int               cfgBenchmark2_Iterations        =       4;
+static const int               cfgBenchmark2_Reference         =       1945;
+//[3] btDbvt::collideTT
+bool                                   cfgBenchmark3_Enable            =       cfgEnable;
+static const int               cfgBenchmark3_Iterations        =       512;
+static const int               cfgBenchmark3_Reference         =       5485;
+//[4] btDbvt::collideTT self
+bool                                   cfgBenchmark4_Enable            =       cfgEnable;
+static const int               cfgBenchmark4_Iterations        =       512;
+static const int               cfgBenchmark4_Reference         =       2814;
+//[5] btDbvt::collideTT xform
+bool                                   cfgBenchmark5_Enable            =       cfgEnable;
+static const int               cfgBenchmark5_Iterations        =       512;
+static const btScalar  cfgBenchmark5_OffsetScale       =       2;
+static const int               cfgBenchmark5_Reference         =       7379;
+//[6] btDbvt::collideTT xform,self
+bool                                   cfgBenchmark6_Enable            =       cfgEnable;
+static const int               cfgBenchmark6_Iterations        =       512;
+static const btScalar  cfgBenchmark6_OffsetScale       =       2;
+static const int               cfgBenchmark6_Reference         =       7270;
+//[7] btDbvt::collideRAY
+bool                                   cfgBenchmark7_Enable            =       cfgEnable;
+static const int               cfgBenchmark7_Passes            =       32;
+static const int               cfgBenchmark7_Iterations        =       65536;
+static const int               cfgBenchmark7_Reference         =       6307;
+//[8] insert/remove
+bool                                   cfgBenchmark8_Enable            =       cfgEnable;
+static const int               cfgBenchmark8_Passes            =       32;
+static const int               cfgBenchmark8_Iterations        =       65536;
+static const int               cfgBenchmark8_Reference         =       2105;
+//[9] updates (teleport)
+bool                                   cfgBenchmark9_Enable            =       cfgEnable;
+static const int               cfgBenchmark9_Passes            =       32;
+static const int               cfgBenchmark9_Iterations        =       65536;
+static const int               cfgBenchmark9_Reference         =       1879;
+//[10] updates (jitter)
+bool                                   cfgBenchmark10_Enable           =       cfgEnable;
+static const btScalar  cfgBenchmark10_Scale            =       cfgVolumeCenterScale/10000;
+static const int               cfgBenchmark10_Passes           =       32;
+static const int               cfgBenchmark10_Iterations       =       65536;
+static const int               cfgBenchmark10_Reference        =       1244;
+//[11] optimize (incremental)
+bool                                   cfgBenchmark11_Enable           =       cfgEnable;
+static const int               cfgBenchmark11_Passes           =       64;
+static const int               cfgBenchmark11_Iterations       =       65536;
+static const int               cfgBenchmark11_Reference        =       2510;
+//[12] btDbvtVolume notequal
+bool                                   cfgBenchmark12_Enable           =       cfgEnable;
+static const int               cfgBenchmark12_Iterations       =       32;
+static const int               cfgBenchmark12_Reference        =       3677;
+//[13] culling(OCL+fullsort)
+bool                                   cfgBenchmark13_Enable           =       cfgEnable;
+static const int               cfgBenchmark13_Iterations       =       1024;
+static const int               cfgBenchmark13_Reference        =       2231;
+//[14] culling(OCL+qsort)
+bool                                   cfgBenchmark14_Enable           =       cfgEnable;
+static const int               cfgBenchmark14_Iterations       =       8192;
+static const int               cfgBenchmark14_Reference        =       3500;
+//[15] culling(KDOP+qsort)
+bool                                   cfgBenchmark15_Enable           =       cfgEnable;
+static const int               cfgBenchmark15_Iterations       =       8192;
+static const int               cfgBenchmark15_Reference        =       1151;
+//[16] insert/remove batch
+bool                                   cfgBenchmark16_Enable           =       cfgEnable;
+static const int               cfgBenchmark16_BatchCount       =       256;
+static const int               cfgBenchmark16_Passes           =       16384;
+static const int               cfgBenchmark16_Reference        =       5138;
+//[17] select
+bool                                   cfgBenchmark17_Enable           =       cfgEnable;
+static const int               cfgBenchmark17_Iterations       =       4;
+static const int               cfgBenchmark17_Reference        =       3390;
+
+btClock                                        wallclock;
+printf("Benchmarking dbvt...\r\n");
+printf("\tWorld scale: %f\r\n",cfgVolumeCenterScale);
+printf("\tExtents base: %f\r\n",cfgVolumeExentsBase);
+printf("\tExtents range: %f\r\n",cfgVolumeExentsScale);
+printf("\tLeaves: %u\r\n",cfgLeaves);
+printf("\tsizeof(btDbvtVolume): %u bytes\r\n",sizeof(btDbvtVolume));
+printf("\tsizeof(btDbvtNode):   %u bytes\r\n",sizeof(btDbvtNode));
+if(cfgBenchmark1_Enable)
+       {// Benchmark 1 
+       srand(380843);
+       btAlignedObjectArray<btDbvtVolume>      volumes;
+       btAlignedObjectArray<bool>                      results;
+       volumes.resize(cfgLeaves);
+       results.resize(cfgLeaves);
+       for(int i=0;i<cfgLeaves;++i)
+               {
+               volumes[i]=btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale);
+               }
+       printf("[1] btDbvtVolume intersections: ");
+       wallclock.reset();
+       for(int i=0;i<cfgBenchmark1_Iterations;++i)
+               {
+               for(int j=0;j<cfgLeaves;++j)
+                       {
+                       for(int k=0;k<cfgLeaves;++k)
+                               {
+                               results[k]=Intersect(volumes[j],volumes[k]);
+                               }
+                       }
+               }
+       const int time=(int)wallclock.getTimeMilliseconds();
+       printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark1_Reference)*100/time);
+       }
+if(cfgBenchmark2_Enable)
+       {// Benchmark 2 
+       srand(380843);
+       btAlignedObjectArray<btDbvtVolume>      volumes;
+       btAlignedObjectArray<btDbvtVolume>      results;
+       volumes.resize(cfgLeaves);
+       results.resize(cfgLeaves);
+       for(int i=0;i<cfgLeaves;++i)
+               {
+               volumes[i]=btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale);
+               }
+       printf("[2] btDbvtVolume merges: ");
+       wallclock.reset();
+       for(int i=0;i<cfgBenchmark2_Iterations;++i)
+               {
+               for(int j=0;j<cfgLeaves;++j)
+                       {
+                       for(int k=0;k<cfgLeaves;++k)
+                               {
+                               Merge(volumes[j],volumes[k],results[k]);
+                               }
+                       }
+               }
+       const int time=(int)wallclock.getTimeMilliseconds();
+       printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark2_Reference)*100/time);
+       }
+if(cfgBenchmark3_Enable)
+       {// Benchmark 3 
+       srand(380843);
+       btDbvt                                          dbvt[2];
+       btDbvtBenchmark::NilPolicy      policy;
+       btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt[0]);
+       btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt[1]);
+       dbvt[0].optimizeTopDown();
+       dbvt[1].optimizeTopDown();
+       printf("[3] btDbvt::collideTT: ");
+       wallclock.reset();
+       for(int i=0;i<cfgBenchmark3_Iterations;++i)
+               {
+               btDbvt::collideTT(dbvt[0].m_root,dbvt[1].m_root,policy);
+               }
+       const int time=(int)wallclock.getTimeMilliseconds();
+       printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark3_Reference)*100/time);
+       }
+if(cfgBenchmark4_Enable)
+       {// Benchmark 4
+       srand(380843);
+       btDbvt                                          dbvt;
+       btDbvtBenchmark::NilPolicy      policy;
+       btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+       dbvt.optimizeTopDown();
+       printf("[4] btDbvt::collideTT self: ");
+       wallclock.reset();
+       for(int i=0;i<cfgBenchmark4_Iterations;++i)
+               {
+               btDbvt::collideTT(dbvt.m_root,dbvt.m_root,policy);
+               }
+       const int time=(int)wallclock.getTimeMilliseconds();
+       printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark4_Reference)*100/time);
+       }
+if(cfgBenchmark5_Enable)
+       {// Benchmark 5 
+       srand(380843);
+       btDbvt                                                          dbvt[2];
+       btAlignedObjectArray<btTransform>       transforms;
+       btDbvtBenchmark::NilPolicy                      policy;
+       transforms.resize(cfgBenchmark5_Iterations);
+       for(int i=0;i<transforms.size();++i)
+               {
+               transforms[i]=btDbvtBenchmark::RandTransform(cfgVolumeCenterScale*cfgBenchmark5_OffsetScale);
+               }
+       btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt[0]);
+       btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt[1]);
+       dbvt[0].optimizeTopDown();
+       dbvt[1].optimizeTopDown();
+       printf("[5] btDbvt::collideTT xform: ");
+       wallclock.reset();
+       for(int i=0;i<cfgBenchmark5_Iterations;++i)
+               {
+               btDbvt::collideTT(dbvt[0].m_root,dbvt[1].m_root,transforms[i],policy);
+               }
+       const int time=(int)wallclock.getTimeMilliseconds();
+       printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark5_Reference)*100/time);
+       }
+if(cfgBenchmark6_Enable)
+       {// Benchmark 6 
+       srand(380843);
+       btDbvt                                                          dbvt;
+       btAlignedObjectArray<btTransform>       transforms;
+       btDbvtBenchmark::NilPolicy                      policy;
+       transforms.resize(cfgBenchmark6_Iterations);
+       for(int i=0;i<transforms.size();++i)
+               {
+               transforms[i]=btDbvtBenchmark::RandTransform(cfgVolumeCenterScale*cfgBenchmark6_OffsetScale);
+               }
+       btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+       dbvt.optimizeTopDown();
+       printf("[6] btDbvt::collideTT xform,self: ");
+       wallclock.reset();
+       for(int i=0;i<cfgBenchmark6_Iterations;++i)
+               {
+               btDbvt::collideTT(dbvt.m_root,dbvt.m_root,transforms[i],policy);                
+               }
+       const int time=(int)wallclock.getTimeMilliseconds();
+       printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark6_Reference)*100/time);
+       }
+if(cfgBenchmark7_Enable)
+       {// Benchmark 7 
+       srand(380843);
+       btDbvt                                                          dbvt;
+       btAlignedObjectArray<btVector3>         rayorg;
+       btAlignedObjectArray<btVector3>         raydir;
+       btDbvtBenchmark::NilPolicy                      policy;
+       rayorg.resize(cfgBenchmark7_Iterations);
+       raydir.resize(cfgBenchmark7_Iterations);
+       for(int i=0;i<rayorg.size();++i)
+               {
+               rayorg[i]=btDbvtBenchmark::RandVector3(cfgVolumeCenterScale*2);
+               raydir[i]=btDbvtBenchmark::RandVector3(cfgVolumeCenterScale*2);
+               }
+       btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+       dbvt.optimizeTopDown();
+       printf("[7] btDbvt::collideRAY: ");
+       wallclock.reset();
+       for(int i=0;i<cfgBenchmark7_Passes;++i)
+               {
+               for(int j=0;j<cfgBenchmark7_Iterations;++j)
+                       {
+                       btDbvt::collideRAY(dbvt.m_root,rayorg[j],raydir[j],policy);
+                       }
+               }
+       const int       time=(int)wallclock.getTimeMilliseconds();
+       unsigned        rays=cfgBenchmark7_Passes*cfgBenchmark7_Iterations;
+       printf("%u ms (%i%%),(%u r/s)\r\n",time,(time-cfgBenchmark7_Reference)*100/time,(rays*1000)/time);
+       }
+if(cfgBenchmark8_Enable)
+       {// Benchmark 8 
+       srand(380843);
+       btDbvt                                                          dbvt;
+       btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+       dbvt.optimizeTopDown();
+       printf("[8] insert/remove: ");
+       wallclock.reset();
+       for(int i=0;i<cfgBenchmark8_Passes;++i)
+               {
+               for(int j=0;j<cfgBenchmark8_Iterations;++j)
+                       {
+                       dbvt.remove(dbvt.insert(btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale),0));
+                       }
+               }
+       const int       time=(int)wallclock.getTimeMilliseconds();
+       const int       ir=cfgBenchmark8_Passes*cfgBenchmark8_Iterations;
+       printf("%u ms (%i%%),(%u ir/s)\r\n",time,(time-cfgBenchmark8_Reference)*100/time,ir*1000/time);
+       }
+if(cfgBenchmark9_Enable)
+       {// Benchmark 9 
+       srand(380843);
+       btDbvt                                                                          dbvt;
+       btAlignedObjectArray<const btDbvtNode*> leaves;
+       btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+       dbvt.optimizeTopDown();
+       dbvt.extractLeaves(dbvt.m_root,leaves);
+       printf("[9] updates (teleport): ");
+       wallclock.reset();
+       for(int i=0;i<cfgBenchmark9_Passes;++i)
+               {
+               for(int j=0;j<cfgBenchmark9_Iterations;++j)
+                       {
+                       dbvt.update(const_cast<btDbvtNode*>(leaves[rand()%cfgLeaves]),
+                                               btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale));
+                       }
+               }
+       const int       time=(int)wallclock.getTimeMilliseconds();
+       const int       up=cfgBenchmark9_Passes*cfgBenchmark9_Iterations;
+       printf("%u ms (%i%%),(%u u/s)\r\n",time,(time-cfgBenchmark9_Reference)*100/time,up*1000/time);
+       }
+if(cfgBenchmark10_Enable)
+       {// Benchmark 10        
+       srand(380843);
+       btDbvt                                                                          dbvt;
+       btAlignedObjectArray<const btDbvtNode*> leaves;
+       btAlignedObjectArray<btVector3>                         vectors;
+       vectors.resize(cfgBenchmark10_Iterations);
+       for(int i=0;i<vectors.size();++i)
+               {
+               vectors[i]=(btDbvtBenchmark::RandVector3()*2-btVector3(1,1,1))*cfgBenchmark10_Scale;
+               }
+       btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+       dbvt.optimizeTopDown();
+       dbvt.extractLeaves(dbvt.m_root,leaves);
+       printf("[10] updates (jitter): ");
+       wallclock.reset();
+       
+       for(int i=0;i<cfgBenchmark10_Passes;++i)
+               {
+               for(int j=0;j<cfgBenchmark10_Iterations;++j)
+                       {                       
+                       const btVector3&        d=vectors[j];
+                       btDbvtNode*             l=const_cast<btDbvtNode*>(leaves[rand()%cfgLeaves]);
+                       btDbvtVolume            v=btDbvtVolume::FromMM(l->volume.Mins()+d,l->volume.Maxs()+d);
+                       dbvt.update(l,v);
+                       }
+               }
+       const int       time=(int)wallclock.getTimeMilliseconds();
+       const int       up=cfgBenchmark10_Passes*cfgBenchmark10_Iterations;
+       printf("%u ms (%i%%),(%u u/s)\r\n",time,(time-cfgBenchmark10_Reference)*100/time,up*1000/time);
+       }
+if(cfgBenchmark11_Enable)
+       {// Benchmark 11        
+       srand(380843);
+       btDbvt                                                                          dbvt;
+       btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+       dbvt.optimizeTopDown();
+       printf("[11] optimize (incremental): ");
+       wallclock.reset();      
+       for(int i=0;i<cfgBenchmark11_Passes;++i)
+               {
+               dbvt.optimizeIncremental(cfgBenchmark11_Iterations);
+               }
+       const int       time=(int)wallclock.getTimeMilliseconds();
+       const int       op=cfgBenchmark11_Passes*cfgBenchmark11_Iterations;
+       printf("%u ms (%i%%),(%u o/s)\r\n",time,(time-cfgBenchmark11_Reference)*100/time,op/time*1000);
+       }
+if(cfgBenchmark12_Enable)
+       {// Benchmark 12        
+       srand(380843);
+       btAlignedObjectArray<btDbvtVolume>      volumes;
+       btAlignedObjectArray<bool>                              results;
+       volumes.resize(cfgLeaves);
+       results.resize(cfgLeaves);
+       for(int i=0;i<cfgLeaves;++i)
+               {
+               volumes[i]=btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale);
+               }
+       printf("[12] btDbvtVolume notequal: ");
+       wallclock.reset();
+       for(int i=0;i<cfgBenchmark12_Iterations;++i)
+               {
+               for(int j=0;j<cfgLeaves;++j)
+                       {
+                       for(int k=0;k<cfgLeaves;++k)
+                               {
+                               results[k]=NotEqual(volumes[j],volumes[k]);
+                               }
+                       }
+               }
+       const int time=(int)wallclock.getTimeMilliseconds();
+       printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark12_Reference)*100/time);
+       }
+if(cfgBenchmark13_Enable)
+       {// Benchmark 13        
+       srand(380843);
+       btDbvt                                                          dbvt;
+       btAlignedObjectArray<btVector3>         vectors;
+       btDbvtBenchmark::NilPolicy                      policy;
+       vectors.resize(cfgBenchmark13_Iterations);
+       for(int i=0;i<vectors.size();++i)
+               {
+               vectors[i]=(btDbvtBenchmark::RandVector3()*2-btVector3(1,1,1)).normalized();
+               }
+       btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+       dbvt.optimizeTopDown();
+       printf("[13] culling(OCL+fullsort): ");
+       wallclock.reset();      
+       for(int i=0;i<cfgBenchmark13_Iterations;++i)
+               {
+               static const btScalar   offset=0;
+               policy.m_depth=-SIMD_INFINITY;
+               dbvt.collideOCL(dbvt.m_root,&vectors[i],&offset,vectors[i],1,policy);
+               }
+       const int       time=(int)wallclock.getTimeMilliseconds();
+       const int       t=cfgBenchmark13_Iterations;
+       printf("%u ms (%i%%),(%u t/s)\r\n",time,(time-cfgBenchmark13_Reference)*100/time,(t*1000)/time);
+       }
+if(cfgBenchmark14_Enable)
+       {// Benchmark 14        
+       srand(380843);
+       btDbvt                                                          dbvt;
+       btAlignedObjectArray<btVector3>         vectors;
+       btDbvtBenchmark::P14                            policy;
+       vectors.resize(cfgBenchmark14_Iterations);
+       for(int i=0;i<vectors.size();++i)
+               {
+               vectors[i]=(btDbvtBenchmark::RandVector3()*2-btVector3(1,1,1)).normalized();
+               }
+       btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+       dbvt.optimizeTopDown();
+       policy.m_nodes.reserve(cfgLeaves);
+       printf("[14] culling(OCL+qsort): ");
+       wallclock.reset();      
+       for(int i=0;i<cfgBenchmark14_Iterations;++i)
+               {
+               static const btScalar   offset=0;
+               policy.m_nodes.resize(0);
+               dbvt.collideOCL(dbvt.m_root,&vectors[i],&offset,vectors[i],1,policy,false);
+               policy.m_nodes.quickSort(btDbvtBenchmark::P14::sortfnc);
+               }
+       const int       time=(int)wallclock.getTimeMilliseconds();
+       const int       t=cfgBenchmark14_Iterations;
+       printf("%u ms (%i%%),(%u t/s)\r\n",time,(time-cfgBenchmark14_Reference)*100/time,(t*1000)/time);
+       }
+if(cfgBenchmark15_Enable)
+       {// Benchmark 15        
+       srand(380843);
+       btDbvt                                                          dbvt;
+       btAlignedObjectArray<btVector3>         vectors;
+       btDbvtBenchmark::P15                            policy;
+       vectors.resize(cfgBenchmark15_Iterations);
+       for(int i=0;i<vectors.size();++i)
+               {
+               vectors[i]=(btDbvtBenchmark::RandVector3()*2-btVector3(1,1,1)).normalized();
+               }
+       btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+       dbvt.optimizeTopDown();
+       policy.m_nodes.reserve(cfgLeaves);
+       printf("[15] culling(KDOP+qsort): ");
+       wallclock.reset();      
+       for(int i=0;i<cfgBenchmark15_Iterations;++i)
+               {
+               static const btScalar   offset=0;
+               policy.m_nodes.resize(0);
+               policy.m_axis=vectors[i];
+               dbvt.collideKDOP(dbvt.m_root,&vectors[i],&offset,1,policy);
+               policy.m_nodes.quickSort(btDbvtBenchmark::P15::sortfnc);
+               }
+       const int       time=(int)wallclock.getTimeMilliseconds();
+       const int       t=cfgBenchmark15_Iterations;
+       printf("%u ms (%i%%),(%u t/s)\r\n",time,(time-cfgBenchmark15_Reference)*100/time,(t*1000)/time);
+       }
+if(cfgBenchmark16_Enable)
+       {// Benchmark 16        
+       srand(380843);
+       btDbvt                                                          dbvt;
+       btAlignedObjectArray<btDbvtNode*>       batch;
+       btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+       dbvt.optimizeTopDown();
+       batch.reserve(cfgBenchmark16_BatchCount);
+       printf("[16] insert/remove batch(%u): ",cfgBenchmark16_BatchCount);
+       wallclock.reset();
+       for(int i=0;i<cfgBenchmark16_Passes;++i)
+               {
+               for(int j=0;j<cfgBenchmark16_BatchCount;++j)
+                       {
+                       batch.push_back(dbvt.insert(btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale),0));
+                       }
+               for(int j=0;j<cfgBenchmark16_BatchCount;++j)
+                       {
+                       dbvt.remove(batch[j]);
+                       }
+               batch.resize(0);
+               }
+       const int       time=(int)wallclock.getTimeMilliseconds();
+       const int       ir=cfgBenchmark16_Passes*cfgBenchmark16_BatchCount;
+       printf("%u ms (%i%%),(%u bir/s)\r\n",time,(time-cfgBenchmark16_Reference)*100/time,int(ir*1000.0/time));
+       }
+if(cfgBenchmark17_Enable)
+       {// Benchmark 17
+       srand(380843);
+       btAlignedObjectArray<btDbvtVolume>      volumes;
+       btAlignedObjectArray<int>                       results;
+       btAlignedObjectArray<int>                       indices;
+       volumes.resize(cfgLeaves);
+       results.resize(cfgLeaves);
+       indices.resize(cfgLeaves);
+       for(int i=0;i<cfgLeaves;++i)
+               {
+               indices[i]=i;
+               volumes[i]=btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale);
+               }
+       for(int i=0;i<cfgLeaves;++i)
+               {
+               btSwap(indices[i],indices[rand()%cfgLeaves]);
+               }
+       printf("[17] btDbvtVolume select: ");
+       wallclock.reset();
+       for(int i=0;i<cfgBenchmark17_Iterations;++i)
+               {
+               for(int j=0;j<cfgLeaves;++j)
+                       {
+                       for(int k=0;k<cfgLeaves;++k)
+                               {
+                               const int idx=indices[k];
+                               results[idx]=Select(volumes[idx],volumes[j],volumes[k]);
+                               }
+                       }
+               }
+       const int time=(int)wallclock.getTimeMilliseconds();
+       printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark17_Reference)*100/time);
+       }
+printf("\r\n\r\n");
+}
+#endif
diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.h
new file mode 100644 (file)
index 0000000..21d69ac
--- /dev/null
@@ -0,0 +1,1112 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2007 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+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.
+*/
+///btDbvt implementation by Nathanael Presson
+
+#ifndef BT_DYNAMIC_BOUNDING_VOLUME_TREE_H
+#define BT_DYNAMIC_BOUNDING_VOLUME_TREE_H
+
+#include "LinearMath/btAlignedObjectArray.h"
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btTransform.h"
+
+//
+// Compile time configuration
+//
+
+
+// Implementation profiles
+#define DBVT_IMPL_GENERIC              0       // Generic implementation       
+#define DBVT_IMPL_SSE                  1       // SSE
+
+// Template implementation of ICollide
+#ifdef WIN32_AVOID_SSE_WHEN_EMBEDDED_INSIDE_BLENDER //there is always some weird compiler that breaks SSE builds
+       #if (defined (_MSC_VER) && _MSC_VER >= 1400)
+       #define DBVT_USE_TEMPLATE               1
+       #else
+       #define DBVT_USE_TEMPLATE               0
+#endif
+#else
+#define        DBVT_USE_TEMPLATE               0
+#endif
+
+// Use only intrinsics instead of inline asm
+#define DBVT_USE_INTRINSIC_SSE 1
+
+// Using memmov for collideOCL
+#define DBVT_USE_MEMMOVE               1
+
+// Enable benchmarking code
+#define        DBVT_ENABLE_BENCHMARK   0
+
+// Inlining
+#define DBVT_INLINE                            SIMD_FORCE_INLINE
+// Align
+#ifdef WIN32
+#define DBVT_ALIGN                             __declspec(align(16))
+#else
+#define DBVT_ALIGN
+#endif
+
+// Specific methods implementation
+
+#ifdef WIN32_AVOID_SSE_WHEN_EMBEDDED_INSIDE_BLENDER //there is always some weird compiler that breaks SSE builds
+#define DBVT_SELECT_IMPL               DBVT_IMPL_SSE
+#define DBVT_MERGE_IMPL                        DBVT_IMPL_SSE
+#define DBVT_INT0_IMPL                 DBVT_IMPL_SSE
+#else
+#define DBVT_SELECT_IMPL               DBVT_IMPL_GENERIC
+#define DBVT_MERGE_IMPL                        DBVT_IMPL_GENERIC
+#define DBVT_INT0_IMPL                 DBVT_IMPL_GENERIC
+#endif
+
+#if    (DBVT_SELECT_IMPL==DBVT_IMPL_SSE)||     \
+       (DBVT_MERGE_IMPL==DBVT_IMPL_SSE)||      \
+       (DBVT_INT0_IMPL==DBVT_IMPL_SSE)
+#include <emmintrin.h>
+#endif
+
+//
+// Auto config and checks
+//
+
+#if DBVT_USE_TEMPLATE
+#define        DBVT_VIRTUAL
+#define DBVT_VIRTUAL_DTOR(a)
+#define DBVT_PREFIX                                    template <typename T>
+#define DBVT_IPOLICY                           T& policy
+#define DBVT_CHECKTYPE                         static const ICollide&  typechecker=*(T*)0;
+#else
+#define        DBVT_VIRTUAL_DTOR(a)            virtual ~a() {}
+#define DBVT_VIRTUAL                           virtual
+#define DBVT_PREFIX
+#define DBVT_IPOLICY                           ICollide& policy
+#define DBVT_CHECKTYPE
+#endif
+
+#if DBVT_USE_MEMMOVE
+#ifndef __CELLOS_LV2__
+#include <memory.h>
+#endif
+#include <string.h>
+#endif
+
+#ifndef DBVT_USE_TEMPLATE
+#error "DBVT_USE_TEMPLATE undefined"
+#endif
+
+#ifndef DBVT_USE_MEMMOVE
+#error "DBVT_USE_MEMMOVE undefined"
+#endif
+
+#ifndef DBVT_ENABLE_BENCHMARK
+#error "DBVT_ENABLE_BENCHMARK undefined"
+#endif
+
+#ifndef DBVT_SELECT_IMPL
+#error "DBVT_SELECT_IMPL undefined"
+#endif
+
+#ifndef DBVT_MERGE_IMPL
+#error "DBVT_MERGE_IMPL undefined"
+#endif
+
+#ifndef DBVT_INT0_IMPL
+#error "DBVT_INT0_IMPL undefined"
+#endif
+
+//
+// Defaults volumes
+//
+
+/* btDbvtAabbMm                        */ 
+struct btDbvtAabbMm
+{
+DBVT_INLINE btVector3                  Center() const  { return((mi+mx)/2); }
+DBVT_INLINE btVector3                  Lengths() const { return(mx-mi); }
+DBVT_INLINE btVector3                  Extents() const { return((mx-mi)/2); }
+DBVT_INLINE const btVector3&   Mins() const    { return(mi); }
+DBVT_INLINE const btVector3&   Maxs() const    { return(mx); }
+static inline btDbvtAabbMm             FromCE(const btVector3& c,const btVector3& e);
+static inline btDbvtAabbMm             FromCR(const btVector3& c,btScalar r);
+static inline btDbvtAabbMm             FromMM(const btVector3& mi,const btVector3& mx);
+static inline btDbvtAabbMm             FromPoints(const btVector3* pts,int n);
+static inline btDbvtAabbMm             FromPoints(const btVector3** ppts,int n);
+DBVT_INLINE void                               Expand(const btVector3& e);
+DBVT_INLINE void                               SignedExpand(const btVector3& e);
+DBVT_INLINE bool                               Contain(const btDbvtAabbMm& a) const;
+DBVT_INLINE int                                        Classify(const btVector3& n,btScalar o,int s) const;
+DBVT_INLINE btScalar                   ProjectMinimum(const btVector3& v,unsigned signs) const;
+DBVT_INLINE friend bool                        Intersect(      const btDbvtAabbMm& a,
+                                                                                       const btDbvtAabbMm& b);
+DBVT_INLINE friend bool                        Intersect(      const btDbvtAabbMm& a,
+                                                                                       const btDbvtAabbMm& b,
+                                                                                       const btTransform& xform);
+DBVT_INLINE friend bool                        Intersect(      const btDbvtAabbMm& a,
+                                                                                       const btVector3& b);
+DBVT_INLINE friend bool                        Intersect(      const btDbvtAabbMm& a,
+                                                                                       const btVector3& org,
+                                                                                       const btVector3& invdir,
+                                                                                       const unsigned* signs);
+DBVT_INLINE friend btScalar            Proximity(      const btDbvtAabbMm& a,
+                                                                                       const btDbvtAabbMm& b);
+DBVT_INLINE friend int                 Select(         const btDbvtAabbMm& o,
+                                                                                       const btDbvtAabbMm& a,
+                                                                                       const btDbvtAabbMm& b);
+DBVT_INLINE friend void                        Merge(          const btDbvtAabbMm& a,
+                                                                                       const btDbvtAabbMm& b,
+                                                                                       btDbvtAabbMm& r);
+DBVT_INLINE friend bool                        NotEqual(       const btDbvtAabbMm& a,
+                                                                                       const btDbvtAabbMm& b);
+private:
+DBVT_INLINE void                               AddSpan(const btVector3& d,btScalar& smi,btScalar& smx) const;
+private:
+btVector3      mi,mx;
+};
+
+// Types       
+typedef        btDbvtAabbMm    btDbvtVolume;
+
+/* btDbvtNode                          */ 
+struct btDbvtNode
+{
+       btDbvtVolume    volume;
+       btDbvtNode*             parent;
+       DBVT_INLINE bool        isleaf() const          { return(childs[1]==0); }
+       DBVT_INLINE bool        isinternal() const      { return(!isleaf()); }
+       union   {
+                       btDbvtNode*     childs[2];
+                       void*   data;
+                       int             dataAsInt;
+                       };
+};
+
+///The btDbvt class implements a fast dynamic bounding volume tree based on axis aligned bounding boxes (aabb tree).
+///This btDbvt is used for soft body collision detection and for the btDbvtBroadphase. It has a fast insert, remove and update of nodes.
+///Unlike the btQuantizedBvh, nodes can be dynamically moved around, which allows for change in topology of the underlying data structure.
+struct btDbvt
+       {
+       /* Stack element        */ 
+       struct  sStkNN
+               {
+               const btDbvtNode*       a;
+               const btDbvtNode*       b;
+               sStkNN() {}
+               sStkNN(const btDbvtNode* na,const btDbvtNode* nb) : a(na),b(nb) {}
+               };
+       struct  sStkNP
+               {
+               const btDbvtNode*       node;
+               int                     mask;
+               sStkNP(const btDbvtNode* n,unsigned m) : node(n),mask(m) {}
+               };
+       struct  sStkNPS
+               {
+               const btDbvtNode*       node;
+               int                     mask;
+               btScalar        value;
+               sStkNPS() {}
+               sStkNPS(const btDbvtNode* n,unsigned m,btScalar v) : node(n),mask(m),value(v) {}
+               };
+       struct  sStkCLN
+               {
+               const btDbvtNode*       node;
+               btDbvtNode*             parent;
+               sStkCLN(const btDbvtNode* n,btDbvtNode* p) : node(n),parent(p) {}
+               };
+       // Policies/Interfaces
+                       
+       /* ICollide     */ 
+       struct  ICollide
+               {               
+               DBVT_VIRTUAL_DTOR(ICollide)
+               DBVT_VIRTUAL void       Process(const btDbvtNode*,const btDbvtNode*)            {}
+               DBVT_VIRTUAL void       Process(const btDbvtNode*)                                      {}
+               DBVT_VIRTUAL void       Process(const btDbvtNode* n,btScalar)                   { Process(n); }
+               DBVT_VIRTUAL bool       Descent(const btDbvtNode*)                                      { return(true); }
+               DBVT_VIRTUAL bool       AllLeaves(const btDbvtNode*)                                    { return(true); }
+               };
+       /* IWriter      */ 
+       struct  IWriter
+               {
+               virtual ~IWriter() {}
+               virtual void            Prepare(const btDbvtNode* root,int numnodes)=0;
+               virtual void            WriteNode(const btDbvtNode*,int index,int parent,int child0,int child1)=0;
+               virtual void            WriteLeaf(const btDbvtNode*,int index,int parent)=0;
+               };
+       /* IClone       */ 
+       struct  IClone
+               {
+               virtual ~IClone()       {}
+               virtual void            CloneLeaf(btDbvtNode*) {}
+               };
+               
+       // Constants
+       enum    {
+                       SIMPLE_STACKSIZE        =       64,
+                       DOUBLE_STACKSIZE        =       SIMPLE_STACKSIZE*2
+                       };
+               
+       // Fields
+       btDbvtNode*             m_root;
+       btDbvtNode*             m_free;
+       int                             m_lkhd;
+       int                             m_leaves;
+       unsigned                m_opath;
+       // Methods
+                                       btDbvt();
+                                       ~btDbvt();
+       void                    clear();
+       bool                    empty() const { return(0==m_root); }
+       void                    optimizeBottomUp();
+       void                    optimizeTopDown(int bu_treshold=128);
+       void                    optimizeIncremental(int passes);
+       btDbvtNode*             insert(const btDbvtVolume& box,void* data);
+       void                    update(btDbvtNode* leaf,int lookahead=-1);
+       void                    update(btDbvtNode* leaf,const btDbvtVolume& volume);
+       bool                    update(btDbvtNode* leaf,btDbvtVolume volume,const btVector3& velocity,btScalar margin);
+       bool                    update(btDbvtNode* leaf,btDbvtVolume volume,const btVector3& velocity);
+       bool                    update(btDbvtNode* leaf,btDbvtVolume volume,btScalar margin);   
+       void                    remove(btDbvtNode* leaf);
+       void                    write(IWriter* iwriter) const;
+       void                    clone(btDbvt& dest,IClone* iclone=0) const;
+       static int              maxdepth(const btDbvtNode* node);
+       static int              countLeaves(const btDbvtNode* node);
+       static void             extractLeaves(const btDbvtNode* node,btAlignedObjectArray<const btDbvtNode*>& leaves);
+       #if DBVT_ENABLE_BENCHMARK
+       static void             benchmark();
+       #else
+       static void             benchmark(){}
+       #endif
+       // DBVT_IPOLICY must support ICollide policy/interface
+       DBVT_PREFIX
+       static void             enumNodes(      const btDbvtNode* root,
+                                                               DBVT_IPOLICY);
+       DBVT_PREFIX
+       static void             enumLeaves(     const btDbvtNode* root,
+                                                               DBVT_IPOLICY);
+       DBVT_PREFIX
+       static void             collideTT(      const btDbvtNode* root0,
+                                                               const btDbvtNode* root1,
+                                                               DBVT_IPOLICY);
+       DBVT_PREFIX
+       static void             collideTT(      const btDbvtNode* root0,
+                                                               const btDbvtNode* root1,
+                                                               const btTransform& xform,
+                                                               DBVT_IPOLICY);
+       DBVT_PREFIX
+       static void             collideTT(      const btDbvtNode* root0,
+                                                               const btTransform& xform0,
+                                                               const btDbvtNode* root1,
+                                                               const btTransform& xform1,
+                                                               DBVT_IPOLICY);
+       DBVT_PREFIX
+       static void             collideTV(      const btDbvtNode* root,
+                                                               const btDbvtVolume& volume,
+                                                               DBVT_IPOLICY);
+       DBVT_PREFIX
+       static void             collideRAY(     const btDbvtNode* root,
+                                                               const btVector3& origin,
+                                                               const btVector3& direction,
+                                                               DBVT_IPOLICY);
+       DBVT_PREFIX
+       static void             collideKDOP(const btDbvtNode* root,
+                                                               const btVector3* normals,
+                                                               const btScalar* offsets,
+                                                               int count,
+                                                               DBVT_IPOLICY);
+       DBVT_PREFIX
+       static void             collideOCL(     const btDbvtNode* root,
+                                                               const btVector3* normals,
+                                                               const btScalar* offsets,
+                                                               const btVector3& sortaxis,
+                                                               int count,                                                              
+                                                               DBVT_IPOLICY,
+                                                               bool fullsort=true);
+       DBVT_PREFIX
+       static void             collideTU(      const btDbvtNode* root,
+                                                               DBVT_IPOLICY);
+       // Helpers      
+       static DBVT_INLINE int  nearest(const int* i,const btDbvt::sStkNPS* a,btScalar v,int l,int h)
+               {
+               int     m=0;
+               while(l<h)
+                       {
+                       m=(l+h)>>1;
+                       if(a[i[m]].value>=v) l=m+1; else h=m;
+                       }
+               return(h);
+               }
+       static DBVT_INLINE int  allocate(       btAlignedObjectArray<int>& ifree,
+                                                                               btAlignedObjectArray<sStkNPS>& stock,
+                                                                               const sStkNPS& value)
+               {
+               int     i;
+               if(ifree.size()>0)
+                       { i=ifree[ifree.size()-1];ifree.pop_back();stock[i]=value; }
+                       else
+                       { i=stock.size();stock.push_back(value); }
+               return(i); 
+               }
+       //
+       private:
+                                       btDbvt(const btDbvt&)   {}      
+       };
+
+//
+// Inline's
+//
+
+//
+inline btDbvtAabbMm                    btDbvtAabbMm::FromCE(const btVector3& c,const btVector3& e)
+{
+btDbvtAabbMm box;
+box.mi=c-e;box.mx=c+e;
+return(box);
+}
+       
+//
+inline btDbvtAabbMm                    btDbvtAabbMm::FromCR(const btVector3& c,btScalar r)
+{
+return(FromCE(c,btVector3(r,r,r)));
+}
+       
+//
+inline btDbvtAabbMm                    btDbvtAabbMm::FromMM(const btVector3& mi,const btVector3& mx)
+{
+btDbvtAabbMm box;
+box.mi=mi;box.mx=mx;
+return(box);
+}
+       
+//
+inline btDbvtAabbMm                    btDbvtAabbMm::FromPoints(const btVector3* pts,int n)
+{
+btDbvtAabbMm box;
+box.mi=box.mx=pts[0];
+for(int i=1;i<n;++i)
+       {
+       box.mi.setMin(pts[i]);
+       box.mx.setMax(pts[i]);
+       }
+return(box);
+}
+
+//
+inline btDbvtAabbMm                    btDbvtAabbMm::FromPoints(const btVector3** ppts,int n)
+{
+btDbvtAabbMm box;
+box.mi=box.mx=*ppts[0];
+for(int i=1;i<n;++i)
+       {
+       box.mi.setMin(*ppts[i]);
+       box.mx.setMax(*ppts[i]);
+       }
+return(box);
+}
+
+//
+DBVT_INLINE void               btDbvtAabbMm::Expand(const btVector3& e)
+{
+mi-=e;mx+=e;
+}
+       
+//
+DBVT_INLINE void               btDbvtAabbMm::SignedExpand(const btVector3& e)
+{
+if(e.x()>0) mx.setX(mx.x()+e[0]); else mi.setX(mi.x()+e[0]);
+if(e.y()>0) mx.setY(mx.y()+e[1]); else mi.setY(mi.y()+e[1]);
+if(e.z()>0) mx.setZ(mx.z()+e[2]); else mi.setZ(mi.z()+e[2]);
+}
+       
+//
+DBVT_INLINE bool               btDbvtAabbMm::Contain(const btDbvtAabbMm& a) const
+{
+return(        (mi.x()<=a.mi.x())&&
+               (mi.y()<=a.mi.y())&&
+               (mi.z()<=a.mi.z())&&
+               (mx.x()>=a.mx.x())&&
+               (mx.y()>=a.mx.y())&&
+               (mx.z()>=a.mx.z()));
+}
+
+//
+DBVT_INLINE int                btDbvtAabbMm::Classify(const btVector3& n,btScalar o,int s) const
+{
+btVector3                      pi,px;
+switch(s)
+       {
+       case    (0+0+0):        px=btVector3(mi.x(),mi.y(),mi.z());
+                                               pi=btVector3(mx.x(),mx.y(),mx.z());break;
+       case    (1+0+0):        px=btVector3(mx.x(),mi.y(),mi.z());
+                                               pi=btVector3(mi.x(),mx.y(),mx.z());break;
+       case    (0+2+0):        px=btVector3(mi.x(),mx.y(),mi.z());
+                                               pi=btVector3(mx.x(),mi.y(),mx.z());break;
+       case    (1+2+0):        px=btVector3(mx.x(),mx.y(),mi.z());
+                                               pi=btVector3(mi.x(),mi.y(),mx.z());break;
+       case    (0+0+4):        px=btVector3(mi.x(),mi.y(),mx.z());
+                                               pi=btVector3(mx.x(),mx.y(),mi.z());break;
+       case    (1+0+4):        px=btVector3(mx.x(),mi.y(),mx.z());
+                                               pi=btVector3(mi.x(),mx.y(),mi.z());break;
+       case    (0+2+4):        px=btVector3(mi.x(),mx.y(),mx.z());
+                                               pi=btVector3(mx.x(),mi.y(),mi.z());break;
+       case    (1+2+4):        px=btVector3(mx.x(),mx.y(),mx.z());
+                                               pi=btVector3(mi.x(),mi.y(),mi.z());break;
+       }
+if((dot(n,px)+o)<0)            return(-1);
+if((dot(n,pi)+o)>=0)   return(+1);
+return(0);
+}
+
+//
+DBVT_INLINE btScalar   btDbvtAabbMm::ProjectMinimum(const btVector3& v,unsigned signs) const
+{
+const btVector3*       b[]={&mx,&mi};
+const btVector3                p(      b[(signs>>0)&1]->x(),
+                                               b[(signs>>1)&1]->y(),
+                                               b[(signs>>2)&1]->z());
+return(dot(p,v));
+}
+
+//
+DBVT_INLINE void               btDbvtAabbMm::AddSpan(const btVector3& d,btScalar& smi,btScalar& smx) const
+{
+for(int i=0;i<3;++i)
+       {
+       if(d[i]<0)
+               { smi+=mx[i]*d[i];smx+=mi[i]*d[i]; }
+               else
+               { smi+=mi[i]*d[i];smx+=mx[i]*d[i]; }
+       }
+}
+       
+//
+DBVT_INLINE bool               Intersect(      const btDbvtAabbMm& a,
+                                                                       const btDbvtAabbMm& b)
+{
+#if    DBVT_INT0_IMPL == DBVT_IMPL_SSE
+const __m128   rt(_mm_or_ps(   _mm_cmplt_ps(_mm_load_ps(b.mx),_mm_load_ps(a.mi)),
+                                                               _mm_cmplt_ps(_mm_load_ps(a.mx),_mm_load_ps(b.mi))));
+const __int32* pu((const __int32*)&rt);
+return((pu[0]|pu[1]|pu[2])==0);
+#else
+return(        (a.mi.x()<=b.mx.x())&&
+               (a.mx.x()>=b.mi.x())&&
+               (a.mi.y()<=b.mx.y())&&
+               (a.mx.y()>=b.mi.y())&&
+               (a.mi.z()<=b.mx.z())&&          
+               (a.mx.z()>=b.mi.z()));
+#endif
+}
+
+//
+DBVT_INLINE bool               Intersect(      const btDbvtAabbMm& a,
+                                                                       const btDbvtAabbMm& b,
+                                                                       const btTransform& xform)
+{
+const btVector3                d0=xform*b.Center()-a.Center();
+const btVector3                d1=d0*xform.getBasis();
+btScalar                       s0[2]={0,0};
+btScalar                       s1[2]={dot(xform.getOrigin(),d0),s1[0]};
+a.AddSpan(d0,s0[0],s0[1]);
+b.AddSpan(d1,s1[0],s1[1]);
+if(s0[0]>(s1[1])) return(false);
+if(s0[1]<(s1[0])) return(false);
+return(true);
+}
+
+//
+DBVT_INLINE bool               Intersect(      const btDbvtAabbMm& a,
+                                                                       const btVector3& b)
+{
+return(        (b.x()>=a.mi.x())&&
+               (b.y()>=a.mi.y())&&
+               (b.z()>=a.mi.z())&&
+               (b.x()<=a.mx.x())&&
+               (b.y()<=a.mx.y())&&
+               (b.z()<=a.mx.z()));
+}
+
+//
+DBVT_INLINE bool               Intersect(      const btDbvtAabbMm& a,
+                                                                       const btVector3& org,
+                                                                       const btVector3& invdir,
+                                                                       const unsigned* signs)
+{
+#if 0
+const btVector3                b0((a.mi-org)*invdir);
+const btVector3                b1((a.mx-org)*invdir);
+const btVector3                tmin(btMin(b0[0],b1[0]),btMin(b0[1],b1[1]),btMin(b0[2],b1[2]));
+const btVector3                tmax(btMax(b0[0],b1[0]),btMax(b0[1],b1[1]),btMax(b0[2],b1[2]));
+const btScalar         tin=btMax(tmin[0],btMax(tmin[1],tmin[2]));
+const btScalar         tout=btMin(tmax[0],btMin(tmax[1],tmax[2]));
+return(tin<tout);
+#else
+const btVector3*       bounds[2]={&a.mi,&a.mx};
+btScalar                       txmin=(bounds[  signs[0]]->x()-org[0])*invdir[0];
+btScalar                       txmax=(bounds[1-signs[0]]->x()-org[0])*invdir[0];
+const btScalar         tymin=(bounds[  signs[1]]->y()-org[1])*invdir[1];
+const btScalar         tymax=(bounds[1-signs[1]]->y()-org[1])*invdir[1];
+if((txmin>tymax)||(tymin>txmax)) return(false);
+if(tymin>txmin) txmin=tymin;
+if(tymax<txmax) txmax=tymax;
+const btScalar         tzmin=(bounds[  signs[2]]->z()-org[2])*invdir[2];
+const btScalar         tzmax=(bounds[1-signs[2]]->z()-org[2])*invdir[2];
+if((txmin>tzmax)||(tzmin>txmax)) return(false);
+if(tzmin>txmin) txmin=tzmin;
+if(tzmax<txmax) txmax=tzmax;
+return(txmax>0);
+#endif
+}
+       
+//
+DBVT_INLINE btScalar   Proximity(      const btDbvtAabbMm& a,
+                                                                       const btDbvtAabbMm& b)
+{
+const btVector3        d=(a.mi+a.mx)-(b.mi+b.mx);
+return(btFabs(d.x())+btFabs(d.y())+btFabs(d.z()));
+}
+
+//
+DBVT_INLINE int                        Select( const btDbvtAabbMm& o,
+                                                               const btDbvtAabbMm& a,
+                                                               const btDbvtAabbMm& b)
+{
+#if    DBVT_SELECT_IMPL == DBVT_IMPL_SSE
+static DBVT_ALIGN const unsigned __int32       mask[]={0x7fffffff,0x7fffffff,0x7fffffff,0x7fffffff};
+       // TODO: the intrinsic version is 11% slower
+       #if DBVT_USE_INTRINSIC_SSE
+       __m128  omi(_mm_load_ps(o.mi));
+       omi=_mm_add_ps(omi,_mm_load_ps(o.mx));
+       __m128  ami(_mm_load_ps(a.mi));
+       ami=_mm_add_ps(ami,_mm_load_ps(a.mx));
+       ami=_mm_sub_ps(ami,omi);
+       ami=_mm_and_ps(ami,_mm_load_ps((const float*)mask));
+       __m128  bmi(_mm_load_ps(b.mi));
+       bmi=_mm_add_ps(bmi,_mm_load_ps(b.mx));
+       bmi=_mm_sub_ps(bmi,omi);
+       bmi=_mm_and_ps(bmi,_mm_load_ps((const float*)mask));
+       __m128  t0(_mm_movehl_ps(ami,ami));
+       ami=_mm_add_ps(ami,t0);
+       ami=_mm_add_ss(ami,_mm_shuffle_ps(ami,ami,1));
+       __m128  t1(_mm_movehl_ps(bmi,bmi));
+       bmi=_mm_add_ps(bmi,t1);
+       bmi=_mm_add_ss(bmi,_mm_shuffle_ps(bmi,bmi,1));
+       return(_mm_cmple_ss(bmi,ami).m128_u32[0]&1);
+       #else
+       DBVT_ALIGN __int32      r[1];
+       __asm
+               {
+               mov             eax,o
+               mov             ecx,a
+               mov             edx,b
+               movaps  xmm0,[eax]
+               movaps  xmm5,mask
+               addps   xmm0,[eax+16]   
+               movaps  xmm1,[ecx]
+               movaps  xmm2,[edx]
+               addps   xmm1,[ecx+16]
+               addps   xmm2,[edx+16]
+               subps   xmm1,xmm0
+               subps   xmm2,xmm0
+               andps   xmm1,xmm5
+               andps   xmm2,xmm5
+               movhlps xmm3,xmm1
+               movhlps xmm4,xmm2
+               addps   xmm1,xmm3
+               addps   xmm2,xmm4
+               pshufd  xmm3,xmm1,1
+               pshufd  xmm4,xmm2,1
+               addss   xmm1,xmm3
+               addss   xmm2,xmm4
+               cmpless xmm2,xmm1
+               movss   r,xmm2
+               }
+       return(r[0]&1);
+       #endif
+#else
+return(Proximity(o,a)<Proximity(o,b)?0:1);
+#endif
+}
+
+//
+DBVT_INLINE void               Merge(  const btDbvtAabbMm& a,
+                                                               const btDbvtAabbMm& b,
+                                                               btDbvtAabbMm& r)
+{
+#if DBVT_MERGE_IMPL==DBVT_IMPL_SSE
+__m128 ami(_mm_load_ps(a.mi));
+__m128 amx(_mm_load_ps(a.mx));
+__m128 bmi(_mm_load_ps(b.mi));
+__m128 bmx(_mm_load_ps(b.mx));
+ami=_mm_min_ps(ami,bmi);
+amx=_mm_max_ps(amx,bmx);
+_mm_store_ps(r.mi,ami);
+_mm_store_ps(r.mx,amx);
+#else
+for(int i=0;i<3;++i)
+       {
+       if(a.mi[i]<b.mi[i]) r.mi[i]=a.mi[i]; else r.mi[i]=b.mi[i];
+       if(a.mx[i]>b.mx[i]) r.mx[i]=a.mx[i]; else r.mx[i]=b.mx[i];
+       }
+#endif
+}
+
+//
+DBVT_INLINE bool               NotEqual(       const btDbvtAabbMm& a,
+                                                                       const btDbvtAabbMm& b)
+{
+return(        (a.mi.x()!=b.mi.x())||
+               (a.mi.y()!=b.mi.y())||
+               (a.mi.z()!=b.mi.z())||
+               (a.mx.x()!=b.mx.x())||
+               (a.mx.y()!=b.mx.y())||
+               (a.mx.z()!=b.mx.z()));
+}
+
+//
+// Inline's
+//
+
+//
+DBVT_PREFIX
+inline void            btDbvt::enumNodes(      const btDbvtNode* root,
+                                                                       DBVT_IPOLICY)
+{
+DBVT_CHECKTYPE
+policy.Process(root);
+if(root->isinternal())
+       {
+       enumNodes(root->childs[0],policy);
+       enumNodes(root->childs[1],policy);
+       }
+}
+
+//
+DBVT_PREFIX
+inline void            btDbvt::enumLeaves(     const btDbvtNode* root,
+                                                                       DBVT_IPOLICY)
+{
+DBVT_CHECKTYPE
+if(root->isinternal())
+       {
+       enumLeaves(root->childs[0],policy);
+       enumLeaves(root->childs[1],policy);
+       }
+       else
+       {
+       policy.Process(root);
+       }
+}
+
+//
+DBVT_PREFIX
+inline void            btDbvt::collideTT(      const btDbvtNode* root0,
+                                                                       const btDbvtNode* root1,
+                                                                       DBVT_IPOLICY)
+{
+DBVT_CHECKTYPE
+if(root0&&root1)
+       {
+       btAlignedObjectArray<sStkNN>    stack;
+       int                                                             depth=1;
+       int                                                             treshold=DOUBLE_STACKSIZE-4;
+       stack.resize(DOUBLE_STACKSIZE);
+       stack[0]=sStkNN(root0,root1);
+       do      {               
+               sStkNN  p=stack[--depth];
+               if(depth>treshold)
+                       {
+                       stack.resize(stack.size()*2);
+                       treshold=stack.size()-4;
+                       }
+               if(p.a==p.b)
+                       {
+                       if(p.a->isinternal())
+                               {
+                               stack[depth++]=sStkNN(p.a->childs[0],p.a->childs[0]);
+                               stack[depth++]=sStkNN(p.a->childs[1],p.a->childs[1]);
+                               stack[depth++]=sStkNN(p.a->childs[0],p.a->childs[1]);
+                               }
+                       }
+               else if(Intersect(p.a->volume,p.b->volume))
+                       {
+                       if(p.a->isinternal())
+                               {
+                               if(p.b->isinternal())
+                                       {
+                                       stack[depth++]=sStkNN(p.a->childs[0],p.b->childs[0]);
+                                       stack[depth++]=sStkNN(p.a->childs[1],p.b->childs[0]);
+                                       stack[depth++]=sStkNN(p.a->childs[0],p.b->childs[1]);
+                                       stack[depth++]=sStkNN(p.a->childs[1],p.b->childs[1]);
+                                       }
+                                       else
+                                       {
+                                       stack[depth++]=sStkNN(p.a->childs[0],p.b);
+                                       stack[depth++]=sStkNN(p.a->childs[1],p.b);
+                                       }
+                               }
+                               else
+                               {
+                               if(p.b->isinternal())
+                                       {
+                                       stack[depth++]=sStkNN(p.a,p.b->childs[0]);
+                                       stack[depth++]=sStkNN(p.a,p.b->childs[1]);
+                                       }
+                                       else
+                                       {
+                                       policy.Process(p.a,p.b);
+                                       }
+                               }
+                       }
+               } while(depth);
+       }
+}
+
+//
+DBVT_PREFIX
+inline void            btDbvt::collideTT(      const btDbvtNode* root0,
+                                                                       const btDbvtNode* root1,
+                                                                       const btTransform& xform,
+                                                                       DBVT_IPOLICY)
+{
+DBVT_CHECKTYPE
+if(root0&&root1)
+       {
+       btAlignedObjectArray<sStkNN>    stack;
+       int                                                             depth=1;
+       int                                                             treshold=DOUBLE_STACKSIZE-4;
+       stack.resize(DOUBLE_STACKSIZE);
+       stack[0]=sStkNN(root0,root1);
+       do      {
+               sStkNN  p=stack[--depth];
+               if(Intersect(p.a->volume,p.b->volume,xform))
+                       {
+                       if(depth>treshold)
+                               {
+                               stack.resize(stack.size()*2);
+                               treshold=stack.size()-4;
+                               }
+                       if(p.a->isinternal())
+                               {
+                               if(p.b->isinternal())
+                                       {                                       
+                                       stack[depth++]=sStkNN(p.a->childs[0],p.b->childs[0]);
+                                       stack[depth++]=sStkNN(p.a->childs[1],p.b->childs[0]);
+                                       stack[depth++]=sStkNN(p.a->childs[0],p.b->childs[1]);
+                                       stack[depth++]=sStkNN(p.a->childs[1],p.b->childs[1]);
+                                       }
+                                       else
+                                       {
+                                       stack[depth++]=sStkNN(p.a->childs[0],p.b);
+                                       stack[depth++]=sStkNN(p.a->childs[1],p.b);
+                                       }
+                               }
+                               else
+                               {
+                               if(p.b->isinternal())
+                                       {
+                                       stack[depth++]=sStkNN(p.a,p.b->childs[0]);
+                                       stack[depth++]=sStkNN(p.a,p.b->childs[1]);
+                                       }
+                                       else
+                                       {
+                                       policy.Process(p.a,p.b);
+                                       }
+                               }
+                       }
+               } while(depth);
+       }
+}
+
+//
+DBVT_PREFIX
+inline void            btDbvt::collideTT(      const btDbvtNode* root0,
+                                                                       const btTransform& xform0,
+                                                                       const btDbvtNode* root1,
+                                                                       const btTransform& xform1,
+                                                                       DBVT_IPOLICY)
+{
+const btTransform      xform=xform0.inverse()*xform1;
+collideTT(root0,root1,xform,policy);
+}
+
+//
+DBVT_PREFIX
+inline void            btDbvt::collideTV(      const btDbvtNode* root,
+                                                                       const btDbvtVolume& vol,
+                                                                       DBVT_IPOLICY)
+{
+DBVT_CHECKTYPE
+if(root)
+       {
+       ATTRIBUTE_ALIGNED16(btDbvtVolume)               volume(vol);
+       btAlignedObjectArray<const btDbvtNode*> stack;
+       stack.reserve(SIMPLE_STACKSIZE);
+       stack.push_back(root);
+       do      {
+               const btDbvtNode*       n=stack[stack.size()-1];
+               stack.pop_back();
+               if(Intersect(n->volume,volume))
+                       {
+                       if(n->isinternal())
+                               {
+                               stack.push_back(n->childs[0]);
+                               stack.push_back(n->childs[1]);
+                               }
+                               else
+                               {
+                               policy.Process(n);
+                               }
+                       }
+               } while(stack.size()>0);
+       }
+}
+
+//
+DBVT_PREFIX
+inline void            btDbvt::collideRAY(     const btDbvtNode* root,
+                                                                       const btVector3& origin,
+                                                                       const btVector3& direction,
+                                                                       DBVT_IPOLICY)
+{
+DBVT_CHECKTYPE
+if(root)
+       {
+       const btVector3 normal=direction.normalized();
+       const btVector3 invdir( 1/normal.x(),
+                                                       1/normal.y(),
+                                                       1/normal.z());
+       const unsigned  signs[]={       direction.x()<0,
+                                                               direction.y()<0,
+                                                               direction.z()<0};
+       btAlignedObjectArray<const btDbvtNode*> stack;
+       stack.reserve(SIMPLE_STACKSIZE);
+       stack.push_back(root);
+       do      {
+               const btDbvtNode*       node=stack[stack.size()-1];
+               stack.pop_back();
+               if(Intersect(node->volume,origin,invdir,signs))
+                       {
+                       if(node->isinternal())
+                               {
+                               stack.push_back(node->childs[0]);
+                               stack.push_back(node->childs[1]);
+                               }
+                               else
+                               {
+                               policy.Process(node);
+                               }
+                       }
+               } while(stack.size());
+       }
+}
+
+//
+DBVT_PREFIX
+inline void            btDbvt::collideKDOP(const btDbvtNode* root,
+                                                                       const btVector3* normals,
+                                                                       const btScalar* offsets,
+                                                                       int count,
+                                                                       DBVT_IPOLICY)
+{
+DBVT_CHECKTYPE
+if(root)
+       {
+       const int                                               inside=(1<<count)-1;
+       btAlignedObjectArray<sStkNP>    stack;
+       int                                                             signs[sizeof(unsigned)*8];
+       btAssert(count<int (sizeof(signs)/sizeof(signs[0])));
+       for(int i=0;i<count;++i)
+               {
+               signs[i]=       ((normals[i].x()>=0)?1:0)+
+                                       ((normals[i].y()>=0)?2:0)+
+                                       ((normals[i].z()>=0)?4:0);
+               }
+       stack.reserve(SIMPLE_STACKSIZE);
+       stack.push_back(sStkNP(root,0));
+       do      {
+               sStkNP  se=stack[stack.size()-1];
+               bool    out=false;
+               stack.pop_back();
+               for(int i=0,j=1;(!out)&&(i<count);++i,j<<=1)
+                       {
+                       if(0==(se.mask&j))
+                               {
+                               const int       side=se.node->volume.Classify(normals[i],offsets[i],signs[i]);
+                               switch(side)
+                                       {
+                                       case    -1:     out=true;break;
+                                       case    +1:     se.mask|=j;break;
+                                       }
+                               }
+                       }
+               if(!out)
+                       {
+                       if((se.mask!=inside)&&(se.node->isinternal()))
+                               {
+                               stack.push_back(sStkNP(se.node->childs[0],se.mask));
+                               stack.push_back(sStkNP(se.node->childs[1],se.mask));
+                               }
+                               else
+                               {
+                               if(policy.AllLeaves(se.node)) enumLeaves(se.node,policy);
+                               }
+                       }
+               } while(stack.size());
+       }
+}
+
+//
+DBVT_PREFIX
+inline void            btDbvt::collideOCL(     const btDbvtNode* root,
+                                                                       const btVector3* normals,
+                                                                       const btScalar* offsets,
+                                                                       const btVector3& sortaxis,
+                                                                       int count,
+                                                                       DBVT_IPOLICY,
+                                                                       bool fsort)
+{
+DBVT_CHECKTYPE
+if(root)
+       {
+       const unsigned                                  srtsgns=(sortaxis[0]>=0?1:0)+
+                                                                                       (sortaxis[1]>=0?2:0)+
+                                                                                       (sortaxis[2]>=0?4:0);
+       const int                                               inside=(1<<count)-1;
+       btAlignedObjectArray<sStkNPS>   stock;
+       btAlignedObjectArray<int>               ifree;
+       btAlignedObjectArray<int>               stack;
+       int                                                             signs[sizeof(unsigned)*8];
+       btAssert(count<int (sizeof(signs)/sizeof(signs[0])));
+       for(int i=0;i<count;++i)
+               {
+               signs[i]=       ((normals[i].x()>=0)?1:0)+
+                                       ((normals[i].y()>=0)?2:0)+
+                                       ((normals[i].z()>=0)?4:0);
+               }
+       stock.reserve(SIMPLE_STACKSIZE);
+       stack.reserve(SIMPLE_STACKSIZE);
+       ifree.reserve(SIMPLE_STACKSIZE);
+       stack.push_back(allocate(ifree,stock,sStkNPS(root,0,root->volume.ProjectMinimum(sortaxis,srtsgns))));
+       do      {
+               const int       id=stack[stack.size()-1];
+               sStkNPS         se=stock[id];
+               stack.pop_back();ifree.push_back(id);
+               if(se.mask!=inside)
+                       {
+                       bool    out=false;
+                       for(int i=0,j=1;(!out)&&(i<count);++i,j<<=1)
+                               {
+                               if(0==(se.mask&j))
+                                       {
+                                       const int       side=se.node->volume.Classify(normals[i],offsets[i],signs[i]);
+                                       switch(side)
+                                               {
+                                               case    -1:     out=true;break;
+                                               case    +1:     se.mask|=j;break;
+                                               }
+                                       }
+                               }
+                       if(out) continue;
+                       }
+               if(policy.Descent(se.node))
+                       {
+                       if(se.node->isinternal())
+                               {
+                               const btDbvtNode* pns[]={       se.node->childs[0],se.node->childs[1]};
+                               sStkNPS         nes[]={ sStkNPS(pns[0],se.mask,pns[0]->volume.ProjectMinimum(sortaxis,srtsgns)),
+                                                                       sStkNPS(pns[1],se.mask,pns[1]->volume.ProjectMinimum(sortaxis,srtsgns))};
+                               const int       q=nes[0].value<nes[1].value?1:0;                                
+                               int                     j=stack.size();
+                               if(fsort&&(j>0))
+                                       {
+                                       /* Insert 0     */ 
+                                       j=nearest(&stack[0],&stock[0],nes[q].value,0,stack.size());
+                                       stack.push_back(0);
+                                       #if DBVT_USE_MEMMOVE
+                                       memmove(&stack[j+1],&stack[j],sizeof(int)*(stack.size()-j-1));
+                                       #else
+                                       for(int k=stack.size()-1;k>j;--k) stack[k]=stack[k-1];
+                                       #endif
+                                       stack[j]=allocate(ifree,stock,nes[q]);
+                                       /* Insert 1     */ 
+                                       j=nearest(&stack[0],&stock[0],nes[1-q].value,j,stack.size());
+                                       stack.push_back(0);
+                                       #if DBVT_USE_MEMMOVE
+                                       memmove(&stack[j+1],&stack[j],sizeof(int)*(stack.size()-j-1));
+                                       #else
+                                       for(int k=stack.size()-1;k>j;--k) stack[k]=stack[k-1];
+                                       #endif
+                                       stack[j]=allocate(ifree,stock,nes[1-q]);
+                                       }
+                                       else
+                                       {
+                                       stack.push_back(allocate(ifree,stock,nes[q]));
+                                       stack.push_back(allocate(ifree,stock,nes[1-q]));
+                                       }
+                               }
+                               else
+                               {
+                               policy.Process(se.node,se.value);
+                               }
+                       }
+               } while(stack.size());
+       }
+}
+
+//
+DBVT_PREFIX
+inline void            btDbvt::collideTU(      const btDbvtNode* root,
+                                                                       DBVT_IPOLICY)
+{
+DBVT_CHECKTYPE
+if(root)
+       {
+       btAlignedObjectArray<const btDbvtNode*> stack;
+       stack.reserve(SIMPLE_STACKSIZE);
+       stack.push_back(root);
+       do      {
+               const btDbvtNode*       n=stack[stack.size()-1];
+               stack.pop_back();
+               if(policy.Descent(n))
+                       {
+                       if(n->isinternal())
+                               { stack.push_back(n->childs[0]);stack.push_back(n->childs[1]); }
+                               else
+                               { policy.Process(n); }
+                       }
+               } while(stack.size()>0);
+       }
+}
+
+//
+// PP Cleanup
+//
+
+#undef DBVT_USE_MEMMOVE
+#undef DBVT_USE_TEMPLATE
+#undef DBVT_VIRTUAL_DTOR
+#undef DBVT_VIRTUAL
+#undef DBVT_PREFIX
+#undef DBVT_IPOLICY
+#undef DBVT_CHECKTYPE
+#undef DBVT_IMPL_GENERIC
+#undef DBVT_IMPL_SSE
+#undef DBVT_USE_INTRINSIC_SSE
+#undef DBVT_SELECT_IMPL
+#undef DBVT_MERGE_IMPL
+#undef DBVT_INT0_IMPL
+
+#endif
diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp
new file mode 100644 (file)
index 0000000..e00fc6a
--- /dev/null
@@ -0,0 +1,548 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2007 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+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"
+
+//
+// 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>pb) 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           =       1/(btScalar)2;
+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 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,
+                                                                                                                               short int collisionFilterGroup,
+                                                                                                                               short int collisionFilterMask,
+                                                                                                                               btDispatcher* /*dispatcher*/,
+                                                                                                                               void* /*multiSapProxy*/)
+{
+btDbvtProxy*           proxy=new(btAlignedAlloc(sizeof(btDbvtProxy),16)) btDbvtProxy(  userPtr,
+                                                                                                                                                                       collisionFilterGroup,
+                                                                                                                                                                       collisionFilterMask);
+proxy->aabb                    =       btDbvtVolume::FromMM(aabbMin,aabbMax);
+proxy->stage           =       m_stageCurrent;
+proxy->m_uniqueId      =       ++m_gid;
+proxy->leaf                    =       m_sets[0].insert(proxy->aabb,proxy);
+listappend(proxy,m_stageRoots[m_stageCurrent]);
+if(!m_deferedcollide)
+       {
+       btDbvtTreeCollider      collider(this);
+       collider.proxy=proxy;
+       btDbvt::collideTV(m_sets[0].m_root,proxy->aabb,collider);
+       btDbvt::collideTV(m_sets[1].m_root,proxy->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::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->aabb.Mins();
+                       btVector3               velocity(aabb.Extents()*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      (
+                               #ifdef DBVT_BP_MARGIN                           
+                               m_sets[0].update(proxy->leaf,aabb,velocity,DBVT_BP_MARGIN)
+                               #else
+                               m_sets[0].update(proxy->leaf,aabb,velocity)
+                               #endif
+                               )
+                               {
+                               ++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->aabb             =       aabb;
+       proxy->stage    =       m_stageCurrent;
+       listappend(proxy,m_stageRoots[m_stageCurrent]);
+       if(docollide)
+               {
+               m_needcleanup=true;
+               if(!m_deferedcollide)
+                       {
+                       btDbvtTreeCollider      collider(this);
+                       btDbvt::collideTT(m_sets[1].m_root,proxy->leaf,collider);
+                       btDbvt::collideTT(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
+}
+
+//
+void                                                   btDbvtBroadphase::collide(btDispatcher* dispatcher)
+{
+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)
+       {
+       btDbvtTreeCollider      collider(this);
+       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);
+               current->leaf   =       m_sets[1].insert(current->aabb,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);
+               btDbvt::collideTT(m_sets[0].m_root,m_sets[1].m_root,collider);
+               }
+       if(m_deferedcollide)
+               {
+               SPC(m_profiling.m_ddcollide);
+               btDbvt::collideTT(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)
+               {
+               const int       ci=pairs.size();
+               int                     ni=btMin(ci,btMax<int>(m_newpairs,(ci*m_cupdates)/100));
+               for(int i=0;i<ni;++i)
+                       {
+                       btBroadphasePair&       p=pairs[(m_cid+i)%ci];
+                       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>pb) 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::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
diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h
new file mode 100644 (file)
index 0000000..1f16043
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2007 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+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
+#ifndef BT_DBVT_BROADPHASE_H
+#define BT_DBVT_BROADPHASE_H
+
+#include "BulletCollision/BroadphaseCollision/btDbvt.h"
+#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
+
+//
+// Compile time config
+//
+
+#define        DBVT_BP_PROFILE                                 0
+#define DBVT_BP_SORTPAIRS                              1
+#define DBVT_BP_PREVENTFALSEUPDATE             0
+#define DBVT_BP_ACCURATESLEEPING               0
+#define DBVT_BP_ENABLE_BENCHMARK               0
+#define DBVT_BP_MARGIN                                 (btScalar)0.05
+
+#if DBVT_BP_PROFILE
+       #define DBVT_BP_PROFILING_RATE  256
+       #include "LinearMath/btQuickprof.h"
+#endif
+
+//
+// btDbvtProxy
+//
+struct btDbvtProxy : btBroadphaseProxy
+{
+/* Fields              */ 
+btDbvtAabbMm   aabb;
+btDbvtNode*            leaf;
+btDbvtProxy*   links[2];
+int                            stage;
+/* ctor                        */ 
+btDbvtProxy(void* userPtr,short int collisionFilterGroup, short int collisionFilterMask) :
+       btBroadphaseProxy(userPtr,collisionFilterGroup,collisionFilterMask)
+       {
+       links[0]=links[1]=0;
+       }
+};
+
+typedef btAlignedObjectArray<btDbvtProxy*>     btDbvtProxyArray;
+
+///The btDbvtBroadphase implements a broadphase using two dynamic AABB bounding volume hierarchies/trees (see btDbvt).
+///One tree is used for static/non-moving objects, and another tree is used for dynamic objects. Objects can move from one tree to the other.
+///This is a very fast broadphase, especially for very dynamic worlds where many objects are moving. Its insert/add and remove of objects is generally faster than the sweep and prune broadphases btAxisSweep3 and bt32BitAxisSweep3.
+struct btDbvtBroadphase : btBroadphaseInterface
+{
+/* Config              */ 
+enum   {
+               DYNAMIC_SET                     =       0,      /* Dynamic set index    */ 
+               FIXED_SET                       =       1,      /* Fixed set index              */ 
+               STAGECOUNT                      =       2       /* Number of stages             */ 
+               };
+/* Fields              */ 
+btDbvt                                 m_sets[2];                                      // Dbvt sets
+btDbvtProxy*                   m_stageRoots[STAGECOUNT+1];     // Stages list
+btOverlappingPairCache*        m_paircache;                            // Pair cache
+btScalar                               m_prediction;                           // Velocity prediction
+int                                            m_stageCurrent;                         // Current stage
+int                                            m_fupdates;                                     // % of fixed updates per frame
+int                                            m_dupdates;                                     // % of dynamic updates per frame
+int                                            m_cupdates;                                     // % of cleanup updates per frame
+int                                            m_newpairs;                                     // Number of pairs created
+int                                            m_fixedleft;                            // Fixed optimization left
+unsigned                               m_updates_call;                         // Number of updates call
+unsigned                               m_updates_done;                         // Number of updates done
+btScalar                               m_updates_ratio;                        // m_updates_done/m_updates_call
+int                                            m_pid;                                          // Parse id
+int                                            m_cid;                                          // Cleanup index
+int                                            m_gid;                                          // Gen id
+bool                                   m_releasepaircache;                     // Release pair cache on delete
+bool                                   m_deferedcollide;                       // Defere dynamic/static collision to collide call
+bool                                   m_needcleanup;                          // Need to run cleanup?
+#if DBVT_BP_PROFILE
+btClock                                        m_clock;
+struct {
+               unsigned long           m_total;
+               unsigned long           m_ddcollide;
+               unsigned long           m_fdcollide;
+               unsigned long           m_cleanup;
+               unsigned long           m_jobcount;
+               }                               m_profiling;
+#endif
+/* Methods             */ 
+btDbvtBroadphase(btOverlappingPairCache* paircache=0);
+~btDbvtBroadphase();
+void                                                   collide(btDispatcher* dispatcher);
+void                                                   optimize();
+/* btBroadphaseInterface Implementation        */ 
+btBroadphaseProxy*                             createProxy(const btVector3& aabbMin,const btVector3& aabbMax,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy);
+void                                                   destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
+void                                                   setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher);
+void                                                   calculateOverlappingPairs(btDispatcher* dispatcher);
+btOverlappingPairCache*                        getOverlappingPairCache();
+const btOverlappingPairCache*  getOverlappingPairCache() const;
+void                                                   getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const;
+void                                                   printStats();
+static void                                            benchmark(btBroadphaseInterface*);
+};
+
+#endif
diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp
new file mode 100644 (file)
index 0000000..3f866ab
--- /dev/null
@@ -0,0 +1,466 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+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.
+*/
+
+#include "btMultiSapBroadphase.h"
+
+#include "btSimpleBroadphase.h"
+#include "LinearMath/btAabbUtil2.h"
+#include "btQuantizedBvh.h"
+
+///    btSapBroadphaseArray    m_sapBroadphases;
+
+///    btOverlappingPairCache* m_overlappingPairs;
+extern int gOverlappingPairs;
+
+/*
+class btMultiSapSortedOverlappingPairCache : public btSortedOverlappingPairCache
+{
+public:
+
+       virtual btBroadphasePair*       addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
+       {
+               return btSortedOverlappingPairCache::addOverlappingPair((btBroadphaseProxy*)proxy0->m_multiSapParentProxy,(btBroadphaseProxy*)proxy1->m_multiSapParentProxy);
+       }
+};
+
+*/
+
+btMultiSapBroadphase::btMultiSapBroadphase(int /*maxProxies*/,btOverlappingPairCache* pairCache)
+:m_overlappingPairs(pairCache),
+m_optimizedAabbTree(0),
+m_ownsPairCache(false),
+m_invalidPair(0)
+{
+       if (!m_overlappingPairs)
+       {
+               m_ownsPairCache = true;
+               void* mem = btAlignedAlloc(sizeof(btSortedOverlappingPairCache),16);
+               m_overlappingPairs = new (mem)btSortedOverlappingPairCache();
+       }
+
+       struct btMultiSapOverlapFilterCallback : public btOverlapFilterCallback
+       {
+               virtual ~btMultiSapOverlapFilterCallback()
+               {}
+               // return true when pairs need collision
+               virtual bool    needBroadphaseCollision(btBroadphaseProxy* childProxy0,btBroadphaseProxy* childProxy1) const
+               {
+                       btBroadphaseProxy* multiProxy0 = (btBroadphaseProxy*)childProxy0->m_multiSapParentProxy;
+                       btBroadphaseProxy* multiProxy1 = (btBroadphaseProxy*)childProxy1->m_multiSapParentProxy;
+                       
+                       bool collides = (multiProxy0->m_collisionFilterGroup & multiProxy1->m_collisionFilterMask) != 0;
+                       collides = collides && (multiProxy1->m_collisionFilterGroup & multiProxy0->m_collisionFilterMask);
+       
+                       return collides;
+               }
+       };
+
+       void* mem = btAlignedAlloc(sizeof(btMultiSapOverlapFilterCallback),16);
+       m_filterCallback = new (mem)btMultiSapOverlapFilterCallback();
+
+       m_overlappingPairs->setOverlapFilterCallback(m_filterCallback);
+//     mem = btAlignedAlloc(sizeof(btSimpleBroadphase),16);
+//     m_simpleBroadphase = new (mem) btSimpleBroadphase(maxProxies,m_overlappingPairs);
+}
+
+btMultiSapBroadphase::~btMultiSapBroadphase()
+{
+       if (m_ownsPairCache)
+       {
+               m_overlappingPairs->~btOverlappingPairCache();
+               btAlignedFree(m_overlappingPairs);
+       }
+}
+
+
+void   btMultiSapBroadphase::buildTree(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax)
+{
+       m_optimizedAabbTree = new btQuantizedBvh();
+       m_optimizedAabbTree->setQuantizationValues(bvhAabbMin,bvhAabbMax);
+       QuantizedNodeArray&     nodes = m_optimizedAabbTree->getLeafNodeArray();
+       for (int i=0;i<m_sapBroadphases.size();i++)
+       {
+               btQuantizedBvhNode node;
+               btVector3 aabbMin,aabbMax;
+               m_sapBroadphases[i]->getBroadphaseAabb(aabbMin,aabbMax);
+               m_optimizedAabbTree->quantize(&node.m_quantizedAabbMin[0],aabbMin,0);
+               m_optimizedAabbTree->quantize(&node.m_quantizedAabbMax[0],aabbMax,1);
+               int partId = 0;
+               node.m_escapeIndexOrTriangleIndex = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | i;
+               nodes.push_back(node);
+       }
+       m_optimizedAabbTree->buildInternal();
+}
+
+btBroadphaseProxy*     btMultiSapBroadphase::createProxy(  const btVector3& aabbMin,  const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* /*ignoreMe*/)
+{
+       //void* ignoreMe -> we could think of recursive multi-sap, if someone is interested
+
+       void* mem = btAlignedAlloc(sizeof(btMultiSapProxy),16);
+       btMultiSapProxy* proxy = new (mem)btMultiSapProxy(aabbMin,  aabbMax,shapeType,userPtr, collisionFilterGroup,collisionFilterMask);
+       m_multiSapProxies.push_back(proxy);
+
+       ///this should deal with inserting/removal into child broadphases
+       setAabb(proxy,aabbMin,aabbMax,dispatcher);
+       return proxy;
+}
+
+void   btMultiSapBroadphase::destroyProxy(btBroadphaseProxy* /*proxy*/,btDispatcher* /*dispatcher*/)
+{
+       ///not yet
+       btAssert(0);
+
+}
+
+
+void   btMultiSapBroadphase::addToChildBroadphase(btMultiSapProxy* parentMultiSapProxy, btBroadphaseProxy* childProxy, btBroadphaseInterface*  childBroadphase)
+{
+       void* mem = btAlignedAlloc(sizeof(btBridgeProxy),16);
+       btBridgeProxy* bridgeProxyRef = new(mem) btBridgeProxy;
+       bridgeProxyRef->m_childProxy = childProxy;
+       bridgeProxyRef->m_childBroadphase = childBroadphase;
+       parentMultiSapProxy->m_bridgeProxies.push_back(bridgeProxyRef);
+}
+
+
+bool boxIsContainedWithinBox(const btVector3& amin,const btVector3& amax,const btVector3& bmin,const btVector3& bmax);
+bool boxIsContainedWithinBox(const btVector3& amin,const btVector3& amax,const btVector3& bmin,const btVector3& bmax)
+{
+return
+amin.getX() >= bmin.getX() && amax.getX() <= bmax.getX() &&
+amin.getY() >= bmin.getY() && amax.getY() <= bmax.getY() &&
+amin.getZ() >= bmin.getZ() && amax.getZ() <= bmax.getZ();
+}
+
+
+
+
+
+
+//#include <stdio.h>
+
+void   btMultiSapBroadphase::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher)
+{
+       btMultiSapProxy* multiProxy = static_cast<btMultiSapProxy*>(proxy);
+       multiProxy->m_aabbMin = aabbMin;
+       multiProxy->m_aabbMax = aabbMax;
+       
+       
+//     bool fullyContained = false;
+//     bool alreadyInSimple = false;
+       
+
+
+       
+       struct MyNodeOverlapCallback : public btNodeOverlapCallback
+       {
+               btMultiSapBroadphase*   m_multiSap;
+               btMultiSapProxy*                m_multiProxy;
+               btDispatcher*                   m_dispatcher;
+
+               MyNodeOverlapCallback(btMultiSapBroadphase* multiSap,btMultiSapProxy* multiProxy,btDispatcher* dispatcher)
+                       :m_multiSap(multiSap),
+                       m_multiProxy(multiProxy),
+                       m_dispatcher(dispatcher)
+               {
+
+               }
+
+               virtual void processNode(int /*nodeSubPart*/, int broadphaseIndex)
+               {
+                       btBroadphaseInterface* childBroadphase = m_multiSap->getBroadphaseArray()[broadphaseIndex];
+
+                       int containingBroadphaseIndex = -1;
+                       //already found?
+                       for (int i=0;i<m_multiProxy->m_bridgeProxies.size();i++)
+                       {
+
+                               if (m_multiProxy->m_bridgeProxies[i]->m_childBroadphase == childBroadphase)
+                               {
+                                       containingBroadphaseIndex = i;
+                                       break;
+                               }
+                       }
+                       if (containingBroadphaseIndex<0)
+                       {
+                               //add it
+                               btBroadphaseProxy* childProxy = childBroadphase->createProxy(m_multiProxy->m_aabbMin,m_multiProxy->m_aabbMax,m_multiProxy->m_shapeType,m_multiProxy->m_clientObject,m_multiProxy->m_collisionFilterGroup,m_multiProxy->m_collisionFilterMask, m_dispatcher,m_multiProxy);
+                               m_multiSap->addToChildBroadphase(m_multiProxy,childProxy,childBroadphase);
+
+                       }
+               }
+       };
+
+       MyNodeOverlapCallback   myNodeCallback(this,multiProxy,dispatcher);
+
+
+
+       
+       m_optimizedAabbTree->reportAabbOverlappingNodex(&myNodeCallback,aabbMin,aabbMax);
+       int i;
+
+       for ( i=0;i<multiProxy->m_bridgeProxies.size();i++)
+       {
+               btVector3 worldAabbMin,worldAabbMax;
+               multiProxy->m_bridgeProxies[i]->m_childBroadphase->getBroadphaseAabb(worldAabbMin,worldAabbMax);
+               bool overlapsBroadphase = TestAabbAgainstAabb2(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax);
+               if (!overlapsBroadphase)
+               {
+                       //remove it now
+                       btBridgeProxy* bridgeProxy = multiProxy->m_bridgeProxies[i];
+
+                       btBroadphaseProxy* childProxy = bridgeProxy->m_childProxy;
+                       bridgeProxy->m_childBroadphase->destroyProxy(childProxy,dispatcher);
+                       
+                       multiProxy->m_bridgeProxies.swap( i,multiProxy->m_bridgeProxies.size()-1);
+                       multiProxy->m_bridgeProxies.pop_back();
+
+               }
+       }
+
+
+       /*
+
+       if (1)
+       {
+
+               //find broadphase that contain this multiProxy
+               int numChildBroadphases = getBroadphaseArray().size();
+               for (int i=0;i<numChildBroadphases;i++)
+               {
+                       btBroadphaseInterface* childBroadphase = getBroadphaseArray()[i];
+                       btVector3 worldAabbMin,worldAabbMax;
+                       childBroadphase->getBroadphaseAabb(worldAabbMin,worldAabbMax);
+                       bool overlapsBroadphase = TestAabbAgainstAabb2(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax);
+                       
+               //      fullyContained = fullyContained || boxIsContainedWithinBox(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax);
+                       int containingBroadphaseIndex = -1;
+                       
+                       //if already contains this
+                       
+                       for (int i=0;i<multiProxy->m_bridgeProxies.size();i++)
+                       {
+                               if (multiProxy->m_bridgeProxies[i]->m_childBroadphase == childBroadphase)
+                               {
+                                       containingBroadphaseIndex = i;
+                               }
+                               alreadyInSimple = alreadyInSimple || (multiProxy->m_bridgeProxies[i]->m_childBroadphase == m_simpleBroadphase);
+                       }
+
+                       if (overlapsBroadphase)
+                       {
+                               if (containingBroadphaseIndex<0)
+                               {
+                                       btBroadphaseProxy* childProxy = childBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher);
+                                       childProxy->m_multiSapParentProxy = multiProxy;
+                                       addToChildBroadphase(multiProxy,childProxy,childBroadphase);
+                               }
+                       } else
+                       {
+                               if (containingBroadphaseIndex>=0)
+                               {
+                                       //remove
+                                       btBridgeProxy* bridgeProxy = multiProxy->m_bridgeProxies[containingBroadphaseIndex];
+
+                                       btBroadphaseProxy* childProxy = bridgeProxy->m_childProxy;
+                                       bridgeProxy->m_childBroadphase->destroyProxy(childProxy,dispatcher);
+                                       
+                                       multiProxy->m_bridgeProxies.swap( containingBroadphaseIndex,multiProxy->m_bridgeProxies.size()-1);
+                                       multiProxy->m_bridgeProxies.pop_back();
+                               }
+                       }
+               }
+
+
+               ///If we are in no other child broadphase, stick the proxy in the global 'simple' broadphase (brute force)
+               ///hopefully we don't end up with many entries here (can assert/provide feedback on stats)
+               if (0)//!multiProxy->m_bridgeProxies.size())
+               {
+                       ///we don't pass the userPtr but our multisap proxy. We need to patch this, before processing an actual collision
+                       ///this is needed to be able to calculate the aabb overlap
+                       btBroadphaseProxy* childProxy = m_simpleBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher);
+                       childProxy->m_multiSapParentProxy = multiProxy;
+                       addToChildBroadphase(multiProxy,childProxy,m_simpleBroadphase);
+               }
+       }
+
+       if (!multiProxy->m_bridgeProxies.size())
+       {
+               ///we don't pass the userPtr but our multisap proxy. We need to patch this, before processing an actual collision
+               ///this is needed to be able to calculate the aabb overlap
+               btBroadphaseProxy* childProxy = m_simpleBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher);
+               childProxy->m_multiSapParentProxy = multiProxy;
+               addToChildBroadphase(multiProxy,childProxy,m_simpleBroadphase);
+       }
+*/
+
+
+       //update
+       for ( i=0;i<multiProxy->m_bridgeProxies.size();i++)
+       {
+               btBridgeProxy* bridgeProxyRef = multiProxy->m_bridgeProxies[i];
+               bridgeProxyRef->m_childBroadphase->setAabb(bridgeProxyRef->m_childProxy,aabbMin,aabbMax,dispatcher);
+       }
+
+}
+bool stopUpdating=false;
+
+
+
+class btMultiSapBroadphasePairSortPredicate
+{
+       public:
+
+               bool operator() ( const btBroadphasePair& a1, const btBroadphasePair& b1 )
+               {
+                               btMultiSapBroadphase::btMultiSapProxy* aProxy0 = a1.m_pProxy0 ? (btMultiSapBroadphase::btMultiSapProxy*)a1.m_pProxy0->m_multiSapParentProxy : 0;
+                               btMultiSapBroadphase::btMultiSapProxy* aProxy1 = a1.m_pProxy1 ? (btMultiSapBroadphase::btMultiSapProxy*)a1.m_pProxy1->m_multiSapParentProxy : 0;
+                               btMultiSapBroadphase::btMultiSapProxy* bProxy0 = b1.m_pProxy0 ? (btMultiSapBroadphase::btMultiSapProxy*)b1.m_pProxy0->m_multiSapParentProxy : 0;
+                               btMultiSapBroadphase::btMultiSapProxy* bProxy1 = b1.m_pProxy1 ? (btMultiSapBroadphase::btMultiSapProxy*)b1.m_pProxy1->m_multiSapParentProxy : 0;
+
+                                return aProxy0 > bProxy0 || 
+                                       (aProxy0 == bProxy0 && aProxy1 > bProxy1) ||
+                                       (aProxy0 == bProxy0 && aProxy1 == bProxy1 && a1.m_algorithm > b1.m_algorithm); 
+               }
+};
+
+
+        ///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb
+void    btMultiSapBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
+{
+
+//     m_simpleBroadphase->calculateOverlappingPairs(dispatcher);
+
+       if (!stopUpdating && getOverlappingPairCache()->hasDeferredRemoval())
+       {
+       
+               btBroadphasePairArray&  overlappingPairArray = getOverlappingPairCache()->getOverlappingPairArray();
+
+       //      quicksort(overlappingPairArray,0,overlappingPairArray.size());
+
+               overlappingPairArray.quickSort(btMultiSapBroadphasePairSortPredicate());
+
+               //perform a sort, to find duplicates and to sort 'invalid' pairs to the end
+       //      overlappingPairArray.heapSort(btMultiSapBroadphasePairSortPredicate());
+
+               overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
+               m_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];
+
+                       btMultiSapProxy* aProxy0 = pair.m_pProxy0 ? (btMultiSapProxy*)pair.m_pProxy0->m_multiSapParentProxy : 0;
+                       btMultiSapProxy* aProxy1 = pair.m_pProxy1 ? (btMultiSapProxy*)pair.m_pProxy1->m_multiSapParentProxy : 0;
+                       btMultiSapProxy* bProxy0 = previousPair.m_pProxy0 ? (btMultiSapProxy*)previousPair.m_pProxy0->m_multiSapParentProxy : 0;
+                       btMultiSapProxy* bProxy1 = previousPair.m_pProxy1 ? (btMultiSapProxy*)previousPair.m_pProxy1->m_multiSapParentProxy : 0;
+
+                       bool isDuplicate = (aProxy0 == bProxy0) && (aProxy1 == bProxy1);
+                       
+                       previousPair = pair;
+
+                       bool needsRemoval = false;
+
+                       if (!isDuplicate)
+                       {
+                               bool hasOverlap = testAabbOverlap(pair.m_pProxy0,pair.m_pProxy1);
+
+                               if (hasOverlap)
+                               {
+                                       needsRemoval = false;//callback->processOverlap(pair);
+                               } else
+                               {
+                                       needsRemoval = true;
+                               }
+                       } else
+                       {
+                               //remove duplicate
+                               needsRemoval = true;
+                               //should have no algorithm
+                               btAssert(!pair.m_algorithm);
+                       }
+                       
+                       if (needsRemoval)
+                       {
+                               getOverlappingPairCache()->cleanOverlappingPair(pair,dispatcher);
+
+               //              m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
+               //              m_overlappingPairArray.pop_back();
+                               pair.m_pProxy0 = 0;
+                               pair.m_pProxy1 = 0;
+                               m_invalidPair++;
+                               gOverlappingPairs--;
+                       } 
+                       
+               }
+
+       ///if you don't like to skip the invalid pairs in the array, execute following code:
+       #define CLEAN_INVALID_PAIRS 1
+       #ifdef CLEAN_INVALID_PAIRS
+
+               //perform a sort, to sort 'invalid' pairs to the end
+               //overlappingPairArray.heapSort(btMultiSapBroadphasePairSortPredicate());
+               overlappingPairArray.quickSort(btMultiSapBroadphasePairSortPredicate());
+
+               overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
+               m_invalidPair = 0;
+       #endif//CLEAN_INVALID_PAIRS
+               
+               //printf("overlappingPairArray.size()=%d\n",overlappingPairArray.size());
+       }
+
+
+}
+
+
+bool   btMultiSapBroadphase::testAabbOverlap(btBroadphaseProxy* childProxy0,btBroadphaseProxy* childProxy1)
+{
+       btMultiSapProxy* multiSapProxy0 = (btMultiSapProxy*)childProxy0->m_multiSapParentProxy;
+               btMultiSapProxy* multiSapProxy1 = (btMultiSapProxy*)childProxy1->m_multiSapParentProxy;
+
+               return  TestAabbAgainstAabb2(multiSapProxy0->m_aabbMin,multiSapProxy0->m_aabbMax,
+                       multiSapProxy1->m_aabbMin,multiSapProxy1->m_aabbMax);
+               
+}
+
+
+void   btMultiSapBroadphase::printStats()
+{
+/*     printf("---------------------------------\n");
+       
+               printf("btMultiSapBroadphase.h\n");
+               printf("numHandles = %d\n",m_multiSapProxies.size());
+                       //find broadphase that contain this multiProxy
+               int numChildBroadphases = getBroadphaseArray().size();
+               for (int i=0;i<numChildBroadphases;i++)
+               {
+
+                       btBroadphaseInterface* childBroadphase = getBroadphaseArray()[i];
+                       childBroadphase->printStats();
+
+               }
+               */
+
+}
diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h
new file mode 100644 (file)
index 0000000..a0c002d
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+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.
+*/
+#ifndef BT_MULTI_SAP_BROADPHASE
+#define BT_MULTI_SAP_BROADPHASE
+
+#include "btBroadphaseInterface.h"
+#include "LinearMath/btAlignedObjectArray.h"
+#include "btOverlappingPairCache.h"
+
+
+class btBroadphaseInterface;
+class btSimpleBroadphase;
+
+
+typedef btAlignedObjectArray<btBroadphaseInterface*> btSapBroadphaseArray;
+
+///The btMultiSapBroadphase is a broadphase that contains multiple SAP broadphases.
+///The user can add SAP broadphases that cover the world. A btBroadphaseProxy can be in multiple child broadphases at the same time.
+///A btQuantizedBvh acceleration structures finds overlapping SAPs for each btBroadphaseProxy.
+///See http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=328
+///and http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1329
+class btMultiSapBroadphase :public btBroadphaseInterface
+{
+       btSapBroadphaseArray    m_sapBroadphases;
+       
+       btSimpleBroadphase*             m_simpleBroadphase;
+
+       btOverlappingPairCache* m_overlappingPairs;
+
+       class btQuantizedBvh*                   m_optimizedAabbTree;
+
+
+       bool                                    m_ownsPairCache;
+       
+       btOverlapFilterCallback*        m_filterCallback;
+
+       int                     m_invalidPair;
+
+       struct  btBridgeProxy
+       {
+               btBroadphaseProxy*              m_childProxy;
+               btBroadphaseInterface*  m_childBroadphase;
+       };
+
+
+public:
+
+       struct  btMultiSapProxy : public btBroadphaseProxy
+       {
+
+               ///array with all the entries that this proxy belongs to
+               btAlignedObjectArray<btBridgeProxy*> m_bridgeProxies;
+               btVector3       m_aabbMin;
+               btVector3       m_aabbMax;
+
+               int     m_shapeType;
+
+/*             void*   m_userPtr;
+               short int       m_collisionFilterGroup;
+               short int       m_collisionFilterMask;
+*/
+               btMultiSapProxy(const btVector3& aabbMin,  const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask)
+                       :btBroadphaseProxy(userPtr,collisionFilterGroup,collisionFilterMask),
+                       m_aabbMin(aabbMin),
+                       m_aabbMax(aabbMax),
+                       m_shapeType(shapeType)
+               {
+                       m_multiSapParentProxy =this;
+               }
+
+               
+       };
+
+protected:
+
+
+       btAlignedObjectArray<btMultiSapProxy*> m_multiSapProxies;
+
+public:
+
+       btMultiSapBroadphase(int maxProxies = 16384,btOverlappingPairCache* pairCache=0);
+
+
+       btSapBroadphaseArray&   getBroadphaseArray()
+       {
+               return m_sapBroadphases;
+       }
+
+       const btSapBroadphaseArray&     getBroadphaseArray() const
+       {
+               return m_sapBroadphases;
+       }
+
+       virtual ~btMultiSapBroadphase();
+
+       virtual btBroadphaseProxy*      createProxy(  const btVector3& aabbMin,  const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy);
+       virtual void    destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
+       virtual void    setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher);
+
+       void    addToChildBroadphase(btMultiSapProxy* parentMultiSapProxy, btBroadphaseProxy* childProxy, btBroadphaseInterface*        childBroadphase);
+
+       ///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb
+       virtual void    calculateOverlappingPairs(btDispatcher* dispatcher);
+
+       bool    testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
+
+       virtual btOverlappingPairCache* getOverlappingPairCache()
+       {
+               return m_overlappingPairs;
+       }
+       virtual const btOverlappingPairCache*   getOverlappingPairCache() const
+       {
+               return m_overlappingPairs;
+       }
+
+       ///getAabb returns the axis aligned bounding box in the 'global' coordinate frame
+       ///will add some transform later
+       virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const
+       {
+               aabbMin.setValue(-1e30f,-1e30f,-1e30f);
+               aabbMax.setValue(1e30f,1e30f,1e30f);
+       }
+
+       void    buildTree(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax);
+
+       virtual void    printStats();
+
+       void quicksort (btBroadphasePairArray& a, int lo, int hi);
+
+};
+
+#endif //BT_MULTI_SAP_BROADPHASE
diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h
new file mode 100644 (file)
index 0000000..9c7b6f8
--- /dev/null
@@ -0,0 +1,40 @@
+
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+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.
+*/
+
+#ifndef OVERLAPPING_PAIR_CALLBACK_H
+#define OVERLAPPING_PAIR_CALLBACK_H
+
+class btDispatcher;
+struct  btBroadphasePair;
+
+///The btOverlappingPairCallback class is an additional optional broadphase user callback for adding/removing overlapping pairs, similar interface to btOverlappingPairCache.
+class btOverlappingPairCallback
+{
+public:
+       virtual ~btOverlappingPairCallback()
+       {
+
+       }
+       
+       virtual btBroadphasePair*       addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) = 0;
+
+       virtual void*   removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher) = 0;
+
+       virtual void    removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy0,btDispatcher* dispatcher) = 0;
+
+};
+
+#endif //OVERLAPPING_PAIR_CALLBACK_H
diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp
new file mode 100644 (file)
index 0000000..a30bd1f
--- /dev/null
@@ -0,0 +1,1025 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+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.
+*/
+
+#include "btQuantizedBvh.h"
+
+#include "LinearMath/btAabbUtil2.h"
+#include "LinearMath/btIDebugDraw.h"
+
+
+btQuantizedBvh::btQuantizedBvh() : m_useQuantization(false), 
+                                       //m_traversalMode(TRAVERSAL_STACKLESS_CACHE_FRIENDLY)
+                                       m_traversalMode(TRAVERSAL_STACKLESS)
+                                       //m_traversalMode(TRAVERSAL_RECURSIVE)
+                                       ,m_subtreeHeaderCount(0) //PCK: add this line
+{ 
+
+}
+
+
+
+
+
+void btQuantizedBvh::buildInternal()
+{
+       ///assumes that caller filled in the m_quantizedLeafNodes
+       m_useQuantization = true;
+       int numLeafNodes = 0;
+       
+       if (m_useQuantization)
+       {
+               //now we have an array of leafnodes in m_leafNodes
+               numLeafNodes = m_quantizedLeafNodes.size();
+
+               m_quantizedContiguousNodes.resize(2*numLeafNodes);
+
+       }
+
+       m_curNodeIndex = 0;
+
+       buildTree(0,numLeafNodes);
+
+       ///if the entire tree is small then subtree size, we need to create a header info for the tree
+       if(m_useQuantization && !m_SubtreeHeaders.size())
+       {
+               btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand();
+               subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[0]);
+               subtree.m_rootNodeIndex = 0;
+               subtree.m_subtreeSize = m_quantizedContiguousNodes[0].isLeafNode() ? 1 : m_quantizedContiguousNodes[0].getEscapeIndex();
+       }
+
+       //PCK: update the copy of the size
+       m_subtreeHeaderCount = m_SubtreeHeaders.size();
+
+       //PCK: clear m_quantizedLeafNodes and m_leafNodes, they are temporary
+       m_quantizedLeafNodes.clear();
+       m_leafNodes.clear();
+}
+
+
+
+///just for debugging, to visualize the individual patches/subtrees
+#ifdef DEBUG_PATCH_COLORS
+btVector3 color[4]=
+{
+       btVector3(255,0,0),
+       btVector3(0,255,0),
+       btVector3(0,0,255),
+       btVector3(0,255,255)
+};
+#endif //DEBUG_PATCH_COLORS
+
+
+
+void   btQuantizedBvh::setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,btScalar quantizationMargin)
+{
+       //enlarge the AABB to avoid division by zero when initializing the quantization values
+       btVector3 clampValue(quantizationMargin,quantizationMargin,quantizationMargin);
+       m_bvhAabbMin = bvhAabbMin - clampValue;
+       m_bvhAabbMax = bvhAabbMax + clampValue;
+       btVector3 aabbSize = m_bvhAabbMax - m_bvhAabbMin;
+       m_bvhQuantization = btVector3(btScalar(65533.0),btScalar(65533.0),btScalar(65533.0)) / aabbSize;
+       m_useQuantization = true;
+}
+
+
+
+
+btQuantizedBvh::~btQuantizedBvh()
+{
+}
+
+#ifdef DEBUG_TREE_BUILDING
+int gStackDepth = 0;
+int gMaxStackDepth = 0;
+#endif //DEBUG_TREE_BUILDING
+
+void   btQuantizedBvh::buildTree       (int startIndex,int endIndex)
+{
+#ifdef DEBUG_TREE_BUILDING
+       gStackDepth++;
+       if (gStackDepth > gMaxStackDepth)
+               gMaxStackDepth = gStackDepth;
+#endif //DEBUG_TREE_BUILDING
+
+
+       int splitAxis, splitIndex, i;
+       int numIndices =endIndex-startIndex;
+       int curIndex = m_curNodeIndex;
+
+       assert(numIndices>0);
+
+       if (numIndices==1)
+       {
+#ifdef DEBUG_TREE_BUILDING
+               gStackDepth--;
+#endif //DEBUG_TREE_BUILDING
+               
+               assignInternalNodeFromLeafNode(m_curNodeIndex,startIndex);
+
+               m_curNodeIndex++;
+               return; 
+       }
+       //calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'.
+       
+       splitAxis = calcSplittingAxis(startIndex,endIndex);
+
+       splitIndex = sortAndCalcSplittingIndex(startIndex,endIndex,splitAxis);
+
+       int internalNodeIndex = m_curNodeIndex;
+       
+       setInternalNodeAabbMax(m_curNodeIndex,m_bvhAabbMin);
+       setInternalNodeAabbMin(m_curNodeIndex,m_bvhAabbMax);
+       
+       for (i=startIndex;i<endIndex;i++)
+       {
+               mergeInternalNodeAabb(m_curNodeIndex,getAabbMin(i),getAabbMax(i));
+       }
+
+       m_curNodeIndex++;
+       
+
+       //internalNode->m_escapeIndex;
+       
+       int leftChildNodexIndex = m_curNodeIndex;
+
+       //build left child tree
+       buildTree(startIndex,splitIndex);
+
+       int rightChildNodexIndex = m_curNodeIndex;
+       //build right child tree
+       buildTree(splitIndex,endIndex);
+
+#ifdef DEBUG_TREE_BUILDING
+       gStackDepth--;
+#endif //DEBUG_TREE_BUILDING
+
+       int escapeIndex = m_curNodeIndex - curIndex;
+
+       if (m_useQuantization)
+       {
+               //escapeIndex is the number of nodes of this subtree
+               const int sizeQuantizedNode =sizeof(btQuantizedBvhNode);
+               const int treeSizeInBytes = escapeIndex * sizeQuantizedNode;
+               if (treeSizeInBytes > MAX_SUBTREE_SIZE_IN_BYTES)
+               {
+                       updateSubtreeHeaders(leftChildNodexIndex,rightChildNodexIndex);
+               }
+       }
+
+       setInternalNodeEscapeIndex(internalNodeIndex,escapeIndex);
+
+}
+
+void   btQuantizedBvh::updateSubtreeHeaders(int leftChildNodexIndex,int rightChildNodexIndex)
+{
+       btAssert(m_useQuantization);
+
+       btQuantizedBvhNode& leftChildNode = m_quantizedContiguousNodes[leftChildNodexIndex];
+       int leftSubTreeSize = leftChildNode.isLeafNode() ? 1 : leftChildNode.getEscapeIndex();
+       int leftSubTreeSizeInBytes =  leftSubTreeSize * static_cast<int>(sizeof(btQuantizedBvhNode));
+       
+       btQuantizedBvhNode& rightChildNode = m_quantizedContiguousNodes[rightChildNodexIndex];
+       int rightSubTreeSize = rightChildNode.isLeafNode() ? 1 : rightChildNode.getEscapeIndex();
+       int rightSubTreeSizeInBytes =  rightSubTreeSize *  static_cast<int>(sizeof(btQuantizedBvhNode));
+
+       if(leftSubTreeSizeInBytes <= MAX_SUBTREE_SIZE_IN_BYTES)
+       {
+               btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand();
+               subtree.setAabbFromQuantizeNode(leftChildNode);
+               subtree.m_rootNodeIndex = leftChildNodexIndex;
+               subtree.m_subtreeSize = leftSubTreeSize;
+       }
+
+       if(rightSubTreeSizeInBytes <= MAX_SUBTREE_SIZE_IN_BYTES)
+       {
+               btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand();
+               subtree.setAabbFromQuantizeNode(rightChildNode);
+               subtree.m_rootNodeIndex = rightChildNodexIndex;
+               subtree.m_subtreeSize = rightSubTreeSize;
+       }
+
+       //PCK: update the copy of the size
+       m_subtreeHeaderCount = m_SubtreeHeaders.size();
+}
+
+
+int    btQuantizedBvh::sortAndCalcSplittingIndex(int startIndex,int endIndex,int splitAxis)
+{
+       int i;
+       int splitIndex =startIndex;
+       int numIndices = endIndex - startIndex;
+       btScalar splitValue;
+
+       btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.));
+       for (i=startIndex;i<endIndex;i++)
+       {
+               btVector3 center = btScalar(0.5)*(getAabbMax(i)+getAabbMin(i));
+               means+=center;
+       }
+       means *= (btScalar(1.)/(btScalar)numIndices);
+       
+       splitValue = means[splitAxis];
+       
+       //sort leafNodes so all values larger then splitValue comes first, and smaller values start from 'splitIndex'.
+       for (i=startIndex;i<endIndex;i++)
+       {
+               btVector3 center = btScalar(0.5)*(getAabbMax(i)+getAabbMin(i));
+               if (center[splitAxis] > splitValue)
+               {
+                       //swap
+                       swapLeafNodes(i,splitIndex);
+                       splitIndex++;
+               }
+       }
+
+       //if the splitIndex causes unbalanced trees, fix this by using the center in between startIndex and endIndex
+       //otherwise the tree-building might fail due to stack-overflows in certain cases.
+       //unbalanced1 is unsafe: it can cause stack overflows
+       //bool unbalanced1 = ((splitIndex==startIndex) || (splitIndex == (endIndex-1)));
+
+       //unbalanced2 should work too: always use center (perfect balanced trees)       
+       //bool unbalanced2 = true;
+
+       //this should be safe too:
+       int rangeBalancedIndices = numIndices/3;
+       bool unbalanced = ((splitIndex<=(startIndex+rangeBalancedIndices)) || (splitIndex >=(endIndex-1-rangeBalancedIndices)));
+       
+       if (unbalanced)
+       {
+               splitIndex = startIndex+ (numIndices>>1);
+       }
+
+       bool unbal = (splitIndex==startIndex) || (splitIndex == (endIndex));
+       (void)unbal;
+       btAssert(!unbal);
+
+       return splitIndex;
+}
+
+
+int    btQuantizedBvh::calcSplittingAxis(int startIndex,int endIndex)
+{
+       int i;
+
+       btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.));
+       btVector3 variance(btScalar(0.),btScalar(0.),btScalar(0.));
+       int numIndices = endIndex-startIndex;
+
+       for (i=startIndex;i<endIndex;i++)
+       {
+               btVector3 center = btScalar(0.5)*(getAabbMax(i)+getAabbMin(i));
+               means+=center;
+       }
+       means *= (btScalar(1.)/(btScalar)numIndices);
+               
+       for (i=startIndex;i<endIndex;i++)
+       {
+               btVector3 center = btScalar(0.5)*(getAabbMax(i)+getAabbMin(i));
+               btVector3 diff2 = center-means;
+               diff2 = diff2 * diff2;
+               variance += diff2;
+       }
+       variance *= (btScalar(1.)/      ((btScalar)numIndices-1)        );
+       
+       return variance.maxAxis();
+}
+
+
+
+void   btQuantizedBvh::reportAabbOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const
+{
+       //either choose recursive traversal (walkTree) or stackless (walkStacklessTree)
+
+       if (m_useQuantization)
+       {
+               ///quantize query AABB
+               unsigned short int quantizedQueryAabbMin[3];
+               unsigned short int quantizedQueryAabbMax[3];
+               quantizeWithClamp(quantizedQueryAabbMin,aabbMin,0);
+               quantizeWithClamp(quantizedQueryAabbMax,aabbMax,1);
+
+               switch (m_traversalMode)
+               {
+               case TRAVERSAL_STACKLESS:
+                               walkStacklessQuantizedTree(nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax,0,m_curNodeIndex);
+                       break;
+               case TRAVERSAL_STACKLESS_CACHE_FRIENDLY:
+                               walkStacklessQuantizedTreeCacheFriendly(nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax);
+                       break;
+               case TRAVERSAL_RECURSIVE:
+                       {
+                               const btQuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[0];
+                               walkRecursiveQuantizedTreeAgainstQueryAabb(rootNode,nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax);
+                       }
+                       break;
+               default:
+                       //unsupported
+                       btAssert(0);
+               }
+       } else
+       {
+               walkStacklessTree(nodeCallback,aabbMin,aabbMax);
+       }
+}
+
+
+int maxIterations = 0;
+
+void   btQuantizedBvh::walkStacklessTree(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const
+{
+       btAssert(!m_useQuantization);
+
+       const btOptimizedBvhNode* rootNode = &m_contiguousNodes[0];
+       int escapeIndex, curIndex = 0;
+       int walkIterations = 0;
+       bool isLeafNode;
+       //PCK: unsigned instead of bool
+       unsigned aabbOverlap;
+
+       while (curIndex < m_curNodeIndex)
+       {
+               //catch bugs in tree data
+               assert (walkIterations < m_curNodeIndex);
+
+               walkIterations++;
+               aabbOverlap = TestAabbAgainstAabb2(aabbMin,aabbMax,rootNode->m_aabbMinOrg,rootNode->m_aabbMaxOrg);
+               isLeafNode = rootNode->m_escapeIndex == -1;
+               
+               //PCK: unsigned instead of bool
+               if (isLeafNode && (aabbOverlap != 0))
+               {
+                       nodeCallback->processNode(rootNode->m_subPart,rootNode->m_triangleIndex);
+               } 
+               
+               //PCK: unsigned instead of bool
+               if ((aabbOverlap != 0) || isLeafNode)
+               {
+                       rootNode++;
+                       curIndex++;
+               } else
+               {
+                       escapeIndex = rootNode->m_escapeIndex;
+                       rootNode += escapeIndex;
+                       curIndex += escapeIndex;
+               }
+       }
+       if (maxIterations < walkIterations)
+               maxIterations = walkIterations;
+
+}
+
+/*
+///this was the original recursive traversal, before we optimized towards stackless traversal
+void   btQuantizedBvh::walkTree(btOptimizedBvhNode* rootNode,btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const
+{
+       bool isLeafNode, aabbOverlap = TestAabbAgainstAabb2(aabbMin,aabbMax,rootNode->m_aabbMin,rootNode->m_aabbMax);
+       if (aabbOverlap)
+       {
+               isLeafNode = (!rootNode->m_leftChild && !rootNode->m_rightChild);
+               if (isLeafNode)
+               {
+                       nodeCallback->processNode(rootNode);
+               } else
+               {
+                       walkTree(rootNode->m_leftChild,nodeCallback,aabbMin,aabbMax);
+                       walkTree(rootNode->m_rightChild,nodeCallback,aabbMin,aabbMax);
+               }
+       }
+
+}
+*/
+
+void btQuantizedBvh::walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantizedBvhNode* currentNode,btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const
+{
+       btAssert(m_useQuantization);
+       
+       bool isLeafNode;
+       //PCK: unsigned instead of bool
+       unsigned aabbOverlap;
+
+       //PCK: unsigned instead of bool
+       aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,currentNode->m_quantizedAabbMin,currentNode->m_quantizedAabbMax);
+       isLeafNode = currentNode->isLeafNode();
+               
+       //PCK: unsigned instead of bool
+       if (aabbOverlap != 0)
+       {
+               if (isLeafNode)
+               {
+                       nodeCallback->processNode(currentNode->getPartId(),currentNode->getTriangleIndex());
+               } else
+               {
+                       //process left and right children
+                       const btQuantizedBvhNode* leftChildNode = currentNode+1;
+                       walkRecursiveQuantizedTreeAgainstQueryAabb(leftChildNode,nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax);
+
+                       const btQuantizedBvhNode* rightChildNode = leftChildNode->isLeafNode() ? leftChildNode+1:leftChildNode+leftChildNode->getEscapeIndex();
+                       walkRecursiveQuantizedTreeAgainstQueryAabb(rightChildNode,nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax);
+               }
+       }               
+}
+
+
+
+
+
+void   btQuantizedBvh::walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const
+{
+       btAssert(m_useQuantization);
+       
+       int curIndex = startNodeIndex;
+       int walkIterations = 0;
+       int subTreeSize = endNodeIndex - startNodeIndex;
+       (void)subTreeSize;
+
+       const btQuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[startNodeIndex];
+       int escapeIndex;
+       
+       bool isLeafNode;
+       //PCK: unsigned instead of bool
+       unsigned boxBoxOverlap = 0;
+       unsigned rayBoxOverlap = 0;
+
+       btScalar lambda_max = 1.0;
+#define RAYAABB2
+#ifdef RAYAABB2
+       btVector3 rayFrom = raySource;
+       btVector3 rayDirection = (rayTarget-raySource);
+       rayDirection.normalize ();
+       lambda_max = rayDirection.dot(rayTarget-raySource);
+       ///what about division by zero? --> just set rayDirection[i] to 1.0
+       rayDirection[0] = rayDirection[0] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDirection[0];
+       rayDirection[1] = rayDirection[1] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDirection[1];
+       rayDirection[2] = rayDirection[2] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDirection[2];
+       unsigned int sign[3] = { rayDirection[0] < 0.0, rayDirection[1] < 0.0, rayDirection[2] < 0.0};
+#endif
+
+       /* Quick pruning by quantized box */
+       btVector3 rayAabbMin = raySource;
+       btVector3 rayAabbMax = raySource;
+       rayAabbMin.setMin(rayTarget);
+       rayAabbMax.setMax(rayTarget);
+
+       /* Add box cast extents to bounding box */
+       rayAabbMin += aabbMin;
+       rayAabbMax += aabbMax;
+
+       unsigned short int quantizedQueryAabbMin[3];
+       unsigned short int quantizedQueryAabbMax[3];
+       quantizeWithClamp(quantizedQueryAabbMin,rayAabbMin,0);
+       quantizeWithClamp(quantizedQueryAabbMax,rayAabbMax,1);
+
+       while (curIndex < endNodeIndex)
+       {
+
+//#define VISUALLY_ANALYZE_BVH 1
+#ifdef VISUALLY_ANALYZE_BVH
+               //some code snippet to debugDraw aabb, to visually analyze bvh structure
+               static int drawPatch = 0;
+               //need some global access to a debugDrawer
+               extern btIDebugDraw* debugDrawerPtr;
+               if (curIndex==drawPatch)
+               {
+                       btVector3 aabbMin,aabbMax;
+                       aabbMin = unQuantize(rootNode->m_quantizedAabbMin);
+                       aabbMax = unQuantize(rootNode->m_quantizedAabbMax);
+                       btVector3       color(1,0,0);
+                       debugDrawerPtr->drawAabb(aabbMin,aabbMax,color);
+               }
+#endif//VISUALLY_ANALYZE_BVH
+
+               //catch bugs in tree data
+               assert (walkIterations < subTreeSize);
+
+               walkIterations++;
+               //PCK: unsigned instead of bool
+               // only interested if this is closer than any previous hit
+               btScalar param = 1.0;
+               rayBoxOverlap = 0;
+               boxBoxOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode->m_quantizedAabbMin,rootNode->m_quantizedAabbMax);
+               isLeafNode = rootNode->isLeafNode();
+               if (boxBoxOverlap)
+               {
+                       btVector3 bounds[2];
+                       bounds[0] = unQuantize(rootNode->m_quantizedAabbMin);
+                       bounds[1] = unQuantize(rootNode->m_quantizedAabbMax);
+                       /* Add box cast extents */
+                       bounds[0] += aabbMin;
+                       bounds[1] += aabbMax;
+                       btVector3 normal;
+#if 0
+                       bool ra2 = btRayAabb2 (raySource, rayDirection, sign, bounds, param, 0.0, lambda_max);
+                       bool ra = btRayAabb (raySource, rayTarget, bounds[0], bounds[1], param, normal);
+                       if (ra2 != ra)
+                       {
+                               printf("functions don't match\n");
+                       }
+#endif
+#ifdef RAYAABB2
+                       ///careful with this check: need to check division by zero (above) and fix the unQuantize method
+                       ///thanks Joerg/hiker for the reproduction case!
+                       ///http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1858
+
+                       rayBoxOverlap = btRayAabb2 (raySource, rayDirection, sign, bounds, param, 0.0f, lambda_max);
+#else
+                       rayBoxOverlap = true;//btRayAabb(raySource, rayTarget, bounds[0], bounds[1], param, normal);
+#endif
+               }
+               
+               if (isLeafNode && rayBoxOverlap)
+               {
+                       nodeCallback->processNode(rootNode->getPartId(),rootNode->getTriangleIndex());
+               }
+               
+               //PCK: unsigned instead of bool
+               if ((rayBoxOverlap != 0) || isLeafNode)
+               {
+                       rootNode++;
+                       curIndex++;
+               } else
+               {
+                       escapeIndex = rootNode->getEscapeIndex();
+                       rootNode += escapeIndex;
+                       curIndex += escapeIndex;
+               }
+       }
+       if (maxIterations < walkIterations)
+               maxIterations = walkIterations;
+
+}
+
+void   btQuantizedBvh::walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,int startNodeIndex,int endNodeIndex) const
+{
+       btAssert(m_useQuantization);
+       
+       int curIndex = startNodeIndex;
+       int walkIterations = 0;
+       int subTreeSize = endNodeIndex - startNodeIndex;
+       (void)subTreeSize;
+
+       const btQuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[startNodeIndex];
+       int escapeIndex;
+       
+       bool isLeafNode;
+       //PCK: unsigned instead of bool
+       unsigned aabbOverlap;
+
+       while (curIndex < endNodeIndex)
+       {
+
+//#define VISUALLY_ANALYZE_BVH 1
+#ifdef VISUALLY_ANALYZE_BVH
+               //some code snippet to debugDraw aabb, to visually analyze bvh structure
+               static int drawPatch = 0;
+               //need some global access to a debugDrawer
+               extern btIDebugDraw* debugDrawerPtr;
+               if (curIndex==drawPatch)
+               {
+                       btVector3 aabbMin,aabbMax;
+                       aabbMin = unQuantize(rootNode->m_quantizedAabbMin);
+                       aabbMax = unQuantize(rootNode->m_quantizedAabbMax);
+                       btVector3       color(1,0,0);
+                       debugDrawerPtr->drawAabb(aabbMin,aabbMax,color);
+               }
+#endif//VISUALLY_ANALYZE_BVH
+
+               //catch bugs in tree data
+               assert (walkIterations < subTreeSize);
+
+               walkIterations++;
+               //PCK: unsigned instead of bool
+               aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode->m_quantizedAabbMin,rootNode->m_quantizedAabbMax);
+               isLeafNode = rootNode->isLeafNode();
+               
+               if (isLeafNode && aabbOverlap)
+               {
+                       nodeCallback->processNode(rootNode->getPartId(),rootNode->getTriangleIndex());
+               } 
+               
+               //PCK: unsigned instead of bool
+               if ((aabbOverlap != 0) || isLeafNode)
+               {
+                       rootNode++;
+                       curIndex++;
+               } else
+               {
+                       escapeIndex = rootNode->getEscapeIndex();
+                       rootNode += escapeIndex;
+                       curIndex += escapeIndex;
+               }
+       }
+       if (maxIterations < walkIterations)
+               maxIterations = walkIterations;
+
+}
+
+//This traversal can be called from Playstation 3 SPU
+void   btQuantizedBvh::walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const
+{
+       btAssert(m_useQuantization);
+
+       int i;
+
+
+       for (i=0;i<this->m_SubtreeHeaders.size();i++)
+       {
+               const btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i];
+
+               //PCK: unsigned instead of bool
+               unsigned overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax);
+               if (overlap != 0)
+               {
+                       walkStacklessQuantizedTree(nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax,
+                               subtree.m_rootNodeIndex,
+                               subtree.m_rootNodeIndex+subtree.m_subtreeSize);
+               }
+       }
+}
+
+
+void   btQuantizedBvh::reportRayOverlappingNodex (btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget) const
+{
+       bool fast_path = m_useQuantization && m_traversalMode == TRAVERSAL_STACKLESS;
+       if (fast_path)
+       {
+               walkStacklessQuantizedTreeAgainstRay(nodeCallback, raySource, rayTarget, btVector3(0, 0, 0), btVector3(0, 0, 0), 0, m_curNodeIndex);
+       } else {
+               /* Otherwise fallback to AABB overlap test */
+               btVector3 aabbMin = raySource;
+               btVector3 aabbMax = raySource;
+               aabbMin.setMin(rayTarget);
+               aabbMax.setMax(rayTarget);
+               reportAabbOverlappingNodex(nodeCallback,aabbMin,aabbMax);
+       }
+}
+
+
+void   btQuantizedBvh::reportBoxCastOverlappingNodex(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin,const btVector3& aabbMax) const
+{
+       bool fast_path = m_useQuantization && m_traversalMode == TRAVERSAL_STACKLESS;
+       if (fast_path)
+       {
+               walkStacklessQuantizedTreeAgainstRay(nodeCallback, raySource, rayTarget, aabbMin, aabbMax, 0, m_curNodeIndex);
+       } else {
+               /* Slow path:
+                  Construct the bounding box for the entire box cast and send that down the tree */
+               btVector3 qaabbMin = raySource;
+               btVector3 qaabbMax = raySource;
+               qaabbMin.setMin(rayTarget);
+               qaabbMax.setMax(rayTarget);
+               qaabbMin += aabbMin;
+               qaabbMax += aabbMax;
+               reportAabbOverlappingNodex(nodeCallback,qaabbMin,qaabbMax);
+       }
+}
+
+
+void   btQuantizedBvh::swapLeafNodes(int i,int splitIndex)
+{
+       if (m_useQuantization)
+       {
+                       btQuantizedBvhNode tmp = m_quantizedLeafNodes[i];
+                       m_quantizedLeafNodes[i] = m_quantizedLeafNodes[splitIndex];
+                       m_quantizedLeafNodes[splitIndex] = tmp;
+       } else
+       {
+                       btOptimizedBvhNode tmp = m_leafNodes[i];
+                       m_leafNodes[i] = m_leafNodes[splitIndex];
+                       m_leafNodes[splitIndex] = tmp;
+       }
+}
+
+void   btQuantizedBvh::assignInternalNodeFromLeafNode(int internalNode,int leafNodeIndex)
+{
+       if (m_useQuantization)
+       {
+               m_quantizedContiguousNodes[internalNode] = m_quantizedLeafNodes[leafNodeIndex];
+       } else
+       {
+               m_contiguousNodes[internalNode] = m_leafNodes[leafNodeIndex];
+       }
+}
+
+//PCK: include
+#include <new>
+
+//PCK: consts
+static const unsigned BVH_ALIGNMENT = 16;
+static const unsigned BVH_ALIGNMENT_MASK = BVH_ALIGNMENT-1;
+
+static const unsigned BVH_ALIGNMENT_BLOCKS = 2;
+
+
+
+unsigned int btQuantizedBvh::getAlignmentSerializationPadding()
+{
+       return BVH_ALIGNMENT_BLOCKS * BVH_ALIGNMENT;
+}
+
+unsigned btQuantizedBvh::calculateSerializeBufferSize()
+{
+       unsigned baseSize = sizeof(btQuantizedBvh) + getAlignmentSerializationPadding();
+       baseSize += sizeof(btBvhSubtreeInfo) * m_subtreeHeaderCount;
+       if (m_useQuantization)
+       {
+               return baseSize + m_curNodeIndex * sizeof(btQuantizedBvhNode);
+       }
+       return baseSize + m_curNodeIndex * sizeof(btOptimizedBvhNode);
+}
+
+bool btQuantizedBvh::serialize(void *o_alignedDataBuffer, unsigned /*i_dataBufferSize */, bool i_swapEndian)
+{
+       assert(m_subtreeHeaderCount == m_SubtreeHeaders.size());
+       m_subtreeHeaderCount = m_SubtreeHeaders.size();
+
+/*     if (i_dataBufferSize < calculateSerializeBufferSize() || o_alignedDataBuffer == NULL || (((unsigned)o_alignedDataBuffer & BVH_ALIGNMENT_MASK) != 0))
+       {
+               ///check alignedment for buffer?
+               btAssert(0);
+               return false;
+       }
+*/
+
+       btQuantizedBvh *targetBvh = (btQuantizedBvh *)o_alignedDataBuffer;
+
+       // construct the class so the virtual function table, etc will be set up
+       // Also, m_leafNodes and m_quantizedLeafNodes will be initialized to default values by the constructor
+       new (targetBvh) btQuantizedBvh;
+
+       if (i_swapEndian)
+       {
+               targetBvh->m_curNodeIndex = static_cast<int>(btSwapEndian(m_curNodeIndex));
+
+
+               btSwapVector3Endian(m_bvhAabbMin,targetBvh->m_bvhAabbMin);
+               btSwapVector3Endian(m_bvhAabbMax,targetBvh->m_bvhAabbMax);
+               btSwapVector3Endian(m_bvhQuantization,targetBvh->m_bvhQuantization);
+
+               targetBvh->m_traversalMode = (btTraversalMode)btSwapEndian(m_traversalMode);
+               targetBvh->m_subtreeHeaderCount = static_cast<int>(btSwapEndian(m_subtreeHeaderCount));
+       }
+       else
+       {
+               targetBvh->m_curNodeIndex = m_curNodeIndex;
+               targetBvh->m_bvhAabbMin = m_bvhAabbMin;
+               targetBvh->m_bvhAabbMax = m_bvhAabbMax;
+               targetBvh->m_bvhQuantization = m_bvhQuantization;
+               targetBvh->m_traversalMode = m_traversalMode;
+               targetBvh->m_subtreeHeaderCount = m_subtreeHeaderCount;
+       }
+
+       targetBvh->m_useQuantization = m_useQuantization;
+
+       unsigned char *nodeData = (unsigned char *)targetBvh;
+       nodeData += sizeof(btQuantizedBvh);
+       
+       unsigned sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
+       nodeData += sizeToAdd;
+       
+       int nodeCount = m_curNodeIndex;
+
+       if (m_useQuantization)
+       {
+               targetBvh->m_quantizedContiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount);
+
+               if (i_swapEndian)
+               {
+                       for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
+                       {
+                               targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0]);
+                               targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1]);
+                               targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2]);
+
+                               targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0]);
+                               targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1]);
+                               targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2]);
+
+                               targetBvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = static_cast<int>(btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex));
+                       }
+               }
+               else
+               {
+                       for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
+                       {
+       
+                               targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0];
+                               targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1];
+                               targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2];
+
+                               targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0];
+                               targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1];
+                               targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2];
+
+                               targetBvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex;
+
+
+                       }
+               }
+               nodeData += sizeof(btQuantizedBvhNode) * nodeCount;
+       }
+       else
+       {
+               targetBvh->m_contiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount);
+
+               if (i_swapEndian)
+               {
+                       for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
+                       {
+                               btSwapVector3Endian(m_contiguousNodes[nodeIndex].m_aabbMinOrg, targetBvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg);
+                               btSwapVector3Endian(m_contiguousNodes[nodeIndex].m_aabbMaxOrg, targetBvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg);
+
+                               targetBvh->m_contiguousNodes[nodeIndex].m_escapeIndex = static_cast<int>(btSwapEndian(m_contiguousNodes[nodeIndex].m_escapeIndex));
+                               targetBvh->m_contiguousNodes[nodeIndex].m_subPart = static_cast<int>(btSwapEndian(m_contiguousNodes[nodeIndex].m_subPart));
+                               targetBvh->m_contiguousNodes[nodeIndex].m_triangleIndex = static_cast<int>(btSwapEndian(m_contiguousNodes[nodeIndex].m_triangleIndex));
+                       }
+               }
+               else
+               {
+                       for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
+                       {
+                               targetBvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg = m_contiguousNodes[nodeIndex].m_aabbMinOrg;
+                               targetBvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg = m_contiguousNodes[nodeIndex].m_aabbMaxOrg;
+
+                               targetBvh->m_contiguousNodes[nodeIndex].m_escapeIndex = m_contiguousNodes[nodeIndex].m_escapeIndex;
+                               targetBvh->m_contiguousNodes[nodeIndex].m_subPart = m_contiguousNodes[nodeIndex].m_subPart;
+                               targetBvh->m_contiguousNodes[nodeIndex].m_triangleIndex = m_contiguousNodes[nodeIndex].m_triangleIndex;
+                       }
+               }
+               nodeData += sizeof(btOptimizedBvhNode) * nodeCount;
+       }
+
+       sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
+       nodeData += sizeToAdd;
+
+       // Now serialize the subtree headers
+       targetBvh->m_SubtreeHeaders.initializeFromBuffer(nodeData, m_subtreeHeaderCount, m_subtreeHeaderCount);
+       if (i_swapEndian)
+       {
+               for (int i = 0; i < m_subtreeHeaderCount; i++)
+               {
+                       targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[0]);
+                       targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[1]);
+                       targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[2]);
+
+                       targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[0]);
+                       targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[1]);
+                       targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[2]);
+
+                       targetBvh->m_SubtreeHeaders[i].m_rootNodeIndex = static_cast<int>(btSwapEndian(m_SubtreeHeaders[i].m_rootNodeIndex));
+                       targetBvh->m_SubtreeHeaders[i].m_subtreeSize = static_cast<int>(btSwapEndian(m_SubtreeHeaders[i].m_subtreeSize));
+               }
+       }
+       else
+       {
+               for (int i = 0; i < m_subtreeHeaderCount; i++)
+               {
+                       targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0] = (m_SubtreeHeaders[i].m_quantizedAabbMin[0]);
+                       targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = (m_SubtreeHeaders[i].m_quantizedAabbMin[1]);
+                       targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = (m_SubtreeHeaders[i].m_quantizedAabbMin[2]);
+
+                       targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = (m_SubtreeHeaders[i].m_quantizedAabbMax[0]);
+                       targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = (m_SubtreeHeaders[i].m_quantizedAabbMax[1]);
+                       targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = (m_SubtreeHeaders[i].m_quantizedAabbMax[2]);
+
+                       targetBvh->m_SubtreeHeaders[i].m_rootNodeIndex = (m_SubtreeHeaders[i].m_rootNodeIndex);
+                       targetBvh->m_SubtreeHeaders[i].m_subtreeSize = (m_SubtreeHeaders[i].m_subtreeSize);
+                       targetBvh->m_SubtreeHeaders[i] = m_SubtreeHeaders[i];
+               }
+       }
+
+       nodeData += sizeof(btBvhSubtreeInfo) * m_subtreeHeaderCount;
+
+       return true;
+}
+
+btQuantizedBvh *btQuantizedBvh::deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian)
+{
+
+       if (i_alignedDataBuffer == NULL)// || (((unsigned)i_alignedDataBuffer & BVH_ALIGNMENT_MASK) != 0))
+       {
+               return NULL;
+       }
+       btQuantizedBvh *bvh = (btQuantizedBvh *)i_alignedDataBuffer;
+
+       if (i_swapEndian)
+       {
+               bvh->m_curNodeIndex = static_cast<int>(btSwapEndian(bvh->m_curNodeIndex));
+
+               btUnSwapVector3Endian(bvh->m_bvhAabbMin);
+               btUnSwapVector3Endian(bvh->m_bvhAabbMax);
+               btUnSwapVector3Endian(bvh->m_bvhQuantization);
+
+               bvh->m_traversalMode = (btTraversalMode)btSwapEndian(bvh->m_traversalMode);
+               bvh->m_subtreeHeaderCount = static_cast<int>(btSwapEndian(bvh->m_subtreeHeaderCount));
+       }
+
+       unsigned int calculatedBufSize = bvh->calculateSerializeBufferSize();
+       btAssert(calculatedBufSize <= i_dataBufferSize);
+
+       if (calculatedBufSize > i_dataBufferSize)
+       {
+               return NULL;
+       }
+
+       unsigned char *nodeData = (unsigned char *)bvh;
+       nodeData += sizeof(btQuantizedBvh);
+       
+       unsigned sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
+       nodeData += sizeToAdd;
+       
+       int nodeCount = bvh->m_curNodeIndex;
+
+       // Must call placement new to fill in virtual function table, etc, but we don't want to overwrite most data, so call a special version of the constructor
+       // Also, m_leafNodes and m_quantizedLeafNodes will be initialized to default values by the constructor
+       new (bvh) btQuantizedBvh(*bvh, false);
+
+       if (bvh->m_useQuantization)
+       {
+               bvh->m_quantizedContiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount);
+
+               if (i_swapEndian)
+               {
+                       for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
+                       {
+                               bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0]);
+                               bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1]);
+                               bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2]);
+
+                               bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0]);
+                               bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1]);
+                               bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2]);
+
+                               bvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = static_cast<int>(btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex));
+                       }
+               }
+               nodeData += sizeof(btQuantizedBvhNode) * nodeCount;
+       }
+       else
+       {
+               bvh->m_contiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount);
+
+               if (i_swapEndian)
+               {
+                       for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
+                       {
+                               btUnSwapVector3Endian(bvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg);
+                               btUnSwapVector3Endian(bvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg);
+                               
+                               bvh->m_contiguousNodes[nodeIndex].m_escapeIndex = static_cast<int>(btSwapEndian(bvh->m_contiguousNodes[nodeIndex].m_escapeIndex));
+                               bvh->m_contiguousNodes[nodeIndex].m_subPart = static_cast<int>(btSwapEndian(bvh->m_contiguousNodes[nodeIndex].m_subPart));
+                               bvh->m_contiguousNodes[nodeIndex].m_triangleIndex = static_cast<int>(btSwapEndian(bvh->m_contiguousNodes[nodeIndex].m_triangleIndex));
+                       }
+               }
+               nodeData += sizeof(btOptimizedBvhNode) * nodeCount;
+       }
+
+       sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
+       nodeData += sizeToAdd;
+
+       // Now serialize the subtree headers
+       bvh->m_SubtreeHeaders.initializeFromBuffer(nodeData, bvh->m_subtreeHeaderCount, bvh->m_subtreeHeaderCount);
+       if (i_swapEndian)
+       {
+               for (int i = 0; i < bvh->m_subtreeHeaderCount; i++)
+               {
+                       bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0]);
+                       bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1]);
+                       bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2]);
+
+                       bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0]);
+                       bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1]);
+                       bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2]);
+
+                       bvh->m_SubtreeHeaders[i].m_rootNodeIndex = static_cast<int>(btSwapEndian(bvh->m_SubtreeHeaders[i].m_rootNodeIndex));
+                       bvh->m_SubtreeHeaders[i].m_subtreeSize = static_cast<int>(btSwapEndian(bvh->m_SubtreeHeaders[i].m_subtreeSize));
+               }
+       }
+
+       return bvh;
+}
+
+// Constructor that prevents btVector3's default constructor from being called
+btQuantizedBvh::btQuantizedBvh(btQuantizedBvh &self, bool /* ownsMemory */) :
+m_bvhAabbMin(self.m_bvhAabbMin),
+m_bvhAabbMax(self.m_bvhAabbMax),
+m_bvhQuantization(self.m_bvhQuantization)
+{
+
+
+}
+
+
+
diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h
new file mode 100644 (file)
index 0000000..8a149b5
--- /dev/null
@@ -0,0 +1,486 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+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.
+*/
+
+#ifndef QUANTIZED_BVH_H
+#define QUANTIZED_BVH_H
+
+//#define DEBUG_CHECK_DEQUANTIZATION 1
+#ifdef DEBUG_CHECK_DEQUANTIZATION
+#ifdef __SPU__
+#define printf spu_printf
+#endif //__SPU__
+
+#include <stdio.h>
+#include <stdlib.h>
+#endif //DEBUG_CHECK_DEQUANTIZATION
+
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btAlignedAllocator.h"
+
+
+//http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/vclrf__m128.asp
+
+
+//Note: currently we have 16 bytes per quantized node
+#define MAX_SUBTREE_SIZE_IN_BYTES  2048
+
+// 10 gives the potential for 1024 parts, with at most 2^21 (2097152) (minus one
+// actually) triangles each (since the sign bit is reserved
+#define MAX_NUM_PARTS_IN_BITS 10
+
+///btQuantizedBvhNode is a compressed aabb node, 16 bytes.
+///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range).
+ATTRIBUTE_ALIGNED16    (struct) btQuantizedBvhNode
+{
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       //12 bytes
+       unsigned short int      m_quantizedAabbMin[3];
+       unsigned short int      m_quantizedAabbMax[3];
+       //4 bytes
+       int     m_escapeIndexOrTriangleIndex;
+
+       bool isLeafNode() const
+       {
+               //skipindex is negative (internal node), triangleindex >=0 (leafnode)
+               return (m_escapeIndexOrTriangleIndex >= 0);
+       }
+       int getEscapeIndex() const
+       {
+               btAssert(!isLeafNode());
+               return -m_escapeIndexOrTriangleIndex;
+       }
+       int     getTriangleIndex() const
+       {
+               btAssert(isLeafNode());
+               // Get only the lower bits where the triangle index is stored
+               return (m_escapeIndexOrTriangleIndex&~((~0)<<(31-MAX_NUM_PARTS_IN_BITS)));
+       }
+       int     getPartId() const
+       {
+               btAssert(isLeafNode());
+               // Get only the highest bits where the part index is stored
+               return (m_escapeIndexOrTriangleIndex>>(31-MAX_NUM_PARTS_IN_BITS));
+       }
+}
+;
+
+/// btOptimizedBvhNode contains both internal and leaf node information.
+/// Total node size is 44 bytes / node. You can use the compressed version of 16 bytes.
+ATTRIBUTE_ALIGNED16 (struct) btOptimizedBvhNode
+{
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       //32 bytes
+       btVector3       m_aabbMinOrg;
+       btVector3       m_aabbMaxOrg;
+
+       //4
+       int     m_escapeIndex;
+
+       //8
+       //for child nodes
+       int     m_subPart;
+       int     m_triangleIndex;
+       int     m_padding[5];//bad, due to alignment
+
+
+};
+
+
+///btBvhSubtreeInfo provides info to gather a subtree of limited size
+ATTRIBUTE_ALIGNED16(class) btBvhSubtreeInfo
+{
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       //12 bytes
+       unsigned short int      m_quantizedAabbMin[3];
+       unsigned short int      m_quantizedAabbMax[3];
+       //4 bytes, points to the root of the subtree
+       int                     m_rootNodeIndex;
+       //4 bytes
+       int                     m_subtreeSize;
+       int                     m_padding[3];
+
+       btBvhSubtreeInfo()
+       {
+               //memset(&m_padding[0], 0, sizeof(m_padding));
+       }
+
+
+       void    setAabbFromQuantizeNode(const btQuantizedBvhNode& quantizedNode)
+       {
+               m_quantizedAabbMin[0] = quantizedNode.m_quantizedAabbMin[0];
+               m_quantizedAabbMin[1] = quantizedNode.m_quantizedAabbMin[1];
+               m_quantizedAabbMin[2] = quantizedNode.m_quantizedAabbMin[2];
+               m_quantizedAabbMax[0] = quantizedNode.m_quantizedAabbMax[0];
+               m_quantizedAabbMax[1] = quantizedNode.m_quantizedAabbMax[1];
+               m_quantizedAabbMax[2] = quantizedNode.m_quantizedAabbMax[2];
+       }
+}
+;
+
+
+class btNodeOverlapCallback
+{
+public:
+       virtual ~btNodeOverlapCallback() {};
+
+       virtual void processNode(int subPart, int triangleIndex) = 0;
+};
+
+#include "LinearMath/btAlignedAllocator.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+
+
+///for code readability:
+typedef btAlignedObjectArray<btOptimizedBvhNode>       NodeArray;
+typedef btAlignedObjectArray<btQuantizedBvhNode>       QuantizedNodeArray;
+typedef btAlignedObjectArray<btBvhSubtreeInfo>         BvhSubtreeInfoArray;
+
+
+///The btQuantizedBvh class stores an AABB tree that can be quickly traversed on CPU and Cell SPU.
+///It is used by the btBvhTriangleMeshShape as midphase, and by the btMultiSapBroadphase.
+///It is recommended to use quantization for better performance and lower memory requirements.
+ATTRIBUTE_ALIGNED16(class) btQuantizedBvh
+{
+protected:
+
+       NodeArray                       m_leafNodes;
+       NodeArray                       m_contiguousNodes;
+
+       QuantizedNodeArray      m_quantizedLeafNodes;
+       
+       QuantizedNodeArray      m_quantizedContiguousNodes;
+       
+       int                                     m_curNodeIndex;
+
+
+       //quantization data
+       bool                            m_useQuantization;
+       btVector3                       m_bvhAabbMin;
+       btVector3                       m_bvhAabbMax;
+       btVector3                       m_bvhQuantization;
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       enum btTraversalMode
+       {
+               TRAVERSAL_STACKLESS = 0,
+               TRAVERSAL_STACKLESS_CACHE_FRIENDLY,
+               TRAVERSAL_RECURSIVE
+       };
+protected:
+
+       btTraversalMode m_traversalMode;
+       
+       BvhSubtreeInfoArray             m_SubtreeHeaders;
+
+       //This is only used for serialization so we don't have to add serialization directly to btAlignedObjectArray
+       int m_subtreeHeaderCount;
+
+
+       ///two versions, one for quantized and normal nodes. This allows code-reuse while maintaining readability (no template/macro!)
+       ///this might be refactored into a virtual, it is usually not calculated at run-time
+       void    setInternalNodeAabbMin(int nodeIndex, const btVector3& aabbMin)
+       {
+               if (m_useQuantization)
+               {
+                       quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] ,aabbMin,0);
+               } else
+               {
+                       m_contiguousNodes[nodeIndex].m_aabbMinOrg = aabbMin;
+
+               }
+       }
+       void    setInternalNodeAabbMax(int nodeIndex,const btVector3& aabbMax)
+       {
+               if (m_useQuantization)
+               {
+                       quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0],aabbMax,1);
+               } else
+               {
+                       m_contiguousNodes[nodeIndex].m_aabbMaxOrg = aabbMax;
+               }
+       }
+
+       btVector3 getAabbMin(int nodeIndex) const
+       {
+               if (m_useQuantization)
+               {
+                       return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMin[0]);
+               }
+               //non-quantized
+               return m_leafNodes[nodeIndex].m_aabbMinOrg;
+
+       }
+       btVector3 getAabbMax(int nodeIndex) const
+       {
+               if (m_useQuantization)
+               {
+                       return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMax[0]);
+               } 
+               //non-quantized
+               return m_leafNodes[nodeIndex].m_aabbMaxOrg;
+               
+       }
+
+       
+       void    setInternalNodeEscapeIndex(int nodeIndex, int escapeIndex)
+       {
+               if (m_useQuantization)
+               {
+                       m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = -escapeIndex;
+               } 
+               else
+               {
+                       m_contiguousNodes[nodeIndex].m_escapeIndex = escapeIndex;
+               }
+
+       }
+
+       void mergeInternalNodeAabb(int nodeIndex,const btVector3& newAabbMin,const btVector3& newAabbMax) 
+       {
+               if (m_useQuantization)
+               {
+                       unsigned short int quantizedAabbMin[3];
+                       unsigned short int quantizedAabbMax[3];
+                       quantize(quantizedAabbMin,newAabbMin,0);
+                       quantize(quantizedAabbMax,newAabbMax,1);
+                       for (int i=0;i<3;i++)
+                       {
+                               if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] > quantizedAabbMin[i])
+                                       m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] = quantizedAabbMin[i];
+
+                               if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] < quantizedAabbMax[i])
+                                       m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] = quantizedAabbMax[i];
+
+                       }
+               } else
+               {
+                       //non-quantized
+                       m_contiguousNodes[nodeIndex].m_aabbMinOrg.setMin(newAabbMin);
+                       m_contiguousNodes[nodeIndex].m_aabbMaxOrg.setMax(newAabbMax);           
+               }
+       }
+
+       void    swapLeafNodes(int firstIndex,int secondIndex);
+
+       void    assignInternalNodeFromLeafNode(int internalNode,int leafNodeIndex);
+
+protected:
+
+       
+
+       void    buildTree       (int startIndex,int endIndex);
+
+       int     calcSplittingAxis(int startIndex,int endIndex);
+
+       int     sortAndCalcSplittingIndex(int startIndex,int endIndex,int splitAxis);
+       
+       void    walkStacklessTree(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const;
+
+       void    walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const;
+       void    walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,int startNodeIndex,int endNodeIndex) const;
+
+       ///tree traversal designed for small-memory processors like PS3 SPU
+       void    walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const;
+
+       ///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal
+       void    walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantizedBvhNode* currentNode,btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const;
+
+       ///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal
+       void    walkRecursiveQuantizedTreeAgainstQuantizedTree(const btQuantizedBvhNode* treeNodeA,const btQuantizedBvhNode* treeNodeB,btNodeOverlapCallback* nodeCallback) const;
+       
+
+#define USE_BANCHLESS 1
+#ifdef USE_BANCHLESS
+       //This block replaces the block below and uses no branches, and replaces the 8 bit return with a 32 bit return for improved performance (~3x on XBox 360)
+       SIMD_FORCE_INLINE unsigned testQuantizedAabbAgainstQuantizedAabb(unsigned short int* aabbMin1,unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2) const
+       {               
+               return static_cast<unsigned int>(btSelect((unsigned)((aabbMin1[0] <= aabbMax2[0]) & (aabbMax1[0] >= aabbMin2[0])
+                       & (aabbMin1[2] <= aabbMax2[2]) & (aabbMax1[2] >= aabbMin2[2])
+                       & (aabbMin1[1] <= aabbMax2[1]) & (aabbMax1[1] >= aabbMin2[1])),
+                       1, 0));
+       }
+#else
+       SIMD_FORCE_INLINE bool testQuantizedAabbAgainstQuantizedAabb(unsigned short int* aabbMin1,unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2) const
+       {
+               bool overlap = true;
+               overlap = (aabbMin1[0] > aabbMax2[0] || aabbMax1[0] < aabbMin2[0]) ? false : overlap;
+               overlap = (aabbMin1[2] > aabbMax2[2] || aabbMax1[2] < aabbMin2[2]) ? false : overlap;
+               overlap = (aabbMin1[1] > aabbMax2[1] || aabbMax1[1] < aabbMin2[1]) ? false : overlap;
+               return overlap;
+       }
+#endif //USE_BANCHLESS
+
+       void    updateSubtreeHeaders(int leftChildNodexIndex,int rightChildNodexIndex);
+
+public:
+       btQuantizedBvh();
+
+       virtual ~btQuantizedBvh();
+
+       
+       ///***************************************** expert/internal use only *************************
+       void    setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,btScalar quantizationMargin=btScalar(1.0));
+       QuantizedNodeArray&     getLeafNodeArray() {                    return  m_quantizedLeafNodes;   }
+       ///buildInternal is expert use only: assumes that setQuantizationValues and LeafNodeArray are initialized
+       void    buildInternal();
+       ///***************************************** expert/internal use only *************************
+
+       void    reportAabbOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const;
+       void    reportRayOverlappingNodex (btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget) const;
+       void    reportBoxCastOverlappingNodex(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin,const btVector3& aabbMax) const;
+
+               SIMD_FORCE_INLINE void quantize(unsigned short* out, const btVector3& point,int isMax) const
+       {
+
+               btAssert(m_useQuantization);
+
+               btAssert(point.getX() <= m_bvhAabbMax.getX());
+               btAssert(point.getY() <= m_bvhAabbMax.getY());
+               btAssert(point.getZ() <= m_bvhAabbMax.getZ());
+
+               btAssert(point.getX() >= m_bvhAabbMin.getX());
+               btAssert(point.getY() >= m_bvhAabbMin.getY());
+               btAssert(point.getZ() >= m_bvhAabbMin.getZ());
+
+               btVector3 v = (point - m_bvhAabbMin) * m_bvhQuantization;
+               ///Make sure rounding is done in a way that unQuantize(quantizeWithClamp(...)) is conservative
+               ///end-points always set the first bit, so that they are sorted properly (so that neighbouring AABBs overlap properly)
+               ///todo: double-check this
+               if (isMax)
+               {
+                       out[0] = (unsigned short) (((unsigned short)(v.getX()+btScalar(1.)) | 1));
+                       out[1] = (unsigned short) (((unsigned short)(v.getY()+btScalar(1.)) | 1));
+                       out[2] = (unsigned short) (((unsigned short)(v.getZ()+btScalar(1.)) | 1));
+               } else
+               {
+                       out[0] = (unsigned short) (((unsigned short)(v.getX()) & 0xfffe));
+                       out[1] = (unsigned short) (((unsigned short)(v.getY()) & 0xfffe));
+                       out[2] = (unsigned short) (((unsigned short)(v.getZ()) & 0xfffe));
+               }
+
+
+#ifdef DEBUG_CHECK_DEQUANTIZATION
+               btVector3 newPoint = unQuantize(out);
+               if (isMax)
+               {
+                       if (newPoint.getX() < point.getX())
+                       {
+                               printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n",newPoint.getX()-point.getX(), newPoint.getX(),point.getX());
+                       }
+                       if (newPoint.getY() < point.getY())
+                       {
+                               printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n",newPoint.getY()-point.getY(), newPoint.getY(),point.getY());
+                       }
+                       if (newPoint.getZ() < point.getZ())
+                       {
+
+                               printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n",newPoint.getZ()-point.getZ(), newPoint.getZ(),point.getZ());
+                       }
+               } else
+               {
+                       if (newPoint.getX() > point.getX())
+                       {
+                               printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n",newPoint.getX()-point.getX(), newPoint.getX(),point.getX());
+                       }
+                       if (newPoint.getY() > point.getY())
+                       {
+                               printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n",newPoint.getY()-point.getY(), newPoint.getY(),point.getY());
+                       }
+                       if (newPoint.getZ() > point.getZ())
+                       {
+                               printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n",newPoint.getZ()-point.getZ(), newPoint.getZ(),point.getZ());
+                       }
+               }
+#endif //DEBUG_CHECK_DEQUANTIZATION
+
+       }
+
+
+       SIMD_FORCE_INLINE void quantizeWithClamp(unsigned short* out, const btVector3& point2,int isMax) const
+       {
+
+               btAssert(m_useQuantization);
+
+               btVector3 clampedPoint(point2);
+               clampedPoint.setMax(m_bvhAabbMin);
+               clampedPoint.setMin(m_bvhAabbMax);
+
+               quantize(out,clampedPoint,isMax);
+
+       }
+       
+       SIMD_FORCE_INLINE btVector3     unQuantize(const unsigned short* vecIn) const
+       {
+                       btVector3       vecOut;
+                       vecOut.setValue(
+                       (btScalar)(vecIn[0]) / (m_bvhQuantization.getX()),
+                       (btScalar)(vecIn[1]) / (m_bvhQuantization.getY()),
+                       (btScalar)(vecIn[2]) / (m_bvhQuantization.getZ()));
+                       vecOut += m_bvhAabbMin;
+                       return vecOut;
+       }
+
+       ///setTraversalMode let's you choose between stackless, recursive or stackless cache friendly tree traversal. Note this is only implemented for quantized trees.
+       void    setTraversalMode(btTraversalMode        traversalMode)
+       {
+               m_traversalMode = traversalMode;
+       }
+
+
+       SIMD_FORCE_INLINE QuantizedNodeArray&   getQuantizedNodeArray()
+       {       
+               return  m_quantizedContiguousNodes;
+       }
+
+
+       SIMD_FORCE_INLINE BvhSubtreeInfoArray&  getSubtreeInfoArray()
+       {
+               return m_SubtreeHeaders;
+       }
+
+
+       /////Calculate space needed to store BVH for serialization
+       unsigned calculateSerializeBufferSize();
+
+       /// Data buffer MUST be 16 byte aligned
+       virtual bool serialize(void *o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian);
+
+       ///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place'
+       static btQuantizedBvh *deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian);
+
+       static unsigned int getAlignmentSerializationPadding();
+
+       SIMD_FORCE_INLINE bool isQuantized()
+       {
+               return m_useQuantization;
+       }
+
+private:
+       // Special "copy" constructor that allows for in-place deserialization
+       // Prevents btVector3's default constructor from being called, but doesn't inialize much else
+       // ownsMemory should most likely be false if deserializing, and if you are not, don't call this (it also changes the function signature, which we need)
+       btQuantizedBvh(btQuantizedBvh &other, bool ownsMemory);
+
+}
+;
+
+
+#endif //QUANTIZED_BVH_H
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp
new file mode 100644 (file)
index 0000000..cd0c028
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+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.
+*/
+
+#include "btBoxBoxCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/CollisionShapes/btBoxShape.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "btBoxBoxDetector.h"
+
+#define USE_PERSISTENT_CONTACTS 1
+
+btBoxBoxCollisionAlgorithm::btBoxBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* obj0,btCollisionObject* obj1)
+: btCollisionAlgorithm(ci),
+m_ownManifold(false),
+m_manifoldPtr(mf)
+{
+       if (!m_manifoldPtr && m_dispatcher->needsCollision(obj0,obj1))
+       {
+               m_manifoldPtr = m_dispatcher->getNewManifold(obj0,obj1);
+               m_ownManifold = true;
+       }
+}
+
+btBoxBoxCollisionAlgorithm::~btBoxBoxCollisionAlgorithm()
+{
+       if (m_ownManifold)
+       {
+               if (m_manifoldPtr)
+                       m_dispatcher->releaseManifold(m_manifoldPtr);
+       }
+}
+
+void btBoxBoxCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+       if (!m_manifoldPtr)
+               return;
+
+       btCollisionObject*      col0 = body0;
+       btCollisionObject*      col1 = body1;
+       btBoxShape* box0 = (btBoxShape*)col0->getCollisionShape();
+       btBoxShape* box1 = (btBoxShape*)col1->getCollisionShape();
+
+
+
+       /// report a contact. internally this will be kept persistent, and contact reduction is done
+       resultOut->setPersistentManifold(m_manifoldPtr);
+#ifndef USE_PERSISTENT_CONTACTS        
+       m_manifoldPtr->clearManifold();
+#endif //USE_PERSISTENT_CONTACTS
+
+       btDiscreteCollisionDetectorInterface::ClosestPointInput input;
+       input.m_maximumDistanceSquared = 1e30f;
+       input.m_transformA = body0->getWorldTransform();
+       input.m_transformB = body1->getWorldTransform();
+
+       btBoxBoxDetector detector(box0,box1);
+       detector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw);
+
+#ifdef USE_PERSISTENT_CONTACTS
+       //  refreshContactPoints is only necessary when using persistent contact points. otherwise all points are newly added
+       if (m_ownManifold)
+       {
+               resultOut->refreshContactPoints();
+       }
+#endif //USE_PERSISTENT_CONTACTS
+
+}
+
+btScalar btBoxBoxCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* /*body0*/,btCollisionObject* /*body1*/,const btDispatcherInfo& /*dispatchInfo*/,btManifoldResult* /*resultOut*/)
+{
+       //not yet
+       return 1.f;
+}
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h
new file mode 100644 (file)
index 0000000..35afaf1
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+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.
+*/
+
+#ifndef BOX_BOX__COLLISION_ALGORITHM_H
+#define BOX_BOX__COLLISION_ALGORITHM_H
+
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
+#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
+
+class btPersistentManifold;
+
+///box-box collision detection
+class btBoxBoxCollisionAlgorithm : public btCollisionAlgorithm
+{
+       bool    m_ownManifold;
+       btPersistentManifold*   m_manifoldPtr;
+       
+public:
+       btBoxBoxCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
+               : btCollisionAlgorithm(ci) {}
+
+       virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+       virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+       btBoxBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1);
+
+       virtual ~btBoxBoxCollisionAlgorithm();
+
+       virtual void    getAllContactManifolds(btManifoldArray& manifoldArray)
+       {
+               if (m_manifoldPtr && m_ownManifold)
+               {
+                       manifoldArray.push_back(m_manifoldPtr);
+               }
+       }
+
+
+       struct CreateFunc :public       btCollisionAlgorithmCreateFunc
+       {
+               virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+               {
+                       int bbsize = sizeof(btBoxBoxCollisionAlgorithm);
+                       void* ptr = ci.m_dispatcher1->allocateCollisionAlgorithm(bbsize);
+                       return new(ptr) btBoxBoxCollisionAlgorithm(0,ci,body0,body1);
+               }
+       };
+
+};
+
+#endif //BOX_BOX__COLLISION_ALGORITHM_H
+
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp
new file mode 100644 (file)
index 0000000..45ebff5
--- /dev/null
@@ -0,0 +1,683 @@
+
+/*
+ * Box-Box collision detection re-distributed under the ZLib license with permission from Russell L. Smith
+ * Original version is from Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org
+ Bullet Continuous Collision Detection and Physics Library
+ Bullet is Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+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.
+*/
+
+///ODE box-box collision detection is adapted to work with Bullet
+
+#include "btBoxBoxDetector.h"
+#include "BulletCollision/CollisionShapes/btBoxShape.h"
+
+#include <float.h>
+#include <string.h>
+
+btBoxBoxDetector::btBoxBoxDetector(btBoxShape* box1,btBoxShape* box2)
+: m_box1(box1),
+m_box2(box2)
+{
+
+}
+
+
+// given two boxes (p1,R1,side1) and (p2,R2,side2), collide them together and
+// generate contact points. this returns 0 if there is no contact otherwise
+// it returns the number of contacts generated.
+// `normal' returns the contact normal.
+// `depth' returns the maximum penetration depth along that normal.
+// `return_code' returns a number indicating the type of contact that was
+// detected:
+//        1,2,3 = box 2 intersects with a face of box 1
+//        4,5,6 = box 1 intersects with a face of box 2
+//        7..15 = edge-edge contact
+// `maxc' is the maximum number of contacts allowed to be generated, i.e.
+// the size of the `contact' array.
+// `contact' and `skip' are the contact array information provided to the
+// collision functions. this function only fills in the position and depth
+// fields.
+struct dContactGeom;
+#define dDOTpq(a,b,p,q) ((a)[0]*(b)[0] + (a)[p]*(b)[q] + (a)[2*(p)]*(b)[2*(q)])
+#define dInfinity FLT_MAX
+
+
+/*PURE_INLINE btScalar dDOT   (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,1); }
+PURE_INLINE btScalar dDOT13 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,3); }
+PURE_INLINE btScalar dDOT31 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,3,1); }
+PURE_INLINE btScalar dDOT33 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,3,3); }
+*/
+static btScalar dDOT   (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,1); }
+static btScalar dDOT44 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,4,4); }
+static btScalar dDOT41 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,4,1); }
+static btScalar dDOT14 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,4); }
+#define dMULTIPLYOP1_331(A,op,B,C) \
+{\
+  (A)[0] op dDOT41((B),(C)); \
+  (A)[1] op dDOT41((B+1),(C)); \
+  (A)[2] op dDOT41((B+2),(C)); \
+}
+
+#define dMULTIPLYOP0_331(A,op,B,C) \
+{ \
+  (A)[0] op dDOT((B),(C)); \
+  (A)[1] op dDOT((B+4),(C)); \
+  (A)[2] op dDOT((B+8),(C)); \
+} 
+
+#define dMULTIPLY1_331(A,B,C) dMULTIPLYOP1_331(A,=,B,C)
+#define dMULTIPLY0_331(A,B,C) dMULTIPLYOP0_331(A,=,B,C)
+
+typedef btScalar dMatrix3[4*3];
+
+void dLineClosestApproach (const btVector3& pa, const btVector3& ua,
+                          const btVector3& pb, const btVector3& ub,
+                          btScalar *alpha, btScalar *beta);
+void dLineClosestApproach (const btVector3& pa, const btVector3& ua,
+                          const btVector3& pb, const btVector3& ub,
+                          btScalar *alpha, btScalar *beta)
+{
+  btVector3 p;
+  p[0] = pb[0] - pa[0];
+  p[1] = pb[1] - pa[1];
+  p[2] = pb[2] - pa[2];
+  btScalar uaub = dDOT(ua,ub);
+  btScalar q1 =  dDOT(ua,p);
+  btScalar q2 = -dDOT(ub,p);
+  btScalar d = 1-uaub*uaub;
+  if (d <= btScalar(0.0001f)) {
+    // @@@ this needs to be made more robust
+    *alpha = 0;
+    *beta  = 0;
+  }
+  else {
+    d = 1.f/d;
+    *alpha = (q1 + uaub*q2)*d;
+    *beta  = (uaub*q1 + q2)*d;
+  }
+}
+
+
+
+// find all the intersection points between the 2D rectangle with vertices
+// at (+/-h[0],+/-h[1]) and the 2D quadrilateral with vertices (p[0],p[1]),
+// (p[2],p[3]),(p[4],p[5]),(p[6],p[7]).
+//
+// the intersection points are returned as x,y pairs in the 'ret' array.
+// the number of intersection points is returned by the function (this will
+// be in the range 0 to 8).
+
+static int intersectRectQuad2 (btScalar h[2], btScalar p[8], btScalar ret[16])
+{
+  // q (and r) contain nq (and nr) coordinate points for the current (and
+  // chopped) polygons
+  int nq=4,nr=0;
+  btScalar buffer[16];
+  btScalar *q = p;
+  btScalar *r = ret;
+  for (int dir=0; dir <= 1; dir++) {
+    // direction notation: xy[0] = x axis, xy[1] = y axis
+    for (int sign=-1; sign <= 1; sign += 2) {
+      // chop q along the line xy[dir] = sign*h[dir]
+      btScalar *pq = q;
+      btScalar *pr = r;
+      nr = 0;
+      for (int i=nq; i > 0; i--) {
+       // go through all points in q and all lines between adjacent points
+       if (sign*pq[dir] < h[dir]) {
+         // this point is inside the chopping line
+         pr[0] = pq[0];
+         pr[1] = pq[1];
+         pr += 2;
+         nr++;
+         if (nr & 8) {
+           q = r;
+           goto done;
+         }
+       }
+       btScalar *nextq = (i > 1) ? pq+2 : q;
+       if ((sign*pq[dir] < h[dir]) ^ (sign*nextq[dir] < h[dir])) {
+         // this line crosses the chopping line
+         pr[1-dir] = pq[1-dir] + (nextq[1-dir]-pq[1-dir]) /
+           (nextq[dir]-pq[dir]) * (sign*h[dir]-pq[dir]);
+         pr[dir] = sign*h[dir];
+         pr += 2;
+         nr++;
+         if (nr & 8) {
+           q = r;
+           goto done;
+         }
+       }
+       pq += 2;
+      }
+      q = r;
+      r = (q==ret) ? buffer : ret;
+      nq = nr;
+    }
+  }
+ done:
+  if (q != ret) memcpy (ret,q,nr*2*sizeof(btScalar));
+  return nr;
+}
+
+
+#define M__PI 3.14159265f
+
+// given n points in the plane (array p, of size 2*n), generate m points that
+// best represent the whole set. the definition of 'best' here is not
+// predetermined - the idea is to select points that give good box-box
+// collision detection behavior. the chosen point indexes are returned in the
+// array iret (of size m). 'i0' is always the first entry in the array.
+// n must be in the range [1..8]. m must be in the range [1..n]. i0 must be
+// in the range [0..n-1].
+
+void cullPoints2 (int n, btScalar p[], int m, int i0, int iret[]);
+void cullPoints2 (int n, btScalar p[], int m, int i0, int iret[])
+{
+  // compute the centroid of the polygon in cx,cy
+  int i,j;
+  btScalar a,cx,cy,q;
+  if (n==1) {
+    cx = p[0];
+    cy = p[1];
+  }
+  else if (n==2) {
+    cx = btScalar(0.5)*(p[0] + p[2]);
+    cy = btScalar(0.5)*(p[1] + p[3]);
+  }
+  else {
+    a = 0;
+    cx = 0;
+    cy = 0;
+    for (i=0; i<(n-1); i++) {
+      q = p[i*2]*p[i*2+3] - p[i*2+2]*p[i*2+1];
+      a += q;
+      cx += q*(p[i*2]+p[i*2+2]);
+      cy += q*(p[i*2+1]+p[i*2+3]);
+    }
+    q = p[n*2-2]*p[1] - p[0]*p[n*2-1];
+    a = 1.f/(btScalar(3.0)*(a+q));
+    cx = a*(cx + q*(p[n*2-2]+p[0]));
+    cy = a*(cy + q*(p[n*2-1]+p[1]));
+  }
+
+  // compute the angle of each point w.r.t. the centroid
+  btScalar A[8];
+  for (i=0; i<n; i++) A[i] = btAtan2(p[i*2+1]-cy,p[i*2]-cx);
+
+  // search for points that have angles closest to A[i0] + i*(2*pi/m).
+  int avail[8];
+  for (i=0; i<n; i++) avail[i] = 1;
+  avail[i0] = 0;
+  iret[0] = i0;
+  iret++;
+  for (j=1; j<m; j++) {
+    a = btScalar(j)*(2*M__PI/m) + A[i0];
+    if (a > M__PI) a -= 2*M__PI;
+    btScalar maxdiff=1e9,diff;
+#if defined(DEBUG) || defined (_DEBUG)
+    *iret = i0;                        // iret is not allowed to keep this value
+#endif
+    for (i=0; i<n; i++) {
+      if (avail[i]) {
+       diff = btFabs (A[i]-a);
+       if (diff > M__PI) diff = 2*M__PI - diff;
+       if (diff < maxdiff) {
+         maxdiff = diff;
+         *iret = i;
+       }
+      }
+    }
+#if defined(DEBUG) || defined (_DEBUG)
+    btAssert (*iret != i0);    // ensure iret got set
+#endif
+    avail[*iret] = 0;
+    iret++;
+  }
+}
+
+
+
+int dBoxBox2 (const btVector3& p1, const dMatrix3 R1,
+            const btVector3& side1, const btVector3& p2,
+            const dMatrix3 R2, const btVector3& side2,
+            btVector3& normal, btScalar *depth, int *return_code,
+                int maxc, dContactGeom * /*contact*/, int /*skip*/,btDiscreteCollisionDetectorInterface::Result& output);
+int dBoxBox2 (const btVector3& p1, const dMatrix3 R1,
+            const btVector3& side1, const btVector3& p2,
+            const dMatrix3 R2, const btVector3& side2,
+            btVector3& normal, btScalar *depth, int *return_code,
+                int maxc, dContactGeom * /*contact*/, int /*skip*/,btDiscreteCollisionDetectorInterface::Result& output)
+{
+  const btScalar fudge_factor = btScalar(1.05);
+  btVector3 p,pp,normalC;
+  const btScalar *normalR = 0;
+  btScalar A[3],B[3],R11,R12,R13,R21,R22,R23,R31,R32,R33,
+    Q11,Q12,Q13,Q21,Q22,Q23,Q31,Q32,Q33,s,s2,l;
+  int i,j,invert_normal,code;
+
+  // get vector from centers of box 1 to box 2, relative to box 1
+  p = p2 - p1;
+  dMULTIPLY1_331 (pp,R1,p);            // get pp = p relative to body 1
+
+  // get side lengths / 2
+  A[0] = side1[0]*btScalar(0.5);
+  A[1] = side1[1]*btScalar(0.5);
+  A[2] = side1[2]*btScalar(0.5);
+  B[0] = side2[0]*btScalar(0.5);
+  B[1] = side2[1]*btScalar(0.5);
+  B[2] = side2[2]*btScalar(0.5);
+
+  // Rij is R1'*R2, i.e. the relative rotation between R1 and R2
+  R11 = dDOT44(R1+0,R2+0); R12 = dDOT44(R1+0,R2+1); R13 = dDOT44(R1+0,R2+2);
+  R21 = dDOT44(R1+1,R2+0); R22 = dDOT44(R1+1,R2+1); R23 = dDOT44(R1+1,R2+2);
+  R31 = dDOT44(R1+2,R2+0); R32 = dDOT44(R1+2,R2+1); R33 = dDOT44(R1+2,R2+2);
+
+  Q11 = btFabs(R11); Q12 = btFabs(R12); Q13 = btFabs(R13);
+  Q21 = btFabs(R21); Q22 = btFabs(R22); Q23 = btFabs(R23);
+  Q31 = btFabs(R31); Q32 = btFabs(R32); Q33 = btFabs(R33);
+
+  // for all 15 possible separating axes:
+  //   * see if the axis separates the boxes. if so, return 0.
+  //   * find the depth of the penetration along the separating axis (s2)
+  //   * if this is the largest depth so far, record it.
+  // the normal vector will be set to the separating axis with the smallest
+  // depth. note: normalR is set to point to a column of R1 or R2 if that is
+  // the smallest depth normal so far. otherwise normalR is 0 and normalC is
+  // set to a vector relative to body 1. invert_normal is 1 if the sign of
+  // the normal should be flipped.
+
+#define TST(expr1,expr2,norm,cc) \
+  s2 = btFabs(expr1) - (expr2); \
+  if (s2 > 0) return 0; \
+  if (s2 > s) { \
+    s = s2; \
+    normalR = norm; \
+    invert_normal = ((expr1) < 0); \
+    code = (cc); \
+  }
+
+  s = -dInfinity;
+  invert_normal = 0;
+  code = 0;
+
+  // separating axis = u1,u2,u3
+  TST (pp[0],(A[0] + B[0]*Q11 + B[1]*Q12 + B[2]*Q13),R1+0,1);
+  TST (pp[1],(A[1] + B[0]*Q21 + B[1]*Q22 + B[2]*Q23),R1+1,2);
+  TST (pp[2],(A[2] + B[0]*Q31 + B[1]*Q32 + B[2]*Q33),R1+2,3);
+
+  // separating axis = v1,v2,v3
+  TST (dDOT41(R2+0,p),(A[0]*Q11 + A[1]*Q21 + A[2]*Q31 + B[0]),R2+0,4);
+  TST (dDOT41(R2+1,p),(A[0]*Q12 + A[1]*Q22 + A[2]*Q32 + B[1]),R2+1,5);
+  TST (dDOT41(R2+2,p),(A[0]*Q13 + A[1]*Q23 + A[2]*Q33 + B[2]),R2+2,6);
+
+  // note: cross product axes need to be scaled when s is computed.
+  // normal (n1,n2,n3) is relative to box 1.
+#undef TST
+#define TST(expr1,expr2,n1,n2,n3,cc) \
+  s2 = btFabs(expr1) - (expr2); \
+  if (s2 > 0) return 0; \
+  l = btSqrt((n1)*(n1) + (n2)*(n2) + (n3)*(n3)); \
+  if (l > 0) { \
+    s2 /= l; \
+    if (s2*fudge_factor > s) { \
+      s = s2; \
+      normalR = 0; \
+      normalC[0] = (n1)/l; normalC[1] = (n2)/l; normalC[2] = (n3)/l; \
+      invert_normal = ((expr1) < 0); \
+      code = (cc); \
+    } \
+  }
+
+  // separating axis = u1 x (v1,v2,v3)
+  TST(pp[2]*R21-pp[1]*R31,(A[1]*Q31+A[2]*Q21+B[1]*Q13+B[2]*Q12),0,-R31,R21,7);
+  TST(pp[2]*R22-pp[1]*R32,(A[1]*Q32+A[2]*Q22+B[0]*Q13+B[2]*Q11),0,-R32,R22,8);
+  TST(pp[2]*R23-pp[1]*R33,(A[1]*Q33+A[2]*Q23+B[0]*Q12+B[1]*Q11),0,-R33,R23,9);
+
+  // separating axis = u2 x (v1,v2,v3)
+  TST(pp[0]*R31-pp[2]*R11,(A[0]*Q31+A[2]*Q11+B[1]*Q23+B[2]*Q22),R31,0,-R11,10);
+  TST(pp[0]*R32-pp[2]*R12,(A[0]*Q32+A[2]*Q12+B[0]*Q23+B[2]*Q21),R32,0,-R12,11);
+  TST(pp[0]*R33-pp[2]*R13,(A[0]*Q33+A[2]*Q13+B[0]*Q22+B[1]*Q21),R33,0,-R13,12);
+
+  // separating axis = u3 x (v1,v2,v3)
+  TST(pp[1]*R11-pp[0]*R21,(A[0]*Q21+A[1]*Q11+B[1]*Q33+B[2]*Q32),-R21,R11,0,13);
+  TST(pp[1]*R12-pp[0]*R22,(A[0]*Q22+A[1]*Q12+B[0]*Q33+B[2]*Q31),-R22,R12,0,14);
+  TST(pp[1]*R13-pp[0]*R23,(A[0]*Q23+A[1]*Q13+B[0]*Q32+B[1]*Q31),-R23,R13,0,15);
+
+#undef TST
+
+  if (!code) return 0;
+
+  // if we get to this point, the boxes interpenetrate. compute the normal
+  // in global coordinates.
+  if (normalR) {
+    normal[0] = normalR[0];
+    normal[1] = normalR[4];
+    normal[2] = normalR[8];
+  }
+  else {
+    dMULTIPLY0_331 (normal,R1,normalC);
+  }
+  if (invert_normal) {
+    normal[0] = -normal[0];
+    normal[1] = -normal[1];
+    normal[2] = -normal[2];
+  }
+  *depth = -s;
+
+  // compute contact point(s)
+
+  if (code > 6) {
+    // an edge from box 1 touches an edge from box 2.
+    // find a point pa on the intersecting edge of box 1
+    btVector3 pa;
+    btScalar sign;
+    for (i=0; i<3; i++) pa[i] = p1[i];
+    for (j=0; j<3; j++) {
+      sign = (dDOT14(normal,R1+j) > 0) ? btScalar(1.0) : btScalar(-1.0);
+      for (i=0; i<3; i++) pa[i] += sign * A[j] * R1[i*4+j];
+    }
+
+    // find a point pb on the intersecting edge of box 2
+    btVector3 pb;
+    for (i=0; i<3; i++) pb[i] = p2[i];
+    for (j=0; j<3; j++) {
+      sign = (dDOT14(normal,R2+j) > 0) ? btScalar(-1.0) : btScalar(1.0);
+      for (i=0; i<3; i++) pb[i] += sign * B[j] * R2[i*4+j];
+    }
+
+    btScalar alpha,beta;
+    btVector3 ua,ub;
+    for (i=0; i<3; i++) ua[i] = R1[((code)-7)/3 + i*4];
+    for (i=0; i<3; i++) ub[i] = R2[((code)-7)%3 + i*4];
+
+    dLineClosestApproach (pa,ua,pb,ub,&alpha,&beta);
+    for (i=0; i<3; i++) pa[i] += ua[i]*alpha;
+    for (i=0; i<3; i++) pb[i] += ub[i]*beta;
+
+       {
+               
+               //contact[0].pos[i] = btScalar(0.5)*(pa[i]+pb[i]);
+               //contact[0].depth = *depth;
+               btVector3 pointInWorld;
+
+#ifdef USE_CENTER_POINT
+           for (i=0; i<3; i++) 
+                       pointInWorld[i] = (pa[i]+pb[i])*btScalar(0.5);
+               output.addContactPoint(-normal,pointInWorld,-*depth);
+#else
+               output.addContactPoint(-normal,pb,-*depth);
+#endif //
+               *return_code = code;
+       }
+    return 1;
+  }
+
+  // okay, we have a face-something intersection (because the separating
+  // axis is perpendicular to a face). define face 'a' to be the reference
+  // face (i.e. the normal vector is perpendicular to this) and face 'b' to be
+  // the incident face (the closest face of the other box).
+
+  const btScalar *Ra,*Rb,*pa,*pb,*Sa,*Sb;
+  if (code <= 3) {
+    Ra = R1;
+    Rb = R2;
+    pa = p1;
+    pb = p2;
+    Sa = A;
+    Sb = B;
+  }
+  else {
+    Ra = R2;
+    Rb = R1;
+    pa = p2;
+    pb = p1;
+    Sa = B;
+    Sb = A;
+  }
+
+  // nr = normal vector of reference face dotted with axes of incident box.
+  // anr = absolute values of nr.
+  btVector3 normal2,nr,anr;
+  if (code <= 3) {
+    normal2[0] = normal[0];
+    normal2[1] = normal[1];
+    normal2[2] = normal[2];
+  }
+  else {
+    normal2[0] = -normal[0];
+    normal2[1] = -normal[1];
+    normal2[2] = -normal[2];
+  }
+  dMULTIPLY1_331 (nr,Rb,normal2);
+  anr[0] = btFabs (nr[0]);
+  anr[1] = btFabs (nr[1]);
+  anr[2] = btFabs (nr[2]);
+
+  // find the largest compontent of anr: this corresponds to the normal
+  // for the indident face. the other axis numbers of the indicent face
+  // are stored in a1,a2.
+  int lanr,a1,a2;
+  if (anr[1] > anr[0]) {
+    if (anr[1] > anr[2]) {
+      a1 = 0;
+      lanr = 1;
+      a2 = 2;
+    }
+    else {
+      a1 = 0;
+      a2 = 1;
+      lanr = 2;
+    }
+  }
+  else {
+    if (anr[0] > anr[2]) {
+      lanr = 0;
+      a1 = 1;
+      a2 = 2;
+    }
+    else {
+      a1 = 0;
+      a2 = 1;
+      lanr = 2;
+    }
+  }
+
+  // compute center point of incident face, in reference-face coordinates
+  btVector3 center;
+  if (nr[lanr] < 0) {
+    for (i=0; i<3; i++) center[i] = pb[i] - pa[i] + Sb[lanr] * Rb[i*4+lanr];
+  }
+  else {
+    for (i=0; i<3; i++) center[i] = pb[i] - pa[i] - Sb[lanr] * Rb[i*4+lanr];
+  }
+
+  // find the normal and non-normal axis numbers of the reference box
+  int codeN,code1,code2;
+  if (code <= 3) codeN = code-1; else codeN = code-4;
+  if (codeN==0) {
+    code1 = 1;
+    code2 = 2;
+  }
+  else if (codeN==1) {
+    code1 = 0;
+    code2 = 2;
+  }
+  else {
+    code1 = 0;
+    code2 = 1;
+  }
+
+  // find the four corners of the incident face, in reference-face coordinates
+  btScalar quad[8];    // 2D coordinate of incident face (x,y pairs)
+  btScalar c1,c2,m11,m12,m21,m22;
+  c1 = dDOT14 (center,Ra+code1);
+  c2 = dDOT14 (center,Ra+code2);
+  // optimize this? - we have already computed this data above, but it is not
+  // stored in an easy-to-index format. for now it's quicker just to recompute
+  // the four dot products.
+  m11 = dDOT44 (Ra+code1,Rb+a1);
+  m12 = dDOT44 (Ra+code1,Rb+a2);
+  m21 = dDOT44 (Ra+code2,Rb+a1);
+  m22 = dDOT44 (Ra+code2,Rb+a2);
+  {
+    btScalar k1 = m11*Sb[a1];
+    btScalar k2 = m21*Sb[a1];
+    btScalar k3 = m12*Sb[a2];
+    btScalar k4 = m22*Sb[a2];
+    quad[0] = c1 - k1 - k3;
+    quad[1] = c2 - k2 - k4;
+    quad[2] = c1 - k1 + k3;
+    quad[3] = c2 - k2 + k4;
+    quad[4] = c1 + k1 + k3;
+    quad[5] = c2 + k2 + k4;
+    quad[6] = c1 + k1 - k3;
+    quad[7] = c2 + k2 - k4;
+  }
+
+  // find the size of the reference face
+  btScalar rect[2];
+  rect[0] = Sa[code1];
+  rect[1] = Sa[code2];
+
+  // intersect the incident and reference faces
+  btScalar ret[16];
+  int n = intersectRectQuad2 (rect,quad,ret);
+  if (n < 1) return 0;         // this should never happen
+
+  // convert the intersection points into reference-face coordinates,
+  // and compute the contact position and depth for each point. only keep
+  // those points that have a positive (penetrating) depth. delete points in
+  // the 'ret' array as necessary so that 'point' and 'ret' correspond.
+  btScalar point[3*8];         // penetrating contact points
+  btScalar dep[8];                     // depths for those points
+  btScalar det1 = 1.f/(m11*m22 - m12*m21);
+  m11 *= det1;
+  m12 *= det1;
+  m21 *= det1;
+  m22 *= det1;
+  int cnum = 0;                        // number of penetrating contact points found
+  for (j=0; j < n; j++) {
+    btScalar k1 =  m22*(ret[j*2]-c1) - m12*(ret[j*2+1]-c2);
+    btScalar k2 = -m21*(ret[j*2]-c1) + m11*(ret[j*2+1]-c2);
+    for (i=0; i<3; i++) point[cnum*3+i] =
+                         center[i] + k1*Rb[i*4+a1] + k2*Rb[i*4+a2];
+    dep[cnum] = Sa[codeN] - dDOT(normal2,point+cnum*3);
+    if (dep[cnum] >= 0) {
+      ret[cnum*2] = ret[j*2];
+      ret[cnum*2+1] = ret[j*2+1];
+      cnum++;
+    }
+  }
+  if (cnum < 1) return 0;      // this should never happen
+
+  // we can't generate more contacts than we actually have
+  if (maxc > cnum) maxc = cnum;
+  if (maxc < 1) maxc = 1;
+
+  if (cnum <= maxc) {
+    // we have less contacts than we need, so we use them all
+    for (j=0; j < cnum; j++) {
+
+               //AddContactPoint...
+
+               //dContactGeom *con = CONTACT(contact,skip*j);
+      //for (i=0; i<3; i++) con->pos[i] = point[j*3+i] + pa[i];
+      //con->depth = dep[j];
+
+               btVector3 pointInWorld;
+               for (i=0; i<3; i++) 
+                       pointInWorld[i] = point[j*3+i] + pa[i];
+               output.addContactPoint(-normal,pointInWorld,-dep[j]);
+
+    }
+  }
+  else {
+    // we have more contacts than are wanted, some of them must be culled.
+    // find the deepest point, it is always the first contact.
+    int i1 = 0;
+    btScalar maxdepth = dep[0];
+    for (i=1; i<cnum; i++) {
+      if (dep[i] > maxdepth) {
+       maxdepth = dep[i];
+       i1 = i;
+      }
+    }
+
+    int iret[8];
+    cullPoints2 (cnum,ret,maxc,i1,iret);
+
+    for (j=0; j < maxc; j++) {
+//      dContactGeom *con = CONTACT(contact,skip*j);
+  //    for (i=0; i<3; i++) con->pos[i] = point[iret[j]*3+i] + pa[i];
+    //  con->depth = dep[iret[j]];
+
+               btVector3 posInWorld;
+               for (i=0; i<3; i++) 
+                       posInWorld[i] = point[iret[j]*3+i] + pa[i];
+               output.addContactPoint(-normal,posInWorld,-dep[iret[j]]);
+    }
+    cnum = maxc;
+  }
+
+  *return_code = code;
+  return cnum;
+}
+
+void   btBoxBoxDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* /*debugDraw*/,bool /*swapResults*/)
+{
+       
+       const btTransform& transformA = input.m_transformA;
+       const btTransform& transformB = input.m_transformB;
+       
+       int skip = 0;
+       dContactGeom *contact = 0;
+
+       dMatrix3 R1;
+       dMatrix3 R2;
+
+       for (int j=0;j<3;j++)
+       {
+               R1[0+4*j] = transformA.getBasis()[j].x();
+               R2[0+4*j] = transformB.getBasis()[j].x();
+
+               R1[1+4*j] = transformA.getBasis()[j].y();
+               R2[1+4*j] = transformB.getBasis()[j].y();
+
+
+               R1[2+4*j] = transformA.getBasis()[j].z();
+               R2[2+4*j] = transformB.getBasis()[j].z();
+
+       }
+
+       
+
+       btVector3 normal;
+       btScalar depth;
+       int return_code;
+       int maxc = 4;
+
+
+       dBoxBox2 (transformA.getOrigin(), 
+       R1,
+       2.f*m_box1->getHalfExtentsWithMargin(),
+       transformB.getOrigin(),
+       R2, 
+       2.f*m_box2->getHalfExtentsWithMargin(),
+       normal, &depth, &return_code,
+       maxc, contact, skip,
+       output
+       );
+
+}
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h
new file mode 100644 (file)
index 0000000..605294d
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Box-Box collision detection re-distributed under the ZLib license with permission from Russell L. Smith
+ * Original version is from Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org
+
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+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.
+*/
+#ifndef BOX_BOX_DETECTOR_H
+#define BOX_BOX_DETECTOR_H
+
+
+class btBoxShape;
+#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
+
+
+/// btBoxBoxDetector wraps the ODE box-box collision detector
+/// re-distributed under the Zlib license with permission from Russell L. Smith
+struct btBoxBoxDetector : public btDiscreteCollisionDetectorInterface
+{
+       btBoxShape* m_box1;
+       btBoxShape* m_box2;
+
+public:
+
+       btBoxBoxDetector(btBoxShape* box1,btBoxShape* box2);
+
+       virtual ~btBoxBoxDetector() {};
+
+       virtual void    getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false);
+
+};
+
+#endif //BT_BOX_BOX_DETECTOR_H
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h
new file mode 100644 (file)
index 0000000..fad770a
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+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.
+*/
+
+#ifndef BT_COLLISION_CONFIGURATION
+#define BT_COLLISION_CONFIGURATION
+struct btCollisionAlgorithmCreateFunc;
+
+class btStackAlloc;
+class btPoolAllocator;
+
+///btCollisionConfiguration allows to configure Bullet collision detection
+///stack allocator size, default collision algorithms and persistent manifold pool size
+///todo: describe the meaning
+class  btCollisionConfiguration
+{
+
+public:
+
+       virtual ~btCollisionConfiguration()
+       {
+       }
+
+       ///memory pools
+       virtual btPoolAllocator* getPersistentManifoldPool() = 0;
+
+       virtual btPoolAllocator* getCollisionAlgorithmPool() = 0;
+
+       virtual btStackAlloc*   getStackAllocator() = 0;
+
+       virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1) =0;
+
+};
+
+#endif //BT_COLLISION_CONFIGURATION
+
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp
new file mode 100644 (file)
index 0000000..391cf6c
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+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.
+*/
+
+#include "btConvexPlaneCollisionAlgorithm.h"
+
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h"
+
+//#include <stdio.h>
+
+btConvexPlaneCollisionAlgorithm::btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped)
+: btCollisionAlgorithm(ci),
+m_ownManifold(false),
+m_manifoldPtr(mf),
+m_isSwapped(isSwapped)
+{
+       btCollisionObject* convexObj = m_isSwapped? col1 : col0;
+       btCollisionObject* planeObj = m_isSwapped? col0 : col1;
+       
+       if (!m_manifoldPtr && m_dispatcher->needsCollision(convexObj,planeObj))
+       {
+               m_manifoldPtr = m_dispatcher->getNewManifold(convexObj,planeObj);
+               m_ownManifold = true;
+       }
+}
+
+
+btConvexPlaneCollisionAlgorithm::~btConvexPlaneCollisionAlgorithm()
+{
+       if (m_ownManifold)
+       {
+               if (m_manifoldPtr)
+                       m_dispatcher->releaseManifold(m_manifoldPtr);
+       }
+}
+
+
+
+void btConvexPlaneCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+       (void)dispatchInfo;
+       (void)resultOut;
+       if (!m_manifoldPtr)
+               return;
+
+       btCollisionObject* convexObj = m_isSwapped? body1 : body0;
+       btCollisionObject* planeObj = m_isSwapped? body0: body1;
+
+       btConvexShape* convexShape = (btConvexShape*) convexObj->getCollisionShape();
+       btStaticPlaneShape* planeShape = (btStaticPlaneShape*) planeObj->getCollisionShape();
+
+       bool hasCollision = false;
+       const btVector3& planeNormal = planeShape->getPlaneNormal();
+       const btScalar& planeConstant = planeShape->getPlaneConstant();
+       btTransform planeInConvex;
+       planeInConvex= convexObj->getWorldTransform().inverse() * planeObj->getWorldTransform();
+       btTransform convexInPlaneTrans;
+       convexInPlaneTrans= planeObj->getWorldTransform().inverse() * convexObj->getWorldTransform();
+
+       btVector3 vtx = convexShape->localGetSupportingVertex(planeInConvex.getBasis()*-planeNormal);
+       btVector3 vtxInPlane = convexInPlaneTrans(vtx);
+       btScalar distance = (planeNormal.dot(vtxInPlane) - planeConstant);
+
+       btVector3 vtxInPlaneProjected = vtxInPlane - distance*planeNormal;
+       btVector3 vtxInPlaneWorld = planeObj->getWorldTransform() * vtxInPlaneProjected;
+
+       hasCollision = distance < m_manifoldPtr->getContactBreakingThreshold();
+       resultOut->setPersistentManifold(m_manifoldPtr);
+       if (hasCollision)
+       {
+               /// report a contact. internally this will be kept persistent, and contact reduction is done
+               btVector3 normalOnSurfaceB = planeObj->getWorldTransform().getBasis() * planeNormal;
+               btVector3 pOnB = vtxInPlaneWorld;
+               resultOut->addContactPoint(normalOnSurfaceB,pOnB,distance);
+       }
+       if (m_ownManifold)
+       {
+               if (m_manifoldPtr->getNumContacts())
+               {
+                       resultOut->refreshContactPoints();
+               }
+       }
+}
+
+btScalar btConvexPlaneCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+       (void)resultOut;
+       (void)dispatchInfo;
+       (void)col0;
+       (void)col1;
+
+       //not yet
+       return btScalar(1.);
+}
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h
new file mode 100644 (file)
index 0000000..7b25855
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+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.
+*/
+
+#ifndef CONVEX_PLANE_COLLISION_ALGORITHM_H
+#define CONVEX_PLANE_COLLISION_ALGORITHM_H
+
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
+class btPersistentManifold;
+#include "btCollisionDispatcher.h"
+
+#include "LinearMath/btVector3.h"
+
+/// btSphereBoxCollisionAlgorithm  provides sphere-box collision detection.
+/// Other features are frame-coherency (persistent data) and collision response.
+class btConvexPlaneCollisionAlgorithm : public btCollisionAlgorithm
+{
+       bool    m_ownManifold;
+       btPersistentManifold*   m_manifoldPtr;
+       bool    m_isSwapped;
+       
+public:
+
+       btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped);
+
+       virtual ~btConvexPlaneCollisionAlgorithm();
+
+       virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+       virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+       virtual void    getAllContactManifolds(btManifoldArray& manifoldArray)
+       {
+               if (m_manifoldPtr && m_ownManifold)
+               {
+                       manifoldArray.push_back(m_manifoldPtr);
+               }
+       }
+
+       struct CreateFunc :public       btCollisionAlgorithmCreateFunc
+       {
+               virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+               {
+                       void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexPlaneCollisionAlgorithm));
+                       if (!m_swapped)
+                       {
+                               return new(mem) btConvexPlaneCollisionAlgorithm(0,ci,body0,body1,false);
+                       } else
+                       {
+                               return new(mem) btConvexPlaneCollisionAlgorithm(0,ci,body0,body1,true);
+                       }
+               }
+       };
+
+};
+
+#endif //CONVEX_PLANE_COLLISION_ALGORITHM_H
+
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp
new file mode 100644 (file)
index 0000000..1c31708
--- /dev/null
@@ -0,0 +1,291 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+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.
+*/
+
+#include "btDefaultCollisionConfiguration.h"
+
+#include "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h"
+#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
+#include "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h"
+#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
+#include "BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
+#include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h"
+#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
+
+
+
+#include "LinearMath/btStackAlloc.h"
+#include "LinearMath/btPoolAllocator.h"
+
+
+
+
+
+btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo)
+//btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(btStackAlloc*       stackAlloc,btPoolAllocator*     persistentManifoldPool,btPoolAllocator* collisionAlgorithmPool)
+{
+
+       void* mem = btAlignedAlloc(sizeof(btVoronoiSimplexSolver),16);
+       m_simplexSolver = new (mem)btVoronoiSimplexSolver();
+       
+#define USE_EPA 1
+#ifdef USE_EPA
+       mem = btAlignedAlloc(sizeof(btGjkEpaPenetrationDepthSolver),16);
+       m_pdSolver = new (mem)btGjkEpaPenetrationDepthSolver;
+#else
+       mem = btAlignedAlloc(sizeof(btMinkowskiPenetrationDepthSolver),16);
+       m_pdSolver = new (mem)btMinkowskiPenetrationDepthSolver;
+#endif//USE_EPA        
+       
+
+       //default CreationFunctions, filling the m_doubleDispatch table
+       mem = btAlignedAlloc(sizeof(btConvexConvexAlgorithm::CreateFunc),16);
+       m_convexConvexCreateFunc = new(mem) btConvexConvexAlgorithm::CreateFunc(m_simplexSolver,m_pdSolver);
+       mem = btAlignedAlloc(sizeof(btConvexConcaveCollisionAlgorithm::CreateFunc),16);
+       m_convexConcaveCreateFunc = new (mem)btConvexConcaveCollisionAlgorithm::CreateFunc;
+       mem = btAlignedAlloc(sizeof(btConvexConcaveCollisionAlgorithm::CreateFunc),16);
+       m_swappedConvexConcaveCreateFunc = new (mem)btConvexConcaveCollisionAlgorithm::SwappedCreateFunc;
+       mem = btAlignedAlloc(sizeof(btCompoundCollisionAlgorithm::CreateFunc),16);
+       m_compoundCreateFunc = new (mem)btCompoundCollisionAlgorithm::CreateFunc;
+       mem = btAlignedAlloc(sizeof(btCompoundCollisionAlgorithm::SwappedCreateFunc),16);
+       m_swappedCompoundCreateFunc = new (mem)btCompoundCollisionAlgorithm::SwappedCreateFunc;
+       mem = btAlignedAlloc(sizeof(btEmptyAlgorithm::CreateFunc),16);
+       m_emptyCreateFunc = new(mem) btEmptyAlgorithm::CreateFunc;
+       
+       mem = btAlignedAlloc(sizeof(btSphereSphereCollisionAlgorithm::CreateFunc),16);
+       m_sphereSphereCF = new(mem) btSphereSphereCollisionAlgorithm::CreateFunc;
+#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
+       mem = btAlignedAlloc(sizeof(btSphereBoxCollisionAlgorithm::CreateFunc),16);
+       m_sphereBoxCF = new(mem) btSphereBoxCollisionAlgorithm::CreateFunc;
+       mem = btAlignedAlloc(sizeof(btSphereBoxCollisionAlgorithm::CreateFunc),16);
+       m_boxSphereCF = new (mem)btSphereBoxCollisionAlgorithm::CreateFunc;
+       m_boxSphereCF->m_swapped = true;
+#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
+
+       mem = btAlignedAlloc(sizeof(btSphereTriangleCollisionAlgorithm::CreateFunc),16);
+       m_sphereTriangleCF = new (mem)btSphereTriangleCollisionAlgorithm::CreateFunc;
+       mem = btAlignedAlloc(sizeof(btSphereTriangleCollisionAlgorithm::CreateFunc),16);
+       m_triangleSphereCF = new (mem)btSphereTriangleCollisionAlgorithm::CreateFunc;
+       m_triangleSphereCF->m_swapped = true;
+       
+       mem = btAlignedAlloc(sizeof(btBoxBoxCollisionAlgorithm::CreateFunc),16);
+       m_boxBoxCF = new(mem)btBoxBoxCollisionAlgorithm::CreateFunc;
+
+       //convex versus plane
+       mem = btAlignedAlloc (sizeof(btConvexPlaneCollisionAlgorithm::CreateFunc),16);
+       m_convexPlaneCF = new (mem) btConvexPlaneCollisionAlgorithm::CreateFunc;
+       mem = btAlignedAlloc (sizeof(btConvexPlaneCollisionAlgorithm::CreateFunc),16);
+       m_planeConvexCF = new (mem) btConvexPlaneCollisionAlgorithm::CreateFunc;
+       m_planeConvexCF->m_swapped = true;
+       
+       ///calculate maximum element size, big enough to fit any collision algorithm in the memory pool
+       int maxSize = sizeof(btConvexConvexAlgorithm);
+       int maxSize2 = sizeof(btConvexConcaveCollisionAlgorithm);
+       int maxSize3 = sizeof(btCompoundCollisionAlgorithm);
+       int maxSize4 = sizeof(btEmptyAlgorithm);
+       
+       int     collisionAlgorithmMaxElementSize = btMax(maxSize,maxSize2);
+       collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize,maxSize3);
+       collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize,maxSize4);
+
+       if (constructionInfo.m_stackAlloc)
+       {
+               m_ownsStackAllocator = false;
+               this->m_stackAlloc = constructionInfo.m_stackAlloc;
+       } else
+       {
+               m_ownsStackAllocator = true;
+               void* mem = btAlignedAlloc(sizeof(btStackAlloc),16);
+               m_stackAlloc = new(mem)btStackAlloc(constructionInfo.m_defaultStackAllocatorSize);
+       }
+               
+       if (constructionInfo.m_persistentManifoldPool)
+       {
+               m_ownsPersistentManifoldPool = false;
+               m_persistentManifoldPool = constructionInfo.m_persistentManifoldPool;
+       } else
+       {
+               m_ownsPersistentManifoldPool = true;
+               void* mem = btAlignedAlloc(sizeof(btPoolAllocator),16);
+               m_persistentManifoldPool = new (mem) btPoolAllocator(sizeof(btPersistentManifold),constructionInfo.m_defaultMaxPersistentManifoldPoolSize);
+       }
+       
+       if (constructionInfo.m_collisionAlgorithmPool)
+       {
+               m_ownsCollisionAlgorithmPool = false;
+               m_collisionAlgorithmPool = constructionInfo.m_collisionAlgorithmPool;
+       } else
+       {
+               m_ownsCollisionAlgorithmPool = true;
+               void* mem = btAlignedAlloc(sizeof(btPoolAllocator),16);
+               m_collisionAlgorithmPool = new(mem) btPoolAllocator(collisionAlgorithmMaxElementSize,constructionInfo.m_defaultMaxCollisionAlgorithmPoolSize);
+       }
+
+
+}
+
+btDefaultCollisionConfiguration::~btDefaultCollisionConfiguration()
+{
+       if (m_ownsStackAllocator)
+       {
+               m_stackAlloc->destroy();
+               m_stackAlloc->~btStackAlloc();
+               btAlignedFree(m_stackAlloc);
+       }
+       if (m_ownsCollisionAlgorithmPool)
+       {
+               m_collisionAlgorithmPool->~btPoolAllocator();
+               btAlignedFree(m_collisionAlgorithmPool);
+       }
+       if (m_ownsPersistentManifoldPool)
+       {
+               m_persistentManifoldPool->~btPoolAllocator();
+               btAlignedFree(m_persistentManifoldPool);
+       }
+
+       m_convexConvexCreateFunc->~btCollisionAlgorithmCreateFunc();
+       btAlignedFree(  m_convexConvexCreateFunc);
+
+       m_convexConcaveCreateFunc->~btCollisionAlgorithmCreateFunc();
+       btAlignedFree( m_convexConcaveCreateFunc);
+       m_swappedConvexConcaveCreateFunc->~btCollisionAlgorithmCreateFunc();
+       btAlignedFree( m_swappedConvexConcaveCreateFunc);
+
+       m_compoundCreateFunc->~btCollisionAlgorithmCreateFunc();
+       btAlignedFree( m_compoundCreateFunc);
+
+       m_swappedCompoundCreateFunc->~btCollisionAlgorithmCreateFunc();
+       btAlignedFree( m_swappedCompoundCreateFunc);
+
+       m_emptyCreateFunc->~btCollisionAlgorithmCreateFunc();
+       btAlignedFree( m_emptyCreateFunc);
+
+       m_sphereSphereCF->~btCollisionAlgorithmCreateFunc();
+       btAlignedFree( m_sphereSphereCF);
+
+#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
+       m_sphereBoxCF->~btCollisionAlgorithmCreateFunc();
+       btAlignedFree( m_sphereBoxCF);
+       m_boxSphereCF->~btCollisionAlgorithmCreateFunc();
+       btAlignedFree( m_boxSphereCF);
+#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
+
+       m_sphereTriangleCF->~btCollisionAlgorithmCreateFunc();
+       btAlignedFree( m_sphereTriangleCF);
+       m_triangleSphereCF->~btCollisionAlgorithmCreateFunc();
+       btAlignedFree( m_triangleSphereCF);
+       m_boxBoxCF->~btCollisionAlgorithmCreateFunc();
+       btAlignedFree( m_boxBoxCF);
+
+       m_convexPlaneCF->~btCollisionAlgorithmCreateFunc();
+       btAlignedFree( m_convexPlaneCF);
+       m_planeConvexCF->~btCollisionAlgorithmCreateFunc();
+       btAlignedFree( m_planeConvexCF);
+
+       m_simplexSolver->~btVoronoiSimplexSolver();
+       btAlignedFree(m_simplexSolver);
+
+       m_pdSolver->~btConvexPenetrationDepthSolver();
+       
+       btAlignedFree(m_pdSolver);
+
+
+}
+
+
+btCollisionAlgorithmCreateFunc* btDefaultCollisionConfiguration::getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1)
+{
+
+
+
+       if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1==SPHERE_SHAPE_PROXYTYPE))
+       {
+               return  m_sphereSphereCF;
+       }
+#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
+       if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1==BOX_SHAPE_PROXYTYPE))
+       {
+               return  m_sphereBoxCF;
+       }
+
+       if ((proxyType0 == BOX_SHAPE_PROXYTYPE ) && (proxyType1==SPHERE_SHAPE_PROXYTYPE))
+       {
+               return  m_boxSphereCF;
+       }
+#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
+
+
+       if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE ) && (proxyType1==TRIANGLE_SHAPE_PROXYTYPE))
+       {
+               return  m_sphereTriangleCF;
+       }
+
+       if ((proxyType0 == TRIANGLE_SHAPE_PROXYTYPE  ) && (proxyType1==SPHERE_SHAPE_PROXYTYPE))
+       {
+               return  m_triangleSphereCF;
+       } 
+
+       if ((proxyType0 == BOX_SHAPE_PROXYTYPE) && (proxyType1 == BOX_SHAPE_PROXYTYPE))
+       {
+               return m_boxBoxCF;
+       }
+       
+       if (btBroadphaseProxy::isConvex(proxyType0) && (proxyType1 == STATIC_PLANE_PROXYTYPE))
+       {
+               return m_convexPlaneCF;
+       }
+
+       if (btBroadphaseProxy::isConvex(proxyType1) && (proxyType0 == STATIC_PLANE_PROXYTYPE))
+       {
+               return m_planeConvexCF;
+       }
+       
+
+
+       if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConvex(proxyType1))
+       {
+               return m_convexConvexCreateFunc;
+       }
+
+       if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConcave(proxyType1))
+       {
+               return m_convexConcaveCreateFunc;
+       }
+
+       if (btBroadphaseProxy::isConvex(proxyType1) && btBroadphaseProxy::isConcave(proxyType0))
+       {
+               return m_swappedConvexConcaveCreateFunc;
+       }
+
+       if (btBroadphaseProxy::isCompound(proxyType0))
+       {
+               return m_compoundCreateFunc;
+       } else
+       {
+               if (btBroadphaseProxy::isCompound(proxyType1))
+               {
+                       return m_swappedCompoundCreateFunc;
+               }
+       }
+
+       //failed to find an algorithm
+       return m_emptyCreateFunc;
+}
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h
new file mode 100644 (file)
index 0000000..df48ee9
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+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.
+*/
+
+#ifndef BT_DEFAULT_COLLISION_CONFIGURATION
+#define BT_DEFAULT_COLLISION_CONFIGURATION
+
+#include "btCollisionConfiguration.h"
+class btVoronoiSimplexSolver;
+class btConvexPenetrationDepthSolver;
+
+struct btDefaultCollisionConstructionInfo
+{
+       btStackAlloc*           m_stackAlloc;
+       btPoolAllocator*        m_persistentManifoldPool;
+       btPoolAllocator*        m_collisionAlgorithmPool;
+       int                                     m_defaultMaxPersistentManifoldPoolSize;
+       int                                     m_defaultMaxCollisionAlgorithmPoolSize;
+       int                                     m_defaultStackAllocatorSize;
+
+       btDefaultCollisionConstructionInfo()
+               :m_stackAlloc(0),
+               m_persistentManifoldPool(0),
+               m_collisionAlgorithmPool(0),
+               m_defaultMaxPersistentManifoldPoolSize(65535),
+               m_defaultMaxCollisionAlgorithmPoolSize(65535),
+               m_defaultStackAllocatorSize(5*1024*1024)
+       {
+       }
+};
+
+
+
+///btCollisionConfiguration allows to configure Bullet collision detection
+///stack allocator, pool memory allocators
+///todo: describe the meaning
+class  btDefaultCollisionConfiguration : public btCollisionConfiguration
+{
+
+protected:
+
+       int     m_persistentManifoldPoolSize;
+       
+       btStackAlloc*   m_stackAlloc;
+       bool    m_ownsStackAllocator;
+
+       btPoolAllocator*        m_persistentManifoldPool;
+       bool    m_ownsPersistentManifoldPool;
+
+
+       btPoolAllocator*        m_collisionAlgorithmPool;
+       bool    m_ownsCollisionAlgorithmPool;
+
+       //default simplex/penetration depth solvers
+       btVoronoiSimplexSolver* m_simplexSolver;
+       btConvexPenetrationDepthSolver* m_pdSolver;
+       
+       //default CreationFunctions, filling the m_doubleDispatch table
+       btCollisionAlgorithmCreateFunc* m_convexConvexCreateFunc;
+       btCollisionAlgorithmCreateFunc* m_convexConcaveCreateFunc;
+       btCollisionAlgorithmCreateFunc* m_swappedConvexConcaveCreateFunc;
+       btCollisionAlgorithmCreateFunc* m_compoundCreateFunc;
+       btCollisionAlgorithmCreateFunc* m_swappedCompoundCreateFunc;
+       btCollisionAlgorithmCreateFunc* m_emptyCreateFunc;
+       btCollisionAlgorithmCreateFunc* m_sphereSphereCF;
+#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
+       btCollisionAlgorithmCreateFunc* m_sphereBoxCF;
+       btCollisionAlgorithmCreateFunc* m_boxSphereCF;
+#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
+
+       btCollisionAlgorithmCreateFunc* m_boxBoxCF;
+       btCollisionAlgorithmCreateFunc* m_sphereTriangleCF;
+       btCollisionAlgorithmCreateFunc* m_triangleSphereCF;
+       btCollisionAlgorithmCreateFunc* m_planeConvexCF;
+       btCollisionAlgorithmCreateFunc* m_convexPlaneCF;
+       
+public:
+
+
+       btDefaultCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo = btDefaultCollisionConstructionInfo());
+
+       virtual ~btDefaultCollisionConfiguration();
+
+               ///memory pools
+       virtual btPoolAllocator* getPersistentManifoldPool()
+       {
+               return m_persistentManifoldPool;
+       }
+
+       virtual btPoolAllocator* getCollisionAlgorithmPool()
+       {
+               return m_collisionAlgorithmPool;
+       }
+
+       virtual btStackAlloc*   getStackAllocator()
+       {
+               return m_stackAlloc;
+       }
+
+
+       virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1);
+
+
+};
+
+#endif //BT_DEFAULT_COLLISION_CONFIGURATION
+
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp
new file mode 100644 (file)
index 0000000..fb81c8a
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+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.
+*/
+
+
+#include "btConvexInternalShape.h"
+
+
+btConvexInternalShape::btConvexInternalShape()
+: m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.)),
+m_collisionMargin(CONVEX_DISTANCE_MARGIN)
+{
+}
+
+
+void   btConvexInternalShape::setLocalScaling(const btVector3& scaling)
+{
+       m_localScaling = scaling.absolute();
+}
+
+
+
+void   btConvexInternalShape::getAabbSlow(const btTransform& trans,btVector3&minAabb,btVector3&maxAabb) const
+{
+
+       btScalar margin = getMargin();
+       for (int i=0;i<3;i++)
+       {
+               btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.));
+               vec[i] = btScalar(1.);
+
+               btVector3 sv = localGetSupportingVertex(vec*trans.getBasis());
+
+               btVector3 tmp = trans(sv);
+               maxAabb[i] = tmp[i]+margin;
+               vec[i] = btScalar(-1.);
+               tmp = trans(localGetSupportingVertex(vec*trans.getBasis()));
+               minAabb[i] = tmp[i]-margin;
+       }
+};
+
+
+btVector3      btConvexInternalShape::localGetSupportingVertex(const btVector3& vec)const
+{
+#ifndef __SPU__
+
+        btVector3      supVertex = localGetSupportingVertexWithoutMargin(vec);
+
+       if ( getMargin()!=btScalar(0.) )
+       {
+               btVector3 vecnorm = vec;
+               if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON))
+               {
+                       vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.));
+               } 
+               vecnorm.normalize();
+               supVertex+= getMargin() * vecnorm;
+       }
+       return supVertex;
+
+#else
+       return btVector3(0,0,0);
+#endif //__SPU__
+
+ }
+
+
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.h
new file mode 100644 (file)
index 0000000..9388ccf
--- /dev/null
@@ -0,0 +1,98 @@
+
+#ifndef BT_CONVEX_INTERNAL_SHAPE_H
+#define BT_CONVEX_INTERNAL_SHAPE_H
+
+#include "btConvexShape.h"
+
+///The btConvexInternalShape is an internal base class, shared by most convex shape implementations.
+class btConvexInternalShape : public btConvexShape
+{
+
+       protected:
+
+       //local scaling. collisionMargin is not scaled !
+       btVector3       m_localScaling;
+
+       btVector3       m_implicitShapeDimensions;
+       
+       btScalar        m_collisionMargin;
+
+       btScalar        m_padding;
+
+public:
+
+       btConvexInternalShape();
+
+       virtual ~btConvexInternalShape()
+       {
+
+       }
+
+
+       virtual btVector3       localGetSupportingVertex(const btVector3& vec)const;
+#ifndef __SPU__
+       virtual btVector3       localGetSupportingVertexWithoutMargin(const btVector3& vec) const= 0;
+       
+       //notice that the vectors should be unit length
+       virtual void    batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const= 0;
+#endif //#ifndef __SPU__
+
+       const btVector3& getImplicitShapeDimensions() const
+       {
+               return m_implicitShapeDimensions;
+       }
+
+       ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
+       void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+       {
+               getAabbSlow(t,aabbMin,aabbMax);
+       }
+
+
+       
+       virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+
+       virtual void    setLocalScaling(const btVector3& scaling);
+       virtual const btVector3& getLocalScaling() const 
+       {
+               return m_localScaling;
+       }
+
+       const btVector3& getLocalScalingNV() const 
+       {
+               return m_localScaling;
+       }
+
+       virtual void    setMargin(btScalar margin)
+       {
+               m_collisionMargin = margin;
+       }
+       virtual btScalar        getMargin() const
+       {
+               return m_collisionMargin;
+       }
+
+       btScalar        getMarginNV() const
+       {
+               return m_collisionMargin;
+       }
+
+       virtual int             getNumPreferredPenetrationDirections() const
+       {
+               return 0;
+       }
+       
+       virtual void    getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
+       {
+               (void)penetrationVector;
+               (void)index;
+               btAssert(0);
+       }
+
+
+       
+};
+
+
+#endif //BT_CONVEX_INTERNAL_SHAPE_H
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btMaterial.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btMaterial.h
new file mode 100644 (file)
index 0000000..7cb6d5a
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2008 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+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.
+*/
+
+/// This file was created by Alex Silverman
+
+#ifndef MATERIAL_H
+#define MATERIAL_H
+
+// Material class to be used by btMultimaterialTriangleMeshShape to store triangle properties
+class btMaterial
+{
+    // public members so that materials can change due to world events
+public:
+    btScalar m_friction;
+    btScalar m_restitution;
+    int pad[2];
+
+    btMaterial(){}
+    btMaterial(btScalar fric, btScalar rest) { m_friction = fric; m_restitution = rest; }
+};
+
+#endif // MATERIAL_H
\ No newline at end of file
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp
new file mode 100644 (file)
index 0000000..fc47e86
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2008 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+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.
+*/
+
+/// This file was created by Alex Silverman
+
+#include "BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h"
+#include "BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h"
+//#include "BulletCollision/CollisionShapes/btOptimizedBvh.h"
+
+
+///Obtains the material for a specific triangle
+const btMaterial * btMultimaterialTriangleMeshShape::getMaterialProperties(int partID, int triIndex)
+{
+    const unsigned char * materialBase = 0;
+    int numMaterials;
+    PHY_ScalarType materialType;
+    int materialStride;
+    const unsigned char * triangleMaterialBase = 0;
+    int numTriangles;
+    int triangleMaterialStride;
+    PHY_ScalarType triangleType;
+
+    ((btTriangleIndexVertexMaterialArray*)m_meshInterface)->getLockedReadOnlyMaterialBase(&materialBase, numMaterials, materialType, materialStride,
+        &triangleMaterialBase, numTriangles, triangleMaterialStride, triangleType, partID);
+
+    // return the pointer to the place with the friction for the triangle
+    // TODO: This depends on whether it's a moving mesh or not
+    // BUG IN GIMPACT
+    //return (btScalar*)(&materialBase[triangleMaterialBase[(triIndex-1) * triangleMaterialStride] * materialStride]);
+    int * matInd = (int *)(&(triangleMaterialBase[(triIndex * triangleMaterialStride)]));
+    btMaterial *matVal = (btMaterial *)(&(materialBase[*matInd * materialStride]));
+    return (matVal);
+}
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h
new file mode 100644 (file)
index 0000000..2f10802
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2008 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+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.
+*/
+
+/// This file was created by Alex Silverman
+
+#ifndef BVH_TRIANGLE_MATERIAL_MESH_SHAPE_H
+#define BVH_TRIANGLE_MATERIAL_MESH_SHAPE_H
+
+#include "btBvhTriangleMeshShape.h"
+#include "btMaterial.h"
+
+///The BvhTriangleMaterialMeshShape extends the btBvhTriangleMeshShape. Its main contribution is the interface into a material array, which allows per-triangle friction and restitution.
+ATTRIBUTE_ALIGNED16(class) btMultimaterialTriangleMeshShape : public btBvhTriangleMeshShape
+{
+    btAlignedObjectArray <btMaterial*> m_materialList;
+    int ** m_triangleMaterials;
+
+public:
+
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+    btMultimaterialTriangleMeshShape(): btBvhTriangleMeshShape() {}
+    btMultimaterialTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh = true):
+        btBvhTriangleMeshShape(meshInterface, useQuantizedAabbCompression, buildBvh)
+        {
+            btVector3 m_triangle[3];
+            const unsigned char *vertexbase;
+            int numverts;
+            PHY_ScalarType type;
+            int stride;
+            const unsigned char *indexbase;
+            int indexstride;
+            int numfaces;
+            PHY_ScalarType indicestype;
+
+            //m_materialLookup = (int**)(btAlignedAlloc(sizeof(int*) * meshInterface->getNumSubParts(), 16));
+
+            for(int i = 0; i < meshInterface->getNumSubParts(); i++)
+            {
+                m_meshInterface->getLockedReadOnlyVertexIndexBase(
+                    &vertexbase,
+                    numverts,
+                    type,
+                    stride,
+                    &indexbase,
+                    indexstride,
+                    numfaces,
+                    indicestype,
+                    i);
+                //m_materialLookup[i] = (int*)(btAlignedAlloc(sizeof(int) * numfaces, 16));
+            }
+        }
+
+       ///optionally pass in a larger bvh aabb, used for quantization. This allows for deformations within this aabb
+       btMultimaterialTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax, bool buildBvh = true):
+        btBvhTriangleMeshShape(meshInterface, useQuantizedAabbCompression, bvhAabbMin, bvhAabbMax, buildBvh)
+        {
+            btVector3 m_triangle[3];
+            const unsigned char *vertexbase;
+            int numverts;
+            PHY_ScalarType type;
+            int stride;
+            const unsigned char *indexbase;
+            int indexstride;
+