用 Blender MCP 让蜘蛛侠自动荡蛛丝:一帧动画都没手 K
原文:https://dev.to/lovestaco/i-made-spider-man-swing-without-animating-a-single-frame-blender-rigging-and-mcp-14f7(作者 @lovestaco)
没错,那是迈尔斯·莫拉莱斯(Miles Morales)。
他顺着蛛丝荡入画面,以超级英雄式的蹲姿落地,朝画面外射出一根蛛丝,把一块巨大的 DEV 板子拽进镜头。
这段动画,我一帧都没有手动做过。
而且在这周之前,我从来没打开过 Blender。
这篇文章讲的就是这一切是怎么发生的,以及一个“简单”的 3D 角色里,藏着多少惊人的计算机科学。
为什么偏偏是 Blender
我当时想做一段视频。
不是屏幕录制,而是真的有东西在动的视频。
我的第一站是 HyperFrames,它让你用 HTML 写视频,然后渲染出来。
它做动态图形(motion graphics)确实很在行。
文字滑入、logo 弹出、图表自己画出来,这些都很好看。
但当我想要一个角色做点动作时,它就碰壁了。
HTML 能把矩形移动得很漂亮。
它没法让一个人荡蛛丝。
于是下一个问题就很明显了,虽然有点吓人:真正的动画师都用什么?
免费又开源的答案是:Blender。
而且 Blender 有 MCP 服务器,这意味着我学它的时候不会是孤身一人。
驱动这一切的 MCP
让一个纯新手也能做成这件事的,是 blender-mcp。
它把 Blender 接到 Claude Code 这样的 LLM 客户端上,于是你不用在 400 个菜单里翻找,只要说一句“加载这个模型并重新链接它的贴图”,事情就办好了。
这个架构值得搞明白,因为它比听起来简单。
flowchart LR
ME[Me typing a prompt] --> CC[Claude Code]
CC -->|MCP over stdio| SRV[blender-mcp server]
SRV -->|JSON over TCP socket| ADDON[Blender add-on]
ADDON -->|runs Python| BPY[bpy API]
BPY --> SCENE[Live Blender scene]
SCENE -->|viewport screenshot| CC
classDef human fill:#e9ecef,stroke:#6c757d,color:#1a1a1a
classDef agent fill:#9d8cff,stroke:#5b4bcc,color:#1a1a1a
classDef bridge fill:#6ea8ff,stroke:#2f62c4,color:#1a1a1a
classDef blender fill:#ff9a5c,stroke:#c4602a,color:#1a1a1a
class ME human
class CC agent
class SRV,ADDON bridge
class BPY,SCENE blender
它分成两半。
Blender 内部的一个插件会开一个小型 socket 服务器,等待命令。
Blender 外部的一个 MCP 服务器,一端用 Model Context Protocol 和 LLM 对话,另一端把 JSON 命令顺着 socket 转发进去。
它暴露出的最强大的工具是 execute_blender_code,可以通过 bpy——Blender 的 Python API——在 Blender 里运行任意 Python 代码。
Blender 里的每个按钮,说到底都只是 bpy 之上的一层薄皮。
所以一个会写 bpy 的智能体(agent),原则上就能按下每一个按钮。
让整个流程真正转起来的,是反方向传回来的截图工具。
智能体改动一些东西,抓一张视口截图,看一眼,再决定下一步修什么。
这和你写代码时“编辑、运行、检查”的循环一模一样,只是对象换成了 3D 场景。
一句实在的警告:这个工具在设计上就是任意代码执行。请像对待任何带 shell 的本地自动化一样对待它,别把它对准一台装满机密的机器。
第一步:搞到一个角色
我不是 3D 建模师,也不打算赶在周五之前变成一个。
于是我直接从 Sketchfab 上抓了一个现成的迈尔斯·莫拉莱斯模型——就是《蜘蛛侠平行宇宙》里那位蜘蛛侠。

