mcpField
B
blender-modeling

blender-modeling

github.com/roble3创意与媒体1282.4k 次安装2 周前更新
代码仓库

关于 blender-modeling

blender-modeling 是用于通过自然语言请求创建和编辑 Blender 几何体的技能,并由 Blender MCP 执行 Python 代码。它提供网格、修改器和硬表面建模流程,也明确说明雕刻等不适用的任务。

主要功能

  1. 01通过自然语言创建几何体
  2. 02使用 Python 编辑网格
  3. 03基于基本体的建模配方
  4. 04修改器堆栈指导
  5. 05布尔、镜像与阵列流程

适用场景

  1. 01制作硬表面道具和建筑
  2. 02通过挤出或内插编辑网格
  3. 03用布尔切割创建孔洞
  4. 04用粗模测试场景构图

MCP 相关

该技能将 Python 代码交由 Blender MCP 执行。它要求首次调用 Blender 前查阅后端参考,并在整个任务中沿用选定的后端。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/roble3/cc-blender-skill --skill blender-modeling

安装后在 Claude Code 中输入/blender-modeling确认已加载。

附带文件evals/evals.jsonreferences/overview.md

详细介绍

MCP 后端

适用于:在 Blender 中创建几何体、编辑网格或处理修改器堆栈。不适用于将线框转换为 3D(请使用 wireframe-to-3d),也不适用于雕刻笔触(Blender 的雕刻模式基于手势操作,而非文本驱动)。

首次调用 Blender 前,请阅读 ../text-to-blender/references/mcp-backends.md。对于共享功能,优先使用官方 MCP;整个任务期间请保持所选后端不变。配方中的工具名称是客户端/旧版示例:请根据该参考文档及其 Agent 宿主指南进行映射。

Blender 建模

通过自然语言在 Blender 中创建几何体。你将输出由 Blender MCP 执行的 Python 代码;以下模式涵盖了常见的 80% 情况。

决策树

What kind of geometry?
├── Hard-surface (vehicles, weapons, architecture, props)
│   → Cube primitive + Bevel + SubSurf modifier stack
│   → See "Hard-surface stack" recipe
│
├── Organic (characters, creatures, plants — block-out only)
│   → Ico Sphere + sculpting (or Voxel Remesh for shape)
│   → For sculpting strokes, redirect: it's gestural, not text-driven
│
├── Architectural / repeating (fences, columns, tile)
│   → Plane/Cube + Array modifier (+ Curve modifier for paths)
│   → See "Array along curve" recipe
│
├── Cylindrical (pipes, columns, bottles)
│   → Cylinder primitive, or Curve + bevel_object
│   → See "Sweep along path" — covered in wireframe-to-3d if needed
│
├── Holes / cuts in existing geometry
│   → Boolean modifier (DIFFERENCE)
│   → See "Boolean cut" recipe
│
└── Quick block-out from primitives only
    → Multiple primitive_*_add calls
    → See "Block-out scene" recipe

代码执行规则(回顾)

  • 每次后端代码执行调用都会获得一个全新的 Python 命名空间。请重新导入所有内容;使用 bpy.data.objects['name'] 标识对象。
  • 对象名称始终使用 GEO- 前缀。绝不要留下 Cube.027。
  • 打印结构化输出,以便解析结果。
  • 将较长的序列拆分为多次调用。

配方

关键:细长物体的轴向

对于任何细长/不对称的对象(剑刃、刀刃、瓶子、木板、骨头、螺丝刀尖端等),三个轴的含义各不相同:

  • 长轴——物体的长度(剑刃为 78cm)
  • 宽轴——较宽的表面轴,即从“实用”视角能看到的方向(剑刃为 4.5cm——将其平放在桌上时朝上的平面)
  • 薄轴——较窄的横截面轴(剑刃为 0.8cm——刀刃)

拍摄主体特写时,细长物体的宽轴始终应朝向摄像机。 如果从刀刃侧面观察一把剑(摄像机沿薄轴方向拍摄),它渲染出来就会像一根细杆,完全不像剑。以下配方遵循此约定:

