想象一下奶奶织毛衣:每一针是一个交叉结点,每一段毛线把两个结点连在一起。线绷紧了就互相拉扯,线松了就自然垂落。如果把整件毛衣拆开看,它就是由成千上万个结点和线段构成的“弹性网”。物理模拟里的布料,就是把这团数字毛线搬进电脑——把一块布拆成一个个“针脚”(质点),针脚之间用“毛线”(弹簧)相连。整块布飘动、垂下、被风吹起的模样,都是无数弹簧互相拉扯的结果。 而软体物理,则是往这件毛衣里塞了一团棉花:捏它凹下去,松手弹回来。布只有“面”,软体却有“体”,它必须守住自己的体积。本文就从一根毛线讲起:质点弹簧的骨架、胡克定律的脾气、一帧一帧推进的数值积分、不许穿模的碰撞约束,再到软体的压力模型、空间哈希加速、引擎调参和常见的抖动伪影。读完你会明白,游戏里飘逸的披风、果冻般的史莱姆,背后藏着的都是一套精细的“针线活”。

岗位关联

掌握布料与软体物理,等于拿到了游戏、影视、机器人仿真领域“让虚拟世界可信”的钥匙,是引擎动画与物理系统岗位的必备内功。

目录
  1. 可视化演示
  2. 布料基石:质点与弹簧网络
  3. 弹簧动力学:胡克定律与阻尼
  4. 数值积分:显式欧拉与 Verlet
  5. 碰撞与约束:投影的艺术
  6. 软体物理:有限元与压力体
  7. 性能优化:空间哈希与 GPU 并行
  8. 引擎实战:稳定条件与参数调优
  9. 常见伪影:抖动、拉伸与锁定
  10. AI 应用场景
  11. Python 演示
  12. 常见误区
  13. 面试题

可视化演示

展示质点弹簧布料网格受风力变形、Verlet积分约束求解与软体四面体碰撞变形,切换模式观察物理模拟。

本节配有交互动效(进入视口后自动加载,约 3KB)。

质点弹簧布料网格 结构弹簧约束相邻质点水平垂直距离 剪切弹簧约束对角线防止过度变形 F = -k(x - x0) - cv 胡克定律计算弹簧恢复力。

布料基石:质点与弹簧网络

织毛衣的第一步是起针。奶奶在针上排出一排针脚,每个针脚只需要记住两件事:我此刻在哪儿,谁在拉着我。布料模拟的第一步也是“起针”——把布面离散成一张网格,每个网格交点叫质点,相邻质点之间用一根弹簧拴住。质点负责记录位置、速度和“轻重”(质量),弹簧负责记住两个质点之间的初始距离,也就是“原长”。

这一步的灵感来自生活:整块布的行为,等于所有针脚互相拉扯的合谋。网格越密,布越细腻,但计算量也越大。最常用的拓扑是四边形网格:每个内部质点与上下左右四个邻居相连。不过四边形抗剪切能力差,一拉就斜——所以工程上会再加对角弹簧,像毛衣的加固线一样,防止布面“扯歪”。

质点弹簧模型(Mass-Spring)是整个布料模拟的基石,它的能量由每根弹簧的形变决定。弹性势能公式如下:

就像起针决定了毛衣的版型,质点和弹簧构成了布料的“骨”。针脚密,布细腻;针脚疏,布粗糙。接下来,我们要看看这些毛线到底是怎么用力的。

E=12k(x−x0)2\displaystyle E = \frac{1}{2} k (x - x_0)^2
这个公式描述一根弹簧“被拉长或压短后存了多少能量”。能量越高,弹簧越想恢复原样。
  1. 形变偏差弹簧当前长度与原长的差值,是回弹力的“证据”。
    x−x0\displaystyle x - x_0
  2. 平方放大取平方后,拉伸和压缩的偏差都变成正值,能量永远不小于零。
    (x−x0)2\displaystyle (x - x_0)^2
  3. 弹性系数k 越大,同样形变储存的能量越高,布料越挺括,像粗毛线织的厚毛衣。
    12k(x−x0)2\displaystyle \frac{1}{2} k (x - x_0)^2

