上一篇文章把旋转的基础补了。这一篇开始进入正题,关于物理模拟。
目前主流的物理引擎都是利用约束求解的方式进行物理模拟,其核心算法包括两点:
(1)如何使用约束对物理场景进行建模
(2)使用何种方式求解约束
那么接下来就从这两点分头讨论。主要参考Erin Catto 对 Box2D 系列文章的介绍,Physx 也基本采用了同样的物理模拟方法。
(1)约束构建 - 以接触约束为例

在碰撞检测阶段结束后,我们可以获取一对物体上的接触点位置
接触约束要求 在
平面的法线指向的同侧:
于是我们可以构建接触约束:
(2)构建约束求解方程
对于这样一个约束 ,当满足
时,
向满足约束的梯度改变。
因此可以改变为求解
因此约束可以重写为:
在 ErinCatto IterativeDynamics GDC2005 link 中 Contact Model 部分有说明,因为假定 penetration 一定很小,所以忽略第二部分
接下来以规范化的形式重写约束,简化推导过程
两个刚体的状态向量:
雅克比矩阵:
假设有 K 个约束, S 个刚体,那么
的维度为
从刚才推导可知 ,第二部分
同样被忽略
不等式约束可以通过拉格朗日乘子法改写为等式,不过基于冲量的模拟后面会用 Projected Gauss Siedel (PGS) 加上不等式截断做简单处理。因此此处先按等式继续求解。
如果当前帧满足约束
那么下一帧仍然满足约束的条件为 :
为包含质量和角速度的矩阵:
使用 semi-implicit euler integration 可以写出两帧之间速度的关系:
为约束前的下一帧速度:
为约束后的下一帧速度:
这里和 PBD 非常像,都是用类似的积分方式构建步进迭代,PBD的文章网上非常多了,后面只会简单写一篇吧。
为了方便写公式,假设 :
约束冲量
到这里已经构建了方程
第一个 trick,为了沿梯度方向求解,可以限制 ,即
与
同方向
第二个 trick,由于这样直接求解速度会有 jitter,所以约束增加一个 bias
当 时
所以有
这就是冲量模拟经典的方程形式。求解目标为 ,
注意这只是一个约束 对应的
,总共有K 个这样的方程,构成约束方程组。
(3) Sequential Impulse 求解约束
为什么叫做 Sequential Impulse:因为对于每个 constraint, 是逐个求解的
Sequential Impulse 算法步骤:
(1) 计算所有的
(2)for k = 1,...,K 的 k个方程:
从 求解每一个
,从而得到
(3)求解 作为下一步的
(4) 更新所有位置
由于是不等式约束,对每一个局部冲量 直接做截断。
这也是一个来自 (Erin,GDC2005) link 的一个近似解法。
其他形式的约束
等式约束的情况:distance constraints, revolute joints, prismatic joints, 以及许多其他的 joint 类型
例如距离约束:
不等式约束的情况 : contact constraints, joint angle limits
使用约束模拟弹性
表示碰撞前相对速度
表示碰撞后相对速度
弹性系数的定义(Unified Framework for Rigid Body Dynamics):
假设 和
方向相反
弹性约束(04-GDC09_Catto_Erin_Solver):
相当于把 bias 中增加了
使用约束模拟摩擦力
库伦模型(Coulomb friction model)
先构建约束模型让切线方向速度为0
假设两个切线方向
摩擦力约束不需要像穿透约束一样增加稳定项 bias,作者说是经验结论。
最后构建出 J, ,
使用这个模型构建出的摩擦力不完全符合真实物理,事实上求解的只是被 限制,而不完全正比于