AI-Agent 驱动 Blender 建模操作手册
AI-Agent 驱动 Blender 建模操作手册
用途:说明 AI agent 如何驱动本机 Blender 建模、验收、渲染、交付,以及别人如何复现。 验证声明:本文所有数字、路径、输出都是 2026-10-17 在本机实测得到的;凡未实测的都明确标注「未验证」。 环境:Linux Mint 22.3 / Blender 5.2.2 LTS / DSH Blender 插件 2.1.0 / RTX 4070 SUPER。 姊妹文档:AI-Agent驱动ComfyUI出图操作手册.md、绘画手册.md 要装环境:Blender 本体 / DSH 插件 / 可选资产集成的下载链接与安装步骤 → 见 §14 下载与安装清单(含实测可达性)
0. 一句话结论
agent 不通过 UI、也不通过图形化 API,而是往 Blender 的 Python 里注入代码(blender_rt_do),配合一套判定/QC/交付算子(blender_rt_plan,28 family / 186 op)在 GUI 会话、独立无头进程、后台作业三种通路上跑。核心设计是”改一步看一眼 + 用数字验收,不靠肉眼”。
能做什么(实测过):参数化硬表面件建模、网格体检、制造性(壁厚/悬垂)检查、多视角对照渲染、对象级与文件级回退、程序化材质、OBJ/MTL + manifest 交付与逐项校验、无头批处理与作业台账。
1. 环境与架构
1.1 事实核查表(逐条实测)
| 项 | 实测值 | 怎么确认的 |
|---|---|---|
| Blender | 5.2.2 LTS(build date 2026-09-15) | .../blender --version |
| Blender 可执行文件 | /home/zero/.local/opt/blender-5.2.2-linux-x64/blender | 同上(也曾是 ~/Downloads/*.tar.xz 解压而来,~/.local/bin/blender 是软链) |
| 插件 | dsh-blender-plugin 2.1.0,runtime 在 /home/zero/.local/share/dsh-plugins/dsh-blender-plugin/runtime/ | 目录列 + blender_viewport(op="status") 的 plugin 块 |
| 后端服务 | 127.0.0.1:9877(常驻,即使 Blender 没开也在) | ss -tln | grep 9877;curl 127.0.0.1:9877/health → 200 |
| addon 监听 | 127.0.0.1:9876(只有 Blender 起来才有) | ss -tln;没起时 blender_rt_commands 报 ECONNREFUSED 127.0.0.1:9876 |
| 工作目录(快照/日志/交付) | /home/zero/.dsh-blender-rt/ | 自动创建,含 snapshots/ out/ jobs/ locks/ deliver/ trajectory/ |
| GPU | NVIDIA RTX 4070 SUPER(12 GB) | qc_render_views 的 device 实测字段 |
| Python | 不要用系统 python3(缺 numpy);建模代码跑在 Blender 自带 Python 里 | 系统 python3 -c "import numpy" → ImportError |
1.2 三条执行通路(理解一切的关键)
| 通路 | 工具 | 进程与会话 | 变量 | 适合 |
|---|---|---|---|---|
| GUI 常驻 | blender_rt_do / blender_rt_see | 你眼前那个 Blender 的主线程 | 持久内核 K 跨调用保留 | 改一步看一眼、交互式建模 |
| 无头进程 | blender_rt_headless / blender_rt_job | 独立 blender -b 进程(cwd 在 UNC 下) | 不保留 | 批量几何、校验、渲染 |
| 热会话 | blender_rt_worker | 常驻 blender -b,复用同一个 K | 保留 | 同一脚本要跑 ≥3 次 |
配套工具:
| 工具 | 一句话 | 本机实测吗 |
|---|---|---|
blender_rt_see | 约 100–500 ms 出一帧;给 from/look_at 走自定义视角,不建相机、不动用户视口 | ✅ 266 ms / 506 ms 各一次 |
blender_rt_watch | 时间窗内连续采样帧,判断”到底动没动” | ❌ 未测 |
blender_rt_loop | 把”试几十~几千组参数”搬进 Blender 主线程(仅 GUI 会话有效) | ❌ 未测 |
blender_rt_txn | 文件级 snapshot/restore + 对象级 mark/revert | ✅ 两者都测 |
blender_rt_plan | 所有判定/验收/QC/导出/雕刻/修复算子(28 family / 186 op) | ✅ 用了 9 个 op |
blender_rt_preset | 参数配方 save/apply/export/import(点路径 data) | ❌ 未测 |
blender_rt_opt / blender_rt_perf | 对象精简(降 Cycles 同步成本)/ 渲染性能诊断 | ❌ 未测 |
blender_rt_pick | 让用户在视口点选对象,返回确切名字(阻塞) | ❌ 未测 |
blender_viewport | status/doctor/launch/who/lease/release | ✅ status / launch / lease |
blender_rt_cmd | 透传 addon 原生命令(34 个名字) | ✅ blender_rt_commands 列过 |
1.3 写租约(lease)
写操作受租约保护(被他人持有时写路由返回 409),只读 op 豁免。
blender_viewport(op="who") # 看谁持有blender_viewport(op="lease", holder="my-agent", ttl_ms=900000)blender_viewport(op="release", holder="my-agent")blender_viewport(op="lease", force=true) # 抢占(默认 false)实测:op="lease" 返回 {"ok":true,"lease":{"active":true,"holder":"plugin-pid-230663","renewals":1567,...}} —— 本机当前由插件进程自身持有并持续续期。
2. 开工前自检(照抄即可)
# ① 后端在不在curl -sS -m 5 -o /dev/null -w "%{http_code}\n" http://127.0.0.1:9877/health # 期望 200
# ② Blender 在不在(看 9876 有没有人听)—— 没有就一键拉起ss -tln | grep 9876 || echo "addon 未连"# ③ 一键拉起 GUI Blender 并自动 Connect addon(幂等,不必有人点面板)blender_viewport(op="launch", wait_ms=120000)
# ④ 三级体检(真跑一次 bpy 往返)blender_viewport(op="doctor")
# ⑤ 命令清单 + 集成开关状态blender_rt_commands
# ⑥ 算子目录(本地直出,不占 Blender 往返)blender_rt_plan(op="catalog")本次实测输出(可作为对照):
LAUNCH ok · 已 spawn pid=297893 · addon 端口 9876 · 等待 2012ms启动后体检:通道健康:TCP + ping + bpy 往返都通blender_rt_commands → 场景 Scene · 未保存文件 可用命令 19 条;被集成开关挡住 15 条 集成:polyhaven=off · hyper3d=off · sketchfab=off · polypizza=off · hunyuan3d=offblender_rt_plan(op="catalog") → 28 个 family / 186 个 op loaded engine.mjs c8f256a06bf2 · 磁盘 c8f256a06bf2 · 一致⚠ 没启动 Blender 时
blender_rt_commands直接失败:COMMANDS 失败 · connect ECONNREFUSED 127.0.0.1:9876。先 launch 再干活。
3. 算子全貌:28 个 family
从 blender_rt_plan(op="catalog") 抄录(未标 ✅ 的家族本次未逐个实测):
| family | 干什么 | 代表 op |
|---|---|---|
audit ✅ | 装配体检与出厂门:连通/干涉/包络/漂移/量测/重复件/浮块 | audit_mesh audit_scene audit_gate audit_interference audit_drift audit_measure |
qc_render ✅ | 多视角 / 逐部件配色对照图(自动取景 + 临时三点光 + 逐张 md5) | qc_render_views |
qc | 与参考图比对(IoU / 剖面差 / 鲁棒性) | qc_compare qc_align_iou qc_profile_diff |
deliver ✅ | 交付导出:单位盒归一化 + OBJ/MTL + manifest(md5) | deliver_export deliver_verify |
material ✅ | 程序化材质(拉丝金属/漆面/锈/玻璃/布料/木纹/混凝土/自发光/全息)+ 烘贴图 | material_build material_apply material_bake |
print ✅ | 制造性:壁厚与悬垂(3D 打印口径) | print_report print_walls print_overhang |
fix | 修网格缺陷 / 减面 | fix_repair fix_decimate |
uv | UV 展开与排布(贴图/交付前置) | uv_smart_project uv_unwrap uv_pack |
sculpt | 程序化雕刻(numpy 位移笔刷,无头可跑) | sculpt_scan→sculpt_setup→sculpt_apply |
sweep | 管路/线缆/轨道(沿路径成形) | sweep_analyze→sweep_build |
shape | 参考图还原:草稿→协议→放样→特征线→IoU | shape_draft shape_plan shape_sections shape_loft |
vehicle | 车辆外壳贴参考图 / 根治穿模(轮眉解析扣出) | vehicle_spec→vehicle_sections→vehicle_loft |
clearance | 成对间隙/互穿判定(按规则表逐对) | clear_check |
human | 人形素体(比例正确)+ 从参考图反推比例 | human_base human_measure human_spec |
face | 人脸比例判定 / 与参考对比(landmarks 需你给) | face_ratios face_compare |
img | 量参考图(轮廓尺寸/长宽比/直线角度/取色)+ 标注 + 差分 | img_scan img_crop img_diff |
calib | 给验收门做”注入已知缺陷量捕获率”的标定 | calib_run |
gate | 把项目验收判据固化,一次跑完(读 verdict 三态) | gate_plan gate_run |
ext | 外部独立通路复核(glTF-Validator / open3d 水密性) | ext_gltf_validate ext_mesh_check |
motion | 机构/铰接:关节轴实测、扫掠验证、URDF/USDA 导出 | motion_joints motion_measure motion_export_urdf |
generator | 参数化重复件(“配方即形状”) | generator_save generator_run ⚠ 见 §10.5 |
pipe | 多步链一次跑完,产出用 @工件 引用(编排层) | pipe_run |
plan / contract | 假设驱动建模:组件/连接/包络注册、三态判定、破坏性门控、证据账本 | plan_load check_interference destructive_guard |
render_guard / render | 渲染卡住/超时诊断;多会话渲染排队锁 | render_state render_wait render_lock |
gui | 只有真 UI 上下文才能做的事(框选/切着色/开文件);无头下会明确报错 | gui_frame gui_shading gui_open |
montage | 把多张对照图拼一张 | montage ❌ 本机坏了,见 §10.4 |
4. 实操:五步做出一个参数化齿轮(全部实测)
目标:12 齿 / 模数 2 / 齿宽 6 mm / 中心孔 ⌀8 mm 的直齿轮,并给出客观验收指标。
Step 1 建模(blender_rt_do)
在 GUI 会话里执行(K 是持久内核,变量跨调用保留):
import bpy, bmesh, math
for ob in list(bpy.data.objects): # 清场 bpy.data.objects.remove(ob, do_unlink=True)for me in list(bpy.data.meshes): if me.users == 0: bpy.data.meshes.remove(me)
N, m, W, RB = 12, 2.0, 6.0, 4.0 # 齿数/模数/齿宽/孔半径RP, RA, RF = m*N/2, m*N/2 + m, m*N/2 - 1.25*m # 分度圆/齿顶圆/齿根圆 = 12/14/9.5P, SEG = 2*math.pi/N, 24 # 每齿 24 段采样
def r_of(t0): t = (t0 % P) / P f = t/0.18 if t < 0.18 else (1.0 if t < 0.82 else (1.0-t)/0.18) return RF + (RA-RF) * max(0.0, min(1.0, f))
bm, n = bmesh.new(), N*SEGvo = [bm.verts.new((r_of(2*math.pi*i/n)*math.cos(2*math.pi*i/n), r_of(2*math.pi*i/n)*math.sin(2*math.pi*i/n), 0.0)) for i in range(n)]vi = [bm.verts.new((RB*math.cos(2*math.pi*i/n), RB*math.sin(2*math.pi*i/n), 0.0)) for i in range(n)]bm.verts.ensure_lookup_table()for i in range(n): j = (i+1) % n bm.faces.new((vo[i], vo[j], vi[j], vi[i])) # 外齿廓 ↔ 内孔 之间的环bmesh.ops.recalc_face_normals(bm, faces=bm.faces[:])ret = bmesh.ops.extrude_face_region(bm, geom=bm.faces[:]) # 挤出齿宽bmesh.ops.translate(bm, vec=(0,0,W), verts=[e for e in ret['geom'] if isinstance(e, bmesh.types.BMVert)])bmesh.ops.recalc_face_normals(bm, faces=bm.faces[:])
me = bpy.data.meshes.new("SpurGear"); bm.to_mesh(me); bm.free()ob = bpy.data.objects.new("SpurGear_12T_m2", me)bpy.context.scene.collection.objects.link(ob)K.gear = ob.name # 存进持久内核,下次调用直接用实测回执:ACT ok · 41ms,对象 SpurGear_12T_m2,1152 顶点 / 1152 面。
blender_rt_do的返回只有”ACT ok · Nms + stdout”,要拿数值必须自己print()。同时它支持see=false关掉回帧(省时间)。
Step 2 客观验收(踩过的坑:不要用 AABB 量旋转体)
第一次我用 ob.dimensions 验收,得到 (27.834, 27.834, 6.0),判 FAIL——但模型是对的:
齿轮顶点不一定落在坐标轴上。最靠近 +X 的齿顶顶点在 6.25°,
x = 14·cos(6.25°) = 13.917,所以 AABB 宽度是 27.834 而不是 28。用 AABB 验收旋转对称体是错的。
正确做法——量最大/最小半径:
import bpy, mathob = bpy.data.objects[K.gear]r = [ob.matrix_world @ v.co for v in ob.data.vertices]Rmax = max(math.hypot(p.x, p.y) for p in r)Rmin = min(math.hypot(p.x, p.y) for p in r)zmax, zmin = max(p.z for p in r), min(p.z for p in r)print("最大半径 %.3f / 最小半径 %.3f / 高度 %.3f" % (Rmax, Rmin, zmax-zmin))实测输出(全过):
SPEC : 齿顶圆半径 14.000 / 齿根圆半径 9.500 / 孔半径 4.000 / 齿宽 6.000MEASURED : 最大半径 14.000 / 最小半径 4.000 / 高度 6.000CHECK : 齿顶 OK | 孔 OK | 齿宽 OKVOLUME : 3003.7 mm^3 (网格法)Step 3 体检(blender_rt_plan(op="audit_mesh"))
blender_rt_plan(op="audit_mesh", args={"objects": ["SpurGear_12T_m2"]})实测输出(节选):
{ "ok": true, "clean": true, "state": "pass", "verdict": "pass", "totals": { "objects":1, "tris":2304, "boundary_edges":0, "nonmanifold_edges":0, "degenerate_faces":0, "loose_verts":0, "self_intersections":0, "normals_inverted":0, "normals_checked":1 }, "objects":[{ "name":"SpurGear_12T_m2", "closed":true, "normals_outward":true, "signed_volume":3003.702415, "self_intersections_analyzed":true, "state":"pass" }] }三态设计:
pass / degraded / fail。自交检查被跳过 ⇒degraded,不假通过;大网格 ⇒analyzed=false,未分析不得读作”已连通”。
Step 4 看一眼(blender_rt_see,约 100 ms,不动场景)
blender_rt_see(from="42,-42,34", look_at="0,0,3", max_size=640)实测:自定义视角 viewport · 1138x640 · 266ms · from [42,-42,34] → look_at [0,0,3] · 覆盖 35.31% · 场景与用户视口均未改动
Step 5 多视角 QC 渲染(qc_render_views)
blender_rt_plan(op="qc_render_views", args={ "views": [{"name":"hero","from":[42,-42,34],"look_at":[0,0,3],"lens":50}, {"name":"front","from":[0,-70,3],"look_at":[0,0,3],"lens":50}, {"name":"side","from":[70,0,3],"look_at":[0,0,3],"lens":50}, {"name":"top","from":[0,0,70],"look_at":[0,0,3],"lens":50}], "res":[960,540], "samples":48, "outdir":"/home/zero/.dsh-blender-rt/out/doc_gear"})实测:4 张全出,total_ms=776(render_ms=392),每张带 md5:
| view | 文件 | md5 | 取景 diagnostics |
|---|---|---|---|
| hero | views_hero.png | 09ad0f4d8c2f… | coverage 0.335 / fill 0.420 |
| front | views_front.png | ca05dcf9a242… | 0.145 / 0.152 |
| side | views_side.png | 096fcdbe55aa… | 0.145 / 0.152 |
| top | views_top.png | 5af9a0bae258… | 0.424 / 0.606 |
同时自动做了:渲染锁(locks/render.lock,held 776 ms 后释放)、view_transform 保存/还原(临时设 Standard,场景原本是 AgX,结束后还原)、逐张 jsonl 台账(out/doc_gear/render_views.jsonl)。
⚠ 俯视图在无材质白模上会过曝(自带三点光是 key 3.2 / fill 1.0 / rim 2.4)。要么先套材质,要么调光——本次套了材质后正常。
5. 实操:回退(两种粒度,别用错)
| 粒度 | 命令 | 记录什么 | 成本 | 边界 |
|---|---|---|---|---|
| 对象级 | rt_txn(op="mark") → 改 → rt_txn(op="revert") | transform / 材质槽 / 可见性 / 修改器开关 | 毫秒级 | 不含拓扑/UV/顶点级改动 |
| 文件级 | rt_txn(op="snapshot") → rt_txn(op="restore") | 整个场景(写 .blend 副本) | MB 级、秒级 | 唯一能回退 Boolean/合并/删面的办法 |
实测(破坏 → 回滚):
# 1) 建回退点blender_rt_txn(op="mark", label="before-move", objects="SpurGear_12T_m2")# 2) 故意破坏# ob.location = (30,-12,5); ob.scale = (1.8,1.8,1.0)# → 破坏后 : loc=(30.0,-12.0,5.0) scale=(1.8,1.8,1.0) dims=(50.1,50.1,6.0)# 3) 回滚blender_rt_txn(op="revert", label="before-move")# → 回滚后 : loc=(0.0,0.0,0.0) scale=(1.0,1.0,1.0) dims=(27.8,27.8,6.0) CHECK OK文件级快照实测:TXN snapshot ok · 快照 gear-baseline · 124764B · 77ms · 1 对象 → snapshots/gear-baseline.blend。
6. 实操:交付(OBJ/MTL + manifest,逐项校验)
blender_rt_plan(op="deliver_export", args={"objects": ["SpurGear_12T_m2"]})blender_rt_plan(op="deliver_verify", args={"path_or_dir": "/home/zero/.dsh-blender-rt/deliver"})实测:导出 model.obj(107989 B, md5 b376f0c24d13…) + model.mtl(287 B, md5 33fb7c7b17fb…) + model_manifest.json。
deliver_verify → passed=18 / failed=0,逐项核对:md5、字节数、三角面数、g/usemtl 计数、法线行数、bbox 与清单一致性、最长边归一化、单位说明、归一化可反推性。
两个必须知道的交付语义:
- 默认做单位盒归一化(
target_half_extent=1),并给出还原公式:p_orig = p_out / scale + center(本次 scale=0.071855651, center=[0,0,3]) - 对象没材质时,MTL 的
Kd用名字 md5 派生的确定性灰阶,并在guessed_colors里点名——“不是真值”会被明确写出来。
7. 实操:制造性检查(print_report)
先把单位设对(我按”毫米数值”建模,所以让 1 场景单位 = 1 mm):
import bpybpy.context.scene.unit_settings.system = 'METRIC'bpy.context.scene.unit_settings.length_unit = 'MILLIMETERS'bpy.context.scene.unit_settings.scale_length = 0.001 # 1 单位 = 1 mmblender_rt_plan(op="print_report", args={"objects":["SpurGear_12T_m2"], "min_mm":1.2, "max_angle_deg":45})实测:walls_ok=true、overhang_ok=true,最薄处 4.887 mm、p05 4.9827、中位 6、最大 9.9994;超 45° 悬垂面积 0 mm²;贴床面 500.62 mm²(占全表面 23.4%)。
并且它主动否证了我给的阈值:
warning: min_mm=1.200 低于本网格的测量分辨率 1.354 mm: 几何本身分辨不出这么薄的壁,结论不可信(先细化/降 voxel_size)这是这套工具最有价值的行为之一:测不出来就说测不出来,不给假通过。
resolution_mm/ray_precision_mm都会一并给出。
8. 实操:材质与参数化复用
8.1 程序化材质
blender_rt_plan(op="material_build", args={"name":"M-gear","preset":"metal_brushed", "params":{"base_color":[0.72,0.74,0.78],"scale":30}})# → ok · 7 nodes / 7 links · ms=3blender_rt_plan(op="material_apply", args={"material":"M-gear", "objects":["SpurGear_12T_m2"], "replace":True})# → slots_before=0 → slots_after=110 个现成 preset:metal_brushed / metal_paint / rust / plastic / glass / fabric / wood / concrete / emission / hologram / unlit。
注意:程序化节点树带不进 OBJ/MTL,要交付就得先 material_bake 烘成贴图(bake 需要 UV,会临时切 Cycles,结束还原)。
8.2 参数化复用(“配方即形状”)
blender_rt_plan(op="generator_save", args={"name":"sprocket", "params":{"n":12,"m":2.0,"w":6.0,"bore":4.0}, "code":"<一段用 PARAMS 的 bmesh 代码>"})# → ok · path=/home/zero/dsh_generators/sprocket.py · sidecar=.json · hash=42b3c3f6d0d6⚠ generator_run 本机跑不通(见 §10.5)。变通办法——直接 exec 配方文件,改参不改码:
PARAMS = {"n": 16, "m": 2.0, "w": 5.0, "bore": 4.5}ns = {"PARAMS": PARAMS, "__name__": "__main__"}exec(compile(open("/home/zero/dsh_generators/sprocket.py").read(), "sprocket.py", "exec"), ns)实测:GEN n=16 m=2.0 -> 外径 36.0 齿宽 5.0 → 对象 Sprocket_16T,1536 面,尺寸 (35.88, 35.88, 5.0)(同样受 AABB 效应影响)。
9. 无头批处理与作业台账
blender_rt_headless(engine="none", script='''import json, bpyout = {"ok": True, "blender": ".".join(map(str, bpy.app.version)), "file": bpy.data.filepath or "(factory startup)", "objects": len(bpy.data.objects)}print("HEADLESS " + json.dumps(out, ensure_ascii=False))''')契约:脚本里 print("HEADLESS " + json.dumps(obj)),必须是单行 JSON,会被解析进 resultJson。
实测:status=finished · exit=0 · 431ms,resultJson={"ok":true,"blender":"5.2.2","file":"(factory startup)","objects":3}。
- 产出物在
outdir,日志在logs.stdout/stderr,过程用DSH_STAGE打点(boot → engine-prelude → preload-done → script-end → done) runId可追溯:blender_rt_job(op="status", id="run-mvbcrpjhn6kp")→status=done, exit=0, ms=431(run 与 job 同一 id 空间)- 预期 >100 s 的活:
rt_headless(as_job=true)或rt_job(op="start"),用op=wait/collect回收;超时 ≠ 失败 - 参数细节:
blender_rt_plan(op="catalog", args={"tool":"rt_headless"})
无头是独立会话:看不到 GUI 里那个齿轮(实测
file="(factory startup)")。要基于同一场景干活就传file=<.blend>。
10. 关键坑(本次实测,10 条)
- 异常也回传 partial stdout —— 这条极其有用。我写错
is_manifold时,报错回执里先给出了出错前已打印的验收结果,不用重跑就能看到进度。写脚本别怕中途抛错,前面 print 的信息不会丢。 - Blender 的
--python抛异常时退出码仍是 0 —— 只看exit会漏判。generator_run自己就是用「回执 + stderr 异常标记」判的,并明确写verdict: "refuted"。自己写批处理时务必也检查 stderr。 - 参数名写错会回
did_you_mean+ 完整签名 —— 别猜,直接按它重发。实测两次踩到:audit_mesh(name=...)→参数不匹配: unexpected keyword argument 'name',回执给出audit_mesh(objects|scope, envelope, eps_area, self_intersect)deliver_verify(dir=...)→ 正确是path_or_dirmaterial_apply(objects=...)→ 少了必填的material
montagefamily 本机是坏的 ——blender_rt_plan(op="montage", ...)和op="montage_help"都抛内部TypeError: can only concatenate str (not "dict") to str(dsh_blender_bridge.py:2135→ 生成的代码里)。要用拼图就自己用 PIL 做。generator_run缺共享内核 —— 报RuntimeError: generator 需要共享内核 K.dsh_kit(由 KERNEL_BOOTSTRAP 注入)。有意思的是几何代码本身跑成功了(stdout 有GEN n=20 m=1.5 -> 外径 33.0 齿宽 4.0),只是包装层起不来。变通:直接exec配方文件(见 §8.2)。- 不要用 AABB 验收旋转对称体 —— 见 §4 Step 2,误差可达 0.6%。
MeshEdge没有is_manifold—— 那是 bmesh 的BMEdge才有的属性。bpy.data.meshes[].edges[]上取会 AttributeError;非流形检查要bm = bmesh.new(); bm.from_mesh(me)。- mm 口径的检查先设
scene.unit_settings.scale_length—— 否则print_*/audit_*的 mm 阈值全是错的(默认 1 单位 = 1 m,我的 28 单位齿轮会被当成 28 米)。 - 阈值低于网格分辨率时结论不可信 ——
print_report会主动报min_mm=1.200 低于本网格的测量分辨率 1.354 mm。要么细化网格(降 voxel_size),要么别用这么严的阈值。 - 无头会话与 GUI 会话是两个世界 —— 变量、场景、甚至
bpy.data都不共享。blender_rt_do的K只在 GUI 会话里持久;rt_worker里的K只在那个 worker 里持久。
11. 从零复现清单(可直接粘贴)
# ── A. 确认 Blender 存在 ────────────────────────────────────────────ls -d /home/zero/.local/opt/blender-*//home/zero/.local/opt/blender-5.2.2-linux-x64/blender --version # 期望 Blender 5.2.2 LTS
# ── B. 后端在不在 ───────────────────────────────────────────────────curl -sS -m 5 -o /dev/null -w "%{http_code}\n" http://127.0.0.1:9877/health # 期望 200ss -tln | grep 9876 || echo "addon 未连 —— 需要 launch"# ── C. 拉起 + 体检 ──────────────────────────────────────────────────blender_viewport(op="launch", wait_ms=120000) # 期望:LAUNCH ok · addon 端口 9876 · ~2sblender_viewport(op="doctor") # 期望:TCP + ping + bpy 往返都通blender_rt_commands # 期望:19 条常驻命令可用blender_rt_plan(op="catalog") # 期望:28 family / 186 op
# ── D. 建一个 12 齿齿轮 ─────────────────────────────────────────────blender_rt_do(code="<§4 Step 1 的代码>", see=false) # 期望 ACT ok · ~40msblender_rt_do(code="<§4 Step 2 的半径验收>", see=false) # 期望 最大半径 14.000 / 孔 4.000 / 齿宽 6.000
# ── E. 体检 ────────────────────────────────────────────────────────blender_rt_plan(op="audit_mesh", args={"objects":["SpurGear_12T_m2"]})# 期望:clean=true / state=pass / boundary_edges=0 / nonmanifold_edges=0
# ── F. 看一眼 ──────────────────────────────────────────────────────blender_rt_see(from="42,-42,34", look_at="0,0,3", max_size=640) # 期望 ~300ms 出图
# ── G. 制造性(先设单位!)──────────────────────────────────────────blender_rt_do(code="<§7 的 unit_settings 三行>", see=false)blender_rt_plan(op="print_report", args={"objects":["SpurGear_12T_m2"], "min_mm":4.0, "max_angle_deg":45})# 期望:walls_ok=true / overhang_ok=true / min_mm≈4.9# 注:阈值别低于网格 resolution_mm,否则工具会判"结论不可信"
# ── H. 多视角 QC ───────────────────────────────────────────────────blender_rt_plan(op="qc_render_views", args={"views":[{"name":"hero","from":[42,-42,34], "look_at":[0,0,3],"lens":50}], "res":[960,540], "samples":48, "outdir":"/home/zero/.dsh-blender-rt/out/mygear"})# 期望:ok=true + 逐张 md5 + render_views.jsonl
# ── I. 交付 + 校验 ─────────────────────────────────────────────────blender_rt_plan(op="deliver_export", args={"objects":["SpurGear_12T_m2"]})blender_rt_plan(op="deliver_verify", args={"path_or_dir":"/home/zero/.dsh-blender-rt/deliver"})# 期望:passed=18 failed=0
# ── J. 无头通路自检 ────────────────────────────────────────────────blender_rt_headless(engine="none", script='import json,bpy;print("HEADLESS "+json.dumps({"ok":True,"v":".".join(map(str,bpy.app.version))}))')# 期望:runId + resultJson.ok=true + exit=0回退点建议:动手改几何前先 rt_txn(op="snapshot", label="...");改 Boolean/合并/删面之后只能用文件级 restore。
12. 证据清单(本次真实输出汇总)
| 能力 | 调用 | 实测输出 | 耗时 |
|---|---|---|---|
| 拉起 GUI + 连 addon | blender_viewport(op="launch") | LAUNCH ok · pid=297893 · addon 9876 · 2012ms | 2.0 s |
| 命令清单 | blender_rt_commands | 19 常驻 / 15 被集成开关挡住 | — |
| 算子目录 | rt_plan(op="catalog") | 28 family / 186 op;engine 哈希自证一致 | — |
| 建模 | rt_do(bmesh 齿轮) | 1152 顶点 / 1152 面;半径 14.000 全过 | 41 ms |
| 体检 | rt_plan(op="audit_mesh") | clean / pass / 非流形 0 / 自交 0 / 封闭 | — |
| 看画面 | rt_see | 1138×640,覆盖 35.31% | 266 ms |
| 多视角 QC | rt_plan(op="qc_render_views") | 4 张 + md5 + 取景诊断 + 渲染锁 | 776 ms |
| 对象级回退 | rt_txn mark/revert | loc/scale 复原 | ms 级 |
| 文件级快照 | rt_txn(op="snapshot") | 124764 B | 77 ms |
| 材质 | material_build+apply | 7 节点 / slots 0→1 | 3 ms |
| 制造性 | rt_plan(op="print_report") | 最薄 4.887 mm;悬垂 0;并否证我的阈值 | — |
| 交付 | deliver_export+verify | OBJ 107989 B / 18 项校验全 PASS | 14 ms |
| 无头 | rt_headless | exit=0 / resultJson.ok=true | 431 ms |
| 作业台账 | rt_job(op="status") | run-mvbcrpjhn6kp · done · 431ms | — |
| 参数化配方 | generator_save + exec | 12 齿→16 齿,1536 面 | — |
13. 未验证 / 已知受限
未验证(不要当成已验证):
- 5 个集成开关全为 off:
polyhaven / hyper3d / sketchfab / polypizza / hunyuan3d(15 条命令被挡)。文档里列出的相关 op 一律未测。 sculpt / sweep / shape / vehicle / clearance / human / face / img / calib / gate / pipe / plan / contract / uv / fix / ext / motion / render_guard / render / gui / qc(比对) / img(量图)家族本次未逐个实测,§3 的说明来自catalog自述。blender_rt_loop(内环参数搜索)、rt_worker(热会话)、rt_preset(配方库)、rt_watch、rt_pick、rt_opt、rt_perf未测。audit_gate/audit_connectivity/audit_interference/audit_drift未测(多零件装配门)。
已知坏/受限:
montagefamily 报内部TypeError(§10.4)generator_run报缺K.dsh_kit(§10.5),变通是直接 exec 配方- 对象级
revert不含拓扑/UV/顶点级改动(Boolean、合并、删面之后回不去) qc_render_views三点光打在无材质白模上会过曝(尤其俯视)- 无头进程看不到 GUI 场景(本该如此,但脚本容易写错)
14. 下载与安装清单(含链接 · 2026-10-17 实测可达性)
本机访问国际站点必须走代理
http://127.0.0.1:7897:实测 Blender 的 tar.xz 直连 403、走代理 206。下面所有curl都带-x。 表中「实测」列是本次curl的真实 HTTP 码,未实测的一律标注。
14.1 Blender 本体
| 项 | 值 |
|---|---|
| 本机版本 | Blender 5.2.2 LTS(build date 2026-09-15) |
| 安装路径 | /home/zero/.local/opt/blender-5.2.2-linux-x64/ |
| 官网下载页 | https://www.blender.org/download/ —— 实测 200 |
| LTS 长期支持页 | https://www.blender.org/download/lts/ —— 实测 200 |
| 本机对应构建直链 | https://download.blender.org/release/Blender5.2/blender-5.2.2-linux-x64.tar.xz —— 直连 403 / 走代理 206 |
| 发布目录(自己挑版本) | https://download.blender.org/release/Blender5.2/ —— 实测含 5.2.0 / 5.2.1 / 5.2.2 |
| Python API 文档 | https://docs.blender.org/api/current/ —— curl 403(被反爬挡,浏览器正常) |
复现本机安装方式:
mkdir -p ~/.local/opt && cd ~/.local/optcurl -x http://127.0.0.1:7897 -sSL -o blender.tar.xz \ https://download.blender.org/release/Blender5.2/blender-5.2.2-linux-x64.tar.xztar xf blender.tar.xz && rm blender.tar.xzmkdir -p ~/.local/binln -sf ~/.local/opt/blender-5.2.2-linux-x64/blender ~/.local/bin/blender
# 验收/home/zero/.local/opt/blender-5.2.2-linux-x64/blender --version # 期望 Blender 5.2.2 LTS⚠ 本机
~/.local/bin只写在~/.profile里,非登录 shell 的PATH里可能没有;在~/.bashrc补一段更稳(本机已补)。
14.2 DSH Blender 插件(本机 2.1.0)
| 项 | 值 |
|---|---|
| 仓库 | https://github.com/sixtysevenlf/dsh-blender-plugin —— 实测 200 |
| 本机安装位置 | /home/zero/.local/share/dsh-plugins/dsh-blender-plugin/ |
| 安装 SOP(随插件分发,权威) | 插件内 docs/部署SOP.md、docs/AI-安装提示词.md、docs/配置参考.md |
| 建模技能(可选) | https://github.com/sixtysevenlf/dsh-skill-blender-modeling —— 实测 200 |
| 风格化着色(可选) | https://github.com/lurenjia-l/dsh-blender-stylized-shading —— 实测 200 |
安装(摘自插件自带 docs/部署SOP.md):
cd <解包后的 dsh-blender-plugin>/bash scripts/build.sh # 链接依赖 + 编译 lib/(需 bash + node/npm 在 PATH)
# 再按 bundle 方式装进 profile:# 1) node_modules/@dsh-external/dsh-blender-plugin 建软链# 2) profile 的 package.json:dependencies 加 "link:" + dsh.profile.bundles 各加一行dsh --profile <profile> --dump-config # 预演,确认没配错# 最后重启 DSH连接 Blender(本机这次是 blender_viewport(op="launch") 自动完成的,正常只需人工一步):
- Blender 里启用 DSH Blender Bridge addon(旧名
MCP for Blender;改名后旧的”已启用”记录会变死引用,需重新启用) - 3D 视口按
N→ DSH Blender Bridge 面板 → Connect(socket 默认127.0.0.1:9876) - 回到 DSH 跑
blender_viewport(op="doctor")复核
唯一验收判据:doctor 返回 kind=ok(TCP + ping + bpy 往返三级都通)。
14.3 可选:5 个资产集成(本机全部关闭)
| 集成 | 本机状态 | 开启方式(摘自 addon 自带提示原文) | 需要 key | key 获取入口(实测) |
|---|---|---|---|---|
| PolyHaven | ⛔ off | N 面板勾 Use assets from Poly Haven | 否 | https://polyhaven.com/ 200 |
| Sketchfab | ⛔ off | 勾 Use assets from Sketchfab + 填 API Key | 是 | https://sketchfab.com/settings/password 200 |
| Poly Pizza | ⛔ off | 勾 Use assets from Poly Pizza + 填 API Key | 是 | addon 指向 https://poly.pizza/settings/api,本机实测 000 不可达;从 https://poly.pizza/ 200 进设置页自取 |
| Hyper3D Rodin | ⛔ off | 勾 Use Hyper3D Rodin 3D model generation | 是 | https://www.hyper3d.ai/ 200 |
| Tencent Hunyuan3D | ⛔ off | 勾 Use Tencent Hunyuan 3D model generation | 是 | 未查证 |
- addon 里实际字段名:
polyhaven无 key;sketchfab_api_key、polypizza_api_key、hyper3d_api_key(另有hyper3d_free_trial_api_key)。 - 改完都要重连(addon 原文 “Restart the connection”)。
- 状态自查:
blender_rt_commands会直接列出集成:polyhaven=off · hyper3d=off · sketchfab=off · polypizza=off · hunyuan3d=off,被挡住的 15 条命令名也一并列出。
⚠ 这 5 个集成的开启与 key 填写本次未实测(本机全 off);上表内容来自 addon 自带提示文本 + 官方入口可达性实测。
14.4 Blender 相关官方资源
| 项 | 链接 | 本机 curl 实测 |
|---|---|---|
| 下载页 | https://www.blender.org/download/ | 200 |
| LTS 页 | https://www.blender.org/download/lts/ | 200 |
| 发布目录(全版本) | https://download.blender.org/release/ | 未测(子目录 5.2/ 实测可用) |
| Python API 文档 | https://docs.blender.org/api/current/ | 403(反爬,浏览器可开) |
附:与 ComfyUI 侧的分工
| Blender(本文) | ComfyUI | |
|---|---|---|
| 驱动方式 | 往 Blender Python 注入代码(rt_do / rt_headless) | 往 HTTP API 提交 JSON 工作流(POST /prompt) |
| 判定 | 有完整判定族(28 family / 186 op)算数字 | 主要靠 MCP 工具 + 脚本,判定靠像素比对 |
| 交付 | OBJ/MTL + manifest md5,逐项校验 | PNG 图 + 可选 4K 放大 |
| 详细文档 | 本文 | AI-Agent驱动ComfyUI出图操作手册.md |
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!