约定X(物体局部空间中的左右方向)Y(物体局部空间中的前后方向)Z(上下方向)
剑刃薄(0.8cm)宽(4.5cm)长(78cm)——垂直
刀刃薄宽长——水平
木板薄宽长
瓶子对称(半径)对称(半径)长(高度)

建模完成后,旋转物体,使宽轴大致朝向摄像机。对于一把直立的剑,若摄像机位于前方(摄像机朝向 -Y 方向),则将剑刃绕 Z 轴旋转 90°,使其局部 Y(宽)轴指向世界 X 轴,这样从摄像机视角就能看到宽面。

关键:让部件平滑连接(不留可见接缝)

组装由多个部分组成的物体时(剑 = 刀刃 + 护手 + 握柄 + 剑首;椅子 = 座面 + 靠背 + 4 条椅腿),若分离的基本体恰好沿着对齐的面边界相接,就会留下可见接缝,尽管从数学上看它们确实相接。更糟的是,不同形状的基本体(圆柱形握柄接入立方体护手)会产生明显的“圆柱接矩形”边界。

两种修复方法,配合使用:

1. 在连接处让部件充分重叠。 在每个连接处,让相邻的基本体相互穿插 5–15mm。隐藏的体积会消失在较大的部件内部,不留下可见接缝。

# Sword example: grip extends 1.5cm INTO the guard above and 1cm INTO the pommel below
GRIP_OVERLAP_INTO_GUARD = 0.015
GRIP_OVERLAP_INTO_POMMEL = 0.010
grip_total_len = GRIP_VISIBLE_LEN + GRIP_OVERLAP_INTO_GUARD + GRIP_OVERLAP_INTO_POMMEL

圆柱形握柄顶部的 1.5cm 位于护手立方体内部——从外部看不见,因此你看到的过渡只是金色护手表面,不会出现圆柱与矩形相接的瑕疵。

2. 对圆润部件应用 shade_smooth()(圆柱体、球体、有机形状)。平面着色的圆柱体会显露每条面片边界;平滑着色则看起来连续。立方体和带倒角的硬表面部件可以保持平面着色(也可以通过 Blender 4.x 中的 Auto Smooth 部分平滑;Blender 5.x 已移除 Mesh.use_auto_smooth,因此请使用基于修改器的平滑或逐面标志)。

# After creating each rounded primitive
bpy.ops.object.shade_smooth()

反面模式(出现可见接缝):

# ❌ Pieces abut exactly — visible seam where surfaces meet
pommel_z = -GRIP_LEN/2 - POMMEL_R     # pommel top exactly at grip bottom
guard_z = GRIP_LEN/2 + GUARD_H/2      # guard bottom exactly at grip top
# Result: clear line where each pair of surfaces meets

正确做法(通过重叠隐藏接缝):

# ✓ Pieces overlap by ~5-15mm; junction lines are inside other geometry
pommel_z = -GRIP_LEN/2 - POMMEL_R + 0.010   # pommel pushed up 1cm into grip
guard_z = GRIP_LEN/2 + GUARD_H/2 - 0.015    # guard pushed down to envelope grip top

若要实现真正无缝的连接(用于高质量渲染),可对相同材质的部件执行布尔并集:例如,将剑首和握柄布尔并集为单个网格,即可彻底消除接缝。但这只适用于两个部件使用相同材质的情况。

关键:收尖至一点(用于刀刃尖端)

不要只把顶部顶点缩放至接近零——那样会产生“凿平”的尖端。将所有顶部顶点收拢到同一个点并合并:

import bpy
import bmesh

obj = bpy.data.objects['GEO-blade']
bpy.context.view_layer.objects.active = obj
bpy.ops.object.mode_set(mode='EDIT')

bm = bmesh.from_edit_mesh(obj.data)
bm.verts.ensure_lookup_table()

# Find vertices at the top (highest local Z)
max_z = max(v.co.z for v in bm.verts)
top_verts = [v for v in bm.verts if abs(v.co.z - max_z) < 0.001]

# Collapse them to centerline
for v in top_verts:
    v.co.x = 0.0
    v.co.y = 0.0