弹簧动力学:胡克定律与阻尼

毛线拉长后会回弹,但不会永远弹跳下去——因为空气和线自身的摩擦在“刹车”。弹簧的这一体两面,正是模拟的日常:回弹交给胡克定律,刹车交给阻尼。如果只有回弹没有阻尼,布会像装了永动机一样荡个没完。

胡克定律说:弹簧的恢复力与形变量成正比,方向与拉伸方向相反。k 是弹性系数,形变量越大,回拉力越猛。而阻尼项与速度成正比:质点动得越快,阻力越大,方向与运动方向相反。把两项叠在一起:

有了力,质点就会动。但“动”是连续的,计算机只能离散地推进——这正是下一节“时间推进器”要解决的事。

F=−k(x−x0)−c v\displaystyle F = -k(x - x_0) - c\,v
第一项是“弹回去的力量”,第二项是“踩刹车的阻力”。两者合起来,决定了布料是轻飘还是厚重。
  1. 恢复力项形变量 x - x₀ 越大,回拉的力越大;负号表示方向指向原长。
    −k(x−x0)\displaystyle -k(x - x_0)
  2. 阻尼项c 是阻尼系数,v 是两端质点的相对速度;负号表示与运动方向相反。
    −c v\displaystyle -c\,v
  3. 合力两项叠加得到弹簧施加在质点上的总力,再除以质量就是加速度(牛顿第二定律)。
    F=−k(x−x0)−c v\displaystyle F = -k(x - x_0) - c\,v

数值积分:显式欧拉与 Verlet

织毛衣不能一步到位,得一行一行往上织。物理模拟也一样:把时间切成一小段一小段,每段叫一个时间步 Δt。每走一步,就根据当前状态推算下一帧。这个过程在数学上叫数值积分。

最直观的推进方法是显式欧拉:用当前速度直接推位置,用当前力直接推速度。但它有个著名的毛病——步长稍大就“爆炸”:位置越过平衡点太多,下一帧回弹更猛,最后整块布崩成雪花。布料模拟界更爱用 Verlet 积分:干脆不显式存速度,而是用前两帧的位置“外推”当前帧:

一针一针往前推,时间步就是“每一针的宽度”:针脚太宽,布就变形;太细,织得慢。但光有推进还不够——布不能穿过身体,这就轮到“版型规则”登场了。

xt+Δt=2xt−xt−Δt+a Δt2\displaystyle x_{t+\Delta t} = 2x_t - x_{t-\Delta t} + a\,\Delta t^2
Verlet 像“看着前两步的脚印迈下一步”:2x_t - x_{t-Δt} 是惯性外推,aΔt² 是重力等外力在这小段时间里造成的偏移。
  1. 惯性外推当前位置的两倍减去上一帧位置,等效于“保持原速度滑行”,不存速度也能隐含速度。
    2xt−xt−Δt\displaystyle 2x_t - x_{t-\Delta t}
  2. 外力修正加速度 a 乘以时间步的平方,表示重力、弹簧力在这一步里的位移贡献。
    a Δt2\displaystyle a\,\Delta t^2
  3. 完整更新惯性外推加外力修正,得到下一帧位置;这个格式天然对称,长时间模拟不容易飘。
    xt+Δt=2xt−xt−Δt+a Δt2\displaystyle x_{t+\Delta t} = 2x_t - x_{t-\Delta t} + a\,\Delta t^2

碰撞与约束:投影的艺术

毛衣穿在身上,不能穿到身体里面去。道理简单,可数字世界里的“身体”和“布”都没有实体,谁都不拦着谁。于是物理引擎想出一个粗暴又聪明的办法:约束——规定某些关系必须满足,不满足就直接“掰”回去。

最典型的约束是距离约束:一根弹簧两端质点的间距要尽量保持原长。我们不调整力,而是直接计算误差,然后沿两点连线方向把位置修正到合法值。这种“直接改位置”的框架叫 PBD(Position Based Dynamics),是游戏引擎里最流行的布料方案。它的核心公式是约束修正量:

