blender-export — скилл для Claude Code: экспорт сцен Blender
Скилл выгружает сцены Blender в glTF/GLB, FBX, OBJ, USD и STL с настройками под целевую платформу. Пригодится, когда модель надо отдать в Unity, на веб или в 3D-печать.
npx skills add RobLe3/cc-blender-skill --skill blender-export -a claude-codeЧто делает blender-export
Скилл подбирает формат и параметры экспорта под то, куда уходит модель: glTF/GLB для веба и AR, FBX для игровых движков, OBJ для простого обмена геометрией, USD для VFX-конвейеров, STL для 3D-печати. Внутри — дерево решений по формату и готовые рецепты вызовов bpy.ops с конкретными флагами. Для незнакомой цели скилл советует glTF/GLB.
Отдельные рецепты закрывают типовые грабли. Decimate уменьшает число полигонов, если файл не влезает в лимит. Для FBX есть bake_space_transform и embed_textures — из-за их отсутствия модель приезжает в движок повёрнутой или без текстур. Для STL скилл напоминает про водонепроницаемую сетку и отсутствие единиц измерения.
Работа идёт через MCP-сервер Blender: скилл вызывает execute_blender_code и читает сцену через get_scene_info и get_objects_summary. Перед первым обращением к Blender нужно прочитать справочник по MCP-бэкендам и дальше держаться выбранного бэкенда до конца задачи. Материалы выгружаются чисто только из Principled BSDF — процедурные шейдеры теряются или упрощаются, это повод проверить сцену заранее.
Какие задачи решает
- выгрузить сцену в GLB для Three.js или model-viewer
- собрать FBX с анимацией и вшитыми текстурами для Unity
- уменьшить число полигонов через Decimate, чтобы файл прошёл по размеру
- подготовить водонепроницаемую сетку и сохранить её в STL для печати
- перевести оси и масштаб, чтобы модель не приехала повёрнутой на 90°
Примеры запросов агенту
- экспортируй эту сцену в GLB для веба
- сделай FBX для Unreal с анимацией и текстурами внутри
- модель слишком тяжёлая — прогони Decimate и пересобери GLB
Как установить blender-export
1Через Skills CLI (Vercel)
npx skills add RobLe3/cc-blender-skill --skill blender-export -a claude-code2Вручную: положить файлы
~/.claude/skills/blender-export/SKILL.mdПапка скилла целиком; для одного проекта — .claude/skills/blender-export/
1Через Skills CLI (Vercel)
npx skills add RobLe3/cc-blender-skill --skill blender-export -a codex2Вручную: положить файлы
.agents/skills/blender-export/SKILL.mdДля всех проектов — ~/.agents/skills/
1Через Skills CLI (Vercel)
npx skills add RobLe3/cc-blender-skill --skill blender-export -a cursor2Вручную: положить файлы
.cursor/skills/blender-export/SKILL.mdCursor читает и .agents/skills/, и .claude/skills/
1GitHub CLI
gh skill install RobLe3/cc-blender-skill blender-export2Вручную: положить файлы
.github/skills/blender-export/SKILL.md1Через Skills CLI (Vercel)
npx skills add RobLe3/cc-blender-skill --skill blender-export -a gemini-cli2Командой платформы
gemini skills install https://github.com/RobLe3/cc-blender-skill --path plugin/skills/blender-exportВручную: положить файлы
.devin/skills/blender-export/SKILL.mdСтарый путь .windsurf/skills/ тоже читается
Через Skills CLI (Vercel)
npx skills add RobLe3/cc-blender-skill --skill blender-export -a opencodeClaude.ai
Упакуйте папку в zip и загрузите в Settings → Capabilities → Skills
По шагам, с командами для каждой платформы: Как установить скилл в Claude Code: пять способов
Вопросы о blender-export
Как установить blender-export в Claude?
Выполните npx skills add RobLe3/cc-blender-skill --skill blender-export -a claude-code. Скилл встанет в ~/.claude/skills/blender-export/SKILL.md.
Что делает blender-export?
Экспортирует сцены Blender в glTF/GLB, FBX, OBJ, USD и STL, подбирая настройки под целевую платформу. Плюс оптимизация полигонов, конвертация осей и проверка под целевую платформу.
Что нужно, чтобы скилл заработал?
MCP-сервер Blender: скилл вызывает execute_blender_code и читает сцену через get_scene_info. Перед первым вызовом он просит прочитать справочник по MCP-бэкендам.
Исходный текст
SKILL.md · MIT
---
name: blender-export
description: Export Blender scenes to glTF/GLB (web/AR), FBX (game engines), OBJ (universal), USD (VFX pipelines), STL (3D printing). Includes Unreal collision hulls and Multires normal-map baking for low-poly export, per-format settings, embed/unpack textures, axis conversion, polygon optimization (Decimate), and target-platform validation. Use whenever the user asks to "export this", "save as glTF / FBX / OBJ / STL / USD", "package for Unity / Unreal / Three.js / web / AR / 3D print", or any output format conversion. Make sure to use this skill even if the user does not say "export" — also covers "package this for the web", "make it work in Unity", "send to Unreal", "save for 3D printing".
allowed-tools: Read Bash mcp__blender__execute_blender_code mcp__blender__get_scene_info mcp__blender__get_object_info mcp__blender__get_objects_summary mcp__blender__get_object_detail_summary mcp__blender__render_viewport_to_path mcp__blender__search_api_docs mcp__blender_official__execute_blender_code mcp__blender_official__get_objects_summary mcp__blender_official__get_object_detail_summary mcp__blender_official__render_viewport_to_path mcp__blender_official__search_api_docs
---
## MCP backend
Use when: Any export to a non-.blend format, packaging for game engines, web, AR, or 3D printing.
Before the first Blender call, read [../text-to-blender/references/mcp-backends.md](../text-to-blender/references/mcp-backends.md). Prefer official MCP for shared capabilities; preserve the selected backend for the whole task. Tool names in recipes are client/legacy examples: map them through that reference and its agent-host guide.
# Blender Export
Export to the right format with the right settings. Wrong format choice = days of debugging in the target platform.
## Format decision tree
```
Where is this going?
├── Web (Three.js, Babylon.js, model-viewer, AR Quick Look) → glTF / GLB
├── Game engine (Unity, Unreal, Godot)
│ ├── Animated/rigged → FBX (or glTF for modern engines)
│ └── Static → OBJ or FBX or glTF
├── Apple AR (USDZ) → USDZ (special, see Recipe 6)
├── 3D printing → STL (geometry only, must be watertight)
├── VFX pipeline (Maya, Houdini, Nuke) → USD
└── DCC roundtrip → FBX (industry standard)
```
**Quick rule for unknown target**: glTF / GLB. Open standard, modern, universally supported.
## Recipes
### Recipe 1 — glTF / GLB export (web / AR / general)
```python
import bpy
bpy.ops.export_scene.gltf(
filepath='/tmp/output.glb',
export_format='GLB', # single-file binary; preferred
export_apply=True, # apply modifiers before export
export_materials='EXPORT',
export_image_format='AUTO', # PNG; AUTO falls back to JPEG for opaque images
export_yup=True, # Y-up convention (most engines / web expect this)
export_animations=True, # toggle off for static models
export_morph=True, # shape keys
export_skins=True, # armatures + weights
export_normals=True,
export_tangents=False, # skip unless target uses tangent-space normals beyond standard
)
# Verify
import os
size_mb = os.path.getsize('/tmp/output.glb') / (1024 * 1024)
print(f"export:gltf {size_mb:.2f} MB")
```
**glTF caveats**:
- Only Principled BSDF materials export cleanly. Procedural shaders are dropped or simplified.
- Hard cap: 15 MB; soft target: 8 MB.
- No KTX2 / Draco compression (unless target supports those loaders).
- PNG textures only (max 1024×1024 typical).
### Recipe 2 — Decimate before export (if too large)
```python
import bpy
obj = bpy.data.objects['GEO-target']
if obj.type != 'MESH':
raise ValueError('Decimation requires a mesh')
selected = list(bpy.context.selected_objects)
active = bpy.context.view_layer.objects.active
mode = active.mode if active else 'OBJECT'
try:
if mode != 'OBJECT':
bpy.ops.object.mode_set(mode='OBJECT')
bpy.ops.object.select_all(action='DESELECT')
obj.select_set(True)
bpy.context.view_layer.objects.active = obj
mod = obj.modifiers.new('Decimate', type='DECIMATE')
mod.decimate_type = 'COLLAPSE'
mod.ratio = 0.7 # keep 70% of faces; lower = more reduction
bpy.ops.object.modifier_apply(modifier=mod.name)
finally:
bpy.ops.object.select_all(action='DESELECT')
for item in selected:
item.select_set(True)
bpy.context.view_layer.objects.active = active
if mode != 'OBJECT':
bpy.ops.object.mode_set(mode=mode)
print(f"decimated:{obj.name} verts:{len(obj.data.vertices)}")
```
Then re-export. Iterate ratio until file size fits target.
### Recipe 3 — FBX export (game engines)
```python
import bpy
bpy.ops.export_scene.fbx(
filepath='/tmp/output.fbx',
use_selection=False,
apply_unit_scale=True,
apply_scale_options='FBX_SCALE_ALL',
bake_space_transform=True, # critical: applies rotation to mesh
object_types={'MESH', 'ARMATURE', 'EMPTY'},
use_mesh_modifiers=True,
mesh_smooth_type='FACE',
use_armature_deform_only=True,
bake_anim=True,
bake_anim_use_all_bones=True,
bake_anim_use_nla_strips=True,
bake_anim_use_all_actions=True,
bake_anim_force_startend_keying=True,
embed_textures=True, # critical: embed textures into FBX
path_mode='COPY',
axis_forward='-Z',
axis_up='Y',
)
print('export:fbx')
```
**Common FBX gotchas**:
- Model rotated 90° in target → check `axis_up='Y', axis_forward='-Z'`
- Model 100× too large → Apply Transform on the object before export
- Textures missing → `embed_textures=True, path_mode='COPY'`
- Animation only plays one action → use NLA + bake all actions
### Recipe 4 — OBJ export (simple / universal)
```python
import bpy
bpy.ops.wm.obj_export(
filepath='/tmp/output.obj',
export_animation=False,
apply_modifiers=True,
export_eval_mode='DAG_EVAL_VIEWPORT',
export_uv=True,
export_normals=True,
export_materials=True,
export_triangulated_mesh=False,
forward_axis='NEGATIVE_Z',
up_axis='Y',
)
print('export:obj')
```
OBJ has no animation, no rigging, basic material support only. Use for simple geometry exchange.
### Recipe 5 — STL export (3D printing)
```python
import bpy
bpy.ops.wm.stl_export(
filepath='/tmp/output.stl',
ascii_format=False, # binary STL (smaller, faster)
apply_modifiers=True,
)
print('export:stl')
```
**Critical for STL**:
- Mesh must be **watertight** (no holes, no flipped normals, no internal faces).
- Pre-export: in Edit Mode, run `Mesh → Clean Up → Make Manifold`.
- STL has NO units — most slicers assume mm. Set Blender scene units to mm before modeling.
- STL has NO color/material — single-color grey only.
### Recipe 6 — USD export (VFX pipeline)
```python
import bpy
bpy.ops.wm.usd_export(
filepath='/tmp/scene.usdc',
export_animation=True,
export_uvmaps=True,
export_normals=True,
export_materials=True,
use_instancing=True,
export_textures=True,
overwrite_textures=True,
)
print('export:usd')
```
USD variants:
- `.usd` — text-based (debuggable, large)
- `.usdc` — binary (compact, fast — **default choice**)
- `.usda` — ASCII (human-readable, larger)
- `.usdz` — zipped USD with all assets (Apple AR / iOS)
### Recipe 7 — Pre-export checklist (run before any export)
```python
import bpy
# 1. Apply transforms (rotation + scale baked into geometry)
obj = bpy.data.objects['GEO-target']
bpy.context.view_layer.objects.active = obj
bpy.ops.object.transform_apply(location=False, rotation=True, scale=True)
# 2. Recompute normals
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.mesh.normals_make_consistent(inside=False)
bpy.ops.mesh.remove_doubles(threshold=0.0001)
bpy.ops.object.mode_set(mode='OBJECT')
# 3. Apply modifiers (some exporters keep them, but for portability apply before export)
# Already done via export_apply=True / use_mesh_modifiers=True flags
# 4. Verify mesh stats
mesh = obj.data
print(f"export_check:{obj.name} verts:{len(mesh.vertices)} faces:{len(mesh.polygons)}")
```
### Recipe 8 — Verify exported file
```python
import os
filepath = '/tmp/output.glb'
if not os.path.exists(filepath):
print(f"ERROR:not_found {filepath}")
else:
size_mb = os.path.getsize(filepath) / (1024 * 1024)
print(f"verified:{filepath} {size_mb:.2f}MB")
```
Always verify after export. Use the host's shell tool: `ls -la /tmp/output.glb`.
### Recipe 9 — Unreal collision meshes
Export a separate collider with the render mesh in the **same FBX**. Its name must
match the render mesh exactly: `SM_Chair` → `UCX_SM_Chair_01`, `_02`, and so on.
For existing `GEO-` names, derive the collider name from that actual name; do not
rename the render mesh just to fit an example.
| Prefix | Required shape |
|--------|----------------|
| `UCX_` | One closed, outward-wound convex hull |
| `UBX_` | Rectangular box, not deformed geometry |
| `USP_` | Sphere, not a stretched ellipsoid |
| `UCP_` | Cylinder with hemispherical ends |
Use several simple hulls for concave props: one hull around a table blocks the
space underneath. Derive positions from geometry, not hand-entered guesses.
A face-plane convexity test alone accepts open or empty meshes; it is not an export
gate. Use `scripts/collision_preflight.py` to inspect the **evaluated** collider,
check names/closedness/winding/volume/convexity, and export only the intended objects.
It rejects rather than repairs invalid geometry and preserves selection/mode.
```python
import bpy, runpy
# Substitute the installed helper path; load inside Blender, not ordinary Python.
helpers = runpy.run_path('/absolute/path/to/blender-export/scripts/collision_preflight.py')
mesh = bpy.data.objects['SM_Chair']
colliders = [bpy.data.objects['UCX_SM_Chair_01']]
result = helpers['export_collision_fbx'](mesh, colliders, '/tmp/chair_collision.fbx')
print(result)
```
The primitive checks cover local-axis authored boxes/spheres/capsules; use `UCX_`
for shapes outside those constraints. Boxes/spheres are unsuitable for a
non-uniformly scaled render object. Use a new output path rather than overwriting.
Only one render mesh per collision FBX is supported by this helper.
**Engine-side behavior is not yet validated.** Epic documents these conventions,
but an Unreal import must verify hull count, openings, scale, and collision before
claiming engine acceptance. Missing custom collision may instead trigger automatic
collision generation; do not assume every importer configuration behaves alike.
### Recipe 10 — Multires: bake to the cage, then export
A live Multires modifier may export every evaluated subdivided face or omit sculpt
geometry, depending on exporter settings. For a low-poly asset, bake the detailed
surface to a normal map and export level 0. A 30-face cage at level 8 is approximately
2 million faces.
Use `scripts/multires_bake_export.py` for a single-material target with UVs, an active
Image Texture holding a **Non-Color** bake image, and exactly one enabled Multires
modifier **last in the stack**. The helper sets viewport level **0 before baking**,
keeps it there through FBX export, saves/connects the normal map, and then restores
selection, active object, mode, bake settings, engine, and subdivision levels.
Use a single-user material and bake image. It does not overwrite an existing normal
connection or accepted output files.
```python
import bpy, runpy
helpers = runpy.run_path('/absolute/path/to/blender-export/scripts/multires_bake_export.py')
result = helpers['bake_export_cage'](
bpy.data.objects['GEO-target'], '/tmp/target_normal.png', '/tmp/target_cage.fbx')
print(result)
```
A saved normal map/material connection is the intended change. On failure,
generated files remain failure evidence; the helper restores temporary state and
removes its new normal connection. Use new paths for a retry. To include colliders,
pass an `export_fbx` callback that calls `export_collision_fbx` **inside** this helper's
level-0 context; see [references/unreal-export.md](references/unreal-export.md).
Do not re-export after subdivision levels have been restored, or add ordinary meshes
to the bake selection.
The helper detects the installed 5.x/4.x bake-property layout rather than assuming
a spelling. **Live validation is on Blender 5.1.1; Blender 4.x and Unreal imports
remain unverified.** Normal maps preserve surface shading, not silhouette changes.
## Polycount targets per platform
| Platform | Target | Notes |
|----------|--------|-------|
| Web (glTF) | ≤ 30 000 tris | Mobile-safe |
| Hero web asset | ≤ 60 000 tris | Desktop OK |
| Unity / Unreal hero | 50 000–100 000 tris | High-end |
| Mobile game | ≤ 10 000 tris | Per asset |
| AR USDZ | ≤ 50 000 tris | iOS recommendation |
| 3D print | unlimited | But export size matters |
## Common pitfalls
| Symptom | Fix |
|---------|-----|
| FBX has no textures | Set `embed_textures=True, path_mode='COPY'` |
| Procedural material missing in glTF | Bake to image textures first; use only Principled BSDF |
| Game engine: model rotated 90° | FBX: `axis_up='Y', axis_forward='-Z'`; glTF: `export_yup=True` |
| Game engine: model 100× too large | Apply Transform; check unit scale |
| OBJ won't import elsewhere | Stick to ASCII filenames |
| STL won't print | Make Manifold; recompute normals |
| GLB > 15 MB | Apply Decimate (Recipe 2); reduce textures to 1024×1024 |
| Bone count exceeded | Limit weights to 4 per vertex; reduce bone count |
| Animation didn't export | glTF: `export_animations=True`; FBX: `bake_anim=True` |
| Unreal: missing/wrong custom collision | Check names, convex closed hulls, and same-file selection (Recipe 9); inspect the import in Unreal |
| Multires bake fails with a misleading multi-resolution error | Keep Multires last and isolate the target selection (Recipe 10) |
| Baked normals disagree with exported cage | Set viewport level 0 **before** baking, not just before export |
| FBX unexpectedly contains millions of faces | Viewport `levels` controls evaluated Multires export, not `total_levels` |
| Unreal: no smoothing-group information | Use `mesh_smooth_type='FACE'`; then verify inside Unreal |
## When to load `references/overview.md`
Load when:
- Multi-format batch export needed
- Asset Browser / library override workflow
- USDZ for Apple AR specifics
- Game engine roundtrip troubleshooting (Unity/Unreal-specific quirks)
- LOD generation strategy
The reference covers: per-format pitfalls, asset browser workflow, library overrides for production, USD composition, polycount targets per platform.
© RobLe3 · MIT · RobLe3/cc-blender-skill