bmesh.update_edit_mesh(obj.data)

# Merge the now-coincident vertices into a true single point
bpy.ops.mesh.select_all(action='DESELECT')
for v in top_verts:
    v.select = True
bmesh.update_edit_mesh(obj.data)
bpy.ops.mesh.remove_doubles(threshold=0.001)
bpy.ops.object.mode_set(mode='OBJECT')

print(f"tapered:{obj.name}")

这样会生成真正的几何尖点。如果不使用 remove_doubles,收拢后的四个顶点仍会作为位于同一坐标的四个独立点保留——尖端看起来是尖的,但拓扑是退化的。

配方 1 — 添加命名清晰的基本体
import bpy

# Add cube
bpy.ops.mesh.primitive_cube_add(size=2.0, location=(0, 0, 1))
obj = bpy.context.active_object
obj.name = 'GEO-base_box'
print(f"created:{obj.name} verts:{len(obj.data.vertices)}")

将 primitive_cube_add 替换为:_plane_、_uv_sphere_、_ico_sphere_、_cylinder_、_cone_、_torus_、_monkey_。每种基本体都接受相应的参数(radius、depth、vertices、segments、subdivisions)。

配方 2 — 硬表面修改器堆栈(“Bevel + SubSurf”模式)
import bpy

obj = bpy.data.objects['GEO-base_box']

# 1. Bevel modifier — round the sharp edges
bevel = obj.modifiers.new('Bevel', type='BEVEL')
bevel.width = 0.02              # 2 cm round-over
bevel.segments = 3              # smoothness
bevel.limit_method = 'ANGLE'    # only bevel edges sharper than threshold
bevel.angle_limit = 0.523599    # 30° in radians

# 2. Subdivision Surface AFTER bevel (critical order)
subsurf = obj.modifiers.new('SubSurf', type='SUBSURF')
subsurf.levels = 2
subsurf.render_levels = 3

# 3. Smooth shading
bpy.context.view_layer.objects.active = obj
bpy.ops.object.shade_smooth()
print(f"hardsurface:{obj.name}")

关键:先 Bevel,再 SubSurf。顺序颠倒会产生挤压伪影。

配方 3 — 编辑模式操作(挤出、内插面、环切)
import bpy

obj = bpy.data.objects['GEO-base_box']
bpy.context.view_layer.objects.active = obj
bpy.ops.object.mode_set(mode='EDIT')

# Select all faces, then extrude up by 1m
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.mesh.extrude_region_move(
    TRANSFORM_OT_translate={'value': (0, 0, 1.0)}
)

# Inset all selected faces by 0.1m
bpy.ops.mesh.inset(thickness=0.1, depth=0)

# Add a loop cut around the middle
bpy.ops.mesh.loopcut_slide(
    MESH_OT_loopcut={'number_cuts': 1, 'edge_index': 0},
    TRANSFORM_OT_edge_slide={'value': 0.0},
)

bpy.ops.object.mode_set(mode='OBJECT')
print(f"edited:{obj.name} verts:{len(obj.data.vertices)}")
配方 4 — 布尔切割(钻孔)
import bpy

target = bpy.data.objects['GEO-base_box']
cutter = bpy.data.objects.get('GEO-cutter')

if cutter is None:
    bpy.ops.mesh.primitive_cylinder_add(radius=0.3, depth=3.0, location=(0, 0, 1))
    cutter = bpy.context.active_object
    cutter.name = 'GEO-cutter'

# Apply boolean
mod = target.modifiers.new('Boolean', type='BOOLEAN')
mod.operation = 'DIFFERENCE'
mod.object = cutter
mod.solver = 'EXACT'

bpy.context.view_layer.objects.active = target
bpy.ops.object.modifier_apply(modifier=mod.name)

# Hide cutter from render
cutter.hide_viewport = True
cutter.hide_render = True
print(f"booleaned:{target.name}")
配方 5 — 镜像修改器(只建模一半)
import bpy

obj = bpy.data.objects['GEO-character_half']
mod = obj.modifiers.new('Mirror', type='MIRROR')
mod.use_axis[0] = True   # mirror across X
mod.use_clip = True       # snap vertices on axis
mod.use_mirror_merge = True
mod.merge_threshold = 0.001
print(f"mirrored:{obj.name}")