这就像织毛衣时随时对照版型修一修:哪里鼓了按回去,哪里紧了松一松——不纠结于力,直接改位置。碰撞检测也同理:质点穿透地面,就把它投影回地面上方。有了这套规则,布才真正“穿得住”。

Δxa=∣xa−xb∣−L2⋅xa−xb∣xa−xb∣\displaystyle \Delta\mathbf{x}_a = \frac{|\mathbf{x}_a - \mathbf{x}_b| - L}{2}\cdot\frac{\mathbf{x}_a - \mathbf{x}_b}{|\mathbf{x}_a - \mathbf{x}_b|}
括号里是“偏离了多少”,箭头方向是“往哪儿掰”。两点各承担一半修正量,弹簧就回到原长附近。
  1. 约束误差两点当前距离减去原长 L,得到一个标量误差 C,正代表拉长了,负代表压短了。
    C=∣xa−xb∣−L\displaystyle C = |\mathbf{x}_a - \mathbf{x}_b| - L
  2. 修正方向单位向量指向分离方向,保证“拉长了就靠近,压短了就远离”。
    d^=xa−xb∣xa−xb∣\displaystyle \hat{d} = \frac{\mathbf{x}_a - \mathbf{x}_b}{|\mathbf{x}_a - \mathbf{x}_b|}
  3. 平分修正误差由两个端点各摊一半,谁被固定住(pin)谁就不动。
    Δxa=C2 d^\displaystyle \Delta\mathbf{x}_a = \frac{C}{2}\,\hat{d}

软体物理:有限元与压力体

如果往毛衣里塞一团棉花,按压会凹、松手会弹——这就是软体。布是“面”,软体是“体”。软体不仅要像布那样抗拉伸,还要对抗一个更重要的东西:体积变化。捏一个果冻,它内部会被挤压,压强升高,然后把你的手指顶回去。

模拟软体有两条主流路线。有限元法(FEM) 把物体切成许多小四面体,逐个分析每个单元的形变与应力,精确但计算量惊人;压力体模型 则把物体内部当成一个气球腔,用气压抵抗挤压。游戏里常用后者:软体表面每个小面元都有面积 A,内部压强 P 沿外法线方向推出去:

就像棉花填充让毛衣立体,软体物理让虚拟物体有了“体积感”。一压一弹,都是压强在说话。从果冻怪物到软体机器人,这套模型撑起了半个“有弹性”的世界。

F=P A n\displaystyle F = P\,A\,\mathbf{n}
这是“气球原理”的数学版:面积越大、压强越高,推得越狠;方向永远是朝外的法线方向。
  1. 面元面积软体表面被切成很多小面片,A 是其中一片的面积。
    A\displaystyle A
  2. 压强推挤内部压强 P 乘面积 A,是这一片受到的推力大小。
    P×A\displaystyle P \times A
  3. 外法线方向单位向量 n 垂直于小面元指向外部,保证力是“向外鼓”,而不是向内塌。
    n\displaystyle \mathbf{n}

性能优化:空间哈希与 GPU 并行

一群织工同时织一件毛衣,得先分好片区:甲织左袖,乙织右袖,最后拼接。可要是所有人的手都能伸到同一个格子里,就打架了。布料模拟里最大的开销是碰撞检测:布料的每一点都要确认自己没穿进别的东西。朴素做法是每对质点都测一遍,复杂度 O(n²),一万个质点就是五千万次运算,直接卡死。

空间哈希 把空间切成均匀的正方格子,每个质点只跟自己所在格子和周围 9 个格子里的邻居比对。查邻居的平均成本从 O(n) 降到 O(1),总复杂度变成 O(n)。格子的坐标经过一个哈希函数,映射到一维数组:

除了空间划分,GPU 并行 是另一大杀器:质点和弹簧彼此独立,天然适合并行——每个线程管几个质点,一帧里跑好几轮迭代。再加上细节层次:远处用粗网格、近处用细网格。十万质点的披风,就这样在游戏里 60 帧飘了起来。

