3.3 接触流形生成与管理


3.3 接触流形生成与管理

本节摘要:盒子压在盒子上不是一个点,而是一个接触面。流形生成把参考面和入射面裁剪出最多四个点,每个点带穿透深度。跨帧缓存这些点并热启动冲量,摩擦才有锚,PGS 才收敛得快。每帧扔掉重建,堆叠会抖,箱子会在静止时自己散步。

读前必看

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

  1. 说明为什么布尔相交不够,堆叠需要多点流形
  2. 描述盒子对盒子的参考面裁剪流程
  3. 实现按特征 id 匹配的接触缓存与冲量热启动
  4. 处理增点和丢点,避免摩擦锚点乱跳

一、一个点撑不住一个面

把箱子放在地板上,若只有中心一个接触点,箱子会绕该点摇,像踩高跷。四个角各一个点,才构成静定支撑。二维多边形对多边形通常最多 2 个点,三维盒子对平面最多 4 个。流形就是“这一对形状当前的接触点集合”,有上限,有特征编号。

特征编号:盒子的面、边、顶点有稳定 id。接触点用“A 的特征 × B 的特征”命名。下一帧还是这两个特征挨着,就认为是同一个点,继承上一帧的法向冲量、切向冲量。这叫热启动。没有它,求解器每帧从零猜接触力,堆叠要很多迭代才压实,看起来像橡皮。

Manifold: pairId normal points[4]: localA, localB featureId impulseN, impulseT penetration

点存在局部坐标里,随刚体变换到世界,比存世界坐标抗积分漂移。穿透每帧重算:世界点沿法向的分离距离。法向通常整帧对流形共用一个,来自窄相的最小分离轴。点各自深度可以不同,角上已经离开的点深度为负,应剔除。

策略 静止堆叠 滑动摩擦 实现量
每帧一个接触点 差,会摇
每帧重建多点无缓存 中,易抖 摩擦无记忆
多点加特征缓存热启动 静摩擦能抓住
只用距离约束无摩擦锚 尚可

产品引擎走第三行。作业可以第二行先看堆叠,但要知道抖动来自何处。

二、裁剪怎么做(盒子为例)

SAT 给出法向后,选法向主要朝向的那一侧的面为参考面(面积大、更对齐法向的那个物体上的面)。另一物体上最朝向参考面的面是入射面。把入射面的顶点裁进参考面的四条边,再投影到参考面平面,去掉深度为负(已分离)的点,若超过 4 个,按深度或面积启发式留 4 个。这是 Sutherland–Hodgman 裁剪在接触生成上的应用。

球对什么都是 1 个点,不用裁剪。胶囊对平面 1 个点。凸包对凸包通用裁剪更烦,许多引擎对凸包用“GJK 最近点 + 若穿透则 EPA 再采样相邻面”。第一版刚体引擎:球、胶囊、盒、平面四种,盒对盒裁剪写对,已经能堆金字塔。

匹配算法:对新点,找旧点中 featureId 相同者;找不到再找世界位置距离小于阈值者;再找不到当新点,冲量清零。旧点本帧没被匹配到就丢弃。阈值约 2 到 5 毫米。太大,滑动时锚点粘在原地,物体被无形绳拉住;太小,每帧都当新点,热启动失效。

💡 关键直觉:静摩擦需要一个“锚在切向平面上的记忆”。记忆就是缓存的切向冲量和接触点局部坐标。没有记忆,库仑锥每帧重启,微观滑动被当成动摩擦,堆叠会慢慢挪。

求解器侧:每个点一条法向约束、两条切向约束(三维)。热启动把 lambda 初值设为上一帧冲量。PGS 会在此附近迭代,静止接触几乎一轮就满足。这是缓存值得写的原因——不只是为了摩擦观感,也是为了性能。

三、增点、减少抖动的工程细节

法向能不能每帧变?可以小变,突变要当新流形。若 SAT 这帧选了另一条几乎同样浅的轴,法向翻 90 度,旧冲量全无意义,应重置。用点积判断:新旧法向点积小于 0.7 左右就重置流形。滞后可以防止轴在两条候选间振荡。

图 四点流形撑住箱子

图 四点流形撑住箱子

接触打破阈值:深度小于负的皮肤半径就移除。不要用“深度<0 立刻删”,否则接触在零附近闪烁,热启动反复清零。迟滞:进入接触用 0,离开用 -skin。触发器同理要迟滞,否则事件每帧进进出出。

⚠️ 常见坑:接触点存在世界坐标,物体一转,点留在空中,摩擦把物体拧成麻花。存局部坐标,每帧用当前变换刷新世界位置再算深度。

多物体:每个 pair 一个流形,不要把所有点塞一张全球表还丢了 pair 信息。宽相不再报告某对时,流形延迟一两帧再删,防止接触在阈值附近闪断。延迟删除要有上限,否则物体飞走后还被幽灵点拉着。

调试可视化:每个接触点画小十字,法向画短线,线长度正比于法向冲量。静止堆叠的线应几乎恒定;若在闪,先查流形匹配,再查求解器。这是 7.1 的预告,但 3.3 实现时就要把冲量写回流形,否则后面没东西可画。

2D 简化:边对边最多两点,裁剪变成区间重叠。先写 2D 流形,测试金字塔,再上 3D。3D 裁剪 bug 极难看,2D 里点的增减一目了然。动手优先在这里非常具体:用十个 2D 盒子堆起来睡住,才配写 3D 裁剪。

缩放再次强调:局部接触点乘了带缩放的变换,深度会错。碰撞体正交矩阵加平移,缩放烘焙。流形局部点定义在无缩放的刚体空间。