将 Mirror 放在堆栈最前面(位于 Bevel/SubSurf 之前)。

配方 6 — 沿曲线阵列(链条、栅栏、珠子)
import bpy

# 1. The base unit
bpy.ops.mesh.primitive_cube_add(size=0.2, location=(0, 0, 0))
unit = bpy.context.active_object
unit.name = 'GEO-bead'

# 2. The path (assume it exists; user provides or we add a Bezier)
path = bpy.data.objects.get('GEO-path')
if path is None:
    bpy.ops.curve.primitive_bezier_curve_add()
    path = bpy.context.active_object
    path.name = 'GEO-path'

# 3. Array modifier (count or fit to length)
arr = unit.modifiers.new('Array', type='ARRAY')
arr.fit_type = 'FIT_CURVE'
arr.curve = path
arr.relative_offset_displace = (1.0, 0, 0)

# 4. Curve modifier — bends the array along the path
crv = unit.modifiers.new('Curve', type='CURVE')
crv.object = path
crv.deform_axis = 'POS_X'
print(f"arrayed:{unit.name}")
配方 7 — 初步建模(快速构图测试)
import bpy

# Floor
bpy.ops.mesh.primitive_plane_add(size=10)
bpy.context.active_object.name = 'GEO-floor'

# Hero subject
bpy.ops.mesh.primitive_cube_add(size=1.5, location=(0, 0, 0.75))
bpy.context.active_object.name = 'GEO-subject'

# Background prop
bpy.ops.mesh.primitive_cylinder_add(radius=0.5, depth=2, location=(2, 1.5, 1))
bpy.context.active_object.name = 'GEO-prop_pillar'

print('blockout:done')
配方 8 — 曲线→网格或布尔运算后的清理
import bpy

obj = bpy.data.objects['GEO-target']
bpy.context.view_layer.objects.active = obj

bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.mesh.remove_doubles(threshold=0.0001)
bpy.ops.mesh.normals_make_consistent(inside=False)
bpy.ops.object.mode_set(mode='OBJECT')

bpy.ops.object.shade_smooth()
print(f"cleanup:{obj.name} verts:{len(obj.data.vertices)}")

修改器堆栈顺序(记住这个顺序)

Mirror → Array → Solidify → Bevel → Subdivision Surface → (Boolean if needed)

顺序错误 = 伪影。最常见的新手错误是先 SubSurf,后 Bevel。

常见问题

症状修复方法
默认立方体的外观添加 Bevel(0.02m,3 个分段)和 SubSurf
圆形造型上出现尖锐挤压先 Bevel,再 SubSurf,而不是反过来
渲染中出现黑面重新计算法线(mesh.normals_make_consistent)
布尔运算生成 n-gon应用 Bool,切换到编辑模式,修复为四边形,然后 SubSurf
对称性被破坏使用 Mirror 修改器,而不是复制并翻转
网格中有隐藏的内部面Mesh → Clean Up → Delete Loose

何时加载 references/overview.md

在以下情况加载:

  • 此处的配方不符合请求(需要 bmesh 级别的精度或自定义操作)
  • 拓扑要求比通常情况更严格(适用于动画或游戏 LOD)
  • 需要考虑性能(需要使用 foreach_set、批量操作)
  • 用户提到了配方中没有的运算符

该参考文档涵盖:bmesh.ops 操作指南、所有值得了解的 bpy.ops.mesh.* 运算符、采用 MESHmachine 风格倒角的硬表面工作流、重拓扑指南、网格清理检查清单。

此技能不适用于

  • 线框绘图 → 3D 模型:请使用 wireframe-to-3d
  • 雕刻笔触:Blender 的雕刻模式依赖手势,难以通过文本有效驱动
  • 沿路径扫掠 / 放样 / 曲线驱动的形状:请参阅 wireframe-to-3d/references/blender-patterns.md
  • 材质 / 灯光 / 渲染:请转到相应技能

评论

支持 Markdown