就连“只是加载进来”这一步都藏着学问。
文件里带着四个迈尔斯站成一排:戴面具的和不戴面具的、摆好姿势的和 T-pose 的。
贴图指向的是原作者的 Windows 文件夹,比如 C:\Users\someone\Desktop\...,所以智能体得把它们重新链接到 zip 包里的文件上。
而且 zip 包里还缺了法线贴图和高光贴图。
在 Blender 里,指向丢失文件的纹理节点会渲染成亮粉色。
这相当于 3D 世界的 404,而且非常、非常显眼。
解决办法是断开这些插槽,代价是战衣损失了一些表面细节。
然后我打开不戴面具的迈尔斯,他的脸看起来像恐怖片,布满了白色的线条和圆点。
结果发现脸本身没问题。
这个模型自带一套 143 根骨骼的面部绑定(眼睑、眉毛、嘴唇、下颌、脸颊,甚至还有舌头),而骨架(armature)开了“Draw in Front”(绘制在最前),所以这些骨骼全都画在了他皮肤的上面。
取消一个复选框之后,他又帅回来了。
解锁一切的那个概念:绑定(Rigging)
就是在这里,我学到了贯穿全文余下部分的那一个词。
一个 3D 角色,本质上是一个网格(mesh):一大串被粘成三角形的顶点(Miles 的模型大约有 27000 个面)。
网格是一座雕像。
你没办法让雕像招手。
要让它动起来,你还需要三样东西。
骨架(Armature),也就是骨骼。
它是一棵由骨骼组成的树,每一根都是下一根的父级:髋部连脊柱,脊柱连胸腔,胸腔连肩,肩连上臂,上臂连前臂,前臂连手,手连手指。
旋转肩关节,树上位于它之下的所有东西都会跟着一起动——和任何游戏引擎里的变换层级(transform hierarchy)一模一样,也像一个嵌套的 <div> 配上 CSS transform。
蒙皮权重,把网格绑定到骨骼上。
每个顶点都存着一张小表,记录每根骨骼对它的影响程度。
前臂上的一个顶点,可能是 100% 归 forearm。
正好落在肘部的一个顶点,可能是 50% 归 upper_arm、50% 归 forearm,正是这一点让手肘能平滑弯曲,而不是像纸吸管那样折成死弯。
这套数学叫线性混合蒙皮(linear blend skinning),说白了就是矩阵的加权平均:
final_position(v) = Σ weight(v, bone) × bone_matrix × rest_position(v)
bones
静止姿势(rest pose),一切度量的参照基准。
这就是为什么你下载到的每个角色都摆着T-pose、双臂笔直张开。
这不是什么舞蹈动作。
它是零点,是身体的 git init,每一段动画都以它为基准、以相对它的旋转来存储。
把这些拼到一起,你就得到了一套绑定(rig)。
然后天真的计划就崩了,因为模型里这套骨架有骨骼、却没有控制器。

正向运动学(FK)与逆向运动学(IK)
我看过一些 YouTube 视频,动画师抓住角色的髋部往下拽,膝盖自动弯曲,双脚却牢牢钉在地板上。
而我拖动 Miles 的髋部时,他整个人像幽灵一样直接穿进了地板。
两者的差别,是这个领域里最漂亮的想法之一。
正向运动学(FK)是裸骨架的行为方式。
你设定每个关节的角度,手最后落在哪,完全由这条旋转链决定。
计算容易,动画难做。想让手抓上门把手?祝你好运,去猜出让它落在那里的肩、肘、腕三个角度吧。
逆向运动学(IK)把问题反了过来。
你说手(或者脚)应该在哪里,求解器就反推回去,找出能把它送到那里的各关节角度。
它本质上就是一个每帧都在求解的优化问题,而 Blender 自带一个 IK 约束替你干这活。
用 IK 目标把双脚钉住,再把髋部往下拽,求解器就不得不弯曲膝盖,因为双脚不允许移动。
那些 YouTube 视频里的"魔法"就是这个。
它不是魔法,是约束求解器。
不过,纯手工搭一套完整的 IK 控制骨架是门真功夫。
而我想要 Miles 这周就翻后空翻,不是下个季度。
Mixamo:绑定即服务
于是 Mixamo 登场——Adobe 的免费自动绑定工具和动画库。
流程是:把角色以 T-pose 导出为 FBX,上传,Mixamo 就替你生成骨架和蒙皮权重。
它唯一要求你做的,是摆几个标记点。

下巴、手腕、手肘、膝盖、裆部。
五个基准点,开着对称模式,所以其实每侧只需要点三下。
它从这几个点推断出整套骨架——这也顺带提醒你,人体有多少现成的结构:只要知道关节在哪,剩下的基本就是比例问题。
标记点摆得准不准,比你想的重要。
我第一遍就把手腕标到了前臂上,那样的话他每次射蛛网,手都会在错误的位置弯折。
我选了 Standard Skeleton (65),它包含手指骨骼,因为两只手一起拉蛛丝却没有手指的话,看起来就像戴着一双烤箱隔热手套。
然后一切就……成了。

绑好的角色可以直接进入 Mixamo 的动作捕捉动画库。
这些都是穿着动捕服的真实演员表演、再经录制清理的成品,自带重心转移和细微微晃,手工 K 帧的动画很难伪造出这些。
跳跃、攀爬、悬挂、投掷、舞蹈、摔倒,应有尽有。


