diff --git a/src/BulletCollision/BroadphaseCollision/btDbvt.cpp b/src/BulletCollision/BroadphaseCollision/btDbvt.cpp index de3f28f76..985dd8133 100644 --- a/src/BulletCollision/BroadphaseCollision/btDbvt.cpp +++ b/src/BulletCollision/BroadphaseCollision/btDbvt.cpp @@ -160,8 +160,7 @@ if(leaf==pdbvt->m_root) Merge(prev->childs[0]->volume,prev->childs[1]->volume,prev->volume); if(NotEqual(pb,prev->volume)) { - sibling = prev; - prev = prev->parent; + prev=prev->parent; } else break; } return(prev?prev:pdbvt->m_root); @@ -177,25 +176,25 @@ if(leaf==pdbvt->m_root) } // -static void fetchleafs( btDbvt* pdbvt, +static void fetchleaves(btDbvt* pdbvt, btDbvt::Node* root, - tNodeArray& leafs, + tNodeArray& leaves, int depth=-1) { if(root->isinternal()&&depth) { - fetchleafs(pdbvt,root->childs[0],leafs,depth-1); - fetchleafs(pdbvt,root->childs[1],leafs,depth-1); + fetchleaves(pdbvt,root->childs[0],leaves,depth-1); + fetchleaves(pdbvt,root->childs[1],leaves,depth-1); deletenode(pdbvt,root); } else { - leafs.push_back(root); + leaves.push_back(root); } } // -static void split( const tNodeArray& leafs, +static void split( const tNodeArray& leaves, tNodeArray& left, tNodeArray& right, const btVector3& org, @@ -203,39 +202,39 @@ static void split( const tNodeArray& leafs, { left.resize(0); right.resize(0); -for(int i=0,ni=leafs.size();ivolume.Center()-org)<0) - left.push_back(leafs[i]); + if(dot(axis,leaves[i]->volume.Center()-org)<0) + left.push_back(leaves[i]); else - right.push_back(leafs[i]); + right.push_back(leaves[i]); } } // -static btDbvt::Volume bounds( const tNodeArray& leafs) +static btDbvt::Volume bounds( const tNodeArray& leaves) { -btDbvt::Volume volume=leafs[0]->volume; -for(int i=1,ni=leafs.size();ivolume; +for(int i=1,ni=leaves.size();ivolume); + volume=merge(volume,leaves[i]->volume); } return(volume); } // static void bottomup( btDbvt* pdbvt, - tNodeArray& leafs) + tNodeArray& leaves) { -while(leafs.size()>1) +while(leaves.size()>1) { btScalar minsize=SIMD_INFINITY; int minidx[2]={-1,-1}; - for(int i=0;ivolume,leafs[j]->volume)); + const btScalar sz=size(merge(leaves[i]->volume,leaves[j]->volume)); if(sz1) } } } - btDbvt::Node* n[] = {leafs[minidx[0]],leafs[minidx[1]]}; + btDbvt::Node* n[] = {leaves[minidx[0]],leaves[minidx[1]]}; btDbvt::Node* p = createnode(pdbvt,0,merge(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; - leafs[minidx[0]] = p; - leafs.swap(minidx[1],leafs.size()-1); - leafs.pop_back(); + leaves[minidx[0]] = p; + leaves.swap(minidx[1],leaves.size()-1); + leaves.pop_back(); } } // static btDbvt::Node* topdown(btDbvt* pdbvt, - tNodeArray& leafs, + tNodeArray& leaves, int bu_treshold) { static const btVector3 axis[]={btVector3(1,0,0), btVector3(0,1,0), btVector3(0,0,1)}; -if(leafs.size()>1) +if(leaves.size()>1) { - if(leafs.size()>bu_treshold) + if(leaves.size()>bu_treshold) { - const btDbvt::Volume vol=bounds(leafs); + const btDbvt::Volume vol=bounds(leaves); const btVector3 org=vol.Center(); tNodeArray sets[2]; int bestaxis=-1; - int bestmidp=leafs.size(); + int bestmidp=leaves.size(); int splitcount[3][2]={{0,0},{0,0},{0,0}}; - for(int i=0;ivolume.Center()-org; + const btVector3 x=leaves[i]->volume.Center()-org; for(int j=0;j<3;++j) { ++splitcount[j][dot(x,axis[j])>0?1:0]; @@ -298,15 +297,15 @@ if(leafs.size()>1) { sets[0].reserve(splitcount[bestaxis][0]); sets[1].reserve(splitcount[bestaxis][1]); - split(leafs,sets[0],sets[1],org,axis[bestaxis]); + split(leaves,sets[0],sets[1],org,axis[bestaxis]); } else { - sets[0].reserve(leafs.size()/2+1); - sets[1].reserve(leafs.size()/2); - for(int i=0,ni=leafs.size();i1) } else { - bottomup(pdbvt,leafs); - return(leafs[0]); + bottomup(pdbvt,leaves); + return(leaves[0]); } } -return(leafs[0]); +return(leaves[0]); } // -static inline btDbvt::Node* refit( btDbvt* pdbvt, - btDbvt::Node* node) +static inline btDbvt::Node* sort(btDbvt::Node* n,btDbvt::Node*& r) { -btDbvt::Node* parent=node->parent; -if(parent) +btDbvt::Node* p=n->parent; +btAssert(n->isinternal()); +if(p>n) { - const int idx=indexof(node); - tNodeArray leafs; - leafs.reserve(64); - fetchleafs(pdbvt,node,leafs,3); - if(leafs.size()>=2) - { - bottomup(pdbvt,leafs); - node=leafs[0]; - node->parent=parent; - parent->childs[idx]=node; - } + const int i=indexof(n); + const int j=1-i; + btDbvt::Node* s=p->childs[j]; + btDbvt::Node* 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(node); +return(n); +} + +// +static inline btDbvt::Node* walkup(btDbvt::Node* n,int count) +{ +while(n&&(count--)) n=n->parent; +return(n); } // @@ -354,11 +366,11 @@ return(node); // btDbvt::btDbvt() { -m_root = 0; -m_free = 0; -m_lkhd = -1; -m_leafs = 0; -m_opath = 0; +m_root = 0; +m_free = 0; +m_lkhd = -1; +m_leaves = 0; +m_opath = 0; } // @@ -380,11 +392,11 @@ void btDbvt::optimizeBottomUp() { if(m_root) { - tNodeArray leafs; - leafs.reserve(m_leafs); - fetchleafs(this,m_root,leafs); - bottomup(this,leafs); - m_root=leafs[0]; + tNodeArray leaves; + leaves.reserve(m_leaves); + fetchleaves(this,m_root,leaves); + bottomup(this,leaves); + m_root=leaves[0]; } } @@ -393,16 +405,17 @@ void btDbvt::optimizeTopDown(int bu_treshold) { if(m_root) { - tNodeArray leafs; - leafs.reserve(m_leafs); - fetchleafs(this,m_root,leafs); - m_root=topdown(this,leafs,bu_treshold); + 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 { @@ -410,7 +423,7 @@ if(m_root&&(passes>0)) unsigned bit=0; while(node->isinternal()) { - node=node->childs[(m_opath>>bit)&1]; + node=sort(node,m_root)->childs[(m_opath>>bit)&1]; bit=(bit+1)&(sizeof(unsigned)*8-1); } update(node); @@ -424,7 +437,7 @@ btDbvt::Node* btDbvt::insert(const Volume& volume,void* data) { Node* leaf=createnode(this,0,volume,data); insertleaf(this,m_root,leaf); -++m_leafs; +++m_leaves; return(leaf); } @@ -496,14 +509,14 @@ void btDbvt::remove(Node* leaf) { removeleaf(this,leaf); deletenode(this,leaf); ---m_leafs; +--m_leaves; } // void btDbvt::write(IWriter* iwriter) const { btDbvtNodeEnumerator nodes; -nodes.nodes.reserve(m_leafs*2); +nodes.nodes.reserve(m_leaves*2); enumNodes(m_root,nodes); iwriter->Prepare(m_root,nodes.nodes.size()); for(int i=0;i stack; + stack.reserve(m_leaves); + stack.push_back(sStkCLN(m_root,0)); + do { + const int i=stack.size()-1; + const sStkCLN e=stack[i]; + Node* 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::countLeaves(const Node* node) +{ +if(node->isinternal()) + return(countLeaves(node->childs[0])+countLeaves(node->childs[1])); + else + return(1); +} + +// +void btDbvt::extractLeaves(const Node* node,btAlignedObjectArray& leaves) +{ +if(node->isinternal()) + { + extractLeaves(node->childs[0],leaves); + extractLeaves(node->childs[1],leaves); + } + else + { + leaves.push_back(node); + } +} + +// +#if DBVT_ENABLE_BENCHMARK + +#include +#include +#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 +[1] btDbvt::Volume intersections: 3986 ms (0%) +[2] btDbvt::Volume merges: 5815 ms (-1%) +[3] btDbvt::collideTT: 3267 ms (0%) +[4] btDbvt::collideTT self: 1657 ms (0%) +[5] btDbvt::collideTT xform: 7201 ms (0%) +[6] btDbvt::collideTT xform,self: 7382 ms (0%) +[7] btDbvt::collideRAY: 8855 ms (-1%),(236832 r/s) +[8] insert/remove: 3574 ms (0%),(586780 ir/s) +[9] updates (teleport): 3281 ms (0%),(639180 u/s) +[10] updates (jitter): 2658 ms (0%),(788996 u/s) +[11] optimize (incremental): 5091 ms (0%),(823000 o/s) +[12] btDbvt::Volume notequal: 4151 ms (0%) +[13] culling(OCL): 2486 ms (0%),(411 t/s) +[14] culling(OCL+qsort): 599 ms (-2%),(1709 t/s) +[15] culling(KDOP+qsort): 306 ms (0%),(3346 t/s) +*/ + +struct btDbvtBenchmark +{ +struct NilPolicy : btDbvt::ICollide + { + NilPolicy() : m_pcount(0),m_depth(-SIMD_INFINITY),m_checksort(true) {} + void Process(const btDbvt::Node*,const btDbvt::Node*) { ++m_pcount; } + void Process(const btDbvt::Node*) { ++m_pcount; } + void Process(const btDbvt::Node*,btScalar depth) + { + ++m_pcount; + if(m_checksort) + { if(depth>=m_depth) m_depth=depth; else printf("wrong depth: %f\r\n",depth); } + } + int m_pcount; + btScalar m_depth; + bool m_checksort; + }; +struct P14 : btDbvt::ICollide + { + struct Node + { + const btDbvt::Node* leaf; + btScalar depth; + }; + void Process(const btDbvt::Node* leaf,btScalar depth) + { + Node n; + n.leaf = leaf; + n.depth = depth; + } + static int sortfnc(const Node& a,const Node& b) + { + if(a.depthb.depth) return(-1); + return(0); + } + btAlignedObjectArray m_nodes; + }; +struct P15 : btDbvt::ICollide + { + struct Node + { + const btDbvt::Node* leaf; + btScalar depth; + }; + void Process(const btDbvt::Node* 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.depthb.depth) return(-1); + return(0); + } + btAlignedObjectArray 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 btDbvt::Volume RandVolume(btScalar cs,btScalar eb,btScalar es) + { + return(btDbvt::Volume::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 volumes; + btAlignedObjectArray results; + volumes.resize(cfgLeaves); + results.resize(cfgLeaves); + for(int i=0;i volumes; + btAlignedObjectArray results; + volumes.resize(cfgLeaves); + results.resize(cfgLeaves); + for(int i=0;i transforms; + btDbvtBenchmark::NilPolicy policy; + transforms.resize(cfgBenchmark5_Iterations); + for(int i=0;i transforms; + btDbvtBenchmark::NilPolicy policy; + transforms.resize(cfgBenchmark6_Iterations); + for(int i=0;i rayorg; + btAlignedObjectArray raydir; + btDbvtBenchmark::NilPolicy policy; + rayorg.resize(cfgBenchmark7_Iterations); + raydir.resize(cfgBenchmark7_Iterations); + for(int i=0;i 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(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 leaves; + btAlignedObjectArray vectors; + vectors.resize(cfgBenchmark10_Iterations); + for(int i=0;i(leaves[rand()%cfgLeaves]); + btDbvt::Volume v=btDbvt::Volume::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 volumes; + btAlignedObjectArray results; + volumes.resize(cfgLeaves); + results.resize(cfgLeaves); + for(int i=0;i vectors; + btDbvtBenchmark::NilPolicy policy; + vectors.resize(cfgBenchmark13_Iterations); + for(int i=0;i vectors; + btDbvtBenchmark::P14 policy; + vectors.resize(cfgBenchmark14_Iterations); + for(int i=0;i vectors; + btDbvtBenchmark::P15 policy; + vectors.resize(cfgBenchmark15_Iterations); + for(int i=0;i -#define DBVT_IPOLICY T& policy -#define DBVT_CHECKTYPE static const ICollide& typechecker=*(T*)0; +#define DBVT_VIRTUAL_DTOR(a) +#define DBVT_PREFIX template +#define DBVT_IPOLICY T& policy +#define DBVT_CHECKTYPE static const ICollide& typechecker=*(T*)0; #else -#define DBVT_VIRTUAL_DESTRUCTOR(a) virtual ~a() {} -#define DBVT_VIRTUAL virtual +#define DBVT_VIRTUAL_DTOR(a) virtual ~a() {} +#define DBVT_VIRTUAL virtual #define DBVT_PREFIX -#define DBVT_IPOLICY ICollide& policy +#define DBVT_IPOLICY ICollide& policy #define DBVT_CHECKTYPE #endif +#if DBVT_USE_MEMMOVE +#include +#include +#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 + // // Defaults volumes // @@ -50,10 +77,10 @@ subject to the following restrictions: struct btDbvtAabbMm { inline btVector3 Center() const { return((mi+mx)/2); } -inline btVector3 Extent() const { return((mx-mi)/2); } +inline btVector3 Lengths() const { return(mx-mi); } +inline btVector3 Extents() const { return((mx-mi)/2); } inline const btVector3& Mins() const { return(mi); } inline const btVector3& Maxs() const { return(mx); } -inline btVector3 Lengths() const { return(mx-mi); } 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); @@ -66,6 +93,9 @@ inline int Classify(const btVector3& n,btScalar o,int s) const; inline btScalar ProjectMinimum(const btVector3& v,unsigned signs) const; inline friend bool Intersect( const btDbvtAabbMm& a, const btDbvtAabbMm& b); +inline friend bool Intersect( const btDbvtAabbMm& a, + const btDbvtAabbMm& b, + const btTransform& xform); inline friend bool Intersect( const btDbvtAabbMm& a, const btVector3& b); inline friend bool Intersect( const btDbvtAabbMm& a, @@ -80,6 +110,8 @@ inline friend void Merge( const btDbvtAabbMm& a, inline friend bool NotEqual( const btDbvtAabbMm& a, const btDbvtAabbMm& b); private: +inline void AddSpan(const btVector3& d,btScalar& smi,btScalar& smx) const; +private: btVector3 mi,mx; }; @@ -112,26 +144,34 @@ struct btDbvt struct sStkNP { const Node* node; - int mask; + int mask; sStkNP(const Node* n,unsigned m) : node(n),mask(m) {} }; struct sStkNPS { const Node* node; - int mask; + int mask; btScalar value; + sStkNPS() {} sStkNPS(const Node* n,unsigned m,btScalar v) : node(n),mask(m),value(v) {} }; + struct sStkCLN + { + const Node* node; + Node* parent; + sStkCLN(const Node* n,Node* p) : node(n),parent(p) {} + }; // Policies/Interfaces /* ICollide */ struct ICollide { - DBVT_VIRTUAL_DESTRUCTOR(ICollide) + DBVT_VIRTUAL_DTOR(ICollide) DBVT_VIRTUAL void Process(const Node*,const Node*) {} DBVT_VIRTUAL void Process(const Node*) {} + DBVT_VIRTUAL void Process(const Node* n,btScalar) { Process(n); } DBVT_VIRTUAL bool Descent(const Node*) { return(true); } - DBVT_VIRTUAL bool AllLeafs(const Node*) { return(true); } + DBVT_VIRTUAL bool AllLeaves(const Node*) { return(true); } }; /* IWriter */ struct IWriter @@ -141,6 +181,12 @@ struct btDbvt virtual void WriteNode(const Node*,int index,int parent,int child0,int child1)=0; virtual void WriteLeaf(const Node*,int index,int parent)=0; }; + /* IClone */ + struct IClone + { + virtual ~IClone() {} + virtual void CloneLeaf(Node*) {} + }; // Constants enum { @@ -152,7 +198,7 @@ struct btDbvt Node* m_root; Node* m_free; int m_lkhd; - int m_leafs; + int m_leaves; unsigned m_opath; // Methods btDbvt(); @@ -167,21 +213,40 @@ struct btDbvt void update(Node* leaf,const Volume& volume); bool update(Node* leaf,Volume volume,const btVector3& velocity,btScalar margin); bool update(Node* leaf,Volume volume,const btVector3& velocity); - bool update(Node* leaf,Volume volume,btScalar margin); + bool update(Node* leaf,Volume volume,btScalar margin); void remove(Node* leaf); void write(IWriter* iwriter) const; + void clone(btDbvt& dest,IClone* iclone=0) const; + static int countLeaves(const Node* node); + static void extractLeaves(const Node* node,btAlignedObjectArray& 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 Node* root, DBVT_IPOLICY); DBVT_PREFIX - static void enumLeafs( const Node* root, + static void enumLeaves( const Node* root, DBVT_IPOLICY); DBVT_PREFIX static void collideTT( const Node* root0, const Node* root1, DBVT_IPOLICY); DBVT_PREFIX + static void collideTT( const Node* root0, + const Node* root1, + const btTransform& xform, + DBVT_IPOLICY); + DBVT_PREFIX + static void collideTT( const Node* root0, + const btTransform& xform0, + const Node* root1, + const btTransform& xform1, + DBVT_IPOLICY); + DBVT_PREFIX static void collideTV( const Node* root, const Volume& volume, DBVT_IPOLICY); @@ -202,13 +267,36 @@ struct btDbvt const btScalar* offsets, const btVector3& sortaxis, int count, - DBVT_IPOLICY); + DBVT_IPOLICY, + bool fullsort=true); DBVT_PREFIX static void collideTU( const Node* root, DBVT_IPOLICY); + // Helpers + static inline int nearest(const int* i,const btDbvt::sStkNPS* a,btScalar v,int l,int h) + { + int m=0; + while(l>1; + if(a[i[m]].value>=v) l=m+1; else h=m; + } + return(h); + } + static inline int allocate( btAlignedObjectArray& ifree, + btAlignedObjectArray& stock, + const btDbvt::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&) {} + btDbvt(const btDbvt&) {} }; // @@ -325,31 +413,45 @@ const btVector3 p( b[(signs>>0)&1]->x(), b[(signs>>2)&1]->z()); return(dot(p,v)); } + +// +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]; } + } +} // inline bool Intersect( const btDbvtAabbMm& a, const btDbvtAabbMm& b) { -#if 0 -const btScalar mi[]={ b.mx.x()-a.mi.x(), - b.mx.y()-a.mi.y(), - b.mx.z()-a.mi.z()}; -const unsigned* imi=(const unsigned*)mi; -if((imi[0]|imi[1]|imi[2])&0x80000000) return(false); -const btScalar mx[]={ a.mx.x()-b.mi.x(), - a.mx.y()-b.mi.y(), - a.mx.z()-b.mi.z()}; -const unsigned* imx=(const unsigned*)mx; -if((imx[0]|imx[1]|imx[2])&0x80000000) return(false); -return(true); -#else return( (a.mi.x()<=b.mx.x())&& - (a.mi.y()<=b.mx.y())&& - (a.mi.z()<=b.mx.z())&& (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 +} + +// +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); } // @@ -399,9 +501,11 @@ inline void Merge( const btDbvtAabbMm& a, const btDbvtAabbMm& b, btDbvtAabbMm& r) { -r=a; -r.mi.setMin(b.mi); -r.mx.setMax(b.mx); +for(int i=0;i<3;++i) + { + if(a.mi[i]b.mx[i]) r.mx[i]=a.mx[i]; else r.mx[i]=b.mx[i]; + } } // @@ -436,14 +540,14 @@ if(root->isinternal()) // DBVT_PREFIX -inline void btDbvt::enumLeafs( const Node* root, +inline void btDbvt::enumLeaves( const Node* root, DBVT_IPOLICY) { DBVT_CHECKTYPE if(root->isinternal()) { - enumLeafs(root->childs[0],policy); - enumLeafs(root->childs[1],policy); + enumLeaves(root->childs[0],policy); + enumLeaves(root->childs[1],policy); } else { @@ -509,6 +613,68 @@ if(root0&&root1) } } +// +DBVT_PREFIX +inline void btDbvt::collideTT( const Node* root0, + const Node* root1, + const btTransform& xform, + DBVT_IPOLICY) +{ +DBVT_CHECKTYPE +if(root0&&root1) + { + btAlignedObjectArray stack; + stack.reserve(DOUBLE_STACKSIZE); + stack.push_back(sStkNN(root0,root1)); + do { + sStkNN p=stack[stack.size()-1]; + stack.pop_back(); + if(Intersect(p.a->volume,p.b->volume,xform)) + { + if(p.a->isinternal()) + { + if(p.b->isinternal()) + { + stack.push_back(sStkNN(p.a->childs[0],p.b->childs[0])); + stack.push_back(sStkNN(p.a->childs[1],p.b->childs[0])); + stack.push_back(sStkNN(p.a->childs[0],p.b->childs[1])); + stack.push_back(sStkNN(p.a->childs[1],p.b->childs[1])); + } + else + { + stack.push_back(sStkNN(p.a->childs[0],p.b)); + stack.push_back(sStkNN(p.a->childs[1],p.b)); + } + } + else + { + if(p.b->isinternal()) + { + stack.push_back(sStkNN(p.a,p.b->childs[0])); + stack.push_back(sStkNN(p.a,p.b->childs[1])); + } + else + { + policy.Process(p.a,p.b); + } + } + } + } while(stack.size()>0); + } +} + +// +DBVT_PREFIX +inline void btDbvt::collideTT( const Node* root0, + const btTransform& xform0, + const Node* root1, + const btTransform& xform1, + DBVT_IPOLICY) +{ +const btTransform xform=xform0.inverse()*xform1; +collideTT(root0,root1,xform,policy); +} + // DBVT_PREFIX inline void btDbvt::collideTV( const Node* root, @@ -627,7 +793,7 @@ if(root) } else { - if(policy.AllLeafs(se.node)) enumLeafs(se.node,policy); + if(policy.AllLeaves(se.node)) enumLeaves(se.node,policy); } } } while(stack.size()); @@ -641,7 +807,8 @@ inline void btDbvt::collideOCL( const Node* root, const btScalar* offsets, const btVector3& sortaxis, int count, - DBVT_IPOLICY) + DBVT_IPOLICY, + bool fsort) { DBVT_CHECKTYPE if(root) @@ -650,7 +817,9 @@ if(root) (sortaxis[1]>=0?2:0)+ (sortaxis[2]>=0?4:0); const int inside=(1< stack; + btAlignedObjectArray stock; + btAlignedObjectArray ifree; + btAlignedObjectArray stack; int signs[sizeof(unsigned)*8]; btAssert(count<(sizeof(signs)/sizeof(signs[0]))); for(int i=0;i=0)?2:0)+ ((normals[i].z()>=0)?4:0); } + stock.reserve(SIMPLE_STACKSIZE); stack.reserve(SIMPLE_STACKSIZE); - stack.push_back(sStkNPS(root,0,root->volume.ProjectMinimum(sortaxis,srtsgns))); + ifree.reserve(SIMPLE_STACKSIZE); + stack.push_back(allocate(ifree,stock,sStkNPS(root,0,root->volume.ProjectMinimum(sortaxis,srtsgns)))); do { - sStkNPS se=stack[stack.size()-1]; - stack.pop_back(); + 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; @@ -685,21 +857,41 @@ if(root) { if(se.node->isinternal()) { - for(int i=0;i<2;++i) + const Node* 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].value0)) { - const Node* n=se.node->childs[i]; - int j=stack.size(); - sStkNPS ne(n,se.mask,n->volume.ProjectMinimum(sortaxis,srtsgns)); - stack.push_back(ne); - while((j>0)&&(ne.value>stack[j-1].value)) - { - btSwap(stack[j],stack[j-1]);--j; - } + /* 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); + policy.Process(se.node,se.value); } } } while(stack.size()); @@ -735,10 +927,9 @@ if(root) // PP Cleanup // -#ifdef DBVT_USE_TEMPLATE - #undef DBVT_USE_TEMPLATE -#endif -#undef DBVT_VIRTUAL_DESTRUCTOR +#undef DBVT_USE_MEMMOVE +#undef DBVT_USE_TEMPLATE +#undef DBVT_VIRTUAL_DTOR #undef DBVT_VIRTUAL #undef DBVT_PREFIX #undef DBVT_IPOLICY diff --git a/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp b/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp index c8a15b108..23f2ca8e9 100644 --- a/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp +++ b/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp @@ -1,3 +1,19 @@ +/* +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" // @@ -120,7 +136,9 @@ void Process(const btDbvt::Node* na,const btDbvt::Node* nb) // btDbvtBroadphase::btDbvtBroadphase(btOverlappingPairCache* paircache) { +btDbvt::benchmark(); m_releasepaircache = (paircache!=0)?false:true; +m_predictedframes = 2; m_stageCurrent = 0; m_fupdates = 1; m_dupdates = 1; @@ -198,9 +216,9 @@ if(proxy->stage==STAGECOUNT) {/* Moving */ const btVector3 delta=(aabbMin+aabbMax)/2-proxy->aabb.Center(); #ifdef DBVT_BP_MARGIN - m_sets[0].update(proxy->leaf,aabb,delta*PREDICTED_FRAMES,DBVT_BP_MARGIN); + m_sets[0].update(proxy->leaf,aabb,delta*m_predictedframes,DBVT_BP_MARGIN); #else - m_sets[0].update(proxy->leaf,aabb,delta*PREDICTED_FRAMES); + m_sets[0].update(proxy->leaf,aabb,delta*m_predictedframes); #endif } else @@ -246,8 +264,8 @@ void btDbvtBroadphase::collide(btDispatcher* dispatcher) { SPC(m_profiling.m_total); /* optimize */ -m_sets[0].optimizeIncremental(1+(m_sets[0].m_leafs*m_dupdates)/100); -m_sets[1].optimizeIncremental(1+(m_sets[1].m_leafs*m_fupdates)/100); +m_sets[0].optimizeIncremental(1+(m_sets[0].m_leaves*m_dupdates)/100); +m_sets[1].optimizeIncremental(1+(m_sets[1].m_leaves*m_fupdates)/100); /* dynamic -> fixed set */ m_stageCurrent=(m_stageCurrent+1)%STAGECOUNT; btDbvtProxy* current=m_stageRoots[m_stageCurrent]; diff --git a/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h b/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h index d78e13394..874ed11ce 100644 --- a/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h +++ b/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h @@ -62,12 +62,12 @@ enum { DYNAMIC_SET = 0, /* Dynamic set index */ FIXED_SET = 1, /* Fixed set index */ STAGECOUNT = 2, /* Number of stages */ - PREDICTED_FRAMES = 2 /* Frames prediction */ }; /* Fields */ btDbvt m_sets[2]; // Dbvt sets btDbvtProxy* m_stageRoots[STAGECOUNT+1]; // Stages list btOverlappingPairCache* m_paircache; // Pair cache +btScalar m_predictedframes; // Frames predicted int m_stageCurrent; // Current stage int m_fupdates; // % of fixed updates per frame int m_dupdates; // % of dynamic updates per frame @@ -100,4 +100,3 @@ void printStats(); }; #endif - diff --git a/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp b/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp index a01836d48..bf1c01401 100644 --- a/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp +++ b/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp @@ -772,16 +772,17 @@ return(sizeof(GJK)+sizeof(EPA)); } // -btScalar btGjkEpaSolver2::Distance( const btConvexShape* shape0, +bool btGjkEpaSolver2::Distance( const btConvexShape* shape0, const btTransform& wtrs0, const btConvexShape* shape1, const btTransform& wtrs1, + const btVector3& guess, sResults& results) { tShape shape; Initialize(shape0,wtrs0,shape1,wtrs1,results,shape,false); -GJK gjk; -GJK::eStatus::_ gjk_status=gjk.Evaluate(shape,btVector3(1,1,1)); +GJK gjk; +GJK::eStatus::_ gjk_status=gjk.Evaluate(shape,guess); if(gjk_status==GJK::eStatus::Valid) { btVector3 w0=btVector3(0,0,0); @@ -794,17 +795,62 @@ if(gjk_status==GJK::eStatus::Valid) } results.witnesses[0] = wtrs0*w0; results.witnesses[1] = wtrs0*w1; - return((w0-w1).length()); + results.normal = w0-w1; + results.distance = results.normal.length(); + results.normal /= results.distance>GJK_MIN_DISTANCE?results.distance:1; + return(true); } else { results.status = gjk_status==GJK::eStatus::Inside? sResults::Penetrating : sResults::GJK_Failed ; - return(-1); + return(false); } } +// +bool btGjkEpaSolver2::Penetration( const btConvexShape* shape0, + const btTransform& wtrs0, + const btConvexShape* shape1, + const btTransform& wtrs1, + const btVector3& guess, + sResults& results, + bool usemargins) +{ +tShape shape; +Initialize(shape0,wtrs0,shape1,wtrs1,results,shape,usemargins); +GJK gjk; +GJK::eStatus::_ gjk_status=gjk.Evaluate(shape,-guess); +switch(gjk_status) + { + case GJK::eStatus::Inside: + { + EPA epa; + EPA::eStatus::_ epa_status=epa.Evaluate(gjk,-guess); + if(epa_status!=EPA::eStatus::Failed) + { + btVector3 w0=btVector3(0,0,0); + for(U i=0;id,0)*epa.m_result.p[i]; + } + results.status = sResults::Penetrating; + results.witnesses[0] = wtrs0*w0; + results.witnesses[1] = wtrs0*(w0-epa.m_normal*epa.m_depth); + results.normal = -epa.m_normal; + results.distance = -epa.m_depth; + return(true); + } else results.status=sResults::EPA_Failed; + } + break; + case GJK::eStatus::Failed: + results.status=sResults::GJK_Failed; + break; + } +return(false); +} + // btScalar btGjkEpaSolver2::SignedDistance(const btVector3& position, btScalar margin, @@ -857,42 +903,17 @@ return(SIMD_INFINITY); } // -bool btGjkEpaSolver2::Penetration( const btConvexShape* shape0, +bool btGjkEpaSolver2::SignedDistance(const btConvexShape* shape0, const btTransform& wtrs0, const btConvexShape* shape1, const btTransform& wtrs1, const btVector3& guess, sResults& results) { -tShape shape; -Initialize(shape0,wtrs0,shape1,wtrs1,results,shape,true); -GJK gjk; -GJK::eStatus::_ gjk_status=gjk.Evaluate(shape,-guess); -switch(gjk_status) - { - case GJK::eStatus::Inside: - { - EPA epa; - EPA::eStatus::_ epa_status=epa.Evaluate(gjk,-guess); - if(epa_status!=EPA::eStatus::Failed) - { - btVector3 w0=btVector3(0,0,0); - for(U i=0;id,0)*epa.m_result.p[i]; - } - results.status = sResults::Penetrating; - results.witnesses[0] = wtrs0*w0; - results.witnesses[1] = wtrs0*(w0-epa.m_normal*epa.m_depth); - return(true); - } else results.status=sResults::EPA_Failed; - } - break; - case GJK::eStatus::Failed: - results.status=sResults::GJK_Failed; - break; - } -return(false); +if(!Distance(shape0,wtrs0,shape1,wtrs1,guess,results)) + return(Penetration(shape0,wtrs0,shape1,wtrs1,guess,results,false)); + else + return(true); } /* Symbols cleanup */ diff --git a/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h b/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h index b1d95bc58..ff083ba41 100644 --- a/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h +++ b/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h @@ -40,24 +40,32 @@ struct sResults } status; btVector3 witnesses[2]; btVector3 normal; + btScalar distance; }; static int StackSizeRequirement(); -static btScalar Distance( const btConvexShape* shape0,const btTransform& wtrs0, +static bool Distance( const btConvexShape* shape0,const btTransform& wtrs0, const btConvexShape* shape1,const btTransform& wtrs1, - sResults& results); - + const btVector3& guess, + sResults& results); + +static bool Penetration(const btConvexShape* shape0,const btTransform& wtrs0, + const btConvexShape* shape1,const btTransform& wtrs1, + const btVector3& guess, + sResults& results, + bool usemargins=true); + static btScalar SignedDistance( const btVector3& position, btScalar margin, const btConvexShape* shape, const btTransform& wtrs, sResults& results); - -static bool Penetration(const btConvexShape* shape0,const btTransform& wtrs0, - const btConvexShape* shape1,const btTransform& wtrs1, - const btVector3& guess, - sResults& results); + +static bool SignedDistance( const btConvexShape* shape0,const btTransform& wtrs0, + const btConvexShape* shape1,const btTransform& wtrs1, + const btVector3& guess, + sResults& results); }; #endif diff --git a/src/BulletSoftBody/btSoftBodyHelpers.cpp b/src/BulletSoftBody/btSoftBodyHelpers.cpp index a85b63526..ef73baeb3 100644 --- a/src/BulletSoftBody/btSoftBodyHelpers.cpp +++ b/src/BulletSoftBody/btSoftBodyHelpers.cpp @@ -1,83 +1,83 @@ -/* -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. -*/ -///btSoftBodyHelpers.cpp by Nathanael Presson - -#include "btSoftBody.h" -#include -#include -#include "btSoftBodyHelpers.h" -#include "LinearMath/btConvexHull.h" - -// -static void drawVertex( btIDebugDraw* idraw, - const btVector3& x,btScalar s,const btVector3& c) - { - idraw->drawLine(x-btVector3(s,0,0),x+btVector3(s,0,0),c); - idraw->drawLine(x-btVector3(0,s,0),x+btVector3(0,s,0),c); - idraw->drawLine(x-btVector3(0,0,s),x+btVector3(0,0,s),c); - } - -// -static void drawBox( btIDebugDraw* idraw, - const btVector3& mins, - const btVector3& maxs, - const btVector3& color) -{ -const btVector3 c[]={ btVector3(mins.x(),mins.y(),mins.z()), - btVector3(maxs.x(),mins.y(),mins.z()), - btVector3(maxs.x(),maxs.y(),mins.z()), - btVector3(mins.x(),maxs.y(),mins.z()), - btVector3(mins.x(),mins.y(),maxs.z()), - btVector3(maxs.x(),mins.y(),maxs.z()), - btVector3(maxs.x(),maxs.y(),maxs.z()), - btVector3(mins.x(),maxs.y(),maxs.z())}; -idraw->drawLine(c[0],c[1],color);idraw->drawLine(c[1],c[2],color); -idraw->drawLine(c[2],c[3],color);idraw->drawLine(c[3],c[0],color); -idraw->drawLine(c[4],c[5],color);idraw->drawLine(c[5],c[6],color); -idraw->drawLine(c[6],c[7],color);idraw->drawLine(c[7],c[4],color); -idraw->drawLine(c[0],c[4],color);idraw->drawLine(c[1],c[5],color); -idraw->drawLine(c[2],c[6],color);idraw->drawLine(c[3],c[7],color); -} - -// -static void drawTree( btIDebugDraw* idraw, - const btDbvt::Node* node, - int depth, - const btVector3& ncolor, - const btVector3& lcolor, - int mindepth, - int maxdepth) -{ -if(node) - { - if(node->isinternal()&&((depthchilds[0],depth+1,ncolor,lcolor,mindepth,maxdepth); - drawTree(idraw,node->childs[1],depth+1,ncolor,lcolor,mindepth,maxdepth); - } - if(depth>=mindepth) - { - const btScalar scl=(btScalar)(node->isinternal()?1:1); - const btVector3 mi=node->volume.Center()-node->volume.Extent()*scl; - const btVector3 mx=node->volume.Center()+node->volume.Extent()*scl; - drawBox(idraw,mi,mx,node->isleaf()?lcolor:ncolor); - } - } -} - -// +/* +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. +*/ +///btSoftBodyHelpers.cpp by Nathanael Presson + +#include "btSoftBody.h" +#include +#include +#include "btSoftBodyHelpers.h" +#include "LinearMath/btConvexHull.h" + +// +static void drawVertex( btIDebugDraw* idraw, + const btVector3& x,btScalar s,const btVector3& c) + { + idraw->drawLine(x-btVector3(s,0,0),x+btVector3(s,0,0),c); + idraw->drawLine(x-btVector3(0,s,0),x+btVector3(0,s,0),c); + idraw->drawLine(x-btVector3(0,0,s),x+btVector3(0,0,s),c); + } + +// +static void drawBox( btIDebugDraw* idraw, + const btVector3& mins, + const btVector3& maxs, + const btVector3& color) +{ +const btVector3 c[]={ btVector3(mins.x(),mins.y(),mins.z()), + btVector3(maxs.x(),mins.y(),mins.z()), + btVector3(maxs.x(),maxs.y(),mins.z()), + btVector3(mins.x(),maxs.y(),mins.z()), + btVector3(mins.x(),mins.y(),maxs.z()), + btVector3(maxs.x(),mins.y(),maxs.z()), + btVector3(maxs.x(),maxs.y(),maxs.z()), + btVector3(mins.x(),maxs.y(),maxs.z())}; +idraw->drawLine(c[0],c[1],color);idraw->drawLine(c[1],c[2],color); +idraw->drawLine(c[2],c[3],color);idraw->drawLine(c[3],c[0],color); +idraw->drawLine(c[4],c[5],color);idraw->drawLine(c[5],c[6],color); +idraw->drawLine(c[6],c[7],color);idraw->drawLine(c[7],c[4],color); +idraw->drawLine(c[0],c[4],color);idraw->drawLine(c[1],c[5],color); +idraw->drawLine(c[2],c[6],color);idraw->drawLine(c[3],c[7],color); +} + +// +static void drawTree( btIDebugDraw* idraw, + const btDbvt::Node* node, + int depth, + const btVector3& ncolor, + const btVector3& lcolor, + int mindepth, + int maxdepth) +{ +if(node) + { + if(node->isinternal()&&((depthchilds[0],depth+1,ncolor,lcolor,mindepth,maxdepth); + drawTree(idraw,node->childs[1],depth+1,ncolor,lcolor,mindepth,maxdepth); + } + if(depth>=mindepth) + { + const btScalar scl=(btScalar)(node->isinternal()?1:1); + const btVector3 mi=node->volume.Center()-node->volume.Extents()*scl; + const btVector3 mx=node->volume.Center()+node->volume.Extents()*scl; + drawBox(idraw,mi,mx,node->isleaf()?lcolor:ncolor); + } + } +} + +// // static inline btScalar tetravolume(const btVector3& x0, const btVector3& x1, @@ -88,420 +88,420 @@ static inline btScalar tetravolume(const btVector3& x0, const btVector3 b=x2-x0; const btVector3 c=x3-x0; return(dot(a,cross(b,c))); -} - -// -#if 0 -static btVector3 stresscolor(btScalar stress) - { - static const btVector3 spectrum[]= { btVector3(1,0,1), - btVector3(0,0,1), - btVector3(0,1,1), - btVector3(0,1,0), - btVector3(1,1,0), - btVector3(1,0,0), - btVector3(1,0,0)}; - static const int ncolors=sizeof(spectrum)/sizeof(spectrum[0])-1; - static const btScalar one=1; - stress=btMax(0,btMin(1,stress))*ncolors; - const int sel=(int)stress; - const btScalar frc=stress-sel; - return(spectrum[sel]+(spectrum[sel+1]-spectrum[sel])*frc); - } -#endif - -// -void btSoftBodyHelpers::Draw( btSoftBody* psb, - btIDebugDraw* idraw, - int drawflags) -{ - const btScalar scl=(btScalar)0.1; - const btScalar nscl=scl*5; - const btVector3 lcolor=btVector3(0,0,0); - const btVector3 ncolor=btVector3(1,1,1); - const btVector3 ccolor=btVector3(1,0,0); - /* Nodes */ - if(0!=(drawflags&fDrawFlags::Nodes)) - { - for(int i=0;im_nodes.size();++i) - { - const btSoftBody::Node& n=psb->m_nodes[i]; - if(0==(n.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue; - idraw->drawLine(n.m_x-btVector3(scl,0,0),n.m_x+btVector3(scl,0,0),btVector3(1,0,0)); - idraw->drawLine(n.m_x-btVector3(0,scl,0),n.m_x+btVector3(0,scl,0),btVector3(0,1,0)); - idraw->drawLine(n.m_x-btVector3(0,0,scl),n.m_x+btVector3(0,0,scl),btVector3(0,0,1)); - } - } - /* Links */ - if(0!=(drawflags&fDrawFlags::Links)) - { - for(int i=0;im_links.size();++i) - { - const btSoftBody::Link& l=psb->m_links[i]; - if(0==(l.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue; - idraw->drawLine(l.m_n[0]->m_x,l.m_n[1]->m_x,lcolor); - } - } - /* Normals */ - if(0!=(drawflags&fDrawFlags::Normals)) - { - for(int i=0;im_nodes.size();++i) - { - const btSoftBody::Node& n=psb->m_nodes[i]; - if(0==(n.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue; - const btVector3 d=n.m_n*nscl; - idraw->drawLine(n.m_x,n.m_x+d,ncolor); - idraw->drawLine(n.m_x,n.m_x-d,ncolor*0.5); - } - } - /* Contacts */ - if(0!=(drawflags&fDrawFlags::Contacts)) - { - static const btVector3 axis[]={btVector3(1,0,0), - btVector3(0,1,0), - btVector3(0,0,1)}; - for(int i=0;im_rcontacts.size();++i) - { - const btSoftBody::RContact& c=psb->m_rcontacts[i]; - const btVector3 o= c.m_node->m_x-c.m_cti.m_normal* - (dot(c.m_node->m_x,c.m_cti.m_normal)+c.m_cti.m_offset); - const btVector3 x=cross(c.m_cti.m_normal,axis[c.m_cti.m_normal.minAxis()]).normalized(); - const btVector3 y=cross(x,c.m_cti.m_normal).normalized(); - idraw->drawLine(o-x*nscl,o+x*nscl,ccolor); - idraw->drawLine(o-y*nscl,o+y*nscl,ccolor); - idraw->drawLine(o,o+c.m_cti.m_normal*nscl*3,btVector3(1,1,0)); - } - } - /* Anchors */ - if(0!=(drawflags&fDrawFlags::Anchors)) - { - for(int i=0;im_anchors.size();++i) - { - const btSoftBody::Anchor& a=psb->m_anchors[i]; - const btVector3 q=a.m_body->getWorldTransform()*a.m_local; - drawVertex(idraw,a.m_node->m_x,0.25,btVector3(1,0,0)); - drawVertex(idraw,q,0.25,btVector3(0,1,0)); - idraw->drawLine(a.m_node->m_x,q,btVector3(1,1,1)); - } - for(int i=0;im_nodes.size();++i) - { - const btSoftBody::Node& n=psb->m_nodes[i]; - if(0==(n.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue; - if(n.m_im<=0) - { - drawVertex(idraw,n.m_x,0.25,btVector3(1,0,0)); - } - } - } - /* Faces */ - if(0!=(drawflags&fDrawFlags::Faces)) - { - const btScalar scl=(btScalar)0.8; - const btScalar alp=(btScalar)1; - const btVector3 col(0,(btScalar)0.7,0); - for(int i=0;im_faces.size();++i) - { - const btSoftBody::Face& f=psb->m_faces[i]; - if(0==(f.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue; - const btVector3 x[]={f.m_n[0]->m_x,f.m_n[1]->m_x,f.m_n[2]->m_x}; - const btVector3 c=(x[0]+x[1]+x[2])/3; - /*idraw->drawLine((x[0]-c)*scl+c,(x[1]-c)*scl+c,col); - idraw->drawLine((x[1]-c)*scl+c,(x[2]-c)*scl+c,col); - idraw->drawLine((x[2]-c)*scl+c,(x[0]-c)*scl+c,col);*/ - idraw->drawTriangle((x[0]-c)*scl+c, - (x[1]-c)*scl+c, - (x[2]-c)*scl+c, - col,alp); - /*idraw->drawTriangle((x[0]-c)*scl+c, - (x[1]-c)*scl+c, - (x[2]-c)*scl+c, - f.m_n[0]->m_n,f.m_n[1]->m_n,f.m_n[2]->m_n, - col,alp);*/ - } - } - /* Notes */ - if(0!=(drawflags&fDrawFlags::Notes)) - { - for(int i=0;im_notes.size();++i) - { - const btSoftBody::Note& n=psb->m_notes[i]; - btVector3 p=n.m_offset; - for(int j=0;jm_x*n.m_coords[j]; - } - idraw->draw3dText(p,n.m_text); - } - } -} - -// -void btSoftBodyHelpers::DrawInfos( btSoftBody* psb, - btIDebugDraw* idraw, - bool masses, - bool areas, - bool /*stress*/) -{ - for(int i=0;im_nodes.size();++i) - { - const btSoftBody::Node& n=psb->m_nodes[i]; - char text[2048]={0}; - char buff[1024]; - if(masses) - { - sprintf(buff," M(%.2f)",1/n.m_im); - strcat(text,buff); - } - if(areas) - { - sprintf(buff," A(%.2f)",n.m_area); - strcat(text,buff); - } - if(text[0]) idraw->draw3dText(n.m_x,text); - } -} - -// -void btSoftBodyHelpers::DrawNodeTree( btSoftBody* psb, - btIDebugDraw* idraw, - int mindepth, - int maxdepth) -{ -drawTree(idraw,psb->m_ndbvt.m_root,0,btVector3(1,0,1),btVector3(1,1,1),mindepth,maxdepth); -} - -// -void btSoftBodyHelpers::DrawFaceTree( btSoftBody* psb, - btIDebugDraw* idraw, - int mindepth, - int maxdepth) -{ -drawTree(idraw,psb->m_fdbvt.m_root,0,btVector3(0,1,0),btVector3(1,0,0),mindepth,maxdepth); -} - -// -void btSoftBodyHelpers::DrawFrame( btSoftBody* psb, - btIDebugDraw* idraw) -{ - if(psb->m_pose.m_bframe) - { - static const btScalar ascl=10; - static const btScalar nscl=(btScalar)0.1; - const btVector3 com=psb->m_pose.m_com; - const btMatrix3x3 trs=psb->m_pose.m_rot*psb->m_pose.m_scl; - const btVector3 Xaxis=(trs*btVector3(1,0,0)).normalized(); - const btVector3 Yaxis=(trs*btVector3(0,1,0)).normalized(); - const btVector3 Zaxis=(trs*btVector3(0,0,1)).normalized(); - idraw->drawLine(com,com+Xaxis*ascl,btVector3(1,0,0)); - idraw->drawLine(com,com+Yaxis*ascl,btVector3(0,1,0)); - idraw->drawLine(com,com+Zaxis*ascl,btVector3(0,0,1)); - for(int i=0;im_pose.m_pos.size();++i) - { - const btVector3 x=com+trs*psb->m_pose.m_pos[i]; - drawVertex(idraw,x,nscl,btVector3(1,0,1)); - } - } -} - -// -btSoftBody* btSoftBodyHelpers::CreateRope( btSoftBody::btSoftBodyWorldInfo& worldInfo, const btVector3& from, - const btVector3& to, - int res, - int fixeds) -{ - /* Create nodes */ - const int r=res+2; - btVector3* x=new btVector3[r]; - btScalar* m=new btScalar[r]; - for(int i=0;isetMass(0,0); - if(fixeds&2) psb->setMass(r-1,0); - delete[] x; - delete[] m; - /* Create links */ - for(int i=1;iappendLink(i-1,i); - } - /* Finished */ - return(psb); -} - -// -btSoftBody* btSoftBodyHelpers::CreatePatch(btSoftBody::btSoftBodyWorldInfo& worldInfo,const btVector3& corner00, - const btVector3& corner10, - const btVector3& corner01, - const btVector3& corner11, - int resx, - int resy, - int fixeds, - bool gendiags) -{ -#define IDX(_x_,_y_) ((_y_)*rx+(_x_)) - /* Create nodes */ - if((resx<2)||(resy<2)) return(0); - const int rx=resx; - const int ry=resy; - const int tot=rx*ry; - btVector3* x=new btVector3[tot]; - btScalar* m=new btScalar[tot]; - for(int iy=0;iysetMass(IDX(0,0),0); - if(fixeds&2) psb->setMass(IDX(rx-1,0),0); - if(fixeds&4) psb->setMass(IDX(0,ry-1),0); - if(fixeds&8) psb->setMass(IDX(rx-1,ry-1),0); - delete[] x; - delete[] m; - /* Create links and faces */ - for(int iy=0;iyappendLink(idx,IDX(ix+1,iy)); - if(mdy) psb->appendLink(idx,IDX(ix,iy+1)); - if(mdx&&mdy) - { - if((ix+iy)&1) - { - psb->appendFace(IDX(ix,iy),IDX(ix+1,iy),IDX(ix+1,iy+1)); - psb->appendFace(IDX(ix,iy),IDX(ix+1,iy+1),IDX(ix,iy+1)); - if(gendiags) - { - psb->appendLink(IDX(ix,iy),IDX(ix+1,iy+1)); - } - } - else - { - psb->appendFace(IDX(ix,iy+1),IDX(ix,iy),IDX(ix+1,iy)); - psb->appendFace(IDX(ix,iy+1),IDX(ix+1,iy),IDX(ix+1,iy+1)); - if(gendiags) - { - psb->appendLink(IDX(ix+1,iy),IDX(ix,iy+1)); - } - } - } - } - } - /* Finished */ -#undef IDX - return(psb); -} - -// -btSoftBody* btSoftBodyHelpers::CreateEllipsoid(btSoftBody::btSoftBodyWorldInfo& worldInfo,const btVector3& center, - const btVector3& radius, - int res) -{ - struct Hammersley - { - static void Generate(btVector3* x,int n) - { - for(int i=0;i>=1) if(j&1) t+=p; - btScalar w=2*t-1; - btScalar a=(SIMD_PI+2*i*SIMD_PI)/n; - btScalar s=btSqrt(1-w*w); - *x++=btVector3(s*btCos(a),s*btSin(a),w); - } - } - }; - btAlignedObjectArray vtx; - vtx.resize(3+res); - Hammersley::Generate(&vtx[0],vtx.size()); - for(int i=0;i chks; - btAlignedObjectArray vtx; - chks.resize(maxidx*maxidx,false); - vtx.resize(maxidx); - for(int i=0,j=0,ni=maxidx*3;iappendLink(idx[j],idx[k]); - } - } -#undef IDX - psb->appendFace(idx[0],idx[1],idx[2]); - } - psb->randomizeConstraints(); - return(psb); -} - -// -btSoftBody* btSoftBodyHelpers::CreateFromConvexHull(btSoftBody::btSoftBodyWorldInfo& worldInfo, const btVector3* vertices, - int nvertices) -{ - HullDesc hdsc(QF_TRIANGLES,nvertices,vertices); - HullResult hres; - HullLibrary hlib;/*??*/ - hdsc.mMaxVertices=nvertices; - hlib.CreateConvexHull(hdsc,hres); - btSoftBody* psb=new btSoftBody(&worldInfo,(int)hres.mNumOutputVertices, - &hres.m_OutputVertices[0],0); - for(int i=0;i<(int)hres.mNumFaces;++i) - { - const int idx[]={ hres.m_Indices[i*3+0], - hres.m_Indices[i*3+1], - hres.m_Indices[i*3+2]}; - if(idx[0]appendLink( idx[0],idx[1]); - if(idx[1]appendLink( idx[1],idx[2]); - if(idx[2]appendLink( idx[2],idx[0]); - psb->appendFace(idx[0],idx[1],idx[2]); - } - hlib.ReleaseResult(hres); - psb->randomizeConstraints(); - return(psb); +} + +// +#if 0 +static btVector3 stresscolor(btScalar stress) + { + static const btVector3 spectrum[]= { btVector3(1,0,1), + btVector3(0,0,1), + btVector3(0,1,1), + btVector3(0,1,0), + btVector3(1,1,0), + btVector3(1,0,0), + btVector3(1,0,0)}; + static const int ncolors=sizeof(spectrum)/sizeof(spectrum[0])-1; + static const btScalar one=1; + stress=btMax(0,btMin(1,stress))*ncolors; + const int sel=(int)stress; + const btScalar frc=stress-sel; + return(spectrum[sel]+(spectrum[sel+1]-spectrum[sel])*frc); + } +#endif + +// +void btSoftBodyHelpers::Draw( btSoftBody* psb, + btIDebugDraw* idraw, + int drawflags) +{ + const btScalar scl=(btScalar)0.1; + const btScalar nscl=scl*5; + const btVector3 lcolor=btVector3(0,0,0); + const btVector3 ncolor=btVector3(1,1,1); + const btVector3 ccolor=btVector3(1,0,0); + /* Nodes */ + if(0!=(drawflags&fDrawFlags::Nodes)) + { + for(int i=0;im_nodes.size();++i) + { + const btSoftBody::Node& n=psb->m_nodes[i]; + if(0==(n.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue; + idraw->drawLine(n.m_x-btVector3(scl,0,0),n.m_x+btVector3(scl,0,0),btVector3(1,0,0)); + idraw->drawLine(n.m_x-btVector3(0,scl,0),n.m_x+btVector3(0,scl,0),btVector3(0,1,0)); + idraw->drawLine(n.m_x-btVector3(0,0,scl),n.m_x+btVector3(0,0,scl),btVector3(0,0,1)); + } + } + /* Links */ + if(0!=(drawflags&fDrawFlags::Links)) + { + for(int i=0;im_links.size();++i) + { + const btSoftBody::Link& l=psb->m_links[i]; + if(0==(l.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue; + idraw->drawLine(l.m_n[0]->m_x,l.m_n[1]->m_x,lcolor); + } + } + /* Normals */ + if(0!=(drawflags&fDrawFlags::Normals)) + { + for(int i=0;im_nodes.size();++i) + { + const btSoftBody::Node& n=psb->m_nodes[i]; + if(0==(n.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue; + const btVector3 d=n.m_n*nscl; + idraw->drawLine(n.m_x,n.m_x+d,ncolor); + idraw->drawLine(n.m_x,n.m_x-d,ncolor*0.5); + } + } + /* Contacts */ + if(0!=(drawflags&fDrawFlags::Contacts)) + { + static const btVector3 axis[]={btVector3(1,0,0), + btVector3(0,1,0), + btVector3(0,0,1)}; + for(int i=0;im_rcontacts.size();++i) + { + const btSoftBody::RContact& c=psb->m_rcontacts[i]; + const btVector3 o= c.m_node->m_x-c.m_cti.m_normal* + (dot(c.m_node->m_x,c.m_cti.m_normal)+c.m_cti.m_offset); + const btVector3 x=cross(c.m_cti.m_normal,axis[c.m_cti.m_normal.minAxis()]).normalized(); + const btVector3 y=cross(x,c.m_cti.m_normal).normalized(); + idraw->drawLine(o-x*nscl,o+x*nscl,ccolor); + idraw->drawLine(o-y*nscl,o+y*nscl,ccolor); + idraw->drawLine(o,o+c.m_cti.m_normal*nscl*3,btVector3(1,1,0)); + } + } + /* Anchors */ + if(0!=(drawflags&fDrawFlags::Anchors)) + { + for(int i=0;im_anchors.size();++i) + { + const btSoftBody::Anchor& a=psb->m_anchors[i]; + const btVector3 q=a.m_body->getWorldTransform()*a.m_local; + drawVertex(idraw,a.m_node->m_x,0.25,btVector3(1,0,0)); + drawVertex(idraw,q,0.25,btVector3(0,1,0)); + idraw->drawLine(a.m_node->m_x,q,btVector3(1,1,1)); + } + for(int i=0;im_nodes.size();++i) + { + const btSoftBody::Node& n=psb->m_nodes[i]; + if(0==(n.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue; + if(n.m_im<=0) + { + drawVertex(idraw,n.m_x,0.25,btVector3(1,0,0)); + } + } + } + /* Faces */ + if(0!=(drawflags&fDrawFlags::Faces)) + { + const btScalar scl=(btScalar)0.8; + const btScalar alp=(btScalar)1; + const btVector3 col(0,(btScalar)0.7,0); + for(int i=0;im_faces.size();++i) + { + const btSoftBody::Face& f=psb->m_faces[i]; + if(0==(f.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue; + const btVector3 x[]={f.m_n[0]->m_x,f.m_n[1]->m_x,f.m_n[2]->m_x}; + const btVector3 c=(x[0]+x[1]+x[2])/3; + /*idraw->drawLine((x[0]-c)*scl+c,(x[1]-c)*scl+c,col); + idraw->drawLine((x[1]-c)*scl+c,(x[2]-c)*scl+c,col); + idraw->drawLine((x[2]-c)*scl+c,(x[0]-c)*scl+c,col);*/ + idraw->drawTriangle((x[0]-c)*scl+c, + (x[1]-c)*scl+c, + (x[2]-c)*scl+c, + col,alp); + /*idraw->drawTriangle((x[0]-c)*scl+c, + (x[1]-c)*scl+c, + (x[2]-c)*scl+c, + f.m_n[0]->m_n,f.m_n[1]->m_n,f.m_n[2]->m_n, + col,alp);*/ + } + } + /* Notes */ + if(0!=(drawflags&fDrawFlags::Notes)) + { + for(int i=0;im_notes.size();++i) + { + const btSoftBody::Note& n=psb->m_notes[i]; + btVector3 p=n.m_offset; + for(int j=0;jm_x*n.m_coords[j]; + } + idraw->draw3dText(p,n.m_text); + } + } +} + +// +void btSoftBodyHelpers::DrawInfos( btSoftBody* psb, + btIDebugDraw* idraw, + bool masses, + bool areas, + bool /*stress*/) +{ + for(int i=0;im_nodes.size();++i) + { + const btSoftBody::Node& n=psb->m_nodes[i]; + char text[2048]={0}; + char buff[1024]; + if(masses) + { + sprintf(buff," M(%.2f)",1/n.m_im); + strcat(text,buff); + } + if(areas) + { + sprintf(buff," A(%.2f)",n.m_area); + strcat(text,buff); + } + if(text[0]) idraw->draw3dText(n.m_x,text); + } +} + +// +void btSoftBodyHelpers::DrawNodeTree( btSoftBody* psb, + btIDebugDraw* idraw, + int mindepth, + int maxdepth) +{ +drawTree(idraw,psb->m_ndbvt.m_root,0,btVector3(1,0,1),btVector3(1,1,1),mindepth,maxdepth); +} + +// +void btSoftBodyHelpers::DrawFaceTree( btSoftBody* psb, + btIDebugDraw* idraw, + int mindepth, + int maxdepth) +{ +drawTree(idraw,psb->m_fdbvt.m_root,0,btVector3(0,1,0),btVector3(1,0,0),mindepth,maxdepth); +} + +// +void btSoftBodyHelpers::DrawFrame( btSoftBody* psb, + btIDebugDraw* idraw) +{ + if(psb->m_pose.m_bframe) + { + static const btScalar ascl=10; + static const btScalar nscl=(btScalar)0.1; + const btVector3 com=psb->m_pose.m_com; + const btMatrix3x3 trs=psb->m_pose.m_rot*psb->m_pose.m_scl; + const btVector3 Xaxis=(trs*btVector3(1,0,0)).normalized(); + const btVector3 Yaxis=(trs*btVector3(0,1,0)).normalized(); + const btVector3 Zaxis=(trs*btVector3(0,0,1)).normalized(); + idraw->drawLine(com,com+Xaxis*ascl,btVector3(1,0,0)); + idraw->drawLine(com,com+Yaxis*ascl,btVector3(0,1,0)); + idraw->drawLine(com,com+Zaxis*ascl,btVector3(0,0,1)); + for(int i=0;im_pose.m_pos.size();++i) + { + const btVector3 x=com+trs*psb->m_pose.m_pos[i]; + drawVertex(idraw,x,nscl,btVector3(1,0,1)); + } + } +} + +// +btSoftBody* btSoftBodyHelpers::CreateRope( btSoftBody::btSoftBodyWorldInfo& worldInfo, const btVector3& from, + const btVector3& to, + int res, + int fixeds) +{ + /* Create nodes */ + const int r=res+2; + btVector3* x=new btVector3[r]; + btScalar* m=new btScalar[r]; + for(int i=0;isetMass(0,0); + if(fixeds&2) psb->setMass(r-1,0); + delete[] x; + delete[] m; + /* Create links */ + for(int i=1;iappendLink(i-1,i); + } + /* Finished */ + return(psb); +} + +// +btSoftBody* btSoftBodyHelpers::CreatePatch(btSoftBody::btSoftBodyWorldInfo& worldInfo,const btVector3& corner00, + const btVector3& corner10, + const btVector3& corner01, + const btVector3& corner11, + int resx, + int resy, + int fixeds, + bool gendiags) +{ +#define IDX(_x_,_y_) ((_y_)*rx+(_x_)) + /* Create nodes */ + if((resx<2)||(resy<2)) return(0); + const int rx=resx; + const int ry=resy; + const int tot=rx*ry; + btVector3* x=new btVector3[tot]; + btScalar* m=new btScalar[tot]; + for(int iy=0;iysetMass(IDX(0,0),0); + if(fixeds&2) psb->setMass(IDX(rx-1,0),0); + if(fixeds&4) psb->setMass(IDX(0,ry-1),0); + if(fixeds&8) psb->setMass(IDX(rx-1,ry-1),0); + delete[] x; + delete[] m; + /* Create links and faces */ + for(int iy=0;iyappendLink(idx,IDX(ix+1,iy)); + if(mdy) psb->appendLink(idx,IDX(ix,iy+1)); + if(mdx&&mdy) + { + if((ix+iy)&1) + { + psb->appendFace(IDX(ix,iy),IDX(ix+1,iy),IDX(ix+1,iy+1)); + psb->appendFace(IDX(ix,iy),IDX(ix+1,iy+1),IDX(ix,iy+1)); + if(gendiags) + { + psb->appendLink(IDX(ix,iy),IDX(ix+1,iy+1)); + } + } + else + { + psb->appendFace(IDX(ix,iy+1),IDX(ix,iy),IDX(ix+1,iy)); + psb->appendFace(IDX(ix,iy+1),IDX(ix+1,iy),IDX(ix+1,iy+1)); + if(gendiags) + { + psb->appendLink(IDX(ix+1,iy),IDX(ix,iy+1)); + } + } + } + } + } + /* Finished */ +#undef IDX + return(psb); +} + +// +btSoftBody* btSoftBodyHelpers::CreateEllipsoid(btSoftBody::btSoftBodyWorldInfo& worldInfo,const btVector3& center, + const btVector3& radius, + int res) +{ + struct Hammersley + { + static void Generate(btVector3* x,int n) + { + for(int i=0;i>=1) if(j&1) t+=p; + btScalar w=2*t-1; + btScalar a=(SIMD_PI+2*i*SIMD_PI)/n; + btScalar s=btSqrt(1-w*w); + *x++=btVector3(s*btCos(a),s*btSin(a),w); + } + } + }; + btAlignedObjectArray vtx; + vtx.resize(3+res); + Hammersley::Generate(&vtx[0],vtx.size()); + for(int i=0;i chks; + btAlignedObjectArray vtx; + chks.resize(maxidx*maxidx,false); + vtx.resize(maxidx); + for(int i=0,j=0,ni=maxidx*3;iappendLink(idx[j],idx[k]); + } + } +#undef IDX + psb->appendFace(idx[0],idx[1],idx[2]); + } + psb->randomizeConstraints(); + return(psb); +} + +// +btSoftBody* btSoftBodyHelpers::CreateFromConvexHull(btSoftBody::btSoftBodyWorldInfo& worldInfo, const btVector3* vertices, + int nvertices) +{ + HullDesc hdsc(QF_TRIANGLES,nvertices,vertices); + HullResult hres; + HullLibrary hlib;/*??*/ + hdsc.mMaxVertices=nvertices; + hlib.CreateConvexHull(hdsc,hres); + btSoftBody* psb=new btSoftBody(&worldInfo,(int)hres.mNumOutputVertices, + &hres.m_OutputVertices[0],0); + for(int i=0;i<(int)hres.mNumFaces;++i) + { + const int idx[]={ hres.m_Indices[i*3+0], + hres.m_Indices[i*3+1], + hres.m_Indices[i*3+2]}; + if(idx[0]appendLink( idx[0],idx[1]); + if(idx[1]appendLink( idx[1],idx[2]); + if(idx[2]appendLink( idx[2],idx[0]); + psb->appendFace(idx[0],idx[1],idx[2]); + } + hlib.ReleaseResult(hres); + psb->randomizeConstraints(); + return(psb); } \ No newline at end of file