basic implementation of self-collision for btSoftBody with collision clusters: perform regular soft body versus soft body, but disable collision detection between clusters that are connected/share any node (vertex).
currently self-collision is always enabled for soft bodies that use clusters collision detectoin. to disable, call 'softbody.m_clusterConnectivity.clear' after 'generateClusters(...) call.
This commit is contained in:
@@ -911,6 +911,35 @@ int btSoftBody::generateClusters(int k,int maxiterations)
|
||||
|
||||
initializeClusters();
|
||||
updateClusters();
|
||||
|
||||
//for self-collision
|
||||
m_clusterConnectivity.resize(m_clusters.size()*m_clusters.size());
|
||||
{
|
||||
for (int c0=0;c0<m_clusters.size();c0++)
|
||||
{
|
||||
m_clusters[c0]->m_clusterIndex=c0;
|
||||
for (int c1=0;c1<m_clusters.size();c1++)
|
||||
{
|
||||
|
||||
bool connected=false;
|
||||
Cluster* cla = m_clusters[c0];
|
||||
Cluster* clb = m_clusters[c1];
|
||||
for (int i=0;!connected&&i<cla->m_nodes.size();i++)
|
||||
{
|
||||
for (int j=0;j<clb->m_nodes.size();j++)
|
||||
{
|
||||
if (cla->m_nodes[i] == clb->m_nodes[j])
|
||||
{
|
||||
connected=true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
m_clusterConnectivity[c0+c1*m_clusters.size()]=connected;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(m_clusters.size());
|
||||
}
|
||||
return(0);
|
||||
@@ -2059,8 +2088,13 @@ void btSoftBody::updateClusters()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
void btSoftBody::cleanupClusters()
|
||||
{
|
||||
@@ -2319,6 +2353,7 @@ void btSoftBody::CJoint::Terminate(btScalar dt)
|
||||
//
|
||||
void btSoftBody::applyForces()
|
||||
{
|
||||
|
||||
BT_PROFILE("SoftBody applyForces");
|
||||
const btScalar dt=m_sst.sdt;
|
||||
const btScalar kLF=m_cfg.kLF;
|
||||
|
||||
@@ -296,6 +296,7 @@ public:
|
||||
btScalar m_adamping; /* Angular damping */
|
||||
btScalar m_matching;
|
||||
bool m_collide;
|
||||
int m_clusterIndex;
|
||||
Cluster() : m_leaf(0),m_ndamping(0),m_ldamping(0),m_adamping(0),m_matching(0) {}
|
||||
};
|
||||
/* Impulse */
|
||||
@@ -603,6 +604,7 @@ public:
|
||||
btDbvt m_fdbvt; // Faces tree
|
||||
btDbvt m_cdbvt; // Clusters tree
|
||||
tClusterArray m_clusters; // Clusters
|
||||
btAlignedObjectArray<bool>m_clusterConnectivity;//cluster connectivity, for self-collision
|
||||
|
||||
//
|
||||
// Api
|
||||
|
||||
@@ -766,21 +766,38 @@ struct btSoftColliders
|
||||
{
|
||||
btSoftBody::Cluster* cla=(btSoftBody::Cluster*)la->data;
|
||||
btSoftBody::Cluster* clb=(btSoftBody::Cluster*)lb->data;
|
||||
btSoftClusterCollisionShape csa(cla);
|
||||
btSoftClusterCollisionShape csb(clb);
|
||||
btGjkEpaSolver2::sResults res;
|
||||
if(btGjkEpaSolver2::SignedDistance( &csa,btTransform::getIdentity(),
|
||||
&csb,btTransform::getIdentity(),
|
||||
cla->m_com-clb->m_com,res))
|
||||
|
||||
|
||||
bool connected=false;
|
||||
if ((bodies[0]==bodies[1])&&(bodies[0]->m_clusterConnectivity.size()))
|
||||
{
|
||||
btSoftBody::CJoint joint;
|
||||
if(SolveContact(res,cla,clb,joint))
|
||||
connected = bodies[0]->m_clusterConnectivity[cla->m_clusterIndex+bodies[0]->m_clusters.size()*clb->m_clusterIndex];
|
||||
}
|
||||
|
||||
if (!connected)
|
||||
{
|
||||
btSoftClusterCollisionShape csa(cla);
|
||||
btSoftClusterCollisionShape csb(clb);
|
||||
btGjkEpaSolver2::sResults res;
|
||||
if(btGjkEpaSolver2::SignedDistance( &csa,btTransform::getIdentity(),
|
||||
&csb,btTransform::getIdentity(),
|
||||
cla->m_com-clb->m_com,res))
|
||||
{
|
||||
btSoftBody::CJoint* pj=new(btAlignedAlloc(sizeof(btSoftBody::CJoint),16)) btSoftBody::CJoint();
|
||||
*pj=joint;bodies[0]->m_joints.push_back(pj);
|
||||
pj->m_erp *= btMax(bodies[0]->m_cfg.kSSHR_CL,bodies[1]->m_cfg.kSSHR_CL);
|
||||
pj->m_split *= (bodies[0]->m_cfg.kSS_SPLT_CL+bodies[1]->m_cfg.kSS_SPLT_CL)/2;
|
||||
btSoftBody::CJoint joint;
|
||||
if(SolveContact(res,cla,clb,joint))
|
||||
{
|
||||
btSoftBody::CJoint* pj=new(btAlignedAlloc(sizeof(btSoftBody::CJoint),16)) btSoftBody::CJoint();
|
||||
*pj=joint;bodies[0]->m_joints.push_back(pj);
|
||||
pj->m_erp *= btMax(bodies[0]->m_cfg.kSSHR_CL,bodies[1]->m_cfg.kSSHR_CL);
|
||||
pj->m_split *= (bodies[0]->m_cfg.kSS_SPLT_CL+bodies[1]->m_cfg.kSS_SPLT_CL)/2;
|
||||
}
|
||||
}
|
||||
} else
|
||||
{
|
||||
static int count=0;
|
||||
count++;
|
||||
//printf("count=%d\n",count);
|
||||
|
||||
}
|
||||
}
|
||||
void Process(btSoftBody* psa,btSoftBody* psb)
|
||||
|
||||
@@ -63,6 +63,13 @@ void btSoftRigidDynamicsWorld::internalSingleStepSimulation( btScalar timeStep)
|
||||
///solve soft bodies constraints
|
||||
solveSoftBodiesConstraints();
|
||||
|
||||
//self collisions
|
||||
for ( int i=0;i<m_softBodies.size();i++)
|
||||
{
|
||||
btSoftBody* psb=(btSoftBody*)m_softBodies[i];
|
||||
psb->defaultCollisionHandler(psb);
|
||||
}
|
||||
|
||||
///update soft bodies
|
||||
updateSoftBodies();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user