Overview
Scene3D Designer
Designer 3D visuale su route #/scene3d_designer. Consente di comporre una scena
tridimensionale (three.js), associarne gli oggetti alle route scaffoldate
dell'app e pubblicarla in sola lettura tramite lo Scene3D Viewer (#/scene3d_viewer/:scene_key).
Scope
- Authoring di scene 3D con primitive, asset importati e componenti data-driven.
- Materiali PBR, shader personalizzati, luci, ombre e — opzionale — path tracing.
- Renderer selezionabile: WebGL (default) o WebGPU (opt-in), con fallback automatico.
- Binding di ciascun oggetto a una route WUIC (con record opzionale) per pilotare
proprietà visive dai dati e aprire la CRUD della route con doppio click.
- Persistenza della scena su
_wuic_scene3d(scene_json) e riapertura runtime
read-only nel viewer.
Palette
Pannello "Oggetti" (sinistra): trascina/clicca una voce per aggiungere l'oggetto
al centro della scena. Ogni oggetto è un THREE.Object3D con geometria e materiale
serializzabili. Gli helper di viewport (griglia, gizmo, luci) sono marcati
userData.wuicTransient e non vengono mai persistiti.
- Primitive: cubo, sfera, piano, cilindro, cono, toro.
- Gruppo: contenitore per raggruppare e trasformare più oggetti insieme.
- Luci: ambiente, direzionale, puntiforme, faretto (spot).
- Camera: punto di vista autorabile, usato dal viewer e dall'anteprima.
- Testo 3D: testo estruso.
- Mesh Repeater: griglia/anello/carosello di istanze generate dai dati (DATAREPEATER 3D).
- Import asset: modello esterno (glTF/GLB, OBJ, FBX, STL, DAE).
La palette è estendibile da metadata: i tipi custom definiti nella route
scene3d_object_type compaiono automaticamente accanto ai tipi built-in.
Import asset
Oltre alle primitive di palette, il designer importa modelli esterni tramite gli
asset loader di three.js. Formati supportati:
- glTF / GLB (
.gltf,.glb) — formato di trasporto raccomandato (PBR, animazioni). - OBJ (
.obj) — geometria + materiali (.mtl) opzionali. - FBX (
.fbx) — mesh, gerarchie e animazioni. - STL (
.stl) — mesh solida (tipico CAD / stampa 3D). - DAE / COLLADA (
.dae) — scene con gerarchia e materiali.
L'asset importato viene inglobato nel gruppo-contenuto della scena e serializzato
con il resto del payload, così la scena resta autoconsistente nel viewer.
Property panel
Pannello "Proprietà" (destra), attivo sull'oggetto selezionato:
- Nome, Posizione (x/y/z), Rotazione (gradi), Scala, Colore.
- Materiale (PBR): metalness, roughness, emissivo, opacità, wireframe, flat
shading, facce (fronte/retro/doppie). Per il materiale fisico anche
transmission, IOR, spessore e assorbimento volumetrico (vetro colorato).
- Gizmo: alla selezione l'oggetto mostra insieme gli handle di traslazione
(frecce) e di rotazione (anelli). Scorciatoie: g = sposta, r = ruota,
s = scala.
Effetti shader
Ogni mesh può ricevere un effetto shader oltre al materiale standard:
- Effetto JSON (con schema): un piccolo JSON descrive l'effetto (base uv/tinta/normale,
pulsazione, luce, displacement, opacità) e viene compilato per il renderer attivo —
GLSL su WebGL, node-material su WebGPU. Si edita con un editor JSON dotato di
autocompletamento e validazione, con vista alternativa "a struttura".
- Shader GLSL custom: vertex/fragment shader scritti a mano (uniform
uTime
animata). Disponibile solo col renderer WebGL.
Renderer WebGL / WebGPU
- WebGL (default): rendering three.js classico, massima compatibilità.
- WebGPU (opt-in dalla toolbar): renderer a node-materials, attivo se il
browser lo supporta; in caso contrario resta automaticamente su WebGL. La
modalità scelta viene salvata con la scena e ripristinata all'apertura.
- Alcune funzioni restano WebGL-only e vengono segnalate quando il renderer
WebGPU è attivo: gli shader GLSL custom (sostituiti da un materiale di fallback
e ripristinati tornando a WebGL) e il path tracing.
- Designer e viewer sono caricati lazy (
import(...)): three.js resta
code-split e non entra nel bundle iniziale né nel barrel della libreria.
Illuminazione
- Luci di scena: direzionali, puntiformi, spot e ambiente, con ombre morbide.
- Bake luci (per-vertice): cuoce l'illuminazione statica nei vertex color e
passa a un materiale unlit — luce "fissa" indipendente dalle luci runtime. Con
il renderer WebGPU il bake gira su compute shader (ombre incluse), molto più
veloce sulle scene dense.
- Path tracing (renderer WebGL): modalità di anteprima fotorealistica
progressiva con illuminazione globale, ombre morbide e ombre colorate
attraverso i materiali in transmission.
Animazioni e fisica
- Animazioni / timeline: le clip degli asset importati (glTF/GLB) hanno un
transport (play/pausa/stop/scrubber) nel designer e vanno in autoplay nel viewer.
- Fisica (opzionale): authoring per-oggetto (statico/dinamico/kinematico,
forma di collisione, massa, attrito, rimbalzo) con simulazione Play/Stop nel
designer e autoplay opzionale nel viewer.
Camera e anteprima
- Camera autorata: la si posiziona come qualsiasi oggetto; il viewer può
aprirsi dal suo punto di vista (#/scene3d_viewer/:scene_key/:camera_id).
- Anteprima camera: popup real-time con la vista della camera selezionata,
utile per inquadrare prima di pubblicare.
Route binding + click → CRUD
Sezione "Binding rotta" del property panel:
- Rotta: la route metadata WUIC a cui l'oggetto è legato (es.
prodotti). - Record ID (opzionale): binding a un record specifico; vuoto = binding di rotta.
- Mappa campi: associa proprietà visive (etichetta, colore, visibilità) alle
colonne della route, così il viewer applica i dati reali agli oggetti.
- Doppio click su un oggetto bindato nel viewer apre la CRUD della route
(parametric-dialog di edit/detail del record collegato).
Mesh Repeater
Il Mesh Repeater (DATAREPEATER 3D) è un oggetto di palette che, invece di
rappresentare un singolo mesh, genera N istanze dai dati di una route: una
mesh per record, disposte secondo un archetipo di layout (carosello su disco
con frecce di navigazione, griglia, anello). È l'equivalente 3D di una
list-grid: le istanze sono ricostruite dai dati e non vengono serializzate nel
JSON della scena — il viewer le rigenera al caricamento. Il repeater si
sposta/ruota come un gruppo con i gizmo; il pulsante Rigenera (o il toggle
Auto-rigenera) rifà il fetch e ricostruisce le mesh.
Sorgente dati e mappatura
- Rotta + Max record: la route WUIC che alimenta il repeater e quanti
record caricare (prima pagina).
- Sorgente mesh: come si ottiene la mesh di ogni istanza —
- Fisso: la stessa primitiva/asset per tutti i record;
- Colonna: il tipo di primitiva è deciso da una colonna;
- Asset (colonna): modello reale per record, caricato da una colonna di
upload che contiene un file GLB/OBJ/STL (mesh product-like anziché box generici).
- Mappa campi → colonne: binding per-istanza di posizione (Pos X/Y/Z),
rotazione (Rot X/Y/Z), scala, etichetta e colore alle colonne della route.
Layout e trasformazioni
- Archetipo: carosello (disco con frecce avanti/indietro), griglia, anello. Il
carosello espone raggio del disco, colore disco e dimensione delle frecce.
- Scala: normalizzazione automatica (ogni asset portato a dimensione unitaria)
più una scala di layout applicata dall'archetipo — così modelli di dimensioni
molto diverse risultano uniformi.
- Offset verticale (
meshYOffset) e rotazione X/Y/Z (meshRotX/Y/Z) per
ritoccare posa e altezza rispetto al disco; le mesh sono ancorate alla base per
non compenetrare la superficie del carosello.
- Auto-rigenera: toggle di toolbar che rigenera automaticamente (con debounce)
a ogni cambio di proprietà, senza premere Rigenera.
Interazioni (callback JS)
Sezione collassabile in fondo al pannello del repeater: per gli eventi click,
doppio-click e tasto destro su un'istanza si scrive un callback JS (editor
Monaco). Vale sia nel designer sia nel viewer. Il contesto espone:
record— il record dell'istanza colpita (raycast), coi campi già unwrappati;mesh— l'Object3Dcliccato; oltre aevent,scene,camera,THREE;wuic.showItemPopup(opts)— helper per un popup "campi + anteprima mesh";
wuic.closePopup() per chiuderlo.
showItemPopup accetta: mode (1 overlay HTML con anteprima 3D live / 2
pannello 3D nella scena, billboard verso la camera), fields (colonne da mostrare),
title, dimensioni width/height (px o %), panelBg, swap (inverte i lati
mesh/campi), maximizable, verticalPosition/horizontalPosition e
autorotateMesh (false = ruoti il modello col mouse). Nell'anteprima overlay la
rotella fa zoom.
// Callback "click": popup con l'anteprima del modello + alcuni campi del record.
wuic.showItemPopup({
mode: 1,
title: record.StockItemName,
fields: ['StockItemName', 'UnitPrice', 'Brand'],
maximizable: true,
autorotateMesh: false // ispeziona il modello ruotandolo col mouseAnteprime automatiche
Al salvataggio, il designer cattura il canvas GPU già renderizzato e genera
un'anteprima della scena (in modo asincrono, senza rallentare il salvataggio).
L'anteprima compare nell'elenco "Carica scena" accanto al nome, così le scene si
riconoscono a colpo d'occhio. Non serve alcuna configurazione né processo esterno.
Permessi
- Le route designer/viewer richiedono la feature
scene3d-designer
(requireFeature sul route guard): senza la feature abilitata la route non è
raggiungibile.
- Il binding rispetta i permessi della route target: l'apertura CRUD dal viewer
passa dal normale controllo di autorizzazione della route bindata.
- La persistenza usa i metodi
MetaService.saveScene3d/getScene3ds/
loadScene3d (metadata DB, tabella _wuic_scene3d), soggetti all'autenticazione
standard (cookie k-user).
Integrazione client/server
- Client:
- authoring scena, interazioni viewport, gizmo, property panel e binding;
- serializzazione THREE.Object3D.toJSON() in { version:1, scene, bindings?, viewport?, physics? };
- cattura dell'anteprima dal canvas al salvataggio.
- Server:
- upsert/lettura scena su _wuic_scene3d.s3d_scene_json (schema creato/aggiornato
automaticamente al primo uso, cross-DBMS);
- risoluzione dati delle route bindate lato viewer.
Note operative
- Salvare prima di navigare via: un guard
canDeactivateavvisa in presenza di
modifiche non salvate.
- Mantenere nomi oggetto stabili per binding e debugging.
- Verificare che le route bindate esistano nei metadata prima di pubblicare la
scena nel viewer.
- WebGPU richiede un browser recente con supporto attivo; in mancanza, il designer
resta su WebGL senza alcun intervento.
Screenshot