h=(⌊xs⌋+⌊ys⌋×W) mod N\displaystyle h = \left(\left\lfloor \frac{x}{s} \right\rfloor + \left\lfloor \frac{y}{s} \right\rfloor \times W\right) \bmod N
把二维格子坐标压成一维编号,像图书馆给书架编号:先按排走,再按层数取模,快速定位“这一格的人”。
  1. 格子坐标用坐标除以格子边长 s 再向下取整,把连续位置变成格子编号。
    cx=⌊xs⌋,cy=⌊ys⌋\displaystyle c_x = \left\lfloor \frac{x}{s} \right\rfloor,\quad c_y = \left\lfloor \frac{y}{s} \right\rfloor
  2. 线性编码按行主序把二维格子编码成一维索引,W 是每行格子数。
    cx+cy×W\displaystyle c_x + c_y \times W
  3. 取模映射对哈希表长度 N 取模,把索引压缩到数组范围内,减少内存浪费。
    (cx+cy×W) mod N\displaystyle \left(c_x + c_y \times W\right) \bmod N

引擎实战:稳定条件与参数调优

奶奶会按季节选毛线:夏天细棉线透气,冬天粗毛线保暖。引擎里的布料也有“线号”——一堆参数等着你调。Unity 的 Cloth、UE 的 Chaos Cloth 都暴露了刚度(stiffness)、阻尼(damping)、迭代次数、质量等旋钮。调之前,必须先懂一条“生死线”:显式积分的稳定条件。

如果时间步长太大,弹簧力会把质点推过头,回弹再推更远,最终爆炸。临界步长由质量和刚度决定:

有了这条公式,调参顺序就清晰了:先定刚度,满足手感;再算临界步长,不够就加密子步;最后微调阻尼,去掉余振。工程上还有个常用技巧:多次小步迭代——把一步拆成几个子步,既绕过稳定性限制,又保持效率。毛线选不好毛衣就织不好,参数配不好布料就变成爆炸粒子特效。

Δtmax⁡=2mk\displaystyle \Delta t_{\max} = 2\sqrt{\frac{m}{k}}
弹簧越硬(k 大),允许的步长窗口越小;质点越重(m 大),窗口越大。超过这个值,模拟必炸。
  1. 质量项质量 m 在分子上,越重的质点越“笨”,越不容易被一步推飞。
    m\displaystyle m
  2. 刚度项k 在分母上,弹簧越硬,临界步长越小,越需要“小步快走”。
    mk\displaystyle \frac{m}{k}
  3. 开方与因子开方让量纲回到时间单位,因子 2 对应临界阻尼的边界。
    Δtmax⁡=2mk\displaystyle \Delta t_{\max} = 2\sqrt{\frac{m}{k}}

常见伪影:抖动、拉伸与锁定

织得太松,毛衣领口越穿越大;织得太紧,缩水硬邦邦。布料模拟也有两个对应毛病:拉伸(超弹)和抖动(jitter)。拉伸来自约束太软或迭代不足:弹簧没被“掰”到位,布越拉越长;抖动来自步长太大或误差来回震荡:画面像筛糠。还有一个更隐蔽的问题——锁定:弯曲约束太强,布料硬得像纸板,怎么都不肯自然打褶。

约束投影的迭代收敛速度能解释很多现象:

知道毛病出在“松紧”,就能对症下药:加迭代、减步长、微调阻尼。若还嫌慢,用过松弛(over-relaxation)加速收敛,或者换 XPBD 消除过冲。一块平静妥帖的数字布料,就织出来了。

ek=e0×2−k\displaystyle e_k = e_0 \times 2^{-k}
每多做一轮约束迭代,残余误差大约减半。迭代 3 次误差剩 1/8,迭代 6 次误差剩 1/64,肉眼基本看不出来了。
  1. 初始误差弹簧当前距离相对原长的偏离程度,是起点。
    e0=∣x−L∣L\displaystyle e_0 = \frac{|x - L|}{L}
  2. 减半收敛投影法每轮迭代把误差压缩一半,k 轮后就是初始误差乘以 2 的负 k 次方。
    ek=e0×(12)k\displaystyle e_k = e_0 \times \left(\frac{1}{2}\right)^k
  3. 工程含义想更平滑,把迭代次数从 3 加到 6;再往上性价比骤降,不如减小时间步长。
    ek=e0 2−k\displaystyle e_k = e_0\,2^{-k}

