+Added btDbvtBroadphase, this very fast/efficient broadphase is based on Dynamic AABB tree (btDbvt).
+SoftBody improvements by Nathanael Presson: +Add tetrahedralization +Add support for tearing/slicing cloth and deformable volumes. Uncomment the line in Bullet/src/BulletSoftBody/btSoftBodyHelpers.h: //#define BT_SOFTBODY_USE_STL 1
This commit is contained in:
@@ -20,6 +20,8 @@ subject to the following restrictions:
|
||||
#include "btDispatcher.h"
|
||||
#include "btCollisionAlgorithm.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int gOverlappingPairs = 0;
|
||||
|
||||
int gRemovePairs =0;
|
||||
@@ -133,12 +135,12 @@ void btHashedOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroad
|
||||
btBroadphasePair* btHashedOverlappingPairCache::findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
|
||||
{
|
||||
gFindPairs++;
|
||||
|
||||
if(proxy0>proxy1) btSwap(proxy0,proxy1);
|
||||
int proxyId1 = proxy0->getUid();
|
||||
int proxyId2 = proxy1->getUid();
|
||||
|
||||
if (proxyId1 > proxyId2)
|
||||
btSwap(proxyId1, proxyId2);
|
||||
/*if (proxyId1 > proxyId2)
|
||||
btSwap(proxyId1, proxyId2);*/
|
||||
|
||||
int hash = getHash(proxyId1, proxyId2) & (m_overlappingPairArray.capacity()-1);
|
||||
|
||||
@@ -196,8 +198,8 @@ void btHashedOverlappingPairCache::growTables()
|
||||
const btBroadphasePair& pair = m_overlappingPairArray[i];
|
||||
int proxyId1 = pair.m_pProxy0->getUid();
|
||||
int proxyId2 = pair.m_pProxy1->getUid();
|
||||
if (proxyId1 > proxyId2)
|
||||
btSwap(proxyId1, proxyId2);
|
||||
/*if (proxyId1 > proxyId2)
|
||||
btSwap(proxyId1, proxyId2);*/
|
||||
int hashValue = getHash(proxyId1,proxyId2) & (m_overlappingPairArray.capacity()-1); // New hash value with new mask
|
||||
m_next[i] = m_hashTable[hashValue];
|
||||
m_hashTable[hashValue] = i;
|
||||
@@ -209,11 +211,12 @@ void btHashedOverlappingPairCache::growTables()
|
||||
|
||||
btBroadphasePair* btHashedOverlappingPairCache::internalAddPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
|
||||
{
|
||||
if(proxy0>proxy1) btSwap(proxy0,proxy1);
|
||||
int proxyId1 = proxy0->getUid();
|
||||
int proxyId2 = proxy1->getUid();
|
||||
|
||||
if (proxyId1 > proxyId2)
|
||||
btSwap(proxyId1, proxyId2);
|
||||
/*if (proxyId1 > proxyId2)
|
||||
btSwap(proxyId1, proxyId2);*/
|
||||
|
||||
int hash = getHash(proxyId1, proxyId2) & (m_overlappingPairArray.capacity()-1);
|
||||
|
||||
@@ -224,7 +227,15 @@ btBroadphasePair* btHashedOverlappingPairCache::internalAddPair(btBroadphaseProx
|
||||
{
|
||||
return pair;
|
||||
}
|
||||
|
||||
/*for(int i=0;i<m_overlappingPairArray.size();++i)
|
||||
{
|
||||
if( (m_overlappingPairArray[i].m_pProxy0==proxy0)&&
|
||||
(m_overlappingPairArray[i].m_pProxy1==proxy1))
|
||||
{
|
||||
printf("Adding duplicated %u<>%u\r\n",proxyId1,proxyId2);
|
||||
internalFindPair(proxy0, proxy1, hash);
|
||||
}
|
||||
}*/
|
||||
int count = m_overlappingPairArray.size();
|
||||
int oldCapacity = m_overlappingPairArray.capacity();
|
||||
void* mem = &m_overlappingPairArray.expand();
|
||||
@@ -255,12 +266,12 @@ btBroadphasePair* btHashedOverlappingPairCache::internalAddPair(btBroadphaseProx
|
||||
void* btHashedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1,btDispatcher* dispatcher)
|
||||
{
|
||||
gRemovePairs++;
|
||||
|
||||
if(proxy0>proxy1) btSwap(proxy0,proxy1);
|
||||
int proxyId1 = proxy0->getUid();
|
||||
int proxyId2 = proxy1->getUid();
|
||||
|
||||
if (proxyId1 > proxyId2)
|
||||
btSwap(proxyId1, proxyId2);
|
||||
/*if (proxyId1 > proxyId2)
|
||||
btSwap(proxyId1, proxyId2);*/
|
||||
|
||||
int hash = getHash(proxyId1, proxyId2) & (m_overlappingPairArray.capacity()-1);
|
||||
|
||||
@@ -316,6 +327,7 @@ void* btHashedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* pro
|
||||
|
||||
// Remove the last pair from the hash table.
|
||||
const btBroadphasePair* last = &m_overlappingPairArray[lastPairIndex];
|
||||
/* missing swap here too, Nat. */
|
||||
int lastHash = getHash(last->m_pProxy0->getUid(), last->m_pProxy1->getUid()) & (m_overlappingPairArray.capacity()-1);
|
||||
|
||||
index = m_hashTable[lastHash];
|
||||
@@ -416,6 +428,7 @@ btBroadphasePair* btSortedOverlappingPairCache::addOverlappingPair(btBroadphaseP
|
||||
void* mem = &m_overlappingPairArray.expand();
|
||||
btBroadphasePair* pair = new (mem) btBroadphasePair(*proxy0,*proxy1);
|
||||
gOverlappingPairs++;
|
||||
gAddedPairs++;
|
||||
return pair;
|
||||
|
||||
}
|
||||
@@ -500,6 +513,7 @@ void btSortedOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair,b
|
||||
pair.m_algorithm->~btCollisionAlgorithm();
|
||||
dispatcher->freeCollisionAlgorithm(pair.m_algorithm);
|
||||
pair.m_algorithm=0;
|
||||
gRemovePairs--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -225,8 +225,10 @@ private:
|
||||
{
|
||||
int proxyId1 = proxy0->getUid();
|
||||
int proxyId2 = proxy1->getUid();
|
||||
#if 0 // wrong, 'equalsPair' use unsorted uids, copy-past devil striked again. Nat.
|
||||
if (proxyId1 > proxyId2)
|
||||
btSwap(proxyId1, proxyId2);
|
||||
#endif
|
||||
|
||||
int index = m_hashTable[hash];
|
||||
|
||||
@@ -432,3 +434,4 @@ public:
|
||||
#endif //OVERLAPPING_PAIR_CACHE_H
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@ ADD_LIBRARY(LibBulletSoftBody
|
||||
btSoftBody.h
|
||||
btSoftBodyHelpers.cpp
|
||||
btSparseSDF.h
|
||||
btDbvtBroadphase.cpp
|
||||
btDbvtBroadphase.h
|
||||
btDbvt.cpp
|
||||
btDbvt.h
|
||||
btSoftBodyHelpers.h
|
||||
@@ -16,6 +18,8 @@ ADD_LIBRARY(LibBulletSoftBody
|
||||
btSoftRigidCollisionAlgorithm.h
|
||||
btSoftSoftCollisionAlgorithm.cpp
|
||||
btSoftSoftCollisionAlgorithm.h
|
||||
btSoftBodyConcaveCollisionAlgorithm.cpp
|
||||
btSoftBodyConcaveCollisionAlgorithm.h
|
||||
btSoftRigidDynamicsWorld.h
|
||||
btSoftRigidDynamicsWorld.cpp
|
||||
)
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
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"
|
||||
|
||||
//
|
||||
@@ -10,16 +26,16 @@ return(node->parent->childs[1]==node);
|
||||
}
|
||||
|
||||
//
|
||||
static inline btDbvt::Aabb merge( const btDbvt::Aabb& a,
|
||||
const btDbvt::Aabb& b)
|
||||
static inline btDbvt::Volume merge( const btDbvt::Volume& a,
|
||||
const btDbvt::Volume& b)
|
||||
{
|
||||
btDbvt::Aabb res;
|
||||
btDbvt::Volume res;
|
||||
Merge(a,b,res);
|
||||
return(res);
|
||||
}
|
||||
|
||||
// volume+edge lengths
|
||||
static inline btScalar size(const btDbvt::Aabb& a)
|
||||
static inline btScalar size(const btDbvt::Volume& a)
|
||||
{
|
||||
const btVector3 edges=a.Lengths();
|
||||
return( edges.x()*edges.y()*edges.z()+
|
||||
@@ -50,7 +66,7 @@ deletenode(pdbvt,node);
|
||||
//
|
||||
static inline btDbvt::Node* createnode( btDbvt* pdbvt,
|
||||
btDbvt::Node* parent,
|
||||
const btDbvt::Aabb& box,
|
||||
const btDbvt::Volume& volume,
|
||||
void* data)
|
||||
{
|
||||
btDbvt::Node* node;
|
||||
@@ -59,7 +75,7 @@ if(pdbvt->m_free)
|
||||
else
|
||||
{ node=new btDbvt::Node(); }
|
||||
node->parent = parent;
|
||||
node->box = box;
|
||||
node->volume = volume;
|
||||
node->data = data;
|
||||
node->childs[1] = 0;
|
||||
return(node);
|
||||
@@ -80,25 +96,25 @@ if(!pdbvt->m_root)
|
||||
if(!root->isleaf())
|
||||
{
|
||||
do {
|
||||
if( Proximity(root->childs[0]->box,leaf->box)<
|
||||
Proximity(root->childs[1]->box,leaf->box))
|
||||
if( Proximity(root->childs[0]->volume,leaf->volume)<
|
||||
Proximity(root->childs[1]->volume,leaf->volume))
|
||||
root=root->childs[0];
|
||||
else
|
||||
root=root->childs[1];
|
||||
} while(!root->isleaf());
|
||||
}
|
||||
btDbvt::Node* prev=root->parent;
|
||||
btDbvt::Node* node=createnode(pdbvt,prev,merge(leaf->box,root->box),0);
|
||||
btDbvt::Node* node=createnode(pdbvt,prev,merge(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->box.Contain(node->box))
|
||||
if(prev->volume.Contain(node->volume))
|
||||
break;
|
||||
else
|
||||
Merge(prev->childs[0]->box,prev->childs[1]->box,prev->box);
|
||||
Merge(prev->childs[0]->volume,prev->childs[1]->volume,prev->volume);
|
||||
node=prev;
|
||||
} while(0!=(prev=node->parent));
|
||||
}
|
||||
@@ -132,9 +148,9 @@ if(leaf==pdbvt->m_root)
|
||||
deletenode(pdbvt,parent);
|
||||
while(prev)
|
||||
{
|
||||
const btDbvt::Aabb pb=prev->box;
|
||||
Merge(prev->childs[0]->box,prev->childs[1]->box,prev->box);
|
||||
if(NotEqual(pb,prev->box))
|
||||
const btDbvt::Volume pb=prev->volume;
|
||||
Merge(prev->childs[0]->volume,prev->childs[1]->volume,prev->volume);
|
||||
if(NotEqual(pb,prev->volume))
|
||||
{
|
||||
sibling = prev;
|
||||
prev = prev->parent;
|
||||
@@ -170,17 +186,6 @@ if(root->isinternal()&&depth)
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
static int leafcount(btDbvt::Node* root)
|
||||
{
|
||||
if(root->isinternal())
|
||||
{
|
||||
return( leafcount(root->childs[0])+
|
||||
leafcount(root->childs[1]));
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
//
|
||||
static void split( const tNodeArray& leafs,
|
||||
tNodeArray& left,
|
||||
@@ -192,7 +197,7 @@ left.resize(0);
|
||||
right.resize(0);
|
||||
for(int i=0,ni=leafs.size();i<ni;++i)
|
||||
{
|
||||
if(dot(axis,leafs[i]->box.Center()-org)<0)
|
||||
if(dot(axis,leafs[i]->volume.Center()-org)<0)
|
||||
left.push_back(leafs[i]);
|
||||
else
|
||||
right.push_back(leafs[i]);
|
||||
@@ -200,14 +205,14 @@ for(int i=0,ni=leafs.size();i<ni;++i)
|
||||
}
|
||||
|
||||
//
|
||||
static btDbvt::Aabb bounds( const tNodeArray& leafs)
|
||||
static btDbvt::Volume bounds( const tNodeArray& leafs)
|
||||
{
|
||||
btDbvt::Aabb box=leafs[0]->box;
|
||||
btDbvt::Volume volume=leafs[0]->volume;
|
||||
for(int i=1,ni=leafs.size();i<ni;++i)
|
||||
{
|
||||
box=merge(box,leafs[i]->box);
|
||||
volume=merge(volume,leafs[i]->volume);
|
||||
}
|
||||
return(box);
|
||||
return(volume);
|
||||
}
|
||||
|
||||
//
|
||||
@@ -222,7 +227,7 @@ while(leafs.size()>1)
|
||||
{
|
||||
for(int j=i+1;j<leafs.size();++j)
|
||||
{
|
||||
const btScalar sz=size(merge(leafs[i]->box,leafs[j]->box));
|
||||
const btScalar sz=size(merge(leafs[i]->volume,leafs[j]->volume));
|
||||
if(sz<minsize)
|
||||
{
|
||||
minsize = sz;
|
||||
@@ -232,7 +237,7 @@ while(leafs.size()>1)
|
||||
}
|
||||
}
|
||||
btDbvt::Node* n[] = {leafs[minidx[0]],leafs[minidx[1]]};
|
||||
btDbvt::Node* p = createnode(pdbvt,0,merge(n[0]->box,n[1]->box),0);
|
||||
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;
|
||||
@@ -255,15 +260,15 @@ if(leafs.size()>1)
|
||||
{
|
||||
if(leafs.size()>bu_treshold)
|
||||
{
|
||||
const btDbvt::Aabb box=bounds(leafs);
|
||||
const btVector3 org=box.Center();
|
||||
tNodeArray sets[2];
|
||||
int bestaxis=-1;
|
||||
int bestmidp=leafs.size();
|
||||
int splitcount[3][2]={0,0,0,0,0,0};
|
||||
const btDbvt::Volume vol=bounds(leafs);
|
||||
const btVector3 org=vol.Center();
|
||||
tNodeArray sets[2];
|
||||
int bestaxis=-1;
|
||||
int bestmidp=leafs.size();
|
||||
int splitcount[3][2]={0,0,0,0,0,0};
|
||||
for(int i=0;i<leafs.size();++i)
|
||||
{
|
||||
const btVector3 x=leafs[i]->box.Center()-org;
|
||||
const btVector3 x=leafs[i]->volume.Center()-org;
|
||||
for(int j=0;j<3;++j)
|
||||
{
|
||||
++splitcount[j][dot(x,axis[j])>0?1:0];
|
||||
@@ -296,7 +301,7 @@ if(leafs.size()>1)
|
||||
sets[i&1].push_back(leafs[i]);
|
||||
}
|
||||
}
|
||||
btDbvt::Node* node=createnode(pdbvt,0,box,0);
|
||||
btDbvt::Node* 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;
|
||||
@@ -344,6 +349,7 @@ return(node);
|
||||
m_root = 0;
|
||||
m_free = 0;
|
||||
m_lkhd = 2;
|
||||
m_leafs = 0;
|
||||
}
|
||||
|
||||
//
|
||||
@@ -360,21 +366,13 @@ delete m_free;
|
||||
m_free=0;
|
||||
}
|
||||
|
||||
//
|
||||
int btDbvt::leafCount() const
|
||||
{
|
||||
if(m_root) return(leafcount(m_root));
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
|
||||
//
|
||||
void btDbvt::optimizeBottomUp()
|
||||
{
|
||||
if(m_root)
|
||||
{
|
||||
tNodeArray leafs;
|
||||
leafs.reserve(leafCount());
|
||||
leafs.reserve(m_leafs);
|
||||
fetchleafs(this,m_root,leafs);
|
||||
bottomup(this,leafs);
|
||||
m_root=leafs[0];
|
||||
@@ -387,22 +385,37 @@ void btDbvt::optimizeTopDown(int bu_treshold)
|
||||
if(m_root)
|
||||
{
|
||||
tNodeArray leafs;
|
||||
leafs.reserve(leafCount());
|
||||
leafs.reserve(m_leafs);
|
||||
fetchleafs(this,m_root,leafs);
|
||||
m_root=topdown(this,leafs,bu_treshold);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
btDbvt::Node* btDbvt::insert(const Aabb& box,void* data)
|
||||
btDbvt::Node* btDbvt::insert(const Volume& volume,void* data)
|
||||
{
|
||||
Node* leaf=createnode(this,0,box,data);
|
||||
Node* leaf=createnode(this,0,volume,data);
|
||||
insertleaf(this,m_root,leaf);
|
||||
++m_leafs;
|
||||
return(leaf);
|
||||
}
|
||||
|
||||
//
|
||||
void btDbvt::update(Node* leaf,const Aabb& box)
|
||||
void btDbvt::update(Node* leaf,int lookahead)
|
||||
{
|
||||
Node* root=removeleaf(this,leaf);
|
||||
if(root)
|
||||
{
|
||||
for(int i=0;(i<lookahead)&&root->parent;++i)
|
||||
{
|
||||
root=root->parent;
|
||||
}
|
||||
}
|
||||
insertleaf(this,root,leaf);
|
||||
}
|
||||
|
||||
//
|
||||
void btDbvt::update(Node* leaf,const Volume& volume)
|
||||
{
|
||||
Node* root=removeleaf(this,leaf);
|
||||
if(root)
|
||||
@@ -412,19 +425,35 @@ if(root)
|
||||
root=root->parent;
|
||||
}
|
||||
}
|
||||
leaf->box=box;
|
||||
leaf->volume=volume;
|
||||
insertleaf(this,root,leaf);
|
||||
}
|
||||
|
||||
//
|
||||
bool btDbvt::update(Node* leaf,Aabb box,const btVector3& velocity,btScalar margin)
|
||||
bool btDbvt::update(Node* leaf,Volume volume,const btVector3& velocity,btScalar margin)
|
||||
{
|
||||
if(leaf->box.Contain(box)) return(false);
|
||||
if(margin>0)
|
||||
box.Expand(btVector3(margin,margin,margin));
|
||||
if(velocity.length2()>0)
|
||||
box.SignedExpand(velocity);
|
||||
update(leaf,box);
|
||||
if(leaf->volume.Contain(volume)) return(false);
|
||||
volume.Expand(btVector3(margin,margin,margin));
|
||||
volume.SignedExpand(velocity);
|
||||
update(leaf,volume);
|
||||
return(true);
|
||||
}
|
||||
|
||||
//
|
||||
bool btDbvt::update(Node* leaf,Volume volume,const btVector3& velocity)
|
||||
{
|
||||
if(leaf->volume.Contain(volume)) return(false);
|
||||
volume.SignedExpand(velocity);
|
||||
update(leaf,volume);
|
||||
return(true);
|
||||
}
|
||||
|
||||
//
|
||||
bool btDbvt::update(Node* leaf,Volume volume,btScalar margin)
|
||||
{
|
||||
if(leaf->volume.Contain(volume)) return(false);
|
||||
volume.Expand(btVector3(margin,margin,margin));
|
||||
update(leaf,volume);
|
||||
return(true);
|
||||
}
|
||||
|
||||
@@ -433,109 +462,32 @@ void btDbvt::remove(Node* leaf)
|
||||
{
|
||||
removeleaf(this,leaf);
|
||||
deletenode(this,leaf);
|
||||
--m_leafs;
|
||||
}
|
||||
|
||||
//
|
||||
void btDbvt::collide(btDbvt* tree,
|
||||
ICollide* icollide) const
|
||||
{
|
||||
if(tree->m_root&&m_root)
|
||||
{
|
||||
btAlignedObjectArray<sStkElm> stack;
|
||||
stack.reserve(128);
|
||||
stack.push_back(sStkElm(m_root,tree->m_root));
|
||||
do {
|
||||
sStkElm p=stack[stack.size()-1];
|
||||
stack.pop_back();
|
||||
if(p.a==p.b)
|
||||
{
|
||||
if(p.a->isinternal())
|
||||
{
|
||||
stack.push_back(sStkElm(p.a->childs[0],p.a->childs[0]));
|
||||
stack.push_back(sStkElm(p.a->childs[1],p.a->childs[1]));
|
||||
stack.push_back(sStkElm(p.a->childs[0],p.a->childs[1]));
|
||||
}
|
||||
}
|
||||
else if(Intersect(p.a->box,p.b->box))
|
||||
{
|
||||
if(p.a->isinternal())
|
||||
{
|
||||
if(p.b->isinternal())
|
||||
{
|
||||
stack.push_back(sStkElm(p.a->childs[0],p.b->childs[0]));
|
||||
stack.push_back(sStkElm(p.a->childs[1],p.b->childs[0]));
|
||||
stack.push_back(sStkElm(p.a->childs[0],p.b->childs[1]));
|
||||
stack.push_back(sStkElm(p.a->childs[1],p.b->childs[1]));
|
||||
}
|
||||
else
|
||||
{
|
||||
stack.push_back(sStkElm(p.a->childs[0],p.b));
|
||||
stack.push_back(sStkElm(p.a->childs[1],p.b));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(p.b->isinternal())
|
||||
{
|
||||
stack.push_back(sStkElm(p.a,p.b->childs[0]));
|
||||
stack.push_back(sStkElm(p.a,p.b->childs[1]));
|
||||
}
|
||||
else
|
||||
{
|
||||
icollide->Process(p.a,p.b);
|
||||
}
|
||||
}
|
||||
}
|
||||
} while(stack.size()>0);
|
||||
}
|
||||
collideGeneric(tree,GCollide(icollide));
|
||||
}
|
||||
|
||||
//
|
||||
void btDbvt::collide(btDbvt::Node* node,
|
||||
ICollide* icollide) const
|
||||
{
|
||||
collideGeneric(node,GCollide(icollide));
|
||||
}
|
||||
|
||||
//
|
||||
void btDbvt::collide(const Aabb& box,
|
||||
void btDbvt::collide(const Volume& volume,
|
||||
ICollide* icollide) const
|
||||
{
|
||||
if(m_root)
|
||||
{
|
||||
btAlignedObjectArray<const Node*> stack;
|
||||
stack.reserve(64);
|
||||
stack.push_back(m_root);
|
||||
do {
|
||||
const Node* n=stack[stack.size()-1];
|
||||
stack.pop_back();
|
||||
if(Intersect(n->box,box))
|
||||
{
|
||||
if(n->isinternal())
|
||||
{
|
||||
stack.push_back(n->childs[0]);
|
||||
stack.push_back(n->childs[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
icollide->Process(n);
|
||||
}
|
||||
}
|
||||
} while(stack.size()>0);
|
||||
}
|
||||
collideGeneric(volume,GCollide(icollide));
|
||||
}
|
||||
|
||||
//
|
||||
void btDbvt::collide(ICollide* icollide) const
|
||||
{
|
||||
if(m_root)
|
||||
{
|
||||
btAlignedObjectArray<const Node*> stack;
|
||||
stack.reserve(64);
|
||||
stack.push_back(m_root);
|
||||
do {
|
||||
const Node* n=stack[stack.size()-1];
|
||||
stack.pop_back();
|
||||
if(icollide->Descent(n))
|
||||
{
|
||||
if(n->isinternal())
|
||||
{ stack.push_back(n->childs[0]);stack.push_back(n->childs[1]); }
|
||||
else
|
||||
{ icollide->Process(n); }
|
||||
}
|
||||
} while(stack.size()>0);
|
||||
}
|
||||
collideGeneric(GCollide(icollide));
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ subject to the following restrictions:
|
||||
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.
|
||||
*/
|
||||
///btSoftBody implementation by Nathanael Presson
|
||||
///btDbvt implementation by Nathanael Presson
|
||||
|
||||
#ifndef BT_DYNAMIC_BOUNDING_VOLUME_TREE_H
|
||||
#define BT_DYNAMIC_BOUNDING_VOLUME_TREE_H
|
||||
@@ -20,46 +20,52 @@ subject to the following restrictions:
|
||||
#include "LinearMath/btAlignedObjectArray.h"
|
||||
#include "LinearMath/btVector3.h"
|
||||
|
||||
//
|
||||
// Defaults volumes
|
||||
//
|
||||
|
||||
/* btDbvtAabbMm */
|
||||
struct btDbvtAabbMm
|
||||
{
|
||||
inline btVector3 Center() const { return((mi+mx)/2); }
|
||||
inline btVector3 Extent() 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);
|
||||
static inline btDbvtAabbMm FromPoints(const btVector3* pts,int n);
|
||||
static inline btDbvtAabbMm FromPoints(const btVector3** ppts,int n);
|
||||
inline void Expand(const btVector3 e);
|
||||
inline void SignedExpand(const btVector3 e);
|
||||
inline bool Contain(const btDbvtAabbMm& a) const;
|
||||
inline friend bool Intersect( const btDbvtAabbMm& a,
|
||||
const btDbvtAabbMm& b);
|
||||
inline friend bool Intersect( const btDbvtAabbMm& a,
|
||||
const btVector3& b);
|
||||
inline friend btScalar Proximity( const btDbvtAabbMm& a,
|
||||
const btDbvtAabbMm& b);
|
||||
inline friend void Merge( const btDbvtAabbMm& a,
|
||||
const btDbvtAabbMm& b,
|
||||
btDbvtAabbMm& r);
|
||||
inline friend bool NotEqual( const btDbvtAabbMm& a,
|
||||
const btDbvtAabbMm& b);
|
||||
private:
|
||||
btVector3 mi,mx;
|
||||
};
|
||||
|
||||
//
|
||||
// Dynamic bounding volume tree
|
||||
//
|
||||
struct btDbvt
|
||||
{
|
||||
// Types
|
||||
|
||||
/* Aabb */
|
||||
struct Aabb
|
||||
{
|
||||
inline btVector3 Center() const { return((mi+mx)/2); }
|
||||
inline btVector3 Extent() 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 Aabb FromCE(const btVector3& c,const btVector3& e);
|
||||
static inline Aabb FromCR(const btVector3& c,btScalar r);
|
||||
static inline Aabb FromMM(const btVector3& mi,const btVector3& mx);
|
||||
static inline Aabb FromPoints(const btVector3* pts,int n);
|
||||
static inline Aabb FromPoints(const btVector3** ppts,int n);
|
||||
inline void Expand(const btVector3 e);
|
||||
inline void SignedExpand(const btVector3 e);
|
||||
inline bool Contain(const Aabb& a) const;
|
||||
inline friend bool Intersect( const Aabb& a,
|
||||
const Aabb& b);
|
||||
inline friend bool Intersect( const Aabb& a,
|
||||
const btVector3& b);
|
||||
inline friend btScalar Proximity( const Aabb& a,
|
||||
const Aabb& b);
|
||||
inline friend void Merge( const Aabb& a,
|
||||
const Aabb& b,
|
||||
Aabb& r);
|
||||
inline friend bool NotEqual( const Aabb& a,
|
||||
const Aabb& b);
|
||||
btVector3 mi,mx;
|
||||
};
|
||||
// Types
|
||||
typedef btDbvtAabbMm Volume;
|
||||
/* Node */
|
||||
struct Node
|
||||
{
|
||||
Aabb box;
|
||||
Volume volume;
|
||||
Node* parent;
|
||||
bool isleaf() const { return(childs[1]==0); }
|
||||
bool isinternal() const { return(!isleaf()); }
|
||||
@@ -83,55 +89,62 @@ struct btDbvt
|
||||
{
|
||||
virtual void Process(const Node*,const Node*) {}
|
||||
virtual void Process(const Node*) {}
|
||||
virtual bool Descent(const Node*) { return(false); }
|
||||
virtual bool Descent(const Node*) { return(false); }
|
||||
};
|
||||
/* GCollide */
|
||||
struct GCollide
|
||||
{
|
||||
ICollide* icollide;
|
||||
GCollide(ICollide* ic) : icollide(ic) {}
|
||||
void Process(const Node* a,const Node* b) { icollide->Process(a,b); }
|
||||
void Process(const Node* a) { icollide->Process(a); }
|
||||
bool Descent(const Node* a) { return(icollide->Descent(a)); }
|
||||
};
|
||||
|
||||
// Constants
|
||||
enum {
|
||||
TREETREE_STACKSIZE = 128,
|
||||
VOLUMETREE_STACKSIZE = 64,
|
||||
};
|
||||
|
||||
// Fields
|
||||
Node* m_root;
|
||||
Node* m_free;
|
||||
int m_lkhd;
|
||||
int m_leafs;
|
||||
// Methods
|
||||
btDbvt();
|
||||
~btDbvt();
|
||||
void clear();
|
||||
bool empty() const { return(0==m_root); }
|
||||
int leafCount() const;
|
||||
void optimizeBottomUp();
|
||||
void optimizeTopDown(int bu_treshold=128);
|
||||
Node* insert(const Aabb& box,void* data);
|
||||
void update(Node* leaf,const Aabb& box);
|
||||
bool update(Node* leaf,Aabb box,const btVector3& velocity,btScalar margin);
|
||||
Node* insert(const Volume& box,void* data);
|
||||
void update(Node* leaf,int lookahead=1);
|
||||
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);
|
||||
void remove(Node* leaf);
|
||||
void collide(btDbvt* tree,
|
||||
ICollide* icollide) const;
|
||||
void collide(const Aabb& box,
|
||||
void collide(btDbvt::Node* node,
|
||||
ICollide* icollide) const;
|
||||
void collide(const Volume& volume,
|
||||
ICollide* icollide) const;
|
||||
void collide(const btVector3& org,
|
||||
const btVector3& dir,
|
||||
ICollide* icollide) const;
|
||||
void collide(ICollide* icollide) const;
|
||||
// Generics
|
||||
template <typename T/* must implement ICollide*/>
|
||||
void collideGeneric(T& policy) const
|
||||
{
|
||||
if(m_root)
|
||||
{
|
||||
btAlignedObjectArray<const Node*> stack;
|
||||
stack.reserve(64);
|
||||
stack.push_back(m_root);
|
||||
do {
|
||||
const Node* 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);
|
||||
}
|
||||
}
|
||||
// Generics : T must implement ICollide
|
||||
template <typename T>
|
||||
void collideGeneric( btDbvt* tree,T& policy) const;
|
||||
template <typename T>
|
||||
void collideGeneric( btDbvt::Node* node,T& policy) const;
|
||||
template <typename T>
|
||||
void collideGeneric(const Volume& volume,T& policy) const;
|
||||
template <typename T>
|
||||
void collideGeneric(T& policy) const;
|
||||
//
|
||||
private:
|
||||
btDbvt(const btDbvt&) {}
|
||||
@@ -142,31 +155,31 @@ struct btDbvt
|
||||
//
|
||||
|
||||
//
|
||||
inline btDbvt::Aabb btDbvt::Aabb::FromCE(const btVector3& c,const btVector3& e)
|
||||
inline btDbvtAabbMm btDbvtAabbMm::FromCE(const btVector3& c,const btVector3& e)
|
||||
{
|
||||
Aabb box;
|
||||
btDbvtAabbMm box;
|
||||
box.mi=c-e;box.mx=c+e;
|
||||
return(box);
|
||||
}
|
||||
|
||||
//
|
||||
inline btDbvt::Aabb btDbvt::Aabb::FromCR(const btVector3& c,btScalar r)
|
||||
inline btDbvtAabbMm btDbvtAabbMm::FromCR(const btVector3& c,btScalar r)
|
||||
{
|
||||
return(FromCE(c,btVector3(r,r,r)));
|
||||
}
|
||||
|
||||
//
|
||||
inline btDbvt::Aabb btDbvt::Aabb::FromMM(const btVector3& mi,const btVector3& mx)
|
||||
inline btDbvtAabbMm btDbvtAabbMm::FromMM(const btVector3& mi,const btVector3& mx)
|
||||
{
|
||||
Aabb box;
|
||||
btDbvtAabbMm box;
|
||||
box.mi=mi;box.mx=mx;
|
||||
return(box);
|
||||
}
|
||||
|
||||
//
|
||||
inline btDbvt::Aabb btDbvt::Aabb::FromPoints(const btVector3* pts,int n)
|
||||
inline btDbvtAabbMm btDbvtAabbMm::FromPoints(const btVector3* pts,int n)
|
||||
{
|
||||
Aabb box;
|
||||
btDbvtAabbMm box;
|
||||
box.mi=box.mx=pts[0];
|
||||
for(int i=1;i<n;++i)
|
||||
{
|
||||
@@ -177,9 +190,9 @@ return(box);
|
||||
}
|
||||
|
||||
//
|
||||
inline btDbvt::Aabb btDbvt::Aabb::FromPoints(const btVector3** ppts,int n)
|
||||
inline btDbvtAabbMm btDbvtAabbMm::FromPoints(const btVector3** ppts,int n)
|
||||
{
|
||||
Aabb box;
|
||||
btDbvtAabbMm box;
|
||||
box.mi=box.mx=*ppts[0];
|
||||
for(int i=1;i<n;++i)
|
||||
{
|
||||
@@ -190,13 +203,13 @@ return(box);
|
||||
}
|
||||
|
||||
//
|
||||
inline void btDbvt::Aabb::Expand(const btVector3 e)
|
||||
inline void btDbvtAabbMm::Expand(const btVector3 e)
|
||||
{
|
||||
mi-=e;mx+=e;
|
||||
}
|
||||
|
||||
//
|
||||
inline void btDbvt::Aabb::SignedExpand(const btVector3 e)
|
||||
inline void btDbvtAabbMm::SignedExpand(const btVector3 e)
|
||||
{
|
||||
if(e.x()>0) mx.setX(mx.x()+e.x()); else mi.setX(mi.x()+e.x());
|
||||
if(e.y()>0) mx.setY(mx.y()+e.y()); else mi.setY(mi.y()+e.y());
|
||||
@@ -204,7 +217,7 @@ if(e.z()>0) mx.setZ(mx.z()+e.z()); else mi.setZ(mi.z()+e.z());
|
||||
}
|
||||
|
||||
//
|
||||
inline bool btDbvt::Aabb::Contain(const Aabb& a) const
|
||||
inline bool btDbvtAabbMm::Contain(const btDbvtAabbMm& a) const
|
||||
{
|
||||
return( (mi.x()<=a.mi.x())&&
|
||||
(mi.y()<=a.mi.y())&&
|
||||
@@ -215,19 +228,33 @@ return( (mi.x()<=a.mi.x())&&
|
||||
}
|
||||
|
||||
//
|
||||
inline bool Intersect( const btDbvt::Aabb& a,
|
||||
const btDbvt::Aabb& b)
|
||||
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.mx.y()>=b.mi.y())&&
|
||||
(a.mx.z()>=b.mi.z()));
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
inline bool Intersect( const btDbvt::Aabb& a,
|
||||
inline bool Intersect( const btDbvtAabbMm& a,
|
||||
const btVector3& b)
|
||||
{
|
||||
return( (b.x()>=a.mi.x())&&
|
||||
@@ -239,17 +266,17 @@ return( (b.x()>=a.mi.x())&&
|
||||
}
|
||||
|
||||
//
|
||||
inline btScalar Proximity( const btDbvt::Aabb& a,
|
||||
const btDbvt::Aabb& b)
|
||||
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()));
|
||||
}
|
||||
|
||||
//
|
||||
inline void Merge( const btDbvt::Aabb& a,
|
||||
const btDbvt::Aabb& b,
|
||||
btDbvt::Aabb& r)
|
||||
inline void Merge( const btDbvtAabbMm& a,
|
||||
const btDbvtAabbMm& b,
|
||||
btDbvtAabbMm& r)
|
||||
{
|
||||
r=a;
|
||||
r.mi.setMin(b.mi);
|
||||
@@ -257,8 +284,8 @@ r.mx.setMax(b.mx);
|
||||
}
|
||||
|
||||
//
|
||||
inline bool NotEqual( const btDbvt::Aabb& a,
|
||||
const btDbvt::Aabb& b)
|
||||
inline bool NotEqual( const btDbvtAabbMm& a,
|
||||
const btDbvtAabbMm& b)
|
||||
{
|
||||
return( (a.mi.x()!=b.mi.x())||
|
||||
(a.mi.y()!=b.mi.y())||
|
||||
@@ -268,4 +295,121 @@ return( (a.mi.x()!=b.mi.x())||
|
||||
(a.mx.z()!=b.mx.z()));
|
||||
}
|
||||
|
||||
//
|
||||
// Generic's
|
||||
//
|
||||
|
||||
//
|
||||
template <typename T>
|
||||
inline void btDbvt::collideGeneric( btDbvt::Node* node,T& policy) const
|
||||
{
|
||||
if(m_root&&node)
|
||||
{
|
||||
btAlignedObjectArray<sStkElm> stack;
|
||||
stack.reserve(TREETREE_STACKSIZE);
|
||||
stack.push_back(sStkElm(m_root,node));
|
||||
do {
|
||||
sStkElm p=stack[stack.size()-1];
|
||||
stack.pop_back();
|
||||
if(p.a==p.b)
|
||||
{
|
||||
if(p.a->isinternal())
|
||||
{
|
||||
stack.push_back(sStkElm(p.a->childs[0],p.a->childs[0]));
|
||||
stack.push_back(sStkElm(p.a->childs[1],p.a->childs[1]));
|
||||
stack.push_back(sStkElm(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.push_back(sStkElm(p.a->childs[0],p.b->childs[0]));
|
||||
stack.push_back(sStkElm(p.a->childs[1],p.b->childs[0]));
|
||||
stack.push_back(sStkElm(p.a->childs[0],p.b->childs[1]));
|
||||
stack.push_back(sStkElm(p.a->childs[1],p.b->childs[1]));
|
||||
}
|
||||
else
|
||||
{
|
||||
stack.push_back(sStkElm(p.a->childs[0],p.b));
|
||||
stack.push_back(sStkElm(p.a->childs[1],p.b));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(p.b->isinternal())
|
||||
{
|
||||
stack.push_back(sStkElm(p.a,p.b->childs[0]));
|
||||
stack.push_back(sStkElm(p.a,p.b->childs[1]));
|
||||
}
|
||||
else
|
||||
{
|
||||
policy.Process(p.a,p.b);
|
||||
}
|
||||
}
|
||||
}
|
||||
} while(stack.size()>0);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
template <typename T>
|
||||
inline void btDbvt::collideGeneric( btDbvt* tree,T& policy) const
|
||||
{
|
||||
collideGeneric<T>(tree->m_root,policy);
|
||||
}
|
||||
|
||||
//
|
||||
template <typename T>
|
||||
inline void btDbvt::collideGeneric(const Volume& volume,T& policy) const
|
||||
{
|
||||
if(m_root)
|
||||
{
|
||||
btAlignedObjectArray<const Node*> stack;
|
||||
stack.reserve(VOLUMETREE_STACKSIZE);
|
||||
stack.push_back(m_root);
|
||||
do {
|
||||
const Node* 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);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
template <typename T>
|
||||
inline void btDbvt::collideGeneric(T& policy) const
|
||||
{
|
||||
if(m_root)
|
||||
{
|
||||
btAlignedObjectArray<const Node*> stack;
|
||||
stack.reserve(VOLUMETREE_STACKSIZE);
|
||||
stack.push_back(m_root);
|
||||
do {
|
||||
const Node* 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);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
342
src/BulletSoftBody/btDbvtBroadphase.cpp
Normal file
342
src/BulletSoftBody/btDbvtBroadphase.cpp
Normal file
@@ -0,0 +1,342 @@
|
||||
/*
|
||||
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
|
||||
#include <stdio.h>
|
||||
struct ProfileScope
|
||||
{
|
||||
ProfileScope(btClock& clock,unsigned long& value)
|
||||
{
|
||||
m_clock=&clock;
|
||||
m_value=&value;
|
||||
m_base=clock.getTimeMicroseconds();
|
||||
}
|
||||
~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
|
||||
//
|
||||
|
||||
//
|
||||
static inline int hash(unsigned int i,unsigned int j)
|
||||
{
|
||||
int key=((unsigned int)i)|(((unsigned int)j)<<16);
|
||||
key+=~(key<<15);
|
||||
key^= (key>>10);
|
||||
key+= (key<<3);
|
||||
key^= (key>>6);
|
||||
key+=~(key<<11);
|
||||
key^= (key>>16);
|
||||
return(key);
|
||||
}
|
||||
|
||||
//
|
||||
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 T zerodummy;
|
||||
value=zerodummy;
|
||||
}
|
||||
|
||||
//
|
||||
// Collider
|
||||
//
|
||||
struct btDbvtBroadphaseCollider : btDbvt::ICollide
|
||||
{
|
||||
btDbvtBroadphase* pbp;
|
||||
int pid;
|
||||
btDbvtBroadphaseCollider(btDbvtBroadphase* p,int id) : pbp(p),pid(id) {}
|
||||
void Process(const btDbvt::Node* na,const btDbvt::Node* nb)
|
||||
{
|
||||
btDbvtProxy* pa=(btDbvtProxy*)na->data;
|
||||
btDbvtProxy* pb=(btDbvtProxy*)nb->data;
|
||||
#if DBVT_BP_DISCRETPAIRS
|
||||
if(Intersect(pa->aabb,pb->aabb))
|
||||
#endif
|
||||
{
|
||||
btBroadphasePair* pp=pbp->m_paircache->addOverlappingPair(pa,pb);
|
||||
if(pp) pp->m_userInfo=*(void**)&pid;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// btDbvtBroadphase
|
||||
//
|
||||
|
||||
//
|
||||
btDbvtBroadphase::btDbvtBroadphase()
|
||||
{
|
||||
m_fcursor = 0;
|
||||
m_dcursor = 0;
|
||||
m_stageCurrent = 0;
|
||||
m_fupdates = 1;
|
||||
m_dupdates = 0;
|
||||
m_paircache = new btHashedOverlappingPairCache();
|
||||
m_gid = 0;
|
||||
m_pid = 0;
|
||||
for(int i=0;i<=STAGECOUNT;++i)
|
||||
{
|
||||
m_stageRoots[i]=0;
|
||||
}
|
||||
#if DBVT_BP_PROFILE
|
||||
clear(m_profiling);
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
btDbvtBroadphase::~btDbvtBroadphase()
|
||||
{
|
||||
delete 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 btDbvtProxy(userPtr,collisionFilterGroup,collisionFilterMask);
|
||||
proxy->aabb = btDbvtAabbMm::FromMM(aabbMin,aabbMax);
|
||||
proxy->leaf = m_sets[0].insert(proxy->aabb,proxy);
|
||||
proxy->stage = m_stageCurrent;
|
||||
proxy->m_uniqueId = ++m_gid;
|
||||
listappend(proxy,m_stageRoots[m_stageCurrent]);
|
||||
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);
|
||||
delete proxy;
|
||||
}
|
||||
|
||||
//
|
||||
void btDbvtBroadphase::setAabb( btBroadphaseProxy* absproxy,
|
||||
const btVector3& aabbMin,
|
||||
const btVector3& aabbMax,
|
||||
btDispatcher* dispatcher)
|
||||
{
|
||||
btDbvtProxy* proxy=(btDbvtProxy*)absproxy;
|
||||
btDbvtAabbMm aabb=btDbvtAabbMm::FromMM(aabbMin,aabbMax);
|
||||
if(proxy->stage==STAGECOUNT)
|
||||
{/* fixed -> dynamic set */
|
||||
m_sets[1].remove(proxy->leaf);
|
||||
proxy->leaf=m_sets[0].insert(aabb,proxy);
|
||||
m_fcursor=0;
|
||||
}
|
||||
else
|
||||
{/* dynamic set */
|
||||
const btVector3 delta=(aabbMin+aabbMax)/2-proxy->aabb.Center();
|
||||
m_sets[0].update(proxy->leaf,aabb,delta*PREDICTED_FRAMES,DBVT_BP_MARGIN);
|
||||
}
|
||||
listremove(proxy,m_stageRoots[proxy->stage]);
|
||||
proxy->aabb = aabb;
|
||||
proxy->stage = m_stageCurrent;
|
||||
listappend(proxy,m_stageRoots[m_stageCurrent]);
|
||||
}
|
||||
|
||||
//
|
||||
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_leafs,m_sets[0].m_leafs,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);
|
||||
clear(m_profiling);
|
||||
m_clock.reset();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
void btDbvtBroadphase::collide(btDispatcher* dispatcher)
|
||||
{
|
||||
SPC(m_profiling.m_total);
|
||||
/* refine dynamic */
|
||||
if(m_stageRoots[m_stageCurrent]&&(m_dupdates>0))
|
||||
{
|
||||
const int count=1+(m_sets[0].m_leafs*m_dupdates)/100;
|
||||
for(int i=0;i<count;++i)
|
||||
{
|
||||
if(!m_dcursor) m_dcursor=m_stageRoots[m_stageCurrent];
|
||||
m_sets[0].update(m_dcursor->leaf);
|
||||
m_dcursor=m_dcursor->links[1];
|
||||
}
|
||||
}
|
||||
/* dynamic -> fixed set */
|
||||
m_stageCurrent=(m_stageCurrent+1)%STAGECOUNT;
|
||||
btDbvtProxy* current=m_stageRoots[m_stageCurrent];
|
||||
if(current)
|
||||
{
|
||||
btDbvtBroadphaseCollider collider(this,m_pid);
|
||||
do {
|
||||
btDbvtProxy* next=current->links[1];
|
||||
if(m_dcursor==current) m_dcursor=0;
|
||||
listremove(current,m_stageRoots[current->stage]);
|
||||
listappend(current,m_stageRoots[STAGECOUNT]);
|
||||
m_sets[1].collideGeneric(current->leaf,collider);
|
||||
m_sets[0].remove(current->leaf);
|
||||
current->leaf = m_sets[1].insert(current->aabb,current);
|
||||
current->stage = STAGECOUNT;
|
||||
current = next;
|
||||
} while(current);
|
||||
}
|
||||
/* refine fixed */
|
||||
if(m_stageRoots[STAGECOUNT]&&(m_fupdates>0))
|
||||
{
|
||||
const int count=1+(m_sets[1].m_leafs*m_fupdates)/100;
|
||||
for(int i=0;i<count;++i)
|
||||
{
|
||||
if(!m_fcursor) m_fcursor=m_stageRoots[STAGECOUNT];
|
||||
m_sets[1].update(m_fcursor->leaf);
|
||||
m_fcursor=m_fcursor->links[1];
|
||||
}
|
||||
}
|
||||
/* collide dynamics */
|
||||
btDbvtBroadphaseCollider collider(this,m_pid);
|
||||
{
|
||||
SPC(m_profiling.m_fdcollide);
|
||||
m_sets[0].collideGeneric(&m_sets[1],collider);
|
||||
}
|
||||
{
|
||||
SPC(m_profiling.m_ddcollide);
|
||||
m_sets[0].collideGeneric(&m_sets[0],collider);
|
||||
}
|
||||
/* clean up */
|
||||
{
|
||||
SPC(m_profiling.m_cleanup);
|
||||
btBroadphasePairArray& pairs=m_paircache->getOverlappingPairArray();
|
||||
for(int i=0,ni=pairs.size();i<ni;++i)
|
||||
{
|
||||
btBroadphasePair& p=pairs[i];
|
||||
if(m_pid!=(*(int*)&p.m_userInfo))
|
||||
{
|
||||
btDbvtProxy* pa=(btDbvtProxy*)p.m_pProxy0;
|
||||
btDbvtProxy* pb=(btDbvtProxy*)p.m_pProxy1;
|
||||
if(!Intersect(pa->aabb,pb->aabb))
|
||||
{
|
||||
m_paircache->removeOverlappingPair(pa,pb,dispatcher);
|
||||
--ni;--i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
++m_pid;
|
||||
}
|
||||
|
||||
//
|
||||
btOverlappingPairCache* btDbvtBroadphase::getOverlappingPairCache()
|
||||
{
|
||||
return(m_paircache);
|
||||
}
|
||||
|
||||
//
|
||||
const btOverlappingPairCache* btDbvtBroadphase::getOverlappingPairCache() const
|
||||
{
|
||||
return(m_paircache);
|
||||
}
|
||||
|
||||
//
|
||||
void btDbvtBroadphase::getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const
|
||||
{
|
||||
btDbvtAabbMm 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=btDbvtAabbMm::FromCR(btVector3(0,0,0),0);
|
||||
aabbMin=bounds.Mins();
|
||||
aabbMax=bounds.Maxs();
|
||||
}
|
||||
|
||||
//
|
||||
void btDbvtBroadphase::printStats()
|
||||
{}
|
||||
|
||||
#if DBVT_BP_PROFILE
|
||||
#undef SPC
|
||||
#endif
|
||||
108
src/BulletSoftBody/btDbvtBroadphase.h
Normal file
108
src/BulletSoftBody/btDbvtBroadphase.h
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
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 "btDbvt.h"
|
||||
#include "LinearMath/btPoint3.h"
|
||||
#include "LinearMath/btVector3.h"
|
||||
#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
|
||||
#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
|
||||
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
|
||||
#include "BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h"
|
||||
#include "BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h"
|
||||
|
||||
//
|
||||
// Compile time config
|
||||
//
|
||||
|
||||
#define DBVT_BP_PROFILE 1
|
||||
#define DBVT_BP_DISCRETPAIRS 0
|
||||
#define DBVT_BP_MARGIN (btScalar)0.05
|
||||
|
||||
#if DBVT_BP_PROFILE
|
||||
#define DBVT_BP_PROFILING_RATE 50
|
||||
#include "LinearMath/btQuickprof.h"
|
||||
#endif
|
||||
|
||||
//
|
||||
// btDbvtProxy
|
||||
//
|
||||
struct btDbvtProxy : btBroadphaseProxy
|
||||
{
|
||||
/* Fields */
|
||||
btDbvtAabbMm aabb;
|
||||
btDbvt::Node* 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;
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// btDbvtBroadphase
|
||||
//
|
||||
struct btDbvtBroadphase : btBroadphaseInterface
|
||||
{
|
||||
/* Config */
|
||||
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
|
||||
int m_stageCurrent; // Current stage
|
||||
btOverlappingPairCache* m_paircache; // Pair cache
|
||||
btDbvtProxy* m_fcursor; // Current fixed cursor
|
||||
btDbvtProxy* m_dcursor; // Current dynamic cursor
|
||||
int m_fupdates; // % of fixed updates per frame
|
||||
int m_dupdates; // % of dynamic updates per frame
|
||||
int m_pid; // Parse id
|
||||
int m_gid; // Gen id
|
||||
#if DBVT_BP_PROFILE
|
||||
btClock m_clock;
|
||||
struct {
|
||||
unsigned long m_total;
|
||||
unsigned long m_ddcollide;
|
||||
unsigned long m_fdcollide;
|
||||
unsigned long m_cleanup;
|
||||
} m_profiling;
|
||||
#endif
|
||||
/* Methods */
|
||||
btDbvtBroadphase();
|
||||
~btDbvtBroadphase();
|
||||
void collide(btDispatcher* dispatcher);
|
||||
/* 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();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -39,12 +39,6 @@ public:
|
||||
// Enumerations
|
||||
//
|
||||
|
||||
///eLType
|
||||
struct eLType { enum _ {
|
||||
Structural, ///Master constraints
|
||||
Bending, ///Secondary constraints
|
||||
};};
|
||||
|
||||
///eAeroModel
|
||||
struct eAeroModel { enum _ {
|
||||
V_Point, ///Vertex normals are oriented toward velocity
|
||||
@@ -54,6 +48,40 @@ public:
|
||||
F_OneSided, ///Face normals are taken as it is
|
||||
};};
|
||||
|
||||
///eVSolver : velocities solvers
|
||||
struct eVSolver { enum _ {
|
||||
Linear, ///Linear solver
|
||||
Volume, ///Volume solver
|
||||
};};
|
||||
|
||||
///ePSolver : positions solvers
|
||||
struct ePSolver { enum _ {
|
||||
Linear, ///Linear solver
|
||||
Volume, ///Volume solver
|
||||
Anchors, ///Anchor solver
|
||||
RContacts, ///Rigid contacts solver
|
||||
SContacts, ///Soft contacts solver
|
||||
};};
|
||||
|
||||
///eSolverPresets
|
||||
struct eSolverPresets { enum _ {
|
||||
Positions,
|
||||
Velocities,
|
||||
Default = Positions,
|
||||
};};
|
||||
|
||||
///eFeature
|
||||
struct eFeature { enum _ {
|
||||
None,
|
||||
Node,
|
||||
Link,
|
||||
Face,
|
||||
Tetra,
|
||||
};};
|
||||
|
||||
typedef btAlignedObjectArray<eVSolver::_> tVSolverArray;
|
||||
typedef btAlignedObjectArray<ePSolver::_> tPSolverArray;
|
||||
|
||||
//
|
||||
// Flags
|
||||
//
|
||||
@@ -69,6 +97,13 @@ public:
|
||||
Default = SDF_RS,
|
||||
};};
|
||||
|
||||
///fMaterial
|
||||
struct fMaterial { enum _ {
|
||||
DebugDraw = 0x0001, /// Enable debug draw
|
||||
/* presets */
|
||||
Default = DebugDraw,
|
||||
};};
|
||||
|
||||
//
|
||||
// API Types
|
||||
//
|
||||
@@ -76,8 +111,16 @@ public:
|
||||
/* sRayCast */
|
||||
struct sRayCast
|
||||
{
|
||||
int face; /// face
|
||||
btScalar time; /// time of impact (rayorg+raydir*time)
|
||||
btSoftBody* body; /// soft body
|
||||
eFeature::_ feature; /// feature type
|
||||
int index; /// feature index
|
||||
btScalar time; /// time of impact (rayorg+raydir*time)
|
||||
};
|
||||
|
||||
/* ImplicitFn */
|
||||
struct ImplicitFn
|
||||
{
|
||||
virtual btScalar Eval(const btVector3& x)=0;
|
||||
};
|
||||
|
||||
//
|
||||
@@ -86,7 +129,6 @@ public:
|
||||
|
||||
typedef btAlignedObjectArray<btScalar> tScalarArray;
|
||||
typedef btAlignedObjectArray<btVector3> tVector3Array;
|
||||
|
||||
/* btSoftBodyWorldInfo */
|
||||
struct btSoftBodyWorldInfo
|
||||
{
|
||||
@@ -121,8 +163,22 @@ public:
|
||||
{
|
||||
void* m_tag; // User data
|
||||
};
|
||||
/* Material */
|
||||
struct Material : Element
|
||||
{
|
||||
btScalar m_kLST; // Linear stiffness coefficient [0,1]
|
||||
btScalar m_kAST; // Area stiffness coefficient [0,1]
|
||||
btScalar m_kVST; // Volume stiffness coefficient [0,1]
|
||||
int m_flags; // Flags
|
||||
};
|
||||
|
||||
/* Feature */
|
||||
struct Feature : Element
|
||||
{
|
||||
Material* m_material; // Material
|
||||
};
|
||||
/* Node */
|
||||
struct Node : Element
|
||||
struct Node : Feature
|
||||
{
|
||||
btVector3 m_x; // Position
|
||||
btVector3 m_q; // Previous step position
|
||||
@@ -135,23 +191,33 @@ public:
|
||||
int m_battach:1; // Attached
|
||||
};
|
||||
/* Link */
|
||||
struct Link : Element
|
||||
struct Link : Feature
|
||||
{
|
||||
Node* m_n[2]; // Node pointers
|
||||
btScalar m_rl; // Rest length
|
||||
btScalar m_kST; // Stiffness coefficient
|
||||
btScalar m_c0; // (ima+imb)*kLST
|
||||
btScalar m_c1; // rl^2
|
||||
btSoftBody::eLType::_ m_type; // Link type
|
||||
btScalar m_c2; // |gradient|^2/c0
|
||||
btVector3 m_c3; // gradient
|
||||
};
|
||||
/* Face */
|
||||
struct Face : Element
|
||||
struct Face : Feature
|
||||
{
|
||||
Node* m_n[3]; // Node pointers
|
||||
btVector3 m_normal; // Normal
|
||||
btScalar m_ra; // Rest area
|
||||
btDbvt::Node* m_leaf; // Leaf data
|
||||
};
|
||||
/* Tetra */
|
||||
struct Tetra : Feature
|
||||
{
|
||||
Node* m_n[4]; // Node pointers
|
||||
btScalar m_rv; // Rest volume
|
||||
btDbvt::Node* m_leaf; // Leaf data
|
||||
btVector3 m_c0[4]; // gradients
|
||||
btScalar m_c1; // (4*kVST)/(im0+im1+im2+im3)
|
||||
btScalar m_c2; // m_c1/sum(|g0..3|^2)
|
||||
};
|
||||
/* RContact */
|
||||
struct RContact
|
||||
{
|
||||
@@ -184,6 +250,15 @@ public:
|
||||
btVector3 m_c1; // Relative anchor
|
||||
btScalar m_c2; // ima*dt
|
||||
};
|
||||
/* Note */
|
||||
struct Note : Element
|
||||
{
|
||||
const char* m_text; // Text
|
||||
btVector3 m_offset; // Offset
|
||||
int m_rank; // Rank
|
||||
Node* m_nodes[4]; // Nodes
|
||||
btScalar m_coords[4]; // Coordinates
|
||||
};
|
||||
/* Pose */
|
||||
struct Pose
|
||||
{
|
||||
@@ -197,16 +272,11 @@ public:
|
||||
btMatrix3x3 m_scl; // Scale
|
||||
btMatrix3x3 m_aqq; // Base scaling
|
||||
};
|
||||
/* DFld */
|
||||
struct DFld
|
||||
{
|
||||
btAlignedObjectArray<btVector3> pts;
|
||||
};
|
||||
/* Config */
|
||||
struct Config
|
||||
{
|
||||
btSoftBody::eAeroModel::_ aeromodel; // Aerodynamic model (default: V_Point)
|
||||
btScalar kLST; // Linear stiffness coefficient [0,1]
|
||||
eAeroModel::_ aeromodel; // Aerodynamic model (default: V_Point)
|
||||
btScalar kVCF; // Velocities correction factor (Baumgarte)
|
||||
btScalar kDP; // Damping coefficient [0,1]
|
||||
btScalar kDG; // Drag coefficient [0,+inf]
|
||||
btScalar kLF; // Lift coefficient [0,+inf]
|
||||
@@ -214,19 +284,23 @@ public:
|
||||
btScalar kVC; // Volume conversation coefficient [0,+inf]
|
||||
btScalar kDF; // Dynamic friction coefficient [0,1]
|
||||
btScalar kMT; // Pose matching coefficient [0,1]
|
||||
btScalar kSOR; // SOR(w) [1,2] default 1, never use with solver!=Accurate
|
||||
btScalar kCHR; // Rigid contacts hardness [0,1]
|
||||
btScalar kKHR; // Kinetic contacts hardness [0,1]
|
||||
btScalar kSHR; // Soft contacts hardness [0,1]
|
||||
btScalar kAHR; // Anchors hardness [0,1]
|
||||
btScalar maxvolume; // Maximum volume ratio for pose
|
||||
btScalar timescale; // Time scale
|
||||
int iterations; // Solver iterations
|
||||
int viterations; // Velocities solver iterations
|
||||
int piterations; // Positions solver iterations
|
||||
int diterations; // Drift solver iterations
|
||||
int collisions; // Collisions flags
|
||||
tVSolverArray m_vsequence; // Velocity solvers sequence
|
||||
tPSolverArray m_psequence; // Position solvers sequence
|
||||
tPSolverArray m_dsequence; // Drift solvers sequence
|
||||
};
|
||||
/* SolverState */
|
||||
struct SolverState
|
||||
{
|
||||
btScalar iit; // 1/iterations
|
||||
btScalar sdt; // dt*timescale
|
||||
btScalar isdt; // 1/sdt
|
||||
btScalar velmrg; // velocity margin
|
||||
@@ -238,14 +312,17 @@ public:
|
||||
// Typedef's
|
||||
//
|
||||
|
||||
typedef btAlignedObjectArray<Note> tNoteArray;
|
||||
typedef btAlignedObjectArray<Node> tNodeArray;
|
||||
typedef btAlignedObjectArray<btDbvt::Node*> tLeafArray;
|
||||
typedef btAlignedObjectArray<Link> tLinkArray;
|
||||
typedef btAlignedObjectArray<Face> tFaceArray;
|
||||
typedef btAlignedObjectArray<Tetra> tTetraArray;
|
||||
typedef btAlignedObjectArray<Anchor> tAnchorArray;
|
||||
typedef btAlignedObjectArray<RContact> tRContactArray;
|
||||
typedef btAlignedObjectArray<SContact> tSContactArray;
|
||||
typedef btAlignedObjectArray<btSoftBody*> tSoftBodyArray;
|
||||
typedef btAlignedObjectArray<Material*> tMaterialArray;
|
||||
typedef btAlignedObjectArray<btSoftBody*> tSoftBodyArray;
|
||||
|
||||
//
|
||||
// Fields
|
||||
@@ -254,18 +331,22 @@ public:
|
||||
Config m_cfg; // Configuration
|
||||
SolverState m_sst; // Solver state
|
||||
Pose m_pose; // Pose
|
||||
DFld m_dfld; // Distance field
|
||||
void* m_tag; // User data
|
||||
btSoftBodyWorldInfo* m_worldInfo; //
|
||||
tNoteArray m_notes; // Notes
|
||||
tNodeArray m_nodes; // Nodes
|
||||
tLinkArray m_links; // Links
|
||||
tFaceArray m_faces; // Faces
|
||||
tTetraArray m_tetras; // Tetras
|
||||
tAnchorArray m_anchors; // Anchors
|
||||
tRContactArray m_rcontacts; // Rigid contacts
|
||||
tSContactArray m_scontacts; // Soft contacts
|
||||
tMaterialArray m_materials; // Materials
|
||||
btScalar m_timeacc; // Time accumulator
|
||||
btVector3 m_bounds[2]; // Spatial bounds
|
||||
bool m_bUpdateRtCst; // Update runtime constants
|
||||
btDbvt m_ndbvt; // Nodes tree
|
||||
btDbvt m_fdbvt; // Faces tree
|
||||
|
||||
//
|
||||
// Api
|
||||
//
|
||||
@@ -285,71 +366,120 @@ public:
|
||||
bool checkFace( int node0,
|
||||
int node1,
|
||||
int node2) const;
|
||||
/* Append material */
|
||||
Material* appendMaterial();
|
||||
/* Append note */
|
||||
void appendNote( const char* text,
|
||||
const btVector3& o,
|
||||
const btVector4& c=btVector4(1,0,0,0),
|
||||
Node* n0=0,
|
||||
Node* n1=0,
|
||||
Node* n2=0,
|
||||
Node* n3=0);
|
||||
void appendNote( const char* text,
|
||||
const btVector3& o,
|
||||
Node* feature);
|
||||
void appendNote( const char* text,
|
||||
const btVector3& o,
|
||||
Link* feature);
|
||||
void appendNote( const char* text,
|
||||
const btVector3& o,
|
||||
Face* feature);
|
||||
void appendNote( const char* text,
|
||||
const btVector3& o,
|
||||
Tetra* feature);
|
||||
/* Append node */
|
||||
void appendNode( const btVector3& x,btScalar m);
|
||||
/* Append link */
|
||||
void appendLink( int node0,
|
||||
int node1,
|
||||
btScalar kST,
|
||||
btSoftBody::eLType::_ type,
|
||||
bool bcheckexist=false);
|
||||
void appendLink( btSoftBody::Node* node0,
|
||||
btSoftBody::Node* node1,
|
||||
btScalar kST,
|
||||
btSoftBody::eLType::_ type,
|
||||
bool bcheckexist=false);
|
||||
void appendLink(int model=-1,Material* mat=0);
|
||||
void appendLink( int node0,
|
||||
int node1,
|
||||
Material* mat=0,
|
||||
bool bcheckexist=false);
|
||||
void appendLink( btSoftBody::Node* node0,
|
||||
btSoftBody::Node* node1,
|
||||
Material* mat=0,
|
||||
bool bcheckexist=false);
|
||||
/* Append face */
|
||||
void appendFace( int node0,
|
||||
int node1,
|
||||
int node2);
|
||||
void appendFace(int model=-1,Material* mat=0);
|
||||
void appendFace( int node0,
|
||||
int node1,
|
||||
int node2,
|
||||
Material* mat=0);
|
||||
/* Append tetrahedron */
|
||||
void appendTetra(int model=-1,Material* mat=0);
|
||||
void appendTetra(int node0,
|
||||
int node1,
|
||||
int node2,
|
||||
int node3,
|
||||
Material* mat=0);
|
||||
/* Append anchor */
|
||||
void appendAnchor( int node,
|
||||
btRigidBody* body);
|
||||
btRigidBody* body);
|
||||
/* Add force (or gravity) to the entire body */
|
||||
void addForce( const btVector3& force);
|
||||
/* Add force (or gravity) to a node of the body */
|
||||
void addForce( const btVector3& force,
|
||||
int node);
|
||||
int node);
|
||||
/* Add velocity to the entire body */
|
||||
void addVelocity( const btVector3& velocity);
|
||||
/* Add velocity to a node of the body */
|
||||
void addVelocity( const btVector3& velocity,
|
||||
int node);
|
||||
int node);
|
||||
/* Set mass */
|
||||
void setMass( int node,
|
||||
btScalar mass);
|
||||
btScalar mass);
|
||||
/* Get mass */
|
||||
btScalar getMass( int node) const;
|
||||
/* Get total mass */
|
||||
btScalar getTotalMass() const;
|
||||
/* Set total mass (weighted by previous masses) */
|
||||
void setTotalMass( btScalar mass,
|
||||
bool fromfaces=false);
|
||||
bool fromfaces=false);
|
||||
/* Set total density */
|
||||
void setTotalDensity(btScalar density);
|
||||
/* Set volume mass (using tetrahedrons) */
|
||||
void setVolumeMass( btScalar mass);
|
||||
/* Set volume density (using tetrahedrons) */
|
||||
void setVolumeDensity( btScalar density);
|
||||
/* Transform */
|
||||
void transform( const btTransform& trs);
|
||||
/* Translate */
|
||||
void translate( const btVector3& trs);
|
||||
/* Rotate */
|
||||
void rotate( const btQuaternion& rot);
|
||||
/* Scale */
|
||||
void scale( const btVector3& scl);
|
||||
void scale( const btVector3& scl);
|
||||
/* Set current state as pose */
|
||||
void setPose( bool bvolume,
|
||||
bool bframe);
|
||||
/* Set current state as distance field */
|
||||
void setDistanceField(int nominalresolution);
|
||||
/* Return the volume */
|
||||
btScalar getVolume() const;
|
||||
/* Generate bending constraints based on distance in the adjency graph */
|
||||
int generateBendingConstraints( int distance,
|
||||
btScalar stiffness);
|
||||
Material* mat=0);
|
||||
/* Generate tetrahedral constraints */
|
||||
int generateTetrahedralConstraints();
|
||||
/* Randomize constraints to reduce solver bias */
|
||||
void randomizeConstraints();
|
||||
/* Refine */
|
||||
void refine(ImplicitFn* ifn,btScalar accurary,bool cut);
|
||||
/* CutLink */
|
||||
bool cutLink(int node0,int node1,btScalar position);
|
||||
bool cutLink(const Node* node0,const Node* node1,btScalar position);
|
||||
/* Ray casting */
|
||||
bool rayCast(const btVector3& org,
|
||||
const btVector3& dir,
|
||||
sRayCast& results,
|
||||
btScalar maxtime=SIMD_INFINITY);
|
||||
/* Solver presets */
|
||||
void setSolver(eSolverPresets::_ preset);
|
||||
/* predictMotion */
|
||||
void predictMotion(btScalar dt);
|
||||
/* solveConstraints */
|
||||
void solveConstraints();
|
||||
/* staticSolve */
|
||||
void staticSolve(int iterations);
|
||||
/* solveCommonConstraints */
|
||||
static void solveCommonConstraints(btSoftBody** bodies,int count,int iterations);
|
||||
/* integrateMotion */
|
||||
@@ -357,24 +487,7 @@ public:
|
||||
/* defaultCollisionHandlers */
|
||||
void defaultCollisionHandler(btCollisionObject* pco);
|
||||
void defaultCollisionHandler(btSoftBody* psb);
|
||||
|
||||
//
|
||||
// Accessor's and cast.
|
||||
//
|
||||
|
||||
tNodeArray& getNodes();
|
||||
const tNodeArray& getNodes() const;
|
||||
tLinkArray& getLinks();
|
||||
const tLinkArray& getLinks() const;
|
||||
tFaceArray& getFaces();
|
||||
const tFaceArray& getFaces() const;
|
||||
|
||||
virtual void getAabb(btVector3& aabbMin,btVector3& aabbMax) const
|
||||
{
|
||||
aabbMin = m_bounds[0];
|
||||
aabbMax = m_bounds[1];
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Cast
|
||||
//
|
||||
@@ -391,6 +504,13 @@ public:
|
||||
return (btSoftBody*)colObj;
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void getAabb(btVector3& aabbMin,btVector3& aabbMax) const
|
||||
{
|
||||
aabbMin = m_bounds[0];
|
||||
aabbMax = m_bounds[1];
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -71,15 +71,27 @@ if(node)
|
||||
if(depth>=mindepth)
|
||||
{
|
||||
const btScalar scl=(btScalar)(node->isinternal()?1:1);
|
||||
const btVector3 mi=node->box.Center()-node->box.Extent()*scl;
|
||||
const btVector3 mx=node->box.Center()+node->box.Extent()*scl;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
#if 0
|
||||
//
|
||||
static inline btScalar tetravolume(const btVector3& x0,
|
||||
const btVector3& x1,
|
||||
const btVector3& x2,
|
||||
const btVector3& x3)
|
||||
{
|
||||
const btVector3 a=x1-x0;
|
||||
const btVector3 b=x2-x0;
|
||||
const btVector3 c=x3-x0;
|
||||
return(dot(a,cross(b,c)));
|
||||
}
|
||||
|
||||
//
|
||||
static btVector3 stresscolor(btScalar stress)
|
||||
{
|
||||
static const btVector3 spectrum[]= { btVector3(1,0,1),
|
||||
@@ -96,7 +108,6 @@ static btVector3 stresscolor(btScalar stress)
|
||||
const btScalar frc=stress-sel;
|
||||
return(spectrum[sel]+(spectrum[sel+1]-spectrum[sel])*frc);
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
void btSoftBodyHelpers::Draw( btSoftBody* psb,
|
||||
@@ -105,16 +116,16 @@ void btSoftBodyHelpers::Draw( btSoftBody* psb,
|
||||
{
|
||||
const btScalar scl=(btScalar)0.1;
|
||||
const btScalar nscl=scl*5;
|
||||
const btVector3 scolor=btVector3(0,0,0);
|
||||
const btVector3 bcolor=btVector3(1,1,0);
|
||||
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;i<psb->getNodes().size();++i)
|
||||
for(int i=0;i<psb->m_nodes.size();++i)
|
||||
{
|
||||
const btSoftBody::Node& n=psb->getNodes()[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));
|
||||
@@ -123,24 +134,20 @@ void btSoftBodyHelpers::Draw( btSoftBody* psb,
|
||||
/* Links */
|
||||
if(0!=(drawflags&fDrawFlags::Links))
|
||||
{
|
||||
for(int i=0;i<psb->getLinks().size();++i)
|
||||
for(int i=0;i<psb->m_links.size();++i)
|
||||
{
|
||||
const btSoftBody::Link& l=psb->getLinks()[i];
|
||||
switch(l.m_type)
|
||||
{
|
||||
case btSoftBody::eLType::Structural:
|
||||
if(0!=(drawflags&fDrawFlags::SLinks)) idraw->drawLine(l.m_n[0]->m_x,l.m_n[1]->m_x,scolor);break;
|
||||
case btSoftBody::eLType::Bending:
|
||||
if(0!=(drawflags&fDrawFlags::BLinks)) idraw->drawLine(l.m_n[0]->m_x,l.m_n[1]->m_x,bcolor);break;
|
||||
}
|
||||
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;i<psb->getNodes().size();++i)
|
||||
for(int i=0;i<psb->m_nodes.size();++i)
|
||||
{
|
||||
const btSoftBody::Node& n=psb->getNodes()[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);
|
||||
@@ -175,9 +182,10 @@ void btSoftBodyHelpers::Draw( btSoftBody* psb,
|
||||
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;i<psb->getNodes().size();++i)
|
||||
for(int i=0;i<psb->m_nodes.size();++i)
|
||||
{
|
||||
const btSoftBody::Node& n=psb->getNodes()[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));
|
||||
@@ -187,21 +195,61 @@ void btSoftBodyHelpers::Draw( btSoftBody* psb,
|
||||
/* Faces */
|
||||
if(0!=(drawflags&fDrawFlags::Faces))
|
||||
{
|
||||
const btScalar scl=(btScalar)0.7;
|
||||
const btScalar scl=(btScalar)0.8;
|
||||
const btScalar alp=(btScalar)1;
|
||||
const btVector3 col(0,(btScalar)0.7,0);
|
||||
for(int i=0;i<psb->getFaces().size();++i)
|
||||
for(int i=0;i<psb->m_faces.size();++i)
|
||||
{
|
||||
const btSoftBody::Face& f=psb->getFaces()[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);
|
||||
col,alp);*/
|
||||
}
|
||||
}
|
||||
/* Tetras */
|
||||
if(0!=(drawflags&fDrawFlags::Tetras))
|
||||
{
|
||||
const btScalar scl=(btScalar)0.8;
|
||||
const btScalar alp=(btScalar)1;
|
||||
const btVector3 col((btScalar)0.7,(btScalar)0.7,(btScalar)0.7);
|
||||
for(int i=0;i<psb->m_tetras.size();++i)
|
||||
{
|
||||
const btSoftBody::Tetra& t=psb->m_tetras[i];
|
||||
if(0==(t.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue;
|
||||
const btVector3 x[]={t.m_n[0]->m_x,t.m_n[1]->m_x,t.m_n[2]->m_x,t.m_n[3]->m_x};
|
||||
const btVector3 c=(x[0]+x[1]+x[2]+x[3])/4;
|
||||
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[3]-c)*scl+c,col,alp);
|
||||
idraw->drawTriangle((x[1]-c)*scl+c,(x[2]-c)*scl+c,(x[3]-c)*scl+c,col,alp);
|
||||
idraw->drawTriangle((x[2]-c)*scl+c,(x[0]-c)*scl+c,(x[3]-c)*scl+c,col,alp);
|
||||
}
|
||||
}
|
||||
/* Notes */
|
||||
if(0!=(drawflags&fDrawFlags::Notes))
|
||||
{
|
||||
for(int i=0;i<psb->m_notes.size();++i)
|
||||
{
|
||||
const btSoftBody::Note& n=psb->m_notes[i];
|
||||
btVector3 p=n.m_offset;
|
||||
for(int j=0;j<n.m_rank;++j)
|
||||
{
|
||||
p+=n.m_nodes[j]->m_x*n.m_coords[j];
|
||||
}
|
||||
idraw->draw3dText(p,n.m_text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
@@ -211,9 +259,9 @@ void btSoftBodyHelpers::DrawInfos( btSoftBody* psb,
|
||||
bool areas,
|
||||
bool /*stress*/)
|
||||
{
|
||||
for(int i=0;i<psb->getNodes().size();++i)
|
||||
for(int i=0;i<psb->m_nodes.size();++i)
|
||||
{
|
||||
const btSoftBody::Node& n=psb->getNodes()[i];
|
||||
const btSoftBody::Node& n=psb->m_nodes[i];
|
||||
char text[2048]={0};
|
||||
char buff[1024];
|
||||
if(masses)
|
||||
@@ -269,11 +317,6 @@ void btSoftBodyHelpers::DrawFrame( btSoftBody* psb,
|
||||
const btVector3 x=com+trs*psb->m_pose.m_pos[i];
|
||||
drawVertex(idraw,x,nscl,btVector3(1,0,1));
|
||||
}
|
||||
for(int i=0;i<psb->m_dfld.pts.size();++i)
|
||||
{
|
||||
const btVector3 x=com+trs*psb->m_dfld.pts[i];
|
||||
drawVertex(idraw,x,nscl*(btScalar)0.5,btVector3(0,0,1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -301,7 +344,7 @@ btSoftBody* btSoftBodyHelpers::CreateRope( btSoftBody::btSoftBodyWorldInfo& wor
|
||||
/* Create links */
|
||||
for(int i=1;i<r;++i)
|
||||
{
|
||||
psb->appendLink(i-1,i,1,btSoftBody::eLType::Structural);
|
||||
psb->appendLink(i-1,i);
|
||||
}
|
||||
/* Finished */
|
||||
return(psb);
|
||||
@@ -352,10 +395,8 @@ btSoftBody* btSoftBodyHelpers::CreatePatch(btSoftBody::btSoftBodyWorldInfo& wor
|
||||
const int idx=IDX(ix,iy);
|
||||
const bool mdx=(ix+1)<rx;
|
||||
const bool mdy=(iy+1)<ry;
|
||||
if(mdx) psb->appendLink(idx,IDX(ix+1,iy),
|
||||
1,btSoftBody::eLType::Structural);
|
||||
if(mdy) psb->appendLink(idx,IDX(ix,iy+1),
|
||||
1,btSoftBody::eLType::Structural);
|
||||
if(mdx) psb->appendLink(idx,IDX(ix+1,iy));
|
||||
if(mdy) psb->appendLink(idx,IDX(ix,iy+1));
|
||||
if(mdx&&mdy)
|
||||
{
|
||||
if((ix+iy)&1)
|
||||
@@ -364,8 +405,7 @@ btSoftBody* btSoftBodyHelpers::CreatePatch(btSoftBody::btSoftBodyWorldInfo& wor
|
||||
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),
|
||||
1,btSoftBody::eLType::Structural);
|
||||
psb->appendLink(IDX(ix,iy),IDX(ix+1,iy+1));
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -374,8 +414,7 @@ btSoftBody* btSoftBodyHelpers::CreatePatch(btSoftBody::btSoftBodyWorldInfo& wor
|
||||
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),
|
||||
1,btSoftBody::eLType::Structural);
|
||||
psb->appendLink(IDX(ix+1,iy),IDX(ix,iy+1));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -448,7 +487,7 @@ btSoftBody* btSoftBodyHelpers::CreateFromTriMesh(btSoftBody::btSoftBodyWorldInf
|
||||
{
|
||||
chks[IDX(idx[j],idx[k])]=true;
|
||||
chks[IDX(idx[k],idx[k])]=true;
|
||||
psb->appendLink(idx[j],idx[k],1,btSoftBody::eLType::Structural);
|
||||
psb->appendLink(idx[j],idx[k]);
|
||||
}
|
||||
}
|
||||
#undef IDX
|
||||
@@ -474,12 +513,9 @@ btSoftBody* btSoftBodyHelpers::CreateFromConvexHull(btSoftBody::btSoftBodyWorld
|
||||
const int idx[]={ hres.m_Indices[i*3+0],
|
||||
hres.m_Indices[i*3+1],
|
||||
hres.m_Indices[i*3+2]};
|
||||
if(idx[0]<idx[1]) psb->appendLink( idx[0],idx[1],
|
||||
1,btSoftBody::eLType::Structural);
|
||||
if(idx[1]<idx[2]) psb->appendLink( idx[1],idx[2],
|
||||
1,btSoftBody::eLType::Structural);
|
||||
if(idx[2]<idx[0]) psb->appendLink( idx[2],idx[0],
|
||||
1,btSoftBody::eLType::Structural);
|
||||
if(idx[0]<idx[1]) psb->appendLink( idx[0],idx[1]);
|
||||
if(idx[1]<idx[2]) psb->appendLink( idx[1],idx[2]);
|
||||
if(idx[2]<idx[0]) psb->appendLink( idx[2],idx[0]);
|
||||
psb->appendFace(idx[0],idx[1],idx[2]);
|
||||
}
|
||||
hlib.ReleaseResult(hres);
|
||||
@@ -487,4 +523,154 @@ btSoftBody* btSoftBodyHelpers::CreateFromConvexHull(btSoftBody::btSoftBodyWorld
|
||||
return(psb);
|
||||
}
|
||||
|
||||
#if BT_SOFTBODY_USE_STL
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
|
||||
//
|
||||
void btSoftBodyHelpers::ExportAsSMeshFile(btSoftBody* psb,
|
||||
const char* filename)
|
||||
{
|
||||
std::ofstream output(filename);
|
||||
output << psb->m_nodes.size() << " " << 3 << " " << 0 << " " << 0 << "\n";
|
||||
for(int i=0;i<psb->m_nodes.size();++i)
|
||||
{
|
||||
const btSoftBody::Node& n=psb->m_nodes[i];
|
||||
output << i << " "
|
||||
<< n.m_x.x() << " "
|
||||
<< n.m_x.y() << " "
|
||||
<< n.m_x.z() << "\n";
|
||||
}
|
||||
output << psb->m_faces.size() << " " << 1 << "\n";
|
||||
for(int i=0;i<psb->m_faces.size();++i)
|
||||
{
|
||||
const btSoftBody::Node* b=&psb->m_nodes[0];
|
||||
const btSoftBody::Face& f=psb->m_faces[i];
|
||||
output << 3 << " "
|
||||
<< int(f.m_n[0]-b) << " "
|
||||
<< int(f.m_n[1]-b) << " "
|
||||
<< int(f.m_n[2]-b) << " "
|
||||
<< 1 << "\n";
|
||||
}
|
||||
output << 0 << "\n";
|
||||
output << 0 << "\n";
|
||||
output.close();
|
||||
}
|
||||
|
||||
/* Create from TetGen .ele, .face, .node files */
|
||||
btSoftBody* btSoftBodyHelpers::CreateFromTetGenFile(btSoftBody::btSoftBodyWorldInfo& worldInfo,
|
||||
const char* ele,
|
||||
const char* face,
|
||||
const char* node,
|
||||
bool bfacelinks,
|
||||
bool btetralinks,
|
||||
bool bfacesfromtetras)
|
||||
{
|
||||
std::ifstream efile(ele?ele:"");
|
||||
std::ifstream ffile(face?face:"");
|
||||
std::ifstream nfile(node);
|
||||
std::string edata;
|
||||
std::string fdata;
|
||||
std::string ndata;
|
||||
if(efile.good()) while(!efile.eof()) edata+=efile.get();
|
||||
if(ffile.good()) while(!ffile.eof()) fdata+=ffile.get();
|
||||
if(nfile.good()) while(!nfile.eof()) ndata+=nfile.get();
|
||||
efile.close();
|
||||
ffile.close();
|
||||
nfile.close();
|
||||
return(CreateFromTetGenData(worldInfo,edata.c_str(),fdata.c_str(),ndata.c_str(),
|
||||
bfacelinks,btetralinks,bfacesfromtetras));
|
||||
}
|
||||
|
||||
/* Create from TetGen .ele, .face, .node data */
|
||||
btSoftBody* btSoftBodyHelpers::CreateFromTetGenData(btSoftBody::btSoftBodyWorldInfo& worldInfo,
|
||||
const char* ele,
|
||||
const char* face,
|
||||
const char* node,
|
||||
bool bfacelinks,
|
||||
bool btetralinks,
|
||||
bool bfacesfromtetras)
|
||||
{
|
||||
std::istringstream se(ele?ele:"");
|
||||
std::istringstream sf(face?face:"");
|
||||
std::istringstream sn(node?node:"");
|
||||
btAlignedObjectArray<btVector3> pos;
|
||||
int nnode=0;
|
||||
int ndims=0;
|
||||
int nattrb=0;
|
||||
int hasbounds=0;
|
||||
sn>>nnode;sn>>ndims;sn>>nattrb;sn>>hasbounds;
|
||||
pos.resize(nnode);
|
||||
for(int i=0;i<pos.size();++i)
|
||||
{
|
||||
int index=0;
|
||||
int bound=0;
|
||||
btScalar x,y,z,a;
|
||||
sn>>index;
|
||||
sn>>x;sn>>y;sn>>z;
|
||||
for(int j=0;j<nattrb;++j) sn>>a;
|
||||
if(hasbounds) sn>>bound;
|
||||
pos[index].setX(x);
|
||||
pos[index].setY(y);
|
||||
pos[index].setZ(z);
|
||||
}
|
||||
btSoftBody* psb=new btSoftBody(&worldInfo,nnode,&pos[0],0);
|
||||
if(face&&face[0])
|
||||
{
|
||||
int nface=0;
|
||||
sf>>nface;sf>>hasbounds;
|
||||
for(int i=0;i<nface;++i)
|
||||
{
|
||||
int index=0;
|
||||
int bound=0;
|
||||
int ni[3];
|
||||
sf>>index;
|
||||
sf>>ni[0];sf>>ni[1];sf>>ni[2];
|
||||
sf>>bound;
|
||||
psb->appendFace(ni[0],ni[1],ni[2]);
|
||||
if(btetralinks)
|
||||
{
|
||||
psb->appendLink(ni[0],ni[1],0,true);
|
||||
psb->appendLink(ni[1],ni[2],0,true);
|
||||
psb->appendLink(ni[2],ni[0],0,true);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(ele&&ele[0])
|
||||
{
|
||||
int ntetra=0;
|
||||
int ncorner=0;
|
||||
int neattrb=0;
|
||||
se>>ntetra;se>>ncorner;se>>neattrb;
|
||||
for(int i=0;i<ntetra;++i)
|
||||
{
|
||||
int index=0;
|
||||
int ni[4],a;
|
||||
se>>index;
|
||||
se>>ni[0];se>>ni[1];se>>ni[2];se>>ni[3];
|
||||
for(int j=0;j<neattrb;++j) se>>a;
|
||||
psb->appendTetra(ni[0],ni[1],ni[2],ni[3]);
|
||||
if(btetralinks)
|
||||
{
|
||||
psb->appendLink(ni[0],ni[1],0,true);
|
||||
psb->appendLink(ni[1],ni[2],0,true);
|
||||
psb->appendLink(ni[2],ni[0],0,true);
|
||||
psb->appendLink(ni[0],ni[3],0,true);
|
||||
psb->appendLink(ni[1],ni[3],0,true);
|
||||
psb->appendLink(ni[2],ni[3],0,true);
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("Nodes: %u\r\n",psb->m_nodes.size());
|
||||
printf("Links: %u\r\n",psb->m_links.size());
|
||||
printf("Faces: %u\r\n",psb->m_faces.size());
|
||||
printf("Tetras: %u\r\n",psb->m_tetras.size());
|
||||
return(psb);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -18,6 +18,9 @@ subject to the following restrictions:
|
||||
|
||||
#include "btSoftBody.h"
|
||||
|
||||
//Can't enable this, Bullet doesn't use STL
|
||||
//#define BT_SOFTBODY_USE_STL 1
|
||||
|
||||
//
|
||||
// Helpers
|
||||
//
|
||||
@@ -25,16 +28,15 @@ subject to the following restrictions:
|
||||
/* fDrawFlags */
|
||||
struct fDrawFlags { enum _ {
|
||||
Nodes = 0x0001,
|
||||
SLinks = 0x0002,
|
||||
BLinks = 0x0004,
|
||||
Faces = 0x0008,
|
||||
Tetras = 0x0010,
|
||||
Normals = 0x0020,
|
||||
Contacts = 0x0040,
|
||||
Anchors = 0x0080,
|
||||
Links = 0x0002,
|
||||
Faces = 0x0004,
|
||||
Tetras = 0x0008,
|
||||
Normals = 0x0010,
|
||||
Contacts = 0x0020,
|
||||
Anchors = 0x0040,
|
||||
Notes = 0x0080,
|
||||
/* presets */
|
||||
Links = SLinks+BLinks,
|
||||
Std = SLinks+Faces+Anchors,
|
||||
Std = Links+Faces+Tetras+Anchors+Notes,
|
||||
StdTetra = Std-Faces+Tetras,
|
||||
};};
|
||||
|
||||
@@ -64,30 +66,56 @@ struct btSoftBodyHelpers
|
||||
static void DrawFrame( btSoftBody* psb,
|
||||
btIDebugDraw* idraw);
|
||||
/* Create a rope */
|
||||
static btSoftBody* CreateRope( btSoftBody::btSoftBodyWorldInfo& worldInfo,const btVector3& from,
|
||||
const btVector3& to,
|
||||
int res,
|
||||
int fixeds);
|
||||
static btSoftBody* CreateRope( btSoftBody::btSoftBodyWorldInfo& worldInfo,
|
||||
const btVector3& from,
|
||||
const btVector3& to,
|
||||
int res,
|
||||
int fixeds);
|
||||
/* Create a patch */
|
||||
static btSoftBody* CreatePatch( btSoftBody::btSoftBodyWorldInfo& worldInfo,const btVector3& corner00,
|
||||
const btVector3& corner10,
|
||||
const btVector3& corner01,
|
||||
const btVector3& corner11,
|
||||
int resx,
|
||||
int resy,
|
||||
int fixeds,
|
||||
bool gendiags);
|
||||
static btSoftBody* CreatePatch(btSoftBody::btSoftBodyWorldInfo& worldInfo,
|
||||
const btVector3& corner00,
|
||||
const btVector3& corner10,
|
||||
const btVector3& corner01,
|
||||
const btVector3& corner11,
|
||||
int resx,
|
||||
int resy,
|
||||
int fixeds,
|
||||
bool gendiags);
|
||||
/* Create an ellipsoid */
|
||||
static btSoftBody* CreateEllipsoid(btSoftBody::btSoftBodyWorldInfo& worldInfo,const btVector3& center,
|
||||
const btVector3& radius,
|
||||
int res);
|
||||
/* Create from convex-hull */
|
||||
static btSoftBody* CreateFromConvexHull( btSoftBody::btSoftBodyWorldInfo& worldInfo, const btVector3* vertices,
|
||||
int nvertices);
|
||||
static btSoftBody* CreateEllipsoid(btSoftBody::btSoftBodyWorldInfo& worldInfo,
|
||||
const btVector3& center,
|
||||
const btVector3& radius,
|
||||
int res);
|
||||
/* Create from trimesh */
|
||||
static btSoftBody* CreateFromTriMesh( btSoftBody::btSoftBodyWorldInfo& worldInfo, const btScalar* vertices,
|
||||
const int* triangles,
|
||||
int ntriangles);
|
||||
static btSoftBody* CreateFromTriMesh( btSoftBody::btSoftBodyWorldInfo& worldInfo,
|
||||
const btScalar* vertices,
|
||||
const int* triangles,
|
||||
int ntriangles);
|
||||
/* Create from convex-hull */
|
||||
static btSoftBody* CreateFromConvexHull( btSoftBody::btSoftBodyWorldInfo& worldInfo,
|
||||
const btVector3* vertices,
|
||||
int nvertices);
|
||||
#if BT_SOFTBODY_USE_STL
|
||||
/* Export TetGen compatible .smesh file */
|
||||
static void ExportAsSMeshFile( btSoftBody* psb,
|
||||
const char* filename);
|
||||
/* Create from TetGen .ele, .face, .node files */
|
||||
static btSoftBody* CreateFromTetGenFile( btSoftBody::btSoftBodyWorldInfo& worldInfo,
|
||||
const char* ele,
|
||||
const char* face,
|
||||
const char* node,
|
||||
bool bfacelinks,
|
||||
bool btetralinks,
|
||||
bool bfacesfromtetras);
|
||||
/* Create from TetGen .ele, .face, .node data */
|
||||
static btSoftBody* CreateFromTetGenData( btSoftBody::btSoftBodyWorldInfo& worldInfo,
|
||||
const char* ele,
|
||||
const char* face,
|
||||
const char* node,
|
||||
bool bfacelinks,
|
||||
bool btetralinks,
|
||||
bool bfacesfromtetras);
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif //SOFT_BODY_HELPERS_H
|
||||
|
||||
@@ -106,7 +106,7 @@ void btSoftRigidDynamicsWorld::debugDrawWorld()
|
||||
{
|
||||
btSoftBody* psb=(btSoftBody*)this->m_softBodies[i];
|
||||
btSoftBodyHelpers::DrawFrame(psb,m_debugDrawer);
|
||||
btSoftBodyHelpers::Draw(psb,m_debugDrawer,fDrawFlags::Std);
|
||||
btSoftBodyHelpers::Draw(psb,m_debugDrawer,fDrawFlags::Nodes+fDrawFlags::Std);
|
||||
if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
|
||||
{
|
||||
btSoftBodyHelpers::DrawNodeTree(psb,m_debugDrawer);
|
||||
|
||||
@@ -109,6 +109,28 @@ struct btSparseSdf
|
||||
/* else setup a priority list... */
|
||||
}
|
||||
//
|
||||
int RemoveReferences(btCollisionShape* pcs)
|
||||
{
|
||||
int refcount=0;
|
||||
for(int i=0;i<cells.size();++i)
|
||||
{
|
||||
Cell*& root=cells[i];
|
||||
Cell* pp=0;
|
||||
Cell* pc=root;
|
||||
while(pc)
|
||||
{
|
||||
Cell* pn=pc->next;
|
||||
if(pc->pclient==pcs)
|
||||
{
|
||||
if(pp) pp->next=pn; else root=pn;
|
||||
delete pc;pc=pp;++refcount;
|
||||
}
|
||||
pp=pc;pc=pn;
|
||||
}
|
||||
}
|
||||
return(refcount);
|
||||
}
|
||||
//
|
||||
btScalar Evaluate( const btVector3& x,
|
||||
btCollisionShape* shape,
|
||||
btVector3& normal,
|
||||
|
||||
Reference in New Issue
Block a user