2.3 半隐式 Verlet 与隐式积分


2.3 半隐式 Verlet 与隐式积分

本节摘要:刚体实时引擎的默认积分是半隐式欧拉:先用当前力更新速度,再用新速度更新位置。布料和绳索常用位置 Verlet 或 XPBD,把约束直接写在位置上。隐式欧拉能吃大步长,但每步要解线性系统,且和冲量求解器叠在一起时容易发黏。按物体类型选加法,不要全局一只积分器打天下。

本节地图

阅读完本节,你应当能够:

  1. 实现半隐式欧拉,并说明它与显式只差“用哪份速度写位置”
  2. 实现位置 Verlet,用上一帧位置反推速度给碰撞用
  3. 说出隐式积分的代价和适用的软体场景
  4. 避免在同一物体上同时跑隐式积分和强位置投影导致过阻尼

一、半隐式欧拉:多写一个字的默认答案

半隐式(也称辛欧拉、半显式)是:

v = v + a(x) * dt x = x + v * dt # 用已经更新的 v

相对纯显式,位置用了新速度。对简谐振子,它接近辛方法,能量在真值附近振荡而不是单调爬。圆轨道走成多边形,半径漂移远小于显式。计算量相同。刚体重力、风力、简单弹簧,用它就对。

角速度同样:先 w += Iinv * tau * dt,再 q += 0.5 * omega(q,w) * dt。有人先积分位置再算碰撞,冲量改速度后位置已经用旧速度走过,接触会少修一帧。标准顺序是:力积分速度 → 碰撞与约束改速度 → 用约束后的速度写位置。也就是把“x += v*dt”放到求解器之后。这仍叫半隐式家族,只是中间插入了冲量。

积分器 存储 能量 加约束 典型用途
半隐式欧拉 x,v 微振荡 冲量改 v 很自然 刚体、角色胶囊
位置 Verlet x, x_prev 近守恒 直接改 x,速度是派生量 布料、绳、头发
速度 Verlet x,v 近守恒 力要可重入 分子动力学、粒子
隐式欧拉 x,v 加矩阵 过阻尼 每步解系统 软体、头发大步长
RK4 多份中间力 约束难插 光滑力场、非实时

我做刚体堆箱子时用半隐式加顺序冲量;做旗帜用 Verlet/XPBD。两者在同一世界共存时,布料粒子不要当刚体积分,刚体不要当 Verlet 点,用接触把两套状态桥接。硬桥接会抖,第 5 章再谈。

Verlet 写法:

x_new = x + (x - x_prev) + a * dt * dt x_prev = x x = x_new

速度不显式存储,v = (x - x_prev) / dt。约束把点拉到满足长度后,速度自动变。这就是位置基动力学的老家。缺点:变 dt 时 (x-x_prev) 仍是旧步长的位移,必须按 dt 比例缩放,否则加速卡顿会把布料射出去。固定步再次成为前提。

二、隐式:大步长的税

隐式欧拉用未来加速度:v_new = v + a(x_new) * dt。弹簧力依赖未来位置,于是变成线性或非线性方程。软体网格几百点,每步解稀疏系统,才能在 1/30 秒步长下不炸。税是:实现复杂、每步迭代、过阻尼(运动发黏、高频被吃掉)。电影布料常用;游戏旗帜未必值得。

隐式不等于无条件稳定到可以乱取 dt。接触、碰撞、非光滑摩擦仍会限制步长。把 dt 开到 1/10 秒,角色会穿透台阶。隐式解决的是“软弹簧刚度高”的刚性 ODE,不是隧道效应。

XPBD 把约束刚度从迭代次数里拆出来,用柔度参数,迭代不够时变软而不是变硬到爆炸。游戏布料这几年多走这条,而不是隐式 FEM。选型时问:我要材料准确性,还是要 60Hz 好看?前者隐式 FEM,后者 XPBD。

💡 关键直觉:半隐式是“速度先行”,Verlet 是“位置先行”。冲量约束喜欢速度先行;长度约束喜欢位置先行。选积分器等于选你的约束主要写在哪一层。