AI 应用场景

游戏角色披风的实时解算

阶段:游戏物理与动画管线

解决的问题:传统做法是美术逐帧 K 动画,角色转身时披风穿模、动作一改就要重 K。用质点弹簧 + PBD 自动模拟,披风每帧自己“飘”,不穿模且随动作自然响应。

具体案例:开放世界 RPG 主角的披风,在奔跑、跳跃、翻滚时都由布料解算驱动;后端跑空间哈希碰撞查询 + 少量迭代,宿主机的 60 帧预算内稳稳跑完。

影视级衣物离线解算

阶段:离线解算与缓存烘焙

解决的问题:电影角色裙摆每帧渲染费时,布料与身体碰撞稍有不慎就穿帮。离线场景追求精度,可以用高迭代 + 有限元软体,把裙摆的每一条褶皱算到满意为止。

具体案例:动画电影角色穿长裙行走,先在 Marvelous Designer 里打版,再导入 Maya nCloth 解算节点,CPU 集群一帧算几分钟到几十分钟,最后烘焙成动画缓存供渲染。

软体机器人抓取的仿真数据生成

阶段:仿真数据生成(具身智能)

解决的问题:软体机械手抓鸡蛋、豆腐等易碎物,真实实验成本高、难复现。用压力体 + 弹簧网格模拟软体抓手,批量生成抓取姿态数据,供强化学习策略训练。

具体案例:在 PyBullet 中搭建果冻质感的软体抓手模型,自动采样上万次抓取,收集力反馈和形变数据,训练出的策略再迁移到真实机械臂。

Python 演示

python95 行
import mathimport random  class Particle:    def __init__(self, x, y, pinned=False):        self.x = x        self.y = y        self.ox = x        self.oy = y        self.pinned = pinned     def step(self, dt, gravity):        if self.pinned:            return        vx = (self.x - self.ox) * 0.98        vy = (self.y - self.oy) * 0.98        self.ox, self.oy = self.x, self.y        self.x += vx        self.y += vy + gravity * dt * dt  class Spring:    def __init__(self, a, b, rest):        self.a = a        self.b = b        self.rest = rest     def solve(self, particles):        p1 = particles[self.a]        p2 = particles[self.b]        dx = p2.x - p1.x        dy = p2.y - p1.y        dist = math.hypot(dx, dy)        if dist < 1e-9:            return        diff = (dist - self.rest) / dist * 0.5        if not p1.pinned:            p1.x += dx * diff            p1.y += dy * diff        if not p2.pinned:            p2.x -= dx * diff            p2.y -= dy * diff  class Cloth:    def __init__(self, cols=12, rows=9, gap=12.0):        self.particles = []        self.springs = []        for r in range(rows):            for c in range(cols):                x = c * gap                y = r * gap                jitter = random.uniform(-0.3, 0.3)                is_pinned = (r == 0)                self.particles.append(Particle(x + jitter, y, pinned=is_pinned))        for r in range(rows):            for c in range(cols):                i = r * cols + c                if c < cols - 1:                    self._add_spring(i, i + 1)                if r < rows - 1:                    self._add_spring(i, i + cols)     def _add_spring(self, i, j):        a = self.particles[i]        b = self.particles[j]        rest = math.hypot(b.x - a.x, b.y - a.y)        self.springs.append(Spring(i, j, rest))     def simulate(self, dt=0.016, gravity=500.0, iterations=4):        for p in self.particles:            p.step(dt, gravity)        for _ in range(iterations):            for s in self.springs:                s.solve(self.particles)        for p in self.particles:            if p.y > 300:                p.y = 300                p.oy = 300  def main():    cloth = Cloth(12, 9, 12.0)    for frame in range(60):        cloth.simulate()        if frame % 10 == 0:            xs = [p.x for p in cloth.particles]            ys = [p.y for p in cloth.particles]            width = max(xs) - min(xs)            print("frame=%3d width=%6.2f  bottom_y=%6.2f" % (frame, width, max(ys)))  if __name__ == "__main__":    main()
目的:纯标准库实现的 2D 布料模拟,包含 Verlet 积分、弹簧约束迭代和地面碰撞,演示一块布料从水平状态在重力下自然下垂的全过程。
  1. is_pinned = (r == 0)第一行质点固定,相当于把毛衣领口挂在衣架上,其余部分才能自由下垂。
  2. vx = (self.x - self.ox) * 0.98用“当前位置减上一帧位置”还原速度,0.98 是隐式阻尼,避免永动。
  3. self.y += vy + gravity * dt * dtVerlet 积分的位移更新,重力在这一小步里贡献一个二次位移。
  4. diff = (dist - self.rest) / dist * 0.5距离误差归一化,两个端点各摊一半修正量。
  5. for _ in range(iterations):迭代次数越多,弹簧越“听话”,布料越不容易拉伸。
  6. if p.y > 300:地面碰撞的暴力投影:不许穿到地板下面,同时重置上一帧位置防止抖振。

