4.1 刚体动力学与冲量响应


4.1 刚体动力学与冲量响应

本节摘要:接触点上的冲量沿法向推开两物体,并因力臂产生角速度变化。有效质量把“这一点沿法向有多容易被推动”收成一个标量,冲量大小等于速度误差除以有效质量。恢复系数进入目标相对速度,鲍姆加特偏置进入穿透修复。写对这一条,顺序求解器只是把它套在循环里。

本节目标

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

  1. 写出接触点相对速度,含角速度项
  2. 推导并实现法向有效质量
  3. 把恢复、斜坡阈值、穿透偏置塞进目标速度
  4. 施加冲量时对两刚体符号相反,动量守恒

一、从速度反射到冲量

弹跳球对无限质量地面:v.n = -e * v.n。两刚体、还有旋转,就要问:沿法向补多少冲量 j,才能让相对法向速度变成目标值。相对速度

vrel = (vA + wA × rA) - (vB + wB × rB) vn = dot(vrel, n)

目标 vn_target = -e * vn(接近时),或 0(低速当非弹性)。需要的法向速度变化 dv = vn_target - vn。冲量 j = dv / K,K 是有效质量的倒数(有人把 K 叫有效质量,符号要在代码里写死一种)。施加:

vA += j * n * invMA wA += invIA * (rA × (j * n)) vB -= j * n * invMB wB -= invIB * (rB × (j * n))

静态地面 invMB=0、wB=0,退回弹跳球。符号错一次,两物体互相吸引,这是第一周最常见的 bug。画 n 从 B 指向 A,j 为正表示推开。

图 接触冲量与力臂

图 接触冲量与力臂

有效质量怎么来:冲量 j 引起的法向相对速度变化是 j 乘一个标量 K,

K = invMA + invMB + n · (invIA (rA × n) × rA) + n · (invIB (rB × n) × rB)

二维里叉积是标量,公式更短。K 接近 0 表示沿该方向推不动(两个静态体),跳过约束。K 很大表示很轻或力臂很长,同样 j 引起的速度变化大。

作用
invM 越轻越容易被推开
旋转项 接触点离质心远,拧起来容易,有效质量变小
锁定轴 对应 inv 置 0,K 变小,更“硬”

二、恢复、阈值、偏置

恢复系数 e 不要对已经几乎静止的接触使用,否则永远睡不着。若 vn > -threshold(正在缓慢接近或已分离),把 e 当 0,目标速度 0。threshold 约 1 m/s 量级,按游戏手感调。分离中的接触 vn >= 0 且没有穿透要修,法向冲量应钳在 0——不能把物体再吸回去。这就是 complementarity:要么有压力且不接近,要么分离且压力为 0。单次冲量先算无约束 j,再 j = max(j, 0)。累计冲量也要整体非负,4.2 节会把累计写清楚。

穿透修复:bias = penetration * beta / dt,目标速度再减去 bias(符号:我们希望 vn 变成分离为正的话,bias 要加到分离方向)。beta 0.1–0.2。穿透很深时钳制 bias 最大值,否则一帧内修正速度巨大,爆炸。位置投影可以辅助,但不要和很大的 bias 同时用满。

vn_target = if approaching_fast: -e * vn else 0 vn_target += bias_separate j = (vn_target - vn) / K j = max(j, 0) # 单次、无累计时

💡 关键直觉:有效质量是“这一点的惯性”。同样误差,轻物体、长力臂需要的冲量更小,因为它们更容易被改速度。公式除以 K,不是随便除以质量。

重力不要在接触里再加一遍。积分阶段已经加了重力。有人用“接触法向抵消重力”的显式力,和冲量叠床架屋。例外:睡醒判定可以看法向冲量是否在支撑重量,那是读 lambda,不是再加力。

三、摩擦预告与数值保护

切向相对速度 vt = vrel - n*vn。动摩擦冲量试图把 vt 刹到 0,但长度不能超过 mu * jn。单次接触可以先看法向再摩擦。旋转加上圆锥摩擦比二维复杂,4.2 展开。这里先保证法向对:无摩擦堆叠应稳定,箱子可以滑。

NaN 防护:K 小于 epsilon 跳过;n 未单位化先单位化;r 用世界坐标。施加后若速度变成 inf,多半是 invI 算错或 q 没归一导致惯性爆炸。

⚠️ 常见坑:用局部 r 叉世界 n,或把 j 乘到力再乘 dt。前者旋转乱,后者飞天。冲量直接改速度。

测试矩阵:

  • 球砸静地面:弹起高度与 e 相关,e=0 不反弹
  • 两等质量球对心碰撞:速度交换
  • 离质心很远的点推盒子:盒子转而不是只平移
  • 深穿透小 beta:几帧内分开,不爆炸

角速度钳制在冲量之后仍要做,细杆被撞会转得离谱。动量守恒测试:两动态体无外力碰撞,总动量应几乎不变(浮点误差内)。静体参与时动量可以进“大地”。

把 1.1 的反射函数删掉,换成这一节的 j。地面仍是哨兵刚体。行为应接近,但盒子现在会转。转起来后流形多点才有意义——单点冲量会拧。所以 4.1 必须和 3.3 一起验收:四点支撑的静止箱子,法向冲量之和应接近重量(质量×g,注意单位与 dt:lambda 常是冲量,重量对应的冲量是 mgdt)。若差很多,不是重力没加,就是接触没撑住在积分里往下掉又被 bias 拉上来,表现为抖动。

