学习进度
0/9 已勾只保存在这台浏览器;勾满 9 项即视为本题完成。
先把题目说成人话
角色抬手时,肩部不能像硬木板一样只跟上臂,也不能完全留在锁骨上;同一个表面点需要同时参考几根骨骼,才能形成平滑过渡。若直接拿骨骼今天的位置去搬这个点,绑定时已经存在的偏移会被再算一次,整块肩膀便像重复搬家。现实要解决的是先恢复“休息姿势下这个点与每根骨骼的关系”,再应用当前姿势,最后才把整个角色放进世界。
让网格跟随多根骨骼变形叫线性蒙皮(Linear Blend Skinning),每根骨骼影响多少叫骨骼权重(Bone Weight)。建立关系时的休息姿势叫绑定姿势(Bind Pose),把绑定关系倒回去的矩阵叫逆绑定矩阵(Inverse Bind Matrix)。这些结果先在角色自身空间合成,角色整体的位置、旋转和缩放最后再进入世界空间。
这是虚构教学故事,不是个人项目经历。
场景:先让问题变得看得见
想象肩部布料上的一个点同时系着上臂和锁骨。先观察角色保持休息姿势时,这个点是否原地不动;再让上臂抬起、锁骨略微跟随,检查它是否在两者之间平滑移动。最后整体移动角色,确认局部变形完成以后,整个人才一起进入世界。
(右脑)画面:肩部布料上的一个点被几根带不同粗细的绳子牵住。每根绳子都先拿出一张休息姿势的合影,找回“那时这个点相对我放在哪里”,把旧关系抵消后,才按骨骼今天的位置重新摆放这个点。几根骨骼各自给出一个候选位置,再按绳子粗细合成最终位置。这个结果仍在角色自己的小舞台里;等所有肩部、手臂和身体点都变形完,舞台才整体搬到世界。绳子只是权重画面,不表示真实弹力或受力模拟。
(左脑)对表:本题对象是绑定模型空间顶点 v、每根骨骼的当前模型空间全局矩阵 G_i、绑定矩阵 B_i、权重 w_i 和角色 M_model。绑定姿态应原地不动、权重和应为 1 是可检验事实;“当前骨骼矩阵可直接乘绑定顶点”是假设。证据来自绑定姿态恒等检查、已知双骨骼帧、顶点/法线调试和极端姿态回归。位置矩阵必须处在声明的同一空间,权重无量纲,法线是方向且不接收平移;列/行向量、Unity 已组合的 bindposes、非均匀或零缩放是前提与边界。橡皮筋类比展示多骨骼影响,但不等于证明矩阵线性混合在大扭转下保体积。
小明:先形成一个完整猜测
小明直接把当前两根骨骼矩阵按权重混合后乘顶点。角色一播放动画,肩膀带着绑定姿态中的骨骼偏移再次移动,像被重复搬家。这个反例说明:当前骨骼变换描述的是骨骼现在在哪,不包含“先抵消绑定姿态”的步骤。
小红:把猜测放回现实检查
小红保持权重和动画帧不变,只把缺失的 inverse bind 补回每根骨骼,观察绑定姿态是否恢复为恒等变换。采用列向量并约定 G_i 是骨骼当前的模型空间全局矩阵、B_i 是该骨骼绑定姿态的模型空间全局矩阵,则皮肤矩阵是
S_i = G_i · B_i⁻¹
绑定姿态中的模型空间顶点 v_m 先分别经过各 S_i,再按权重求和:
v'_m = Σ_i w_i (S_i · v_m),其中 Σ_i w_i = 1。
当当前姿态等于绑定姿态时,G_i=B_i,每个 S_i=I,顶点应原地不动;这是最直接的正确性检查。
我:用检查结果修正模型
我补全从模型到最终画面的链:
v_world = M_model · Σ_i w_i (G_i · B_i⁻¹ · v_model)
继续到裁剪空间则为
v_clip = P · V · M_model · Σ_i w_i (G_i · B_i⁻¹ · v_model)。
法线不接收平移。骨骼各自为刚性旋转或统一缩放时,常见实时近似是用各 3×3 线性部分变换法线、按顶点权重混合后归一化;多个旋转的线性混合通常已不再是正交矩阵,所以这仍是近似。存在非均匀缩放时,先得到该顶点的合成线性变换 L = Σw_i(S_i)₃ₓ₃,再用 N=(L⁻¹)ᵀ 变换法线更符合正交约束;这里把权重视为该顶点局部邻域内不变,并要求 L 可逆,本身仍是实时近似。“先算各骨骼 normal matrix 再混合”是另一种近似,不能声称与前者恒等。inverse-transpose 正是处理非均匀缩放的工具,不会因为非均匀缩放自动失效;真正无法求逆的是零缩放等奇异矩阵。
最后用绑定姿态、极端弯曲、非均匀缩放和权重未归一化输入回归。Unity 实际上传的 bindposes 与 bone matrices 可能已组合部分矩阵,因此实现时先核对引擎约定,不能再乘一次。线性混合蒙皮本身还会有糖纸扭曲等局限,那是算法近似,不应误判成矩阵链写错。
(右脑)画面修正:小明直接混合当前骨骼矩阵,肩部连同绑定偏移被重复搬家;小红补回每根骨骼的 inverse bind 后,在绑定姿态得到 G_i=B_i、皮肤矩阵为恒等,顶点终于原地不动。证据把“骨骼当前位置加权”改成“每根骨骼先抵消绑定关系,再施加当前关系,最后合成”;随后非均匀缩放和极端弯曲又提醒,位置链正确并不意味着法线近似或 LBS 保体积也自动正确,法线仍要按可逆线性变换处理,大扭转仍可能出现糖纸塌陷。
(左脑)严格对表:在列向量约定下定义 S_i=G_i·B_i⁻¹。先要求权重有限且非负,不满足就报错;再计算 W=Σ_i w_i:W>eps_w 时用 ŵ_i=w_i/W,同时把偏离 1 的程度写入质检;W≤eps_w 时拒绝资产,或按项目明示的 fallback 骨骼产生确定结果,不能静默继续。绑定模型空间位置为 v_m 时,v′_m=Σ_i ŵ_i(S_i·v_m),再求 v_world=M_model·v′_m 与 v_clip=P·V·M_model·v′_m。对刚性或统一缩放骨骼,把各 S_i 的 3×3 线性部分变换法线后按权重混合并归一化,只是常用实时近似;非均匀缩放下令 L=Σ_i ŵ_i(S_i)₃ₓ₃,在 L 可逆且权重在局部邻域近似不变时取 n′_m=normalize((L⁻¹)ᵀn_m)。若权重在表面邻域变化明显,真实变形导数还含权重梯度,前述法线矩阵仍只是实时近似。若 (M_model)₃ₓ₃ 也可逆,则 n_world=normalize(((M_model)₃ₓ₃⁻¹)ᵀn′_m);等价地可对 J=(M_model)₃ₓ₃L 使用 (J⁻¹)ᵀ。验收必须规定:可归一化权重得到预期顶点,W≤eps_w 触发拒绝或指定 fallback,奇异 L/J 明确报错,并核对 Unity 已组合的矩阵因子。
老师解惑
- bind pose / inverse bind:
B_i⁻¹抵消骨骼绑定时相对模型的初始位置,避免重复变换。 - 权重归一化:通常要求
Σw_i=1;导入压缩后仍应验证,零权重顶点要有明确处理。 - 完整空间链:绑定模型空间 → 各骨骼绑定局部 → 当前模型空间 → 角色世界空间 → 视图/裁剪空间。
- 法线矩阵:线性变换
L下,法线用(L⁻¹)ᵀ才保持与表面切线垂直;变换后再归一化。 - LBS 边界:矩阵线性混合在大角度扭转时可能损失体积,可考虑 Dual Quaternion Skinning 或关节修形。
工具分工
- animation-deformation/deep-dive Lab:观察 bind、inverse bind、当前骨骼矩阵和权重合成。
- Unity SkinnedMeshRenderer / Mesh.bindposes:核对引擎提供的矩阵空间与骨骼顺序。
- 顶点/法线调试视图:定位权重、法线和奇异缩放问题。
- 极端姿态回归集:区分矩阵链错误、权重问题与 LBS 固有限制。
记忆钩子
每根骨骼先用 inverse bind 抵消旧姿态,再搬到当前姿态;合成后进世界,法线遇非均匀缩放就用逆转置。
这是教学场景,不是目标项目的真实捕获或个人经历。
下一步:验证这条因果
同一绑定顶点怎样经过 inverse bind、当前全局骨骼、matrix palette 与权重混合,再由 object-to-world 进入世界空间。
教学边界:二维教学骨架不会执行 Unity SkinnedMeshRenderer、真实 GPU buffer 或随表面变化的精确法线导数;法线与切线只标出必须另验的变换边界。