常见误区

误区布料不够挺括?那就多加弹簧,横的竖的斜的全加上,总该真实了吧?

正解弹簧过量会导致“锁定”(locking):约束互相矛盾,布料反而硬得像纸板,动都动不了。真实感来自恰当的拓扑和迭代次数,而不是弹簧数量。就像毛衣不是线越多越好,线乱成一团反而皱巴巴。

为何常见:初学者直觉认为约束越多越精确,忽略了约束之间会互相打架。

误区把弹簧刚度 k 调到很大,布料不就笔挺了吗?

正解刚度越大,稳定条件 Δt ≤ 2√(m/k) 越苛刻,显式积分更容易爆炸。工程上更常用“多次迭代 + 约束投影”来保持形状,而不是一味加刚度。现实中想把毛衣织挺,靠的是针法,不是把线勒断。

为何常见:胡克定律的直觉是“力大就有用”,但忽略了数值稳定性这条天花板。

误区Verlet 积分不用显式存速度,所以它天然稳定,步长可以随便给。

正解Verlet 只是比显式欧拉更宽容,步长过大同样会过冲、抖动,甚至爆炸。它还需要阻尼和碰撞处理配合。就像看脚印预测下一步,步子迈太大照样摔跤。

为何常见:把“无需速度”误解为“无条件稳定”,混淆了数值格式本身的特性。

误区布料模拟不就是给游戏角色做衣服吗?跟 AI 有什么关系?

正解布料和软体物理是游戏物理、影视特效、机器人仿真、具身智能数据生成的基础。软体抓手的仿真数据训练策略,靠的正是这套“弹性网”思想。毛衣能织衣服,也能织出果冻机械手。

为何常见:只看到“布料”的字面含义,没看到“质点弹簧 = 通用弹性模型”这个抽象内核。

面试题

Q1. 布料模拟中最基本的组成单元是什么?

单选题 · easy

  • A.网格顶点与弹簧← 正确答案
  • B.三角面片与材质
  • C.刚体与碰撞盒
  • D.光源与渲染贴图

答案:A。布料模拟的基石是质点弹簧模型:质点记录位置质量,弹簧记录原长和弹性。就像毛衣的针脚和毛线,两者配合才构成布。三角面片和材质是渲染层的概念,不是物理模拟的基本单元。

Q2. 胡克定律中弹簧恢复力与什么成正比?

单选题 · easy

  • A.弹簧当前长度的平方
  • B.相对原长的形变量← 正确答案
  • C.质点自身的质量
  • D.模拟的时间步长

答案:B。胡克定律 F = -k(x - x₀),恢复力正比于形变量(当前长度减原长)。形变量越大回弹越猛,就像毛线拉得越长回弹力越强。质量是 F=ma 中的角色,时间步长属于积分环节。