传感器流形可以不缓存冲量,但要缓存重叠状态以生成 enter/stay/exit。和物理流形分开存,免得传感器点进求解器。

毕业实验:斜坡上放箱子,摩擦足够时应静止。没有切向热启动时,箱子会一帧一帧往下蠕动。加上缓存,蠕动消失。这比任何公式都能说服你为什么要写这么麻烦的匹配。

点的顺序:求解器不依赖顺序,但可视化依赖。保持特征 id 排序,画面上点不会每帧换颜色。减少“看起来在抖其实只是调试颜色在抖”的误报。

凹包分解后,一对刚体可能有多个凸块对,因而多个流形。这是正常的。求解器按流形点迭代,不必合并。合并反而破坏特征 id。一对刚体 4×4 个凸块最坏 16 个流形,要用上限保护,超出则按深度优先保留。

四、特征 id 怎么编号,调试颜色怎么稳

盒子六个面、十二条边、八个顶点,编号写死。接触特征用“参考面 id + 入射边或顶点 id”打包成 32 位。不要用世界坐标哈希当 id,坐标一抖 id 就变,热启动全失效。多边形凸包用顶点索引对,注意索引顺序按最小编号在前,避免 (1,2) 和 (2,1) 当两个点。

调试颜色按 featureId 哈希,不按数组下标。下标每帧因剔除变化,颜色会闪,你会误判流形不稳。真不稳是十字位置闪,不是颜色闪。把这句话贴在显示器上。

延迟删除:宽相本帧没报告的 pair,寿命减一,减到零才删流形。寿命 2 足够。寿命 10 会让飞走的物体还被幽灵点拉。和接触进入迟滞是两件事,不要合成一个魔法数。

2D 验收金字塔:十层盒子,绘制打开,底层四点(二维是两点)位置在 2 秒后应几乎不动。若底层点在左右边之间跳,裁剪在边端点间抖动,加大特征匹配距离或给点位置加微小滞后。滞后太大摩擦会拖影,用斜坡蠕动实验盯住。

实践问答

匹配阈值太大或太小外观差在哪?

太大,滑动锚点粘住像无形绳;太小,每帧新点,热启动失效,斜坡蠕动。用斜坡静摩擦实验盯这个数,不要凭空拍。

法向点积小于多少重置流形?

大约 0.7 作起点。太敏感会常重置,热启动没了;太钝会把近 90 度跳仍当同一流形,冲量方向错。滞后可一起用。

一对刚体多个凸块多个流形要合并吗?

不要。合并破坏特征 id。用上限按深度保留。求解器按点迭代,多流形是正常的。

世界坐标存点为什么拧成麻花?

物体一转,点留空中,摩擦把物体拧向幽灵点。局部坐标每帧刷新世界位置再算深度。这是流形第一铁律。

参数扫描笔记:流形稳定

扫描 1:点存世界坐标

一转拧麻花。存局部。

扫描 2:featureId 用坐标哈希

坐标一抖身份变。用拓扑编号。

扫描 3:调试颜色按下标

颜色闪误报不稳。按特征哈希。

扫描 4:延迟删除寿命 10

飞走仍被幽灵拉。寿命 2 够。

扫描 5:宽相消失立刻删流形

阈值附近闪断。延迟一两帧。

扫描 6:法向跳 90 度仍热启动

冲量方向无意义。点积过低重置。

扫描 7:2D 金字塔未睡先写 3D 裁剪

3D bug 极难看。先 2D 睡住。

扫描 8:传感器点进求解器

零力仍可能挡。分表。

工程备忘录

备忘 1

可视化是「03-接触流形生成」的一部分而不是插件。接触生成时就把点、法向、深度留下来给绘制。事后从形状重新推断,会和求解器看到的数据不一致,你会修一个并不存在的偏差。 本条对应「03-接触流形生成」第 1 号备忘,和相邻条目不要合并成一句空话,分开验收。

备忘 2

固定时间步是「03-接触流形生成」所有数值实验的尺子。尺子在抖,你无法比较积分器,无法调 beta,无法谈确定性。谁把渲染帧时间直接喂进物理,谁就在用弹性的尺子量钢梁。 本条对应「03-接触流形生成」第 2 号备忘,和相邻条目不要合并成一句空话,分开验收。

备忘 3

「03-接触流形生成」里出现 NaN 要在源头断言:未归一化法向、零长度边当轴、除以过小的有效质量、四元数没归一。把 NaN 传到求解器再查,整场速度都会脏,回溯成本高一个数量级。 本条对应「03-接触流形生成」第 3 号备忘,和相邻条目不要合并成一句空话,分开验收。

备忘 4

和美术、策划交接「03-接触流形生成」参数时,用测试盒而不是形容词。说清楚二十厘米台阶能上、八十厘米不能,比说手感更跟手有用。测试盒还能在引擎升级后当合同跑一遍。 本条对应「03-接触流形生成」第 4 号备忘,和相邻条目不要合并成一句空话,分开验收。

本节速览

  • 堆叠需要多点流形,单点是高跷。
  • 点存在局部坐标,用法向深度每帧刷新;特征 id 做跨帧身份。
  • 热启动继承冲量,既为静摩擦也为少迭代。
  • 法向突变则重置流形;进出接触用迟滞,避免闪烁。
  • 宽相消失后延迟删流形,但必须有上限。
  • 先 2D 堆金字塔睡住,再写 3D 裁剪
  • 斜坡静摩擦蠕动是缓存没写对的经典症状

下一章用这些点计算冲量:法向分开、切向摩擦、再把关节当成另一类约束一起迭代。


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