第一步:问题设定
我们有一个物理系统,包含 个粒子。每个粒子的位置为 ,质量为 。系统的总位置向量记作:
质量矩阵为对角矩阵:
系统受到一组约束,但我们不要求约束被严格满足。相反,我们给每个约束赋予一个弹性势能。对于单个约束 (C(x) \in \mathbb{R}),其势能定义为:
其中 是柔度(compliance),物理意义是刚度的倒数,单位是米/牛顿。对于多个约束,总势能是各约束势能之和。
第二步:隐式时间积分
我们采用隐式欧拉法进行时间步进。从时间 到 ,运动方程为:
为了方便,定义预测位置(也叫惯性位置):
(这里假设速度是 ,所以 。)
代入运动方程,整理得:
令 ,则方程变为:
第三步:引入拉格朗日乘子
对于每个约束 ,其势能梯度为:
代入运动方程:
令
注意: 是时间尺度调整后的柔度,它的引入是 XPBD 能够解耦时间步长的关键。
现在,我们定义一个拉格朗日乘子向量(对于多约束系统):
注意:这是定义,不是推导。它的作用是把非线性方程拆成两个联立的线性方程。
根据这个定义,我们有:
并且运动方程可以改写为:
第四步:联立方程组
我们现在有了一个关于 和 的联立方程组:
注意这里 。
第五步:线性化(牛顿迭代的一步)
方程组是非线性的,因为 和 都依赖于未知的 。我们采用单步牛顿法来近似求解。
将 在预测位置 处一阶泰勒展开:
将梯度也近似为在 处的值:
代入联立方程组:
其中 ,。
第六步:求解 (\Delta \lambda) 和 (\Delta x)
从第一个方程解出 :
代入第二个方程:
解得:
然后代回求 :
第七步:迭代形式(XPBD 的核心)
上面的推导给出的是单次牛顿步的解。但在实际模拟中,我们需要多次迭代来收敛到非线性方程组的真解。更重要的是,XPBD 的 是累积的,它代表从时间步开始以来累积的总约束冲量。
因此,我们采用迭代更新的形式。设当前迭代步的乘子为 (初始为上一帧结束时保留的值,或零),我们计算增量 :
由约束方程的一阶展开(注意此时当前位置是 ,而不是 ):
代入 :
整理得:
解得:
然后更新:
第八步:完整算法流程
对于每一帧:
- 对于所有粒子,计算预测位置
- 初始化所有约束的 (或者保留上一帧的值)
- 重复若干次(求解迭代):
- 对于每个约束:
- 计算 和
- 计算
- 更新
- 计算
- 更新
- 对于每个约束:
- 更新速度:
- 更新位置:
推导中的关键点总结
| 步骤 | 关键操作 | 物理/数学意义 |
|---|---|---|
| 1 | 定义弹性势能,赋予约束物理刚度 | |
| 2 | 时间步长解耦,保证材料属性一致 | |
| 3 | 引入对偶变量,将非线性方程拆为联立方程 | |
| 4 | 泰勒展开 | 线性化,使问题可解 |
| 5 | 迭代更新 | 累积乘子,解耦迭代次数与刚度 |
| 6 | 分母加 | 正则化项,防止柔度为零时除零 |
这就是 XPBD 从物理原理到数值算法的完整推导链条。