// Point Wrangle: Inicializa partículas con velocidad // convergente hacia el attractor central vector center = chv("attractor_pos"); // UI param float speed = chf("base_speed"); // 1.0 – 8.0 float chaos = chf("chaos"); // 0.0 – 1.0 // Dirección desde punto hasta centro vector dir = normalize(center - @P); // Añadir perturbación noise para trayectorias orgánicas vector noise_v = (curlnoise(@P * 2.3 + @Time * 0.4) - 0.5) * 2.0 * chaos; // Velocidad base + perturbación @v = (dir + noise_v) * speed; // Masa inversa a la distancia (más rápido al acercarse) float dist = length(center - @P); @v *= fit(dist, 0, 15, 3.0, 0.8); // acelera // Lifetime aleatorio per-partícula @life = 0.0; @nlife = rand(@ptnum * 17.7); @pscale = fit01(rand(@ptnum * 3.14), 0.008, 0.022);
// Point Wrangle: Colorea partículas según // distancia al centro y velocidad actual vector center = chv("attractor_pos"); vector col_far = chv("color_far"); // Brand color vector col_near = chv("color_near"); // White/bloom float glow_exp = chf("glow_exponent"); // 1.5–4.0 float dist = length(center - @P); float t = 1.0 - fit(dist, 0, 12, 0, 1); // Mezcla de color basada en proximidad @Cd = lerp(col_far, col_near, pow(t, glow_exp)); // Alpha = velocidad normalizada (trails más brillantes) float spd = length(@v); @Alpha = fit(spd, 0.5, 8.0, 0.2, 1.0); // Emission strength para Redshift (HDR glow) f@emission = pow(t, 2.0) * chf("emission_mult"); // Attr para shader (Redshift UserData) i@variant = chi("color_variant"); // 0–4
| Parámetro | Tipo | Rango / Default | Descripción |
|---|---|---|---|
| particle_count | int | 500 – 50000 / 8000 | Número total de partículas emitidas por frame |
| emitter_radius | float | 1.0 – 30.0 / 12.0 | Radio de la esfera de emisión (en unidades Houdini) |
| attractor_pos | vector3 | — | Posición del nodo central (por defecto origen {0,0,0}) |
| base_speed | float | 0.5 – 12.0 / 4.5 | Velocidad base de convergencia hacia el centro |
| chaos | float | 0.0 – 1.0 / 0.35 | Cantidad de turbulencia curlnoise en las trayectorias |
| trail_length | int | 2 – 60 / 18 | Frames de historia para el Trail SOP (efecto fibra óptica) |
| color_far | color | — | Color de partículas lejanas al centro (brand color) |
| color_near | color | — | Color de partículas cerca del centro (bloom blanco) |
| emission_mult | float | 0.5 – 10.0 / 3.5 | Multiplicador de intensidad de emisión HDR para glow Redshift |
| glow_exponent | float | 0.5 – 6.0 / 2.2 | Exponente de la curva de glow hacia el centro (pow(t, exp)) |
| color_variant | int (menu) | 0 – 4 / 0 | Índice de paleta PDG: 0=Lime, 1=Blue, 2=Purple, 3=White, 4=Rainbow |
import hou import csv # Ruta al HDA y al CSV de paletas HDA_PATH = "/job/cultiva/hda/cultiva_neuro_v1.0.hda" PALETTES = "/job/cultiva/data/palettes.csv" OUTPUT_DIR = "/job/cultiva/output/renders" # Instalar HDA hou.hda.installFile(HDA_PATH) # Obtener nodo TOP de paletas en la red PDG tops = hou.node("/tasks/cultiva_batch") csv_node = tops.node("csv_palettes") csv_node.parm("csvfile").set(PALETTES) # Cargar paletas y verificar conteo with open(PALETTES) as f: palettes = list(csv.DictReader(f)) print(f"✓ {len(palettes)} variantes de color cargadas") # Cookear la red PDG completa tops.cookWorkItems(block=True) # Reporte de resultados for item in tops.scheduledItems(): variant = item.attribValue("variant_id") frames = item.attribValue("frame_count") time_s = item.attribValue("cook_time") print(f" variant_{variant:02d}: {frames} frames · {time_s:.1f}s") print(f"✓ PDG batch completado → {OUTPUT_DIR}")
cultiva_neuro_v1.0.hda expone solo los parámetros relevantes con UI limpia; el equipo de motion lo usa sin conocer los internals del SOP/DOP.@emission, @variant, @pscale viajan por la red de nodos y el shader Redshift los lee como UserData, manteniendo la pipeline art-directable./cache/popnet_####.bgeo.sc antes del render; re-simular cuesta ~12min, el playback desde cache es instantáneo.