有一个代价,而且有点疼。
Mixamo 搭建的是它自己的身体骨架。
它既不知道也不关心模型原本自带的那套精美的 143 根骨骼的面部绑定。
「带皮肤」与「不带皮肤」
下载动画时,Mixamo 会问你要带皮肤(with skin)还是不带皮肤(without skin)的版本。
这正好是「数据与表现分离」的一堂小巧示范课。
带皮肤版本给你网格体、骨架和动作。
不带皮肤版本只给骨架和动作——几百 KB 的骨骼旋转时间序列数据。
因为每个片段针对的都是同一套 65 根骨骼的骨架、骨骼名完全相同,所以皮肤你只需要下载一次。
其余的一切都只是以骨骼名为键的关键帧数据,只要某个 Blender 骨架的骨骼名对得上,Blender 就能欣然把这些数据套用上去。
于是,第一个片段我下了带皮肤的,其余全部不带皮肤。
然后我下了很多很多。

七十八个文件。
一个一个点出来的,因为 Mixamo 没有多选功能。
有些文件甚至文件名相同、里面装的却是另一个动画,因为这个网站只会往你最后下载的那个文件名后面追加 (1)。

它们可不是同一张图。
到头来,智能体把每个 FBX 都扫描了一遍、看清里面到底装了什么,才敢相信任何一个文件名。
从一堆片段到一场表演
整条流水线,端到端如下:
flowchart TD
A[Sketchfab model] --> B[Clean up in Blender<br/>relink textures, drop pink slots]
B --> C[Export T-pose FBX]
C --> D[Mixamo auto-rig<br/>5 markers]
D --> E[Download clips<br/>1 with skin, rest without]
E --> F[Import as Blender actions]
F --> G{Clip looks right<br/>from this angle?}
G -->|no| E
G -->|yes| H[Chain clips on NLA<br/>crossfades + root motion]
H --> I[Webs, board, camera]
I --> J[360p preview render]
J --> K{Good enough?}
K -->|no| H
K -->|yes| L[Final render]
classDef decision fill:#f4d35e,stroke:#b8991f,color:#1a1a1a
classDef source fill:#e9ecef,stroke:#6c757d,color:#1a1a1a
classDef rig fill:#5ee6c8,stroke:#1f9c86,color:#1a1a1a
classDef scene fill:#9d8cff,stroke:#5b4bcc,color:#1a1a1a
classDef out fill:#ff9a5c,stroke:#c4602a,color:#1a1a1a
class G,K decision
class A,B,C source
class D,E,F rig
class H,I scene
class J,L out
每个 Mixamo 片段进入 Blender 后都成为一个动作(action):一捆带名字的动画曲线(每根骨骼的每个旋转通道各对应一条 f-curve)。
孤零零一个动作,只是一招。
一场表演是多个动作接连上演,而这正是 Blender 的非线性动画编辑器(NLA)存在的意义。
NLA 基本上就是给动画用的视频剪辑时间线。
每个动作变成一条条带(strip),条带安放在轨道上,相互重叠的条带可以彼此混合(blend)。
正是这种混合,让「悬吊」切到「落地」的过渡不至于像坏掉的 GIF 一样生硬跳变。
智能体把这一切封装成了一个微型序列器,于是整个镜头就用一份动作列表来描述,而不是一堆帧号:
perf = Performer(rig)
perf.then("Hanging Idle", length=40)
perf.then("Hard Landing", to=50, speed=1.3, blend=6)
perf.then("Standing 1H Magic Attack 02", frm=16, to=40, speed=1.25, blend=6)
perf.then("Pull Heavy Object Stop", to=30, speed=1.1, blend=5, face=65)
perf.then("Victory Idle", blend=8, face=10, length=51)
perf.build() # NLA strips, crossfades, stitched root motion
blend=6 表示与下一个片段之间做 6 帧的交叉淡化。
face=65 让他把身体转 65 度,好让那记猛拽正对着板子。
至于「射网」——我向你保证——用的就是一个字面意义上叫 Magic Attack 的片段。Mixamo 可没有「thwip」这种射网专用动作。
藏在 build() 里的有趣难题是根运动(root motion)。
有些片段会让角色在空间里发生位移(落地会让他坠下,拉拽会让他后仰),而每个片段又都从各自的原点出发。
要是把两个片段想当然地首尾连播,Miles 就会在动作之间瞬移回起点。
于是序列器会读取上一个片段结束时髋部所在的位置,并把下一个片段的起点偏移到那里。
这和拼接 GPS 轨迹是同一个思路:每一段都是相对位移,所以要维护一个不断累加的总和。
由于所有时序都由那份列表推导而来,换掉任何一个片段,蛛网、板子和相机的时序都会自动重新对齐。
蛛丝、板子和相机压根与 Mixamo 无关,它们就是普通的 Blender 物体,由脚本打上关键帧,在他伸手的那一帧准时触发。
像个正常人一样,用 360p 迭代
第一次完整渲染是 720p 的 16 秒动画,在我的 GTX 1650 上跑了大约八分钟。
如果只渲染一次,这没什么问题。
但当反馈一口气甩来“动作再利落点”“板子再大点”“他的战衣太暗了”的时候,这就是个大问题了。
于是预览降到 360p,速度快了大约 4 倍,720p 只留给最终成片。
写代码的那条老规矩在这里同样适用:先把反馈循环做快,再把输出做好。
还有两件真正吃时间的事:
战衣渲染出来是一团扁平的黑块。
模型用的是卡通着色器(toon shader),它把光照压缩成几条硬边色带——做卡通片很出彩,想看清肌肉时就很糟糕。
换成基于物理的着色(PBR),再给他单独打一盏灯,配上红、蓝两色轮廓光,他的身形就回来了。
浅灰影棚还是深色影棚?
近乎全黑的战衣配上近乎全黑的背景,就是一个什么都看不出来的剪影。
浅色背景更易读,深色背景更帅。文章开头那张 GIF 用的就是深色版,因为我心里有优先级。
逃离下载按钮
点了 78 次"Download"之后,我问了一个工程师自然会问的问题:能不能干脆在本地做?
Mixamo 的自动绑定和动作库只存在于 Adobe 的服务器上。
但动作捕捉数据并不是 Adobe 的发明。
CMU 图形实验室动作捕捉数据库有大约 2500 段免费动作片段,GitHub 上还有一个 BVH 镜像,附带一份说明每段内容的文本索引。
侧手翻、萨尔萨、攀爬、武术、“拉绳子”,应有尽有。
麻烦在于,CMU 的骨架并不是 Mixamo 的骨架。
把动作从一副骨架搬到另一副骨架,这个过程叫重定向(retargeting),是个相当可爱的小型线性代数问题。
你不能直接照抄旋转值,因为两副骨架的静止姿势(rest pose)不一样。从“手臂略微下垂”出发转 30 度,和从“手臂平伸”出发转 30 度,得到的根本不是同一个姿势。
所以重定向器会把每根骨骼的旋转先从源静止姿势里拆出来,转换到一个共享的世界坐标系,再装回目标骨架的静止姿势里。
它还会按腿长缩放髋部的移动幅度,免得高个子表演者的步幅把迈尔斯走成太空步。
第一次尝试渲染出来……什么都没有。
迈尔斯不在画面里。他哪儿都不在。
BVH 的静止姿势把髋部正好放在原点上,于是“静止髋高”是零,缩放系数就成了拿它当分母。
一次除以零,把迈尔斯直接发射进了轨道。
修复办法是改从片段里位置最低的那只脚来测地面,然后他突然就会走路、跳舞、侧手翻了——用的还是多年前在卡内基梅隆大学录下的数据集。
我真正学到的东西
我出发时,只是想让一个小人在蛛网上荡来荡去。
回来时,却带走了一串我没想到会从美术工具里学到的概念:
- 角色是一张网格(mesh),由一棵骨骼树借助逐顶点权重来变形。
- 动画是相对于静止姿势的旋转,这也是为什么所有东西都摆成 T-pose。
- IK 是一个约束求解器,它就是提线木偶和尸体的区别所在。
- 动作片段是以骨骼名索引的数据,所以一张皮能穿一千套动作。
- NLA 轨道条是可复用动作的时间线,把它们串起来就意味着缝合根运动(root motion)。
- 重定向(retargeting)是一次基变换,你若放任不管,它就会除以零。
- Blender 本质上是一个套着 UI 的 Python 程序,这正是 MCP 桥接能驱动它的根本原因。
对一个计算机专业出身的人来说,这里面还有一大堆可挖的:着色器节点图是数据流程序,Cycles 是路径追踪器,物理模拟是数值积分器,几何节点基本上是一种面向网格的函数式语言。
但一步一步来。
清单上的下一项,是那套被我在那个泳池里狠心抛弃的面部绑定,也许还要让迈尔斯真的开口说话。
如果你玩过 Blender、绑定或者 MCP,告诉我接下来该学什么。
原文:https://dev.to/lovestaco/i-made-spider-man-swing-without-animating-a-single-frame-blender-rigging-and-mcp-14f7(作者 @lovestaco)