Q3. 显式欧拉积分在大时间步长下容易出现什么现象?

单选题 · easy

  • A.布料逐渐变僵硬
  • B.位置爆炸式发散← 正确答案
  • C.布料变成完全透明
  • D.纹理被无限拉伸

答案:B。显式欧拉用当前状态外推,步长过大时位置越过平衡点太远,回弹再推更远,形成正反馈爆炸。就像织毛衣针脚太宽,整件衣服越扯越大最后崩线。

Q4. Verlet 积分相比显式欧拉的主要优势是?

单选题 · mid

  • A.无需显式存储速度← 正确答案
  • B.完全避免碰撞穿透
  • C.自动生成网格拓扑
  • D.不需要消耗算力

答案:A。Verlet 用前两帧位置外推当前位置,速度信息隐含在位置差里,因此无需显式存储速度。它只是更稳定,并不能完全避免穿透,也照样消耗算力、需要手动建网格。

Q5. 空间哈希加速碰撞检测的核心思想是?

单选题 · mid

  • A.只检测相邻格子内的对象← 正确答案
  • B.用神经网络预测所有碰撞
  • C.把布料烘焙成静态贴图
  • D.每个质点单独检测全部

答案:A。空间哈希把空间切分成均匀格子,每个质点只检查所在格子及周围相邻格子里的对象,把 O(n²) 降到 O(n)。就像工厂分区流水线,工人只跟同区的同事打交道。

Q6. 约束投影公式中 C(x) 代表什么?

单选题 · mid

  • A.质点在场景中的颜色值
  • B.描述约束违反程度的函数← 正确答案
  • C.弹簧阻尼系数的缩写
  • D.相机空间裁剪面的编号

答案:B。C(x) 是约束函数,计算当前状态偏离目标值的程度。比如距离约束 C = |x_a - x_b| - L,数值越大说明布被拉得越远,需要修正得越狠。

Q7. 减少布料模拟抖动的常用手段包括?

多选题 · mid

  • A.减小模拟的时间步长← 正确答案
  • B.增加每帧约束迭代次数← 正确答案
  • C.把弹簧刚度调到无穷大
  • D.为速度增加少量阻尼← 正确答案

答案:ABD。抖动源于误差累积,减小步长、增加迭代、加阻尼都能压住误差。刚度调到无穷大会让临界步长趋近于零,反而更容易爆炸,是错误选项。

Q8. 显式积分的稳定条件 Δt ≤ 2√(m/k) 说明什么?

单选题 · hard

  • A.弹簧越硬允许步长越小← 正确答案
  • B.时间步长与弹簧刚度无关
  • C.质点质量越小越稳定
  • D.阻尼增大反而容易爆炸

答案:A。公式中 k 在分母上,k 越大临界步长越小;m 在分子上,质量越大越稳。这条公式是布料调参的定盘星,决定了“小步快走”还是“大步流星”。

Q9. 关于布料模拟中的“锁定”现象,正确的说法有?

多选题 · hard

  • A.弯曲约束过强布料像纸板← 正确答案
  • B.添加对角弹簧缓解锁定← 正确答案
  • C.无限加密网格必然消除锁定
  • D.锁定与约束迭代次数无关← 正确答案

答案:ABD。锁定是约束方向性导致的,约束过强或拓扑不当都会让布料变硬。对角弹簧能增加剪切自由度,缓解锁定。网格加密不一定消除锁定,甚至可能加剧;这是几何拓扑问题,与迭代次数无关。

Q10. PBD 中多个距离约束互相矛盾时,正确处理方式是?

单选题 · extreme

  • A.多次重复迭代直到收敛← 正确答案
  • B.只应用一次约束就停止
  • C.增大时间步长加速求解
  • D.删除所有相互矛盾的约束

答案:A。互相矛盾的约束无法一次满足,PBD 采用 Gauss-Seidel 式多次迭代,让所有约束逐渐逼近平衡。只迭代一次或删约束都会失真,增大步长反而加剧震荡。这就像多位织工同时拉一根线,只能来回协调几次才能都满意。