dsh-plugin-blender-3d 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +59 -0
- package/cordis.patch.yml +4 -0
- package/lib/bridge-client.js +109 -0
- package/lib/index.js +117 -0
- package/lib/runtime/blender_ai_bridge/README.md +57 -0
- package/lib/runtime/blender_ai_bridge/__init__.py +159 -0
- package/lib/runtime/blender_ai_bridge/commands.py +617 -0
- package/lib/runtime/blender_ai_bridge/headless_start.py +62 -0
- package/lib/runtime/blender_ai_bridge/server.py +205 -0
- package/lib/runtime/blender_driver.js +192 -0
- package/lib/runtime/headless_bridge.py +575 -0
- package/lib/runtime/requirements.txt +3 -0
- package/package.json +61 -0
- package/skill/blender-3d-modeling/SKILL.md +118 -0
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: blender-3d-modeling
|
|
3
|
+
description: Drive Blender 3D modeling from the harness — create primitives, run boolean CSG, transform, material, modifier, scene query, and export STL/OBJ/PLY/GLTF via a JSON bridge. Works with the Blender add-on (bpy) or a pure-Python headless runtime (trimesh+manifold3d).
|
|
4
|
+
whenToUse: Use when the task involves creating, combining, transforming, or exporting 3D models/meshes, or driving Blender programmatically from the agent. Start the bridge, then send commands through the Node driver or HTTP.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Blender 3D Modeling (AI Bridge)
|
|
8
|
+
|
|
9
|
+
This skill lets the harness agent **drive 3D modeling** through a JSON command
|
|
10
|
+
bridge. There are two interchangeable runtimes speaking the **same protocol**:
|
|
11
|
+
|
|
12
|
+
| Runtime | When to use | How to start |
|
|
13
|
+
|---|---|---|
|
|
14
|
+
| **Blender add-on** (`bpy`) | Real Blender (desktop or `--background`); full power (modifiers, edit mode, render, FBX) | Install `blender_ai_bridge/` in Blender, press **Start** in the N panel; or `blender --background --python blender_ai_bridge/headless_start.py` |
|
|
15
|
+
| **Headless Python** | No Blender installed; pure modeling + CSG + export | `python3 blender_harness/headless_bridge.py --port 13082` |
|
|
16
|
+
|
|
17
|
+
Both expose `POST / {"id","command","args"} -> {"id","result"|"error"}` and
|
|
18
|
+
`GET /health`, `GET /scene`. Default port `13080` (add-on) / choose any free port.
|
|
19
|
+
|
|
20
|
+
## Files (in this workspace)
|
|
21
|
+
|
|
22
|
+
- `blender_ai_bridge/` — the Blender add-on (`__init__.py`, `server.py`,
|
|
23
|
+
`commands.py`, `headless_start.py`, `README.md`). Install into Blender via
|
|
24
|
+
Edit > Preferences > Add-ons > Install.
|
|
25
|
+
- `blender_harness/headless_bridge.py` — pure-Python runtime (trimesh +
|
|
26
|
+
manifold3d). No Blender required.
|
|
27
|
+
- `blender_harness/blender_driver.js` — Node.js harness driver (zero deps,
|
|
28
|
+
Node >= 18). Works with either runtime.
|
|
29
|
+
|
|
30
|
+
## Starting a bridge
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
# Headless (works in this container right now):
|
|
34
|
+
python3 /workspace/blender_harness/headless_bridge.py --port 13082 &
|
|
35
|
+
|
|
36
|
+
# Real Blender, headless:
|
|
37
|
+
AIB_PORT=13080 blender --background --python /workspace/blender_ai_bridge/headless_start.py
|
|
38
|
+
|
|
39
|
+
# Real Blender, GUI: install the add-on, open N panel > AI Bridge > Start.
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Verify: `curl -s http://127.0.0.1:13082/health` → `{"ok":true,...}`.
|
|
43
|
+
|
|
44
|
+
## Driving modeling from the agent
|
|
45
|
+
|
|
46
|
+
Prefer the Node driver (typed API, OOM-safe file reads):
|
|
47
|
+
|
|
48
|
+
```js
|
|
49
|
+
const { BlenderBridge } = require('/workspace/blender_harness/blender_driver.js');
|
|
50
|
+
const b = new BlenderBridge('http://127.0.0.1:13082');
|
|
51
|
+
await b.sceneClear({ all: true });
|
|
52
|
+
await b.box('body', 4, 4, 4);
|
|
53
|
+
await b.sphere('hole', 1.5);
|
|
54
|
+
await b.cut('carved', 'body', 'hole', true); // boolean difference, remove tool
|
|
55
|
+
await b.transform({ name: 'carved', location: [0, 0, 1] });
|
|
56
|
+
const stl = await b.exportModel({ format: 'stl', path: '/tmp/out.stl', names: ['carved'] });
|
|
57
|
+
const bytes = await b.readFile(stl.file_path); // read geometry from disk
|
|
58
|
+
console.log(await b.scene());
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Or one-shot via CLI:
|
|
62
|
+
```bash
|
|
63
|
+
node /workspace/blender_harness/blender_driver.js --url http://127.0.0.1:13082 demo
|
|
64
|
+
node /workspace/blender_harness/blender_driver.js --url http://127.0.0.1:13082 cmd create_shape '{"type":"torus","major_radius":2,"minor_radius":0.3,"name":"ring"}'
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Or raw HTTP:
|
|
68
|
+
```bash
|
|
69
|
+
curl -X POST http://127.0.0.1:13082/ -H 'Content-Type: application/json' \
|
|
70
|
+
-d '{"id":1,"command":"create_shape","args":{"type":"cylinder","radius":1,"height":3,"name":"cyl"}}'
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Command catalog
|
|
74
|
+
|
|
75
|
+
| command | key args |
|
|
76
|
+
|---|---|
|
|
77
|
+
| `create_shape` | `type` ∈ box/sphere/ico_sphere/cylinder/cone/torus/plane/grid/circle/monkey + dims + `location`/`rotation`/`scale`/`name` |
|
|
78
|
+
| `boolean` | `target`, `tool`/`tools`, `operation` ∈ union/difference/intersect, `apply`, `remove_tools`, `name` |
|
|
79
|
+
| `transform` | `name`, `location`, `rotation` (+`rotation_degrees`), `scale` |
|
|
80
|
+
| `duplicate` / `delete` / `rename` | `name`, `count`/`offset`, `names`, `new_name` |
|
|
81
|
+
| `material` | `action` ∈ create/assign/list + `color`, `metallic`, `roughness` |
|
|
82
|
+
| `modifier` | `action` ∈ add/remove/list + `type` ∈ subsurf/bevel/array/mirror/solidify + `params`, `apply` |
|
|
83
|
+
| `mesh_edit` | `name`, `action` ∈ subdivide/extrude/inset/recalc_normals |
|
|
84
|
+
| `scene` / `selection` / `scene_clear` | lightweight query (no mesh data in JSON) |
|
|
85
|
+
| `camera` / `light` / `render` | camera/light/render-to-file (Blender add-on only) |
|
|
86
|
+
| `export` | `format` ∈ stl/obj/ply/fbx/gltf/glb/blend + `path`/`names` → returns **`file_path`** |
|
|
87
|
+
| `import` | `format` + `path` |
|
|
88
|
+
| `script` / `command` / `document` | run Python / Blender operator / new-save-open |
|
|
89
|
+
|
|
90
|
+
## Critical rules
|
|
91
|
+
|
|
92
|
+
1. **Never expect mesh bytes in the JSON.** `export` returns `file_path` only.
|
|
93
|
+
Read the file from disk (`b.readFile(res.file_path)`). This avoids Node OOM
|
|
94
|
+
on large meshes.
|
|
95
|
+
2. `scene`/`selection` return **lightweight summaries** (name, type, location,
|
|
96
|
+
vert/face counts) — never full geometry.
|
|
97
|
+
3. In the Blender add-on, all `bpy.ops` run on the **main thread** (the server
|
|
98
|
+
marshals via `bpy.app.timers`); do not call bpy from a request thread.
|
|
99
|
+
4. The headless runtime bakes transforms into the mesh so booleans are correct
|
|
100
|
+
in world space.
|
|
101
|
+
5. CSG backend: headless uses `manifold3d` (watertight results). The Blender
|
|
102
|
+
add-on uses the Boolean modifier (`EXACT` solver on 4.0+).
|
|
103
|
+
|
|
104
|
+
## Version compatibility
|
|
105
|
+
|
|
106
|
+
- Add-on loads on Blender 3.0+ (`bl_info.blender: (3,0,0)`).
|
|
107
|
+
- Export auto-adapts: 4.1+ `wm.stl_export`/`wm.obj_export` vs 3.x
|
|
108
|
+
`export_mesh.stl`/`export_scene.obj`.
|
|
109
|
+
- Boolean solver set only on 4.0+.
|
|
110
|
+
|
|
111
|
+
## Quick verification (run in this workspace)
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
python3 /workspace/blender_harness/headless_bridge.py --port 13082 &
|
|
115
|
+
sleep 1
|
|
116
|
+
node /workspace/blender_harness/blender_driver.js --url http://127.0.0.1:13082 demo
|
|
117
|
+
# expect: DEMO OK + /workspace/demo_cli.stl written
|
|
118
|
+
```
|