bullet入门-精细阶段

Posted by ysd on September 13, 2017

其实就是对每个overlap pair,执行一个nearcallback
在这个函数里,通过pair的两个形状的类型查找一个算法btCollisionAlgorithm
比如两个球体,就得到btSphereSphereCollisionAlgorithm(继承btCollisionAlgorithm
查找是通过一个二维数组,里面都是各个算法的CreateFunc,在btDefaultCollisionConfiguration就配置好了
找到之后就调用btCollisionAlgorithm::processCollision
以两个球体为例,这个比较简单

void btSphereSphereCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* col0Wrap,const btCollisionObjectWrapper* col1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
(void)dispatchInfo;

if (!m_manifoldPtr)
return;

resultOut->setPersistentManifold(m_manifoldPtr);

btSphereShape* sphere0 = (btSphereShape*)col0Wrap->getCollisionShape();
btSphereShape* sphere1 = (btSphereShape*)col1Wrap->getCollisionShape();

btVector3 diff = col0Wrap->getWorldTransform().getOrigin() - col1Wrap->getWorldTransform().getOrigin();
btScalar len = diff.length();
btScalar radius0 = sphere0->getRadius();
btScalar radius1 = sphere1->getRadius();

/*iff distance positive, don't generate a new contact*/
if ( len > (radius0+radius1+resultOut->m_closestPointDistanceThreshold))
{
return;
}
/*distance (negative means penetration)*/
btScalar dist = len - (radius0+radius1);

btVector3 normalOnSurfaceB(1, 0, 0);
if (len > SIMD_EPSILON)
{
normalOnSurfaceB = diff / len;
}

/*point on A (worldspace)*/
/*btVector3 pos0 = col0->getWorldTransform().getOrigin() - radius0 * normalOnSurfaceB;*/
/*point on B (worldspace)*/
btVector3 pos1 = col1Wrap->getWorldTransform().getOrigin() + radius1* normalOnSurfaceB;

/* report a contact. internally this will be kept persistent, and contact reduction is done */
resultOut->addContactPoint(normalOnSurfaceB, pos1, dist);

}

再看一个刚体和柔体的,其实就是刚体和柔体的dbvt测试,而柔体的dbvt的叶子节点就是模型的顶点

void btSoftBody::defaultCollisionHandler(const btCollisionObjectWrapper* pcoWrap)
{

switch(m_cfg.collisions&fCollision::RVSmask)
{
// 逐顶点的

case fCollision::SDF_RS:
{
btSoftColliders::CollideSDF_RS docollide;
btRigidBody* prb1=(btRigidBody*) btRigidBody::upcast(pcoWrap->getCollisionObject());
btTransform wtr=pcoWrap->getWorldTransform();

const btTransform ctr=pcoWrap->getWorldTransform();
const btScalar timemargin=(wtr.getOrigin()-ctr.getOrigin()).length();
const btScalar basemargin=getCollisionShape()->getMargin();
btVector3 mins;
btVector3 maxs;
ATTRIBUTE_ALIGNED16(btDbvtVolume) volume;
pcoWrap->getCollisionShape()->getAabb( pcoWrap->getWorldTransform(),
mins,
maxs);
volume=btDbvtVolume::FromMM(mins,maxs);
volume.Expand(btVector3(basemargin,basemargin,basemargin));
docollide.psb = this;
docollide.m_colObj1Wrap = pcoWrap;
docollide.m_rigidBody = prb1;

docollide.dynmargin = basemargin+timemargin;
docollide.stamargin = basemargin;
m_ndbvt.collideTV(m_ndbvt.m_root,volume,docollide);
}
break;
// 基于cluster
case fCollision::CL_RS:
{
btSoftColliders::CollideCL_RS collider;
collider.ProcessColObj(this,pcoWrap);
}
break;
}
}

// 上面SDF_RS中,传入collideTV的回调函数最终调下面这个

void DoNode(btSoftBody::Node& n) const
{
const btScalar m=n.m_im>0?dynmargin:stamargin;
// R应该就是rigidbody的意思

btSoftBody::RContact c;

if( (!n.m_battach)&&
// 这个函数里将测试顶点和刚体碰撞体的距离

psb->checkContact(m_colObj1Wrap,n.m_x,m,c.m_cti))
{
const btScalar ima=n.m_im;
const btScalar imb= m_rigidBody? m_rigidBody->getInvMass() : 0.f;
const btScalar ms=ima+imb;
if(ms>0)
{
// 这一堆没看懂_(:зゝ∠)_

const btTransform& wtr=m_rigidBody?m_rigidBody->getWorldTransform() : m_colObj1Wrap->getCollisionObject()->getWorldTransform();
static const btMatrix3x3 iwiStatic(0,0,0,0,0,0,0,0,0);
const btMatrix3x3& iwi=m_rigidBody?m_rigidBody->getInvInertiaTensorWorld() : iwiStatic;
const btVector3 ra=n.m_x-wtr.getOrigin();
const btVector3 va=m_rigidBody ? m_rigidBody->getVelocityInLocalPoint(ra)*psb->m_sst.sdt : btVector3(0,0,0);
const btVector3 vb=n.m_x-n.m_q;
const btVector3 vr=vb-va;
const btScalar dn=btDot(vr,c.m_cti.m_normal);
const btVector3 fv=vr-c.m_cti.m_normal*dn;
const btScalar fc=psb->m_cfg.kDF*m_colObj1Wrap->getCollisionObject()->getFriction();
c.m_node = &n;
c.m_c0 = ImpulseMatrix(psb->m_sst.sdt,ima,imb,iwi,ra);
c.m_c1 = ra;
c.m_c2 = ima*psb->m_sst.sdt;
c.m_c3 = fv.length2()<(dn*fc*dn*fc)?0:1-fc;
c.m_c4 = m_colObj1Wrap->getCollisionObject()->isStaticOrKinematicObject()?psb->m_cfg.kKHR:psb->m_cfg.kCHR;
// 在约束处理阶段,会处理所有的接触

psb->m_rcontacts.push_back(c);
if (m_rigidBody)
m_rigidBody->activate();
}
}
}