# Blender Coordinator

> >

- **Type:** Skill
- **Install:** `agentstack add skill-max-786-claude-3d-harness-blender-coordinator`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [MAX-786](https://agentstack.voostack.com/s/max-786)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [MAX-786](https://github.com/MAX-786)
- **Source:** https://github.com/MAX-786/claude-3d-harness/tree/main/library/gaius/blender-coordinator

## Install

```sh
agentstack add skill-max-786-claude-3d-harness-blender-coordinator
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Skill: Blender Coordinator

Sei l'architetto della pipeline di modellazione 3D. Il tuo ruolo è trasformare
una richiesta (vaga o dettagliata) in un **build_plan** eseguibile, coordinando
la ricerca e la modellazione senza sovrapporre le responsabilità.

---

## PIPELINE COMPLETA

```
UTENTE: "voglio creare X"
        │
        ▼
[COORDINATOR — questa skill]
        │
        ├─► STEP 0: valuta la richiesta
        │     Vaga? → chiama blender-research
        │     Dettagliata? → costruisci spec_sheet manuale
        │
        ├─► STEP 1: analizza spec_sheet
        │     Quante parti? Dipendenze? Complessità?
        │
        ├─► STEP 2: scegli SKILL + tecnica per ogni parte
        │     (vedi tabella ROUTING SKILL)
        │
        ├─► STEP 3: pianifica dipendenze e ordine
        │     Chi dipende da chi? Cosa va fatto prima?
        │
        ├─► STEP 4: pianifica materiali e scena
        │     Materiali condivisi? Luci appropriate?
        │
        └─► STEP 5: produci build_plan
```

---

## ROUTING SKILL — Quale skill usare?

| Tipo di geometria / richiesta | Skill da invocare |
|-------------------------------|-------------------|
| Oggetti rigidi, architettura, mobili, prodotti | **blender-arch** |
| Strutture biologiche (cuore, vasi, DNA) | **blender-procedural** |
| Tubi, cavi, pipe lungo una curva 3D | **blender-procedural** |
| Eliche, strutture ripetitive su spine | **blender-procedural** |
| Loft da profili variabili (colonna, vaso anatomico) | **blender-procedural** |
| Crescita differenziale, superfici organiche | **blender-procedural** |
| Scheletro / armatura / rig | **blender-rig** |
| Deformazioni biomeccaniche (nocca, muscolo) | **blender-rig** |
| Pelle su scheletro, weight painting | **blender-rig** |
| FK/IK, animazione articolata | **blender-rig** |
| Forma organica/irregolare (frutta, roccia, terreno) | **blender-sculpt** |
| Dettagli superficie (rughe, pori, bump, dents) | **blender-sculpt** |
| Displacement noise su mesh | **blender-sculpt** |
| Morphing / Shape Key da sculpt | **blender-sculpt** |
| Posizionamento preciso, attach point | **blender-space** |
| Materiali, UV unwrap, baking, PBR texture | **blender-texture** |
| SSS, Fresnel, materiali organici/ceramica/legno | **blender-texture** |
| Bake AO / Normal Map su immagine | **blender-texture** |
| Scatter su superficie, istanziazione non-distruttiva | **blender-geonodes** |
| Curve-to-mesh, pipe via modifier | **blender-geonodes** |
| Displacement / noise via Geometry Nodes | **blender-geonodes** |
| Setup luci, camera, render per product shot | **blender-lighting** |
| Oggetti bianchi/chiari sovraesposti nel render | **blender-lighting** |
| AgX/Filmic look, color management, exposure | **blender-lighting** |
| World/background, contrasto soggetto/sfondo | **blender-lighting** |
| Oggetto che cade / rimbalza senza deformarsi | **blender-physics** (Rigid Body) |
| Oggetto morbido che si schiaccia / deforma | **blender-physics** (Soft Body) |
| Pallone / oggetto gonfiabile con deformazione | **blender-physics** (Cloth + Pressure) |
| Tessuto / vestito / bandiera / tenda | **blender-physics** (Cloth) |
| Vento / turbolenza su Cloth o Soft Body | **blender-physics** (Force Field) |
| Pioggia / polvere / particelle / fumo | **blender-physics** (Particles) |
| Oggetto complesso = parti miste | **più skill in sequenza** |

### Regola di composizione (parti miste):
```
Esempio: "mano animata che tiene un oggetto"
  ├─ geometria mano (skin) → blender-procedural (Generalized Cylinder)
  ├─ scheletro + deformazioni → blender-rig
  └─ oggetto tenuto (spada) → blender-arch (product modeling)
         │
         └─► Socket System (CHILD_OF) → blender-rig
```

---

## STEP 0 — VALUTA LA RICHIESTA

### Criteri per chiamare blender-research:

| Condizione | Azione |
|-----------|--------|
| Richiesta vaga (solo nome oggetto) | → chiama blender-research |
| Mancano dimensioni | → chiama blender-research |
| Mancano colori/materiali | → chiama blender-research |
| Oggetto con parti multiple non descritte | → chiama blender-research |
| Richiesta dettagliata con misure esplicite | → costruisci spec_sheet diretto |
| Oggetto semplice (sfera, cubo, piano) | → vai diretto a blender-arch |

### Livelli di complessità:

```
SEMPLICE  (1 parte, forma primitiva)      → diretto a blender-arch
MEDIO     (2-4 parti, forme standard)     → research + coordinator + arch
COMPLESSO (5+ parti, forme organiche)     → research + coordinator + arch iterativo
```

---

## STEP 1 — ANALISI SPEC_SHEET

Dopo aver ricevuto lo spec_sheet da blender-research (o averlo costruito):

```python
def analizza_spec(spec_sheet):
    """
    Esamina lo spec_sheet e produce una mappa di complessità per parte.
    """
    analysis = {}
    for part_name, part in spec_sheet["parts"].items():
        analysis[part_name] = {
            "shape_family":  classifica_forma(part["shape"]),
            "complexity":    stima_complessita(part),
            "technique":     scegli_tecnica(part),
            "dependencies":  spec_sheet["dependencies"].get(part_name, None),
            "blender_units": converti_blender_units(part),
        }
    return analysis

def classifica_forma(shape_str):
    """Mappa la descrizione testuale a una famiglia geometrica."""
    shape_str = shape_str.lower()
    if any(k in shape_str for k in ["sphere","ball","round","glob"]):
        return "sphere"
    if any(k in shape_str for k in ["cylinder","tube","pipe","rod"]):
        return "cylinder"
    if any(k in shape_str for k in ["cone","taper","truncat"]):
        return "cone"
    if any(k in shape_str for k in ["disc","disk","flat","plate","saucer"]):
        return "disc"
    if any(k in shape_str for k in ["box","cube","rect","block"]):
        return "box"
    if any(k in shape_str for k in ["arc","loop","curve","bend","hook"]):
        return "curve"
    if any(k in shape_str for k in ["organic","irregular","freeform","sculpt"]):
        return "organic"
    if any(k in shape_str for k in ["lathe","revolv","revolution","vase"]):
        return "lathe"
    return "unknown"
```

---

## STEP 2 — METHOD SELECTION FRAMEWORK

Prima di scegliere la tecnica, esegui questo decision tree per ogni parte:

```
Parte da modellare
        │
        ▼
Ha una SPINE (asse principale lungo cui scorre la geometria)?
        │
       SÌ ──────────────────────────────────────────► NO
        │                                              │
La sezione cambia                          Ha forma definita e
significativamente lungo la spine?          parametrizzabile?
   SÌ          NO                           SÌ          NO
    │           │                            │           │
build_shell  build_vessel              arch / lathe    sculpt
(profili     (sezione                  (box/cyl/disc/  (UV sphere
 variabili)   costante)                 revolution)     + brush)
                │
    Ha influenze globali (gravità, attrattori, rumore)?
        SÌ  → vector_blend + tropismo / noise (Sez. 10)
        NO, ha waypoint + cambi direzione discreti?
        SÌ  → state_machine + fillet (Sez. 11)
    Ha biforcazioni / topologia complessa?
        SÌ  → grafo + cinematica ibrida (Sez. 12-13)
```

### Tabella diagnostica rapida

| Segnale diagnostico | Tecnica primaria | Skill |
|--------------------|-----------------|-------|
| Simmetria di rivoluzione (tazza, vaso) | LATHE / bmesh rings | arch |
| Sezione costante su percorso (tubo, cavo) | build_vessel | procedural |
| Sezione variabile su percorso (cuore, osso) | build_shell | procedural |
| Spine + influenza globale (vite rampicante) | vector_blend_step | procedural |
| Spine + waypoint discreti (bambù, tubatura) | state_machine + fillet | procedural |
| Biforcazioni / albero vascolare | grafo (MST) + build_vessel | procedural |
| Box/cylinder/cone con modificatori | CUBE/CYL + bevel/boolean | arch |
| Forma libera senza asse (frutta, roccia) | UV_SPHERE + sculpt | sculpt |
| Ripetizione su superficie | scatter / array | geonodes |
| Deformazione animata | armature + skin | rig |

### Priorità in caso di ambiguità

```
1. Spine presente?         → procedural batte arch
2. Animazione richiesta?   → rig batte tutto il resto
3. Forma organica pura?    → sculpt batte arch
4. Scatter/ripetizione?    → geonodes batte arch (array)
5. Default (forma rigida)  → arch
```

---

## STEP 2b — FALLBACK CHAINS

Quando il metodo primario produce artefatti, segui questa catena prima di ricominciare da zero:

```python
FALLBACK_CHAINS = {

    "LATHE / bmesh_rings": [
        # Artefatto               Fix
        ("topologia sporca ai poli",  "aggiungi ring intermedio vicino all'apice"),
        ("shade stripes su cilindro", "usa obj.data.shade_smooth() NON ops.shade_smooth"),
        ("boolean fallisce",          "subdivide PRIMA del boolean, solver='EXACT'"),
        ("pareti troppo sottili",     "aumenta segments o aggiungi loop_cuts manuali"),
        # Fallback totale: LATHE → build_shell (più controllo sui profili)
    ],

    "build_vessel": [
        ("frame flippa 180°",         "reortho(T, N) ogni 10-20 passi"),
        ("mesh non chiusa alle capi", "aggiungi cap: bm.faces.new(ring_end)"),
        ("sezione deformata",         "riduci step_distance o aumenta segments"),
        ("self-intersection su curva stretta", "riduci radius o aumenta n_steps"),
        # Fallback totale: build_vessel → geonodes curve-to-mesh (più flessibile sui cap)
    ],

    "build_shell": [
        ("profili non allineati tra ring",  "verifica ordine CCW di tutti i ring"),
        ("facce invertite",                 "bm.normal_update() dopo ogni loft_rings"),
        ("transizione brusca tra sezioni",  "interpola frame intermedi con lerp"),
        # Fallback totale: build_shell → sculpt su UV_SPHERE (se forma troppo complessa)
    ],

    "sculpt": [
        ("troppo coarse",        "remesh voxel 0.003-0.005 prima di sculptare"),
        ("normali invertite",    "Recalculate Outside in Edit Mode"),
        ("no UV per texture",    "smart_uv_project() dopo sculpt"),
        # Fallback totale: sculpt → procedural con più rings (se serve parametrizzabilità)
    ],

    "state_machine + fillet": [
        ("spigolo vivo al cambio",    "aumenta fillet_steps (1 → 8)"),
        ("self-intersection al raccordo", "riduci step_size × fillet_steps"),
        ("direzioni non allineate",   "usa rotation_difference() non angoli Euler"),
        # Fallback totale: state_machine → vector_blend (se i cambi sono fluidi non discreti)
    ],

    "boolean": [
        ("mesh non manifold dopo cut",  "valida con obj.data.validate(), usa EXACT"),
        ("SubSurf dopo boolean → artefatti", "SubSurf PRIMA del boolean, poi applicalo"),
        ("cutter troppo piccolo",       "scala cutter 1.01x sull'asse di taglio"),
        # Fallback totale: boolean → displacement/sculpt (per dettagli non critici)
    ],
}
```

### Regola generale di fallback

```
Se il metodo A fallisce dopo 2 tentativi di fix:
  1. Valuta se il problema è geometrico (topologia) → passa a metodo B più controllato
  2. Valuta se il problema è di scala → verifica UNIT = 0.1, converti tutto in BU
  3. Valuta se il problema è di ordine (SubSurf/Boolean) → riparti dall'ordine corretto
  4. Solo dopo: passa alla tecnica alternativa

Mai: eliminare la mesh e rifare senza diagnosticare l'artefatto.
```

---

## STEP 2c — TECNICHE DI MODELLAZIONE

Per ogni parte, scegli la tecnica più appropriata:

| Famiglia | Tecnica consigliata | Quando usarla |
|----------|--------------------|----|
| `sphere` | `UV_SPHERE` + sculpt | Frutta, teste, oggetti rotondi |
| `cylinder` | `CYLINDER` + bevel | Tazze, barattoli, colonne |
| `cone` | `CONE` o bmesh rings | Imbuti, coni, beakers |
| `disc` | `CIRCLE` + fill + extrude | Piatti, coperchi, monete |
| `box` | `CUBE` + loop cuts | Mobili, scatole, edifici |
| `curve` | Bezier/NURBS + bevel | Manici, fili, tubi curvi |
| `organic` | UV_SPHERE + sculpt_brush | Frutti, rocce, forme libere |
| `lathe` | bmesh profile rings | Vasi, bottiglie, oggetti di rivoluzione |
| `flat_sheet` | `PLANE` + subdivide | Foglie, tessuti, piani |

### Pattern di codice per ogni tecnica:

```python
# ── UV_SPHERE (frutta, palloni) ──────────────────────────────────
"""
bpy.ops.mesh.primitive_uv_sphere_add(
    radius=r,          # dal spec_sheet: width_cm/2 * 0.01
    segments=64,       # più segmenti = più definizione
    ring_count=48,
    location=(0,0,0)
)
# Poi: origin_set, safe_place, sculpt per dettagli
"""

# ── CYLINDER (tazze, barattoli) ──────────────────────────────────
"""
# Preferire bmesh rings per controllo preciso del taper:
top_r  = spec["diam_top_cm"]  / 2 * 0.01
bot_r  = spec["diam_bot_cm"]  / 2 * 0.01
height = spec["height_cm"] * 0.01
# → crea rings a z=0 e z=height con raggi diversi
# → bridge per pareti, fill per fondo
"""

# ── CURVE LOOP (manici, fili) ────────────────────────────────────
"""
# Genera N punti sul percorso, estrudi sezione circolare:
for i, pt in enumerate(path_points):
    tang = calcola_tangente(path_points, i)
    ring = crea_ring_perpendicolare(pt, tang, radius, segs)
    rings.append(ring)
# → bridge anelli consecutivi
"""

# ── LATHE / REVOLUTION (vasi, bottiglie) ────────────────────────
"""
# Definisci profilo 2D (lista di (r, z) in cm * 0.01):
profile = [(r0,z0), (r1,z1), ...]
# Genera rings a ogni altezza z con raggio r
# → bridge per pareti, fill per fondo
"""

# ── DISC + INSET (piatti, coperchi) ─────────────────────────────
"""
# Rings concentrici con z diversi per creare depressioni/rilievi:
r_outer = ring(bm, OR, z_top)
r_inner = ring(bm, IR, z_top)
r_dep   = ring(bm, IR, z_top - depth)
bridge(bm, r_outer, r_inner)   # piano
bridge(bm, r_inner, r_dep)     # parete depressione
"""
```

---

## FILOSOFIA MODULARE — Le 3 Fasi Separate

Ogni oggetto complesso va costruito in **3 fasi distinte e non mescolate**.
Mescolare le fasi è la causa più comune di bug di posizionamento e materiali duplicati.

```
FASE 1 — BUILD (ogni modulo costruisce se stesso)
    ├─ input:  spec dimensionali + tecnica
    ├─ output: oggetto nominato, origin al bottom, socket_dict
    └─ regola: nessuna dipendenza da altri oggetti ancora

FASE 2 — ASSEMBLY (il coordinator posiziona i moduli)
    ├─ input:  lista oggetti + socket_dict di ognuno
    ├─ output: scena con tutti gli oggetti posizionati
    └─ regola: usa attach_to() / attach_bounds(), mai location dirette

FASE 3 — MATERIAL (materiali applicati dopo l'assembly)
    ├─ input:  gruppi di materiali + lista oggetti per gruppo
    ├─ output: tutti gli slot materiale assegnati
    └─ regola: un materiale condiviso per gruppo → nessun duplicato
```

### Interfaccia standard di ogni modulo (socket_dict)

Ogni modulo deve restituire un dizionario di socket — punti di attacco in coordinate **locali** dell'oggetto. Il coordinator usa questi socket nella fase di assembly senza dover conoscere l'implementazione interna del modulo.

```python
# Convenzione: ogni funzione build_* ritorna (obj, socket_dict)
# socket_dict: nome_socket → (x, y, z) in coordinate locali dell'oggetto

# Esempio: tazza espresso
def build_cup_body(spec) -> tuple[bpy.types.Object, dict]:
    # ... costruzione ...
    socket_dict = {
        "handle_top":    (top_r, 0, attach_top_z),   # dove si attacca il manico in alto
        "handle_bottom": (top_r, 0, attach_bot_z),   # dove si attacca il manico in basso
        "saucer_center": (0, 0, 0),                   # centro del fondo (contatto piattino)
        "rim_center":    (0, 0, height),              # centro del bordo superiore
    }
    return obj, socket_dict

def build_handle(spec) -> tuple[bpy.types.Object, dict]:
    socket_dict = {
        "attach_top":    (0, 0, loop_h / 2),    # punto di attacco superiore
        "attach_bottom": (0, 0, -loop_h / 2),   # punto di attacco inferiore
    }
    return obj, socket_dict

# FASE 2 — Assembly: il coordinator usa i socket
body_obj, body_sockets   = build_cup_body(spec["

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [MAX-786](https://github.com/MAX-786)
- **Source:** [MAX-786/claude-3d-harness](https://github.com/MAX-786/claude-3d-harness)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-max-786-claude-3d-harness-blender-coordinator
- Seller: https://agentstack.voostack.com/s/max-786
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