单位再核对:j 的单位是动量,lambda 在有的文献里是力。你的公式若从速度误差除以 K 来,得到的是冲量。不要和“力约束”文献混抄系数。注释写明:本引擎 lambda 是冲量。

四、有效质量的直觉实验与符号表

把盒子质心抬高,在底边角上施加同样法向冲量,角速度应更大,平动更小——因为杠杆项进了 K,同样速度误差需要的 j 更小,但角增量更大。把这个实验做成可视化:同一个 j 画平动箭头和转动弧。新人能凭这个记住“K 不是质量”。

符号表写进代码注释并保持:n 从 B 指向 A;j>0 推开;相对速度 A 减 B;bias 使穿透减小,即让 vn 朝分离为正方向增加。每次改公式对照这张表。组员各自发明符号,代码会有一半吸引接触。

恢复系数曲线:用球砸地,e=0、0.3、0.6 测弹起高度。高度不应超过释放高度。超过说明能量注入,查是否把重力在接触里又加了一次,或 j 乘了 dt。e=1 时高度应略低于释放高度(数值耗散)。略高则有 bug。

静止支撑:质量 10 的箱子 dt=1/60,重力 9.81,每步需要的法向冲量约 10*9.81/60。打印 lambda 之和对比。差一个 dt,多半把冲量当力或把力当冲量。这个数字验收比看“好像托住了”可靠。

旋转接触:在离质心远处的点碰撞,盒子应转。若不转,r 叉乘没写或 r 用了零向量。画 r 从质心到接触点,必须落到十字上。

实践问答

相对速度为什么是 A 减 B?

与 n 从 B 指向 A 配套。vn<0 表示接近。符号表写进注释。组员若改成 B 减 A,必须同时翻 n,否则吸引。

K 接近 0 时为什么跳过?

两静态或沿该方向完全锁死,除以 K 会爆。跳过这条约束。细杆最小惯量下限也是为了让 K 别极端。

低速为什么把 e 当 0?

否则永远睡不着,微弹。阈值约 1 米每秒量级,按手感调。堆叠场景尤其要。

静止 lambda 和对账差很多说明什么?

差一个 dt:冲量当力或反过来。差很多且抖动:接触没托住,积分往下掉又被 bias 拉回。先对账再看绘制。

摩擦这一节为什么先不做完?

法向不对时做摩擦是在错误法向上刹车。先无摩擦堆稳,再切向。顺序能省一天调试。

参数扫描笔记:单接触冲量

扫描 1:n 从 A 指向 B 却加到 A

吸引。画箭头。

扫描 2:r 用零向量

盒子不转。十字必须落在 r 终点。

扫描 3:e=1 弹起超过释放高度

能量注入。查重力是否加了两次或 j 乘 dt。

扫描 4:低速仍用 e

永不睡眠。阈值当 0。

扫描 5:K 过小仍除

inf。跳过约束。

扫描 6:静止 lambda 与 m g dt 差一倍

冲量力混用。

扫描 7:先做法向不对的摩擦

错误方向刹车。先无摩擦堆稳。

扫描 8:世界惯性用错 q

转起来质量会变的感觉。先画轴。

工程备忘录

备忘 1

先写 2D 再写 3D 适用于「01-刚体动力学与冲量响应」里所有几何麻烦事。二维金字塔、二维绳、二维铰链能看见点的增减。三维裁剪 bug 极难看,会让你怀疑人生。二维过了再加一根轴。 本条对应「01-刚体动力学与冲量响应」第 1 号备忘,和相邻条目不要合并成一句空话,分开验收。

备忘 2

「01-刚体动力学与冲量响应」不要在热路径调用脚本。求解器迭代十次回调十次,缓存和确定性一起死。标记事件,步末再发。这是布局问题也是架构问题。 本条对应「01-刚体动力学与冲量响应」第 2 号备忘,和相邻条目不要合并成一句空话,分开验收。

备忘 3

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

备忘 4

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

备忘 5

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

备忘 6

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

备忘 7

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

备忘 8

在「01-刚体动力学与冲量响应」路径上加计数器要进 step 末尾快照,不要在热循环里格式化字符串。计数器本身若分配内存,你会优化一个被测量污染的世界。发布版可用宏剥掉绘制,但计数器的定义要保留,方便线上开一个极轻的统计开关。 本条对应「01-刚体动力学与冲量响应」第 8 号备忘,和相邻条目不要合并成一句空话,分开验收。

本章回顾

  • 相对速度含 w×r;冲量对两体符号相反。
  • j = 速度误差 / K,K 含平动与两端旋转杠杆。
  • 低速碰撞把 e 当 0;j 法向累计非负。
  • bias 修穿透要钳最大值;别和硬投影同时拉满。
  • 冲量不再乘 dt;惯性用世界系。
  • 用速度交换和动量守恒做单元测试
  • 静止支撑时法向冲量应能托住重量对应的动量增量

下一节把这一条公式放进循环:很多接触互相拉扯时,轮流投影,直到大家大致都合法。


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