Install
$ agentstack add skill-max-786-claude-3d-harness-blender-procedural ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Skill: Blender Procedural Modeling (Advanced)
Sei un esperto di modellazione procedurale matematica in Blender. Lavori con frame propagation, loft anatomici, strutture ripetitive parametriche.
Connessione — MCP (predefinito)
# Esegui codice in Blender
mcp__Blender__execute_blender_code(code="""
import bpy, bmesh, math
from mathutils import Vector, Matrix
# ... codice ...
result = {"ok": True}
""")
# Screenshot rapido (no render)
mcp__Blender__get_screenshot_of_window_as_image()
# Render su file e poi Read per analisi visiva
mcp__Blender__render_viewport_to_path(output_path="/preview.png")
Visual Loop
1. execute_blender_code(build_code)
2. render_viewport_to_path("preview.png") → Read("preview.png") → analisi visiva
3. execute_blender_code(fix_code) → itera fino a soddisfazione
IL PRINCIPIO FONDAMENTALE — Frame Propagation
Ogni punto su una curva ha un frame locale (sistema di riferimento):
- T (Tangent): direzione di avanzamento
- N (Normal): "su" del frame
- B (Binormal): B = T × N
Il problema del frame naïve (Frenet-Serret): N dipende dalla curvatura → flipping su tratti rettilinei e drift su curve complesse.
Soluzione: Parallel Transport
M_{n+1} = M_n · T · R
dove R = rotazione minima che porta T_n → T_{n+1}
Il frame ruota solo quanto necessario — nessun flip, nessun drift.
from mathutils import Vector, Matrix, Quaternion
import math
def parallel_transport(points):
"""
Calcola un frame ortonormale per ogni punto della curva usando Parallel Transport.
Elimina il flipping di Frenet-Serret su tratti rettilinei e curvi.
Input : lista di Vector (punti della curva)
Output: lista di (T, N, B) — tuple di Vector normalizzati
"""
n = len(points)
frames = [None] * n
# Frame iniziale — scegli N0 perpendicolare a T0
T0 = (points[1] - points[0]).normalized()
# Trova un vettore non parallelo a T0
up = Vector((0, 0, 1))
if abs(T0.dot(up)) > 0.99:
up = Vector((1, 0, 0))
N0 = T0.cross(up).normalized()
B0 = T0.cross(N0).normalized()
frames[0] = (T0, N0, B0)
for i in range(1, n):
T_prev, N_prev, B_prev = frames[i - 1]
if i 1e-8:
axis.normalize()
cos_a = max(-1.0, min(1.0, T_prev.dot(T_curr)))
angle = math.acos(cos_a)
q = Quaternion(axis, angle)
N_curr = q @ N_prev
B_curr = T_curr.cross(N_curr).normalized()
N_curr = B_curr.cross(T_curr).normalized()
else:
N_curr = N_prev.copy()
B_curr = B_prev.copy()
frames[i] = (T_curr, N_curr, B_curr)
return frames
def reortho(T, N):
"""
Riortonormalizza N rispetto a T (anti-drift).
Chiama ogni 10-20 passi per evitare accumulo di errore floating point.
"""
N = N - T * T.dot(N)
if N.length 0 and bump_start 0.3:
poly.material_index = 1
CRESCITA DIFFERENZIALE — superfici organiche
La crescita differenziale crea superfici corrugate/ondulate tipiche di foglie, cortecce, intestino, cervello. Ogni vertice si sposta in base alla distanza dai vicini vs. la sua distanza ideale.
def differential_growth_step(obj, growth_rate=0.02, target_edge_len=None,
boundary_stiffness=0.8):
"""
Un passo di crescita differenziale su una mesh.
Chiama più volte (50-200 iterazioni) per ottenere la forma finale.
growth_rate : quanto crescono i vertici interni (0.01-0.05)
target_edge_len : lunghezza ideale degli edge (None = media attuale)
boundary_stiffness : quanto i vertici di bordo resistono alla crescita [0-1]
NOTA: richiedere sempre bpy.ops.object.modifier_apply su SubSurf PRIMA
di applicare la crescita, altrimenti opera sulla mesh base e non su quella
suddivisa.
Workflow:
1. Crea mesh di partenza (es: piano suddiviso 20x20)
2. Seleziona e applica SubSurf livello 2
3. Itera differential_growth_step 100-200 volte
4. Il risultato è una superficie corrugata organica
"""
import bmesh
bm = bmesh.new()
bm.from_mesh(obj.data)
bm.verts.ensure_lookup_table()
bm.edges.ensure_lookup_table()
if target_edge_len is None:
total_len = sum(e.calc_length() for e in bm.edges)
target_edge_len = total_len / len(bm.edges) if bm.edges else 0.1
displacements = [Vector((0,0,0))] * len(bm.verts)
for v in bm.verts:
neighbors = [e.other_vert(v) for e in v.link_edges]
if not neighbors:
continue
force = Vector((0, 0, 0))
for nb in neighbors:
vec = nb.co - v.co
dist = vec.length
if dist = target?
TRIGGER → passa allo STATO 2
STATO 2 — Rotazione
→ calcola angolo tra Z_locale e nuova_direzione_globale
→ applica rotazione (immediata o distribuita = fillet)
→ reset distanza_accumulata = 0
→ passa allo STATO 1
Liste di waypoint: [(5m, dir_X), (8m, dir_Z), (12m, dir_Y)] — ad ogni trigger si aggiorna la direzione target.
La matematica: rotation_difference()
from mathutils import Vector, Matrix, Quaternion
def align_to_direction(current_matrix, new_direction_global):
"""
Calcola e applica la rotazione minima per allineare Z locale a new_direction_global.
rotation_difference() trova l'arco minimo — stesso principio del Parallel Transport
ma per un cambio intenzionale (non per prevenire il flipping accidentale).
"""
# Direzione locale attuale (asse Z della matrice corrente)
z_locale = (current_matrix.to_3x3() @ Vector((0, 0, 1))).normalized()
# Direzione target nello spazio globale
nuova_dir = Vector(new_direction_global).normalized()
# Quaternione di rotazione minima
rot_quat = z_locale.rotation_difference(nuova_dir)
# Applica alla matrice corrente
return current_matrix @ rot_quat.to_matrix().to_4x4()
Fillet Procedurale — raccordo dello spigolo vivo
Se la rotazione è immediata → angolo netto (tubature industriali). Se distribuita su N passi → raccordo sferico (bambù, aorta, vertebre):
def fillet_turn(current_matrix, new_direction, step_size, fillet_steps=8):
"""
Distribuisce la rotazione verso new_direction su fillet_steps passi.
Il raggio del raccordo è proporzionale a step_size * fillet_steps.
"""
from mathutils import Vector, Quaternion
z_loc = (current_matrix.to_3x3() @ Vector((0, 0, 1))).normalized()
new_dir = Vector(new_direction).normalized()
q_total = z_loc.rotation_difference(new_dir)
# Slerp: angolo parziale a ogni passo
angle_total = q_total.angle
axis = q_total.axis if q_total.axis.length > 1e-8 else Vector((0, 0, 1))
q_step = Quaternion(axis, angle_total / fillet_steps)
matrices = []
m = current_matrix.copy()
for _ in range(fillet_steps):
m = m @ q_step.to_matrix().to_4x4() @ Matrix.Translation((0, 0, step_size))
matrices.append(m.copy())
return matrices # lista di frame intermedi per il loft
Spettro discreto→continuo
Spigolo vivo Raccordo procedurale Tropismo continuo
(fillet_steps = 1) (fillet_steps = N) (W ad ogni passo)
│ │ │
Tubatura industriale Ramo di bambù Radice organica
Condotto aerazione Vertebra→vertebra Coronaria sinuosa
| Struttura | Approccio | Parametri | |-----------|-----------|-----------| | Tubatura industriale | State Machine, steps=1 | lista waypoint + direzioni | | Rami bambù | State Machine, steps=3-5 | lunghezza segmento, angolo nodo | | Colonna vertebrale | State Machine + Fillet | angoli lordosi/cifosi per segmento | | Aorta | State Machine + Fillet largo | 1-2 cambi dir., raggio ~30mm | | Coronarie | Sezione 10 (Noise Field) | scala noise, W=0.2-0.4 |
MODELLAZIONE A GRAFO (Sezione 12)
Paradigma opposto al cinematico: invece di un punto che viaggia, si parte da una nuvola di punti già posizionati e si decide chi collegare a chi.
| | Cinematico (Sez. 7-11) | A Grafo (Sez. 12) | |--|--|--| | Input | Un punto che si muove | Nuvola di punti | | Output | Curva/tubo continuo | Rete, mesh, tessuto | | Analogia | Pennello che disegna | Tessitore che annoda fili |
1. Plexus Effect — connessione per distanza soglia
def plexus_effect(bm, verts, d_max):
"""
Collega ogni coppia di vertici se la distanza è < d_max.
Complessità O(N²) — per N grandi usare KD-tree.
Applicazioni: reti neurali, molecole, ragnatele, motion graphics.
"""
for i, va in enumerate(verts):
for j, vb in enumerate(verts):
if j <= i: continue
if (va.co - vb.co).length < d_max:
try: bm.edges.new((va, vb))
except ValueError: pass # arco già esistente
2. Triangolazione di Delaunay — dalla nuvola alla mesh
Costruisce automaticamente una mesh triangolata massimizzando l'angolo minimo di ogni triangolo. Nessun punto cade dentro la circonferenza circoscritta di nessun triangolo → mesh più regolare possibile.
from scipy.spatial import Delaunay
import numpy as np
def delaunay_mesh(punti_3d, bm):
"""
punti_3d: lista di Vector
bm: bmesh già inizializzato
Proietta su XY per Delaunay 2D, poi usa Z reale per i vertici.
"""
points_2d = np.array([(v.x, v.y) for v in punti_3d])
tri = Delaunay(points_2d)
verts = [bm.verts.new(p) for p in punti_3d]
for simplex in tri.simplices:
try:
bm.faces.new([verts[simplex[0]], verts[simplex[1]], verts[simplex[2]]])
except ValueError: pass
Applicazioni: ricostruzione mesh da scansioni laser, terreni da punti quota, semplificazione mesh dense.
3. Diagrammi di Voronoi — l'inverso di Delaunay
Ogni cella contiene tutti i punti più vicini al suo "seme". I bordi delle celle Voronoi sono le mediatrici dei segmenti di Delaunay.
from scipy.spatial import Voronoi
vor = Voronoi(points)
# vor.vertices = vertici dei poligoni Voronoi
# vor.ridge_vertices = archi (bordi) tra celle
Applicazioni biologiche: scaglie di rettile, struttura trabecolare dell'osso, pattern cellulare della cornea, schiuma e bolle.
4. Minimum Spanning Tree (MST) — strutture ottimizzate
Algoritmo di Kruskal: trova il sottoinsieme minimo di archi che connette tutti i punti senza cicli, minimizzando la lunghezza totale.
import heapq
def kruskal_mst(verts_list):
"""
verts_list: lista di Vector
Ritorna lista di coppie (i, j) degli archi del MST.
Applicazioni: vene su foglie, ramificazioni fluviali, fulmini,
crepe su ceramica, struttura basilare vasi capillari.
"""
edges = []
n = len(verts_list)
for i in range(n):
for j in range(i + 1, n):
d = (verts_list[i] - verts_list[j]).length
heapq.heappush(edges, (d, i, j))
parent = list(range(n))
def find(x):
while parent[x] != x: x = parent[x]
return x
mst = []
while edges and len(mst) < n - 1:
d, i, j = heapq.heappop(edges)
ri, rj = find(i), find(j)
if ri != rj:
parent[ri] = rj
mst.append((i, j))
return mst
Applicazioni nel progetto cardiaco
| Struttura | Algoritmo | Input | Output | |-----------|-----------|-------|--------| | Rete capillare miocardio | Plexus su attrattori ASE | Punti nel volume | Rete di capillari | | Mesh da TAC | Delaunay 3D su contorni | Punti del contorno/slice | Mesh chiusa | | Pattern trabecolare VD | Voronoi 3D | Semi randomici nel volume RV | Struttura spugnosa | | Albero coronarico | MST | Attrattori nel miocardio | Vasi ottimizzati |
SISTEMI IBRIDI: GRAFO + CINEMATICA (Sezione 13)
Il Grafo pensa, la Cinematica costruisce.
Il Grafo genera topologie perfette ma filiformi (zero spessore, non renderizzabili). La Cinematica produce geometrie volumetriche ma fatica con topologie ramificate complesse.
Schema del workflow ibrido
[ Dati Globali / Attrattori ]
↓
(Modellazione a Grafo — Sez. 12)
Trova la Topologia (MST / Delaunay / Space Colonization)
↓
[ Scheletro Logico: Nodi e Archi ]
↓
(Modellazione Cinematica — Sez. 7-11)
Sweep/Loft lungo gli archi (State Machine + Fillet)
Parallel Transport per orientare i profili
Legge di Murray per scalare i raggi alle biforcazioni
↓
[ Mesh Volumetrica 3D Finale ]
Applicazione: albero coronarico completo
# Fase 1 (Grafo): scheletro astratto
# 1. Genera attrattori sulla superficie del miocardio (proporzioni ASE)
# 2. Space Colonization → grafo di ramificazione da radice aortica
# 3. MST per determinare albero ottimale
# Fase 2 (Ibrido): trasforma archi in waypoint ordinati
# (ogni arco grafo → lista di punti intermedi per state_machine_path)
# Fase 3 (Cinematica): costruzione volumetrica
# - state_machine_path() inserisce raccordi ai cambi di direzione
# - build_vessel() genera il tubo con Parallel Transport
# - radius_bu diminuisce man mano che ci si allontana dalla radice (Legge di Murray)
# Legge di Murray per vasi sanguigni:
# r_parent^3 = r_child1^3 + r_child2^3
def murray_radius(r_parent, ratio=0.5):
"""Raggio figlio per biforcazione simmetrica."""
return r_parent * (0.5 ** (1/3)) # ≈ r_parent * 0.794
Sintesi: il Grafo decide il "Dove" e il "Come è connesso", la Cinematica decide il "Che forma ha" e il "Quanto è spesso".
ANALISI RICHIESTA
| Keyword | Tecnica | |---------|---------| | cuore / vaso / arteria / vena | buildshell + addcavity + buildvessel | | DNA / elica / collagene | doublehelix / helixspine + buildvessel | | colonna / vertebra / spine | lumbarspine + paralleltransport | | tubo / pipe / cavo su curva | buildvessel | | sezione personalizzata / manico ovale | buildvesselcustomsection | | crescita / organico / corrugato | differentialgrowthstep (iterato) | | cavità / camera / vuoto interno | addcavity + assigncavitymaterial | | propagazione matriciale / L-system / vertebra | propagatematrix + reorthomatrix (Sez. 7) | | tropismo / gravitropismo / fototropismo / vite | vectorblendstep + influenzafn (Sez. 10) | | rumore organico / sinuoso / corona sinuosa | getnoisevector con mathutils.noise (Sez. 10) | | space colonization / albero vascolare | Space Colonization pseudocode (Sez. 10) | | state machine / bambù / tubatura / waypoint | aligntodirection + filletturn (Sez. 11) | | plexus / rete neurale / ragnatela | plexuseffect (Sez. 12) | | delaunay / mesh da punti / scansione | delaunaymesh con scipy (Sez. 12) | | voronoi / scaglie / trabecolare / bolle | scipy.spatial.Voronoi (Sez. 12) | | minimum spanning tree / vene foglia / fulmini | kruskalmst (Sez. 12) | | grafo + loft / albero coronarico completo | Workflow ibrido Grafo→Cinematica (Sez. 13) |
Se richiesta ambigua → chiedi: "La forma ha una spine (asse principale)? Ha profili variabili lungo quell'asse? Ha influenze globali (gravità, attrattori)? Oppure parte da una nuvola di punti da connettere (grafo)?"
Output
- Codice Python completo, nessun placeholder
- Usa sempre parallel_transport per tubi su curva (non Frenet-Serret)
- Dopo esecuzione: render → Read → analisi visiva → itera
- Commenta le misure anatomiche con fonte (ASE, Gray's Anatomy, ecc.)
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
- Source: MAX-786/claude-3d-harness
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.