Bullet 学习笔记之 软体仿真流程(一)
下面梳理软体对象的仿真过程。
在例程 VolumetricDeformable 中,使用了 btDeformableMultiBodyDynamicsWrold
类以及 btDeformableBodySolver
类,因此,该仿真流程即为对 btDeformableMultiBodyDynamicsWrold
和 btDeformableBodySolver
的梳理。
1、仿真主流程
仿真主要流程,由 btDeformableMultiBodyDynamicsWrold
类控制,细节部分则由 btDeformableBodySolver
类控制。主要有以下几个步骤:
- 初始化工作
- 计算无约束运动
- 碰撞检测
- 求解约束
- 位移积分
(1) 初始化工作
细节略
(2)计算无约束运动
这部分内容由函数 btDeformableRigidDynamicsWorld::predictUnconstraintMotion(..)
完成。是计算场景中的物体(软体/刚体)仅在重力和弹性力作用下的运动,不考虑约束、接触等。具体来说,这部分工作包含了以下内容:
btDiscreteDynamicsWorld::predictUnconstraintMotion(timeStep);
btDeformableBodySolver::predictMotion(timeStep);
在 btDeformableBodySolver::predictMotion(..)
中,计算软体在重力、弹性力作用下的运动,得到了一个临时位置(a temporary position),存放在 node.m_q
中,在此后的仿真步骤中,是基于这个临时位置做碰撞检测。
具体内容参考文章:btDeformableBodySolver::predictMotion(..)
(3) 碰撞检测
这部分内容由函数 btDiscreteDynamicsWorld::performDiscreteCollisionDetection()
和 函数 btDeformableRigidDynamicsWorld::softBodySelfCollision()
完成。在计算得到本时间步骤,场景中物体的临时位置(temporary position)后,进行了碰撞检测。在仿真场景中,已将所有软体作为碰撞对象加入到了 btDiscreteDynamicsWorld
中,因此,直接对两两做碰撞检测就可以了。此外,如果需要对软体做自碰撞检测,还需要执行 psb->defaultCollisionHandler(psb)
函数。
软体碰撞检测所执行的函数应该是 btSoftBody::defaultCollisionHandler(..)
,得到的结果应该是放在了 btSoftBody::m_nodeRigidContacts
btSoftBody::m_faceNodeContacts
btSoftBody::m_faceRigidContacts
里面。不同的检测方法,应该是对应于不同的碰撞结果的。
(4)求解约束
(略)
(5)位移积分
这部分工作由函数 btDeformableRigidDynamicsWorld::integrateTransforms(..)
完成。具体来说,应该有刚体位移积分 btDiscreteDynamicsWorld::integrateTransforms(..)
和软体位移积分两部分组成。其中,软体位移积分可用以下公式表述:
node.m_x = node.m_x + timeStep * node.m_v;
也就是说,在约束求解时,计算得到的是软体在本时间步骤内的速度值 node.m_v
。
下面,详细介绍其中的一些细节。
2、软体的无约束运动
软体的无约束运动计算,是由函数 srDeformableBodySolver::predictMotion(..)
完成,其具体步骤可如下表示:
calculate forces applied on node
node.m_v += f / m
node.m_q = m_x + m_v * dt
首先,通过函数 btDeformableBackwardEulerObjective::applyExplicitForce(..)
计算得到作用在软体质点上的合力(只考虑重力和弹性力),并更新软体的(临时)速度。具体来说,分为三个部分:(1)通过函数 btSoftBody::advanceDeformation()
计算当前软体的形变度量,如 F、J、C、tr(C) 等。(2)通过函数 btDeformableLagrangianForce::addScaledExplicitForce()
计算得到作用在节点上的合力,(统一存放在一个数组中)。(3)通过函数 btDeformableBackwardEulerObjective::applyForce(..)
计算软体节点的速度值,即 node.m_v += f / m 。
接下来,通过函数 btDeformableBodySolver::predictDeformableMotion(..)
更新软体节点的(临时)位置,即 node.m_q = m_x + m_v * dt 。
此外,在这个过程中,还涉及到碰撞对象(信息)的更新,比如,更新碰撞包围盒的边界信息等,(毕竟软体发生了形变)。这部分工作主要涉及到成员变量 btSoftBody::m_ndbvt
和 btSoftBody::m_ndbvt
的更新。同时,清空上一个时间步骤中的碰撞检测结果,即成员变量 btSoftBody::m_nodeRigidContacts
btSoftBody::m_faceRigidContacts
btSoftBody::m_faceNodeContacts
。
3、碰撞检测
先大致弄清楚碰撞检测的类型,执行函数,结果存放在哪儿,以及结果中都包含了那些信息
4、约束求解
约束求解是这里面最为复杂的内容了,专门写一篇笔记:软体的约束求解
5、位置更新
这部分最简单了,更新得到本时间步骤的最终位置。
小结
(待续)