3 步搞定 Blockbench 骨骼权重绘制:从 VertexGroups 到 Skinning
【免费下载链接】blockbenchBlockbench - A low poly 3D model editor项目地址: https://gitcode.com/GitHub_Trending/bl/blockbench
你刚在 Blockbench 里给低模角色绑完骨骼,一按播放——肩膀直接撕成两半。十有八九这不是建模的问题,而是骨骼权重没画好:顶点没拿到对应骨骼的权重,动画一来就被两边扯开。这篇以权重笔刷为主线,带你走一遍从 VertexGroups 创建到 Skinning 预览的完整路径,外加 3 个最常见的权重事故。5 分钟上手。
⚡ 为什么你的模型"动不起来":一次骨骼绑定翻车现场
场景很典型:一个方块人的模型绑了 Armature,手臂骨骼也摆好了位置,播放动画的那一刻,上臂和躯干之间的网格像被手撕的纸一样裂开,甚至整块飞出屏幕。
根因其实就一句话:顶点不知道听谁的。Skinned Mesh 的变形逻辑是"每个顶点被若干骨骼按各自权重拉扯",如果你从没给顶点写过权重,所有骨骼对它的权重都是 0——骨骼转了,顶点原地不动,缝隙就这么撕出来了。
VertexGroups(顶点组)就是那张"听谁的话、听几成"的声明表。在 Blockbench 里它不单独存在,而是直接挂在每根骨骼上。
VertexGroups 到底在管什么:3 个数字完成一次骨骼绑定
整个数据结构可以压缩成三要素:一个顶点、一根骨骼、一个权重值。顶点可以同时对多根骨骼持有权重,理想情况下总和为 1。
具体存储长这样(骨架来自 js/outliner/types/armature_bone.ts):
this.vertex_weights = {}; // 形如 { "a1b2c3:17": 1, "a1b2c3:18": 0.6 } getVertexWeight(mesh, vkey) { const key = mesh.uuid.slice(0, 6) + ':' + vkey; return this.vertex_weights[key] ?? 0; } setVertexWeight(mesh, vkey, weight) { const key = mesh.uuid.slice(0, 6) + ':' + vkey; weight ? this.vertex_weights[key] = weight : delete this.vertex_weights[key]; }也就是说,权重表的 key 是"网格 ID 前 6 位 + 顶点编号",value 就是 0~1 的浮点数。传 0 或不传等价于删除这条权重,所以"清掉权重"和"写权重"走的是同一个入口。
| 权重值 | 含义 |
|---|---|
| 0.0 | 这根骨骼对该顶点完全无效,等于没绑 |
| 0.5 | 和邻接骨骼五五分成,顶点停在两者中间 |
| 1.0 | 顶点完全跟随这根骨骼,动画里它只认这一个方向 |
权重相关的动作注册都汇聚在 js/modeling/mesh_editing.js,里面 import 了 set_vertex_weights 这套"选中顶点 → 选骨骼 → 填权重"的对话框逻辑。
🖌️ 动手:框选 → 权重笔刷 → 镜像,笔刷权重绘制全流程
先说结论:80% 的权重靠笔刷磨出来,框选只负责铺底。下面按顺序做。
框选顶点,让权重"扩散"出去
- 编辑模式下把选择切到顶点层级,拉框框住上臂全部顶点(漏掉的用 Shift 点选补上)。
- 在 Outliner 里选中对应骨骼,
Shift+E可以给当前骨骼快速加子骨——先保证骨骼链和模型对得上。 - 触发"设置顶点权重"动作,选上臂骨骼,权重填
1.0,勾选 overwrite,把这块区域彻底划归它。 - 没把握哪块归谁时,直接点"计算顶点权重"让引擎自动分配一遍,再手动修正——它的算法在 js/modeling/mesh/attach_armature.ts,按"顶点离骨骼线段多近、是否被骨骼轮廓环包围"来打分。
- 留一手:关节处(肘、肩、胯)的顶点先别给满权重,给到 0.5 左右,留给笔刷过渡。
拿权重笔刷把过渡区域"磨"平滑
- 在 Outliner 选中目标骨骼(比如前臂骨),在 Toolbox 点权重笔刷,核心逻辑在 js/modeling/weight_paint.ts。
- 底部两个滑杆:size(默认 50)管笔刷直径,limit(默认 100)是"画上去想达到的权重值"。
- 按住鼠标在肘部区域拖动,圈内顶点按距离衰减混合向 limit 靠近。衰减核心不长:
const falloff = (1 - distance / radius) * (1 + baseRadius); const influence = Math.hermiteBlend(Math.clamp(falloff, 0, 1)); if (event.ctrlKey) { value = value * (1 - influence); // Ctrl:减去 } else { value = value + (limit - value) * influence; // 默认:向目标值混合 } value < 0.04 ? deleteWeight(vkey) : setWeight(value); // 自动清掉微量权重注意最后一行:小于 0.04 的权重会被直接删掉,所以"擦掉"一笔就够干净,不用抠像素。
- 按住 Ctrl 切减去模式,把画歪的地方扣回来;按住 Shift 强度降为 1/8,专门给过渡带做细磨。
- 混合模式选 "set" 时,给这根骨加权重会自动从其他骨等量扣减——总权重天然不超过 1。
这套屏幕坐标 → 模型空间的映射,和 UV 编辑里 js/texturing/uv.js 的 getBrushCoordinates 是同款思路:先算笔刷半径覆盖范围,再对覆盖到的顶点逐一点算。这些按钮背后的动作注册系统,入口在 js/interface/actions.js 和共享动作表里。
镜像复制,省掉一半工作量
- 确认左右网格关于 X=0 对称摆放——镜像识别靠"找到对面的镜像顶点",摆歪了它找不到对应点,直接不生效。
- 打开 Mirror Modeling 开关,并在工具配置里勾上 enabled(两处都要开)。
- 只画左侧:brush 每落一笔,js/modeling/mirror_modeling.ts 里的 symmetrizeArmature 会把刚改的顶点权重同步写到右侧镜像骨骼上。
- 中间轴上的顶点(x≈0)会被跳过,不会自我覆盖——脊柱附近的权重建议单独手画。
- 画完切到"顶点权重"显示模式扫一眼左右对称性,色块不对称的地方就是漏网的。
🦴 Skinning 技术:骨骼矩阵怎么搬动顶点
权重画完,变形公式只有一条:最终位置 = Σ(骨骼世界矩阵 × 逆绑定矩阵 × 静息位置)× 该骨权重。
function applyBoneInfluence(vertex, boneList) { const rest = vertex.position.clone().applyMatrix4(vertex.inverseBind); const result = new THREE.Vector3(); for (const {bone, weight} of boneList) { if (weight <= 0) continue; result.add(rest.clone() .applyMatrix4(bone.matrixWorld) .multiplyScalar(weight)); } return result; }一句话人话:顶点先"还原"到绑定时刻的姿势,再让每根骨骼按自己动画后的姿态把它拉过去,各拉各的比例由权重决定。骨骼的世界矩阵和逆绑定矩阵的更新逻辑在 js/modeling/transform.js 这条变换链上。
两条性能建议,够用就行:
- 权重烘焙:把权重表烘成顶点数据随几何体一起导出(glTF 的 JOINTS/WEIGHTS 属性),运行时零查表开销。
- 顶点合并:相邻顶点权重差小于 0.01 的,合并成共享顶点,既省顶点数又天然消除接缝——笔刷那行
< 0.04 删权重就是同一思想的轻量版。
🕳️ 踩坑记录:权重衰减 Falloff 最常见的 3 起事故
坑 1:权重总和溢出,手臂像面团一样膨胀
事故现象:播放动画时某块区域被"吹大",越动越肿。原因:用 "add" 混合模式在同一批顶点上连刷了多根骨骼,权重和远超 1。修复:
- 混合模式切回 "set",加权重时自动从其他骨扣减。
- limit 滑杆压到 60~80 重刷一遍事故区域。
- 切到顶点权重显示模式复核——一个顶点被两根骨骼同时亮满就是还没修干净。
坑 2:关节处动画抖动,肘部像"腿软"
事故现象:弯曲手臂时过渡区高频颤动。原因:两根骨骼影响区的边界太陡,骨骼转 1° 顶点位移差就很大,帧与帧之间互相抢。修复:
- 范围滑杆调大(比如 8 → 12),重刷过渡区把过渡带拉宽。
- falloff 换成 hermite spline,让衰减曲线变圆润。
- 抖动顽固时跑一次"计算顶点权重"重算,再手动微调回退的部分。
坑 3:过渡区出现一条"硬边"
事故现象:关节弯下去的瞬间,皮肤表面折出一道清晰的折线。原因:用 constant falloff(硬衰减)画的,权重从 1 直接跳到 0,中间没有过渡顶点。这个坑我上周也踩过,重刷一次就好。修复:
- falloff 改回 linear 或 hermite,limit 降到 50 左右。
- 按住 Shift(1/8 强度)沿折线补刷一两遍,把硬切磨成渐变。
- 折线所在的环如果本来就是分裂顶点,在建模菜单里把它们焊接合并,避免变形时各自为政。
🎯 收尾:从 VertexGroups 到 Skinning 技术
到这里你手里已经有一条完整链路:框选铺底权重的 VertexGroups,笔刷把 Falloff 过渡磨平滑,镜像把工作量砍半,Skinning 公式负责把骨骼矩阵和权重合成最终动画。剩下的功夫都花在"看"上——多切顶点权重显示模式,眼睛比任何算法都先发现问题。
下一步建议:读一遍 js/modeling/mesh/attach_armature.ts 里自动权重的打分逻辑,你会发现它处理"顶点被骨骼环包围"的几何判断比想象中讲究,改一改就能变成自己的自动绑骨脚本。源码可以本地拉下来翻:git clone https://gitcode.com/GitHub_Trending/bl/blockbench
【免费下载链接】blockbenchBlockbench - A low poly 3D model editor项目地址: https://gitcode.com/GitHub_Trending/bl/blockbench
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考