子步:一次逻辑步里把 dt 切成 k 份,积分-碰撞-求解循环 k 次。对堆叠稳定性极有效,成本近似线性。很多引擎对外 60Hz,对内 2 到 4 子步。比把求解器迭代从 10 加到 40 更管用,因为子步会重新生成接触。只加迭代、不子步,接触法向还是这一帧开头那份,高速旋转时会过时。

三、和约束叠在一起时的发黏

隐式积分自带数值阻尼,再加鲍姆加特位置修正,物体像泡在糖浆里。表现:箱子放下后要半秒才“坐实”,关节电机推不动。对策:刚体走半隐式;软体走隐式或 XPBD,但位置修正系数分开调;不要全局一个 beta。

冲量求解后不要再跑一遍完整隐式系统去“光滑”,除非你清楚在解什么。常见错误是:半隐式预测 → PGS → 又用罚弹簧隐式拉一次。两套接触模型互殴,能量和穿透指标都会撒谎。

⚠️ 常见坑:Verlet 物体和刚体碰撞时,用刚体那套恢复系数直接改 Verlet 速度,再写回 x_prev,符号一错布料爆炸。应把接触写成 XPBD 的不等式约束,或把碰撞点当刚体接触只推刚体。

调试清单:

  • 关掉碰撞,只留弹簧,能量应有界
  • 打开碰撞,关掉摩擦,堆叠应在若干帧内睡住
  • 摩擦打开后,斜坡上的箱子应在静摩擦角内停住,不要慢慢爬回去(那是错误的切向偏置)

RK4 什么时候用?几乎不用在带接触的刚体世界。用于:载具悬挂的光滑力、自定义轨道摄像机、非碰撞粒子力场。一旦有非光滑碰撞,高阶方法的中间点没有良好定义的接触力,精度优势消失。

把第 2.2 节的弹簧实验换成半隐式和 Verlet 各跑一次。半隐式能量振荡;Verlet 更平。再把 dt 加倍,看谁先坏。你会得到自己的选型表,而不是抄一句“用 Verlet 更稳”。稳的定义依赖你的约束写在速度还是位置。

重力在 Verlet 里是 a*dt*dt 加到位置,数量级容易写错成 a*dt。单位测试:自由质点 1 秒下落距离应接近 0.5gt^2。半隐式因速度先行,自由落体位置会略大于解析值,游戏里可忽略。若差出一个 dt 因子,屏幕上物体第一帧就消失,那是乘法写错,不是稳定性。

多种积分器共存时,时间戳必须同一固定 dt。不要刚体 60Hz、布料 30Hz 还共用一个接触池,除非你明确做了多速率耦合。多速率是高级话题:慢系统用大步,快系统子步,接触在细步上生成。第一版引擎用全球一种 dt 加子步,够了。

四、混用积分器的耦合清单

刚体半隐式、布料 Verlet 同屏时,接触点一侧有 v 一侧只有派生速度。要把布料顶点速度在碰撞前算出来,冲量改完再写回 x_prev,使 x_prev = x - v*dt。写反则布料下一帧朝错误方向飞。先做“刚体球撞静态布”再做“布盖动态箱”,单向比双向容易验。

隐式软体与刚体 PGS 同屏,时间步必须同一固定 dt 或明确多速率。多速率时细步上冻结刚体位置,只把冲量累积到刚体,粗步再一次施加。第一版不做多速率,布料用子步、刚体也跟着子步,贵但正确。

RK4 中间点没有接触力的良好定义。有人把接触只加在整步上、中间点当无碰撞,高速时等于关闭接触。不要混。光滑力场(风力、向心力演示)可以用 RK4,接触物体不要用。

检查表:关掉碰撞弹簧能量有界;自由落体 1 秒位移接近 4.9 米;Verlet 变 dt 必须缩放 x-x_prev。三条不过,积分器没毕业。

实践问答

半隐式为什么把写位置放到求解后?

让位置用约束后的速度走,接触才来得及在这一步起作用。先写位置再求解,等于这一帧已经穿过去了,求解只改速度,画面上仍穿。顺序是半隐式家族的工程形态。

Verlet 变 dt 必须缩放位移吗?

必须。x-x_prev 带旧 dt 的量纲。固定步则无此问题。这是又一个固定步的理由。

子步和加迭代如何选?

子步会刷新接触,高速旋转时更值。只加迭代,法向还是步初那份。先子步 2,再看迭代。手机上子步也费电,用分析器。

刚体和布料混用第一版怎么做?

同一 dt,布料子步时刚体跟着。接触先单向。双向冲量还回放在软体稳之后。多速率耦合是进阶,先别做。

参数扫描笔记:积分耦合

扫描 1:先写位置再求解

这一帧已经穿了。位置用约束后速度写。

扫描 2:Verlet 卡顿不缩放位移

布料射出。固定步可避免。

扫描 3:隐式加很大 bias

糖浆。刚体不要隐式,软体分开调 beta。

扫描 4:两套接触模型叠同一物体

能量指标撒谎。选一套。

扫描 5:布料改速度不写回 x_prev

下一帧飞。派生速度要自洽。

扫描 6:全球一种 dt 加子步

第一版够。多速率以后再说。

扫描 7:RK4 中间点加接触

中间点接触力无良好定义。接触物体不用 RK4。

扫描 8:重力写成 a*dt 进 Verlet

第一帧消失。自由质点 1 秒 4.9 米验收。

工程备忘录

备忘 1

对账数字比观感先行。静止支撑冲量是否接近质量乘重力乘 dt,自由落体一秒是否接近四点九米,两球对心是否交换速度。「03-半隐式Verlet与隐式积分」相关实现先过对账,再谈好看。 本条对应「03-半隐式Verlet与隐式积分」第 1 号备忘,和相邻条目不要合并成一句空话,分开验收。

备忘 2

「03-半隐式Verlet与隐式积分」出抖动时按清单:时间步是否固定、流形点是否闪、法向是否跳、恢复系数是否在静止时仍生效、bias 是否过大、迭代是否其实在清零热启动。不要先把摩擦系数调到十。 本条对应「03-半隐式Verlet与隐式积分」第 2 号备忘,和相邻条目不要合并成一句空话,分开验收。

备忘 3

空间结构必须在世界系。把「03-半隐式Verlet与隐式积分」绑到摄像机或屏幕格子,逻辑和确定性都会在转视角时崩。渲染剔除不能代替宽相,看不见的物体仍能被撞到。 本条对应「03-半隐式Verlet与隐式积分」第 3 号备忘,和相邻条目不要合并成一句空话,分开验收。

备忘 4

「03-半隐式Verlet与隐式积分」的预分配策略:按关卡上限留容量,超出打日志并降级,不要在 step 中途默默扩容。扩容是卡顿尖峰,也是回放时分配顺序不同导致的潜在分叉源。 本条对应「03-半隐式Verlet与隐式积分」第 4 号备忘,和相邻条目不要合并成一句空话,分开验收。

备忘 5

把「03-半隐式Verlet与隐式积分」相关的失败做成最小复现:关掉渲染特效、关掉音频、只留固定 dt 的 step 和一份输入日志。能在十秒内重放出来的 bug 才叫被抓住。不能重放就先补录制,再谈修。很多人在这一步省时间,后面用几天陪着偶发抖动。 本条对应「03-半隐式Verlet与隐式积分」第 5 号备忘,和相邻条目不要合并成一句空话,分开验收。

温故知新

  • 刚体默认半隐式:先更新速度,约束改速度,再写位置。
  • Verlet/XPBD 适合网状约束;速度是位置差出来的派生量。
  • 隐式换大步长,税是线性求解和过阻尼,不治隧道效应。
  • 子步比盲加迭代更稳,因为接触会刷新。
  • 不要两套接触模型叠在同一物体上
  • 用自由落体距离和弹簧能量两条测试卡住实现
  • 高阶 RK 不适合非光滑接触;光滑力场再考虑。

下一章进入碰撞。积分给出可能非法的预测位置,宽相和窄相负责把“谁和谁可能碰上”变成接触数据。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U