Le richieste che riceviamo su questo tema arrivano quasi sempre nello stesso formato: "abbiamo i modelli 3D della macchina, quanto ci vuole a metterli in un visore?".
La risposta onesta è che i modelli 3D che avete non esistono, nel senso che serve. Un file CAD non contiene mesh: contiene superfici matematiche. E il target su cui volete farle girare ha circa 13 millisecondi per disegnare due immagini, una per occhio, ogni volta che qualcuno muove la testa. Tra quelle due cose c'è una pipeline, ed è dove sta il lavoro vero.
Il vincolo che comanda tutto
Un Quest 3 gira a 72 Hz di default e arriva a 90 o 120. A 72 Hz avete 13,9 ms per frame; a 90 Hz ne avete 11,1. In quel tempo il chipset mobile deve disegnare la scena due volte, con due matrici di proiezione leggermente diverse.
Se non ci state dentro, non succede che l'esperienza diventa "meno fluida": succede che il compositore inizia a riproiettare frame vecchi, il mondo si stacca dal movimento della testa e alla persona che ha il visore viene male. Non è un problema estetico, è un problema di persone che si tolgono il visore dopo novanta secondi.
Tutto quello che segue esiste per rispettare quel budget.
Cosa esce davvero da un CAD
Un assieme meccanico nativo (SolidWorks, Inventor, NX) è B-Rep: geometria descritta da superfici analitiche e topologia, non da triangoli. Per portarlo in un motore realtime bisogna tessellare, cioè approssimare quelle superfici con una mesh, e la tolleranza di tessellation decide quanti triangoli escono. Stretta abbastanza da rendere bene un raccordo, produce numeri che si contano in milioni per un singolo sottoassieme.
Poi ci sono i problemi che nessuno racconta.
La gerarchia. Un assieme industriale ha migliaia di nodi, tra cui ogni singola vite, ogni rondella, ogni staffa. In un motore realtime ogni nodo separato è potenzialmente una draw call.
Le normali e le facce. Gli export attraverso STEP o IGES arrivano con normali incoerenti e facce invertite, che a video si traducono in superfici nere o in illuminazione sbagliata sugli spigoli.
Le UV non ci sono. Il CAD non ne ha bisogno, il rendering PBR sì. Vanno generate.
I materiali non ci sono. Nel CAD "acciaio inox" è un'etichetta con una densità, non un set di mappe albedo, metallic, roughness e normal.
La geometria interna. Un modello di progettazione contiene tutto ciò che sta dentro la macchina, comprese parti che nessuno vedrà mai. Sono triangoli che pagate a ogni frame.
Il primo passaggio della pipeline non è "ottimizzare": è decidere cosa esiste nell'applicazione.
Ridurre senza mentire
La decimazione automatica funziona bene sulle superfici estese e male dove la forma porta informazione. Su un carter va benissimo; su una filettatura, su un profilo di taglio o su una zona dove il cliente vuole capire un accoppiamento, produce risultati che un tecnico riconosce come falsi. E il cliente che guarda è un tecnico.
Quindi si lavora a due velocità: decimazione aggressiva sulle parti che fanno volume, sostituzione o rimodellazione selettiva sui dettagli che portano significato. Viti e bulloneria di solito si sostituiscono con versioni a basso conteggio e si instanziano, perché sono migliaia di copie dello stesso oggetto.
Sopra a questo si costruiscono i LOD: versioni a densità decrescente che il motore scambia con la distanza. Su un impianto lungo venti metri, dove il visitatore sta vicino a una macchina per volta, è la singola ottimizzazione con il rapporto costo/beneficio migliore.
Il nemico vero sono le draw call
Su hardware desktop si può essere generosi con il numero di oggetti; su un chipset mobile no. Il costo non è solo nei triangoli, è nel numero di volte che la CPU dice alla GPU di disegnare qualcosa.
Le contromisure sono note e vanno applicate tutte insieme: accorpare le mesh statiche che condividono lo stesso materiale, ridurre il numero di materiali distinti costruendo atlas di texture, usare il GPU instancing per tutto ciò che si ripete, e abilitare lo stereo rendering single-pass instanced, che disegna i due occhi in un passaggio solo invece di due.
Poi c'è l'occlusion culling, che su una fabbrica funziona benissimo: dentro un capannone la maggior parte della scena è nascosta dietro le macchine più vicine.
La luce si cuoce prima
L'illuminazione in tempo reale con ombre dinamiche su tutta la scena è fuori budget su standalone. Quello che si fa è cuocere l'illuminazione statica in lightmap, tenere dinamiche solo le poche luci che devono cambiare, e usare reflection probe per i riflessi delle superfici metalliche, che su un impianto industriale sono più o meno ovunque.
Il baking è anche il momento in cui si scopre che le UV generate automaticamente hanno sovrapposizioni, e che una parte del lavoro di preparazione va rifatta. Succede sempre.
Tenere il legame con il dato
Qui sta la parte che distingue un'applicazione utile da una demo, ed è quella che si rompe per prima quando si ottimizza con l'accetta.
Ogni componente che deve essere interrogabile — puntarlo e vedere la sua scheda tecnica, il codice, i ricambi — deve mantenere un identificativo stabile che sopravvive a decimazione, merge e riorganizzazione della gerarchia. Se accorpate venti mesh in una sola per risparmiare draw call, avete perso la possibilità di selezionarle singolarmente.
La regola che usiamo è semplice: si decide prima quali componenti sono interattivi, quelli restano entità separate con il loro ID, tutto il resto si può accorpare liberamente. Farlo dopo significa rifare l'ottimizzazione.
Nel progetto per Emmepi, dove si punta un componente e si apre la sua scheda tecnica, i dati vengono dal loro materiale tecnico e sono agganciati ai nodi che abbiamo tenuto vivi apposta. Gli esplosi delle parti e le animazioni del flusso di materiali lungo la linea vivono sulla stessa gerarchia.
Su una cosa vale la pena essere pedanti: un esploso deve avere senso meccanico. Se i pezzi si allontanano in direzioni che non corrispondono a come si smonta davvero la macchina, chi la monta per mestiere se ne accorge e smette di fidarsi del resto.
Due target, due build
Chi vende ha due contesti d'uso incompatibili, ed è il motivo per cui in progetti come quello per Surteco abbiamo costruito due applicazioni invece di una.
Il tethered (visore collegato a un PC) serve in showroom e in fiera: la GPU è vera, il budget poligonale è un altro pianeta, si possono tenere illuminazione avanzata e cataloghi ampi caricati in locale.
Lo standalone è quello che il commerciale mette in valigia: nessun cavo, nessun PC, si accende e funziona. In cambio è lui a dettare tutte le regole di cui sopra.
Provare a servire entrambi con un'unica build significa, nella pratica, consegnare la versione standalone anche a chi aveva l'hardware per qualcosa di meglio.
Cosa resta fuori
Per onestà, l'elenco delle cose che questa pipeline non fa.
Non è una simulazione fisica: le animazioni sono cinematiche autorizzate da chi conosce la macchina, non un solutore. Non verifica tolleranze né interferenze, per quello esistono strumenti CAE ed è lì che vanno fatte. E non sostituisce il collaudo: serve a far capire, a far decidere e a formare, che sono già tre cose.
Se avete un assieme che pesa qualche giga e una fiera tra due mesi, la domanda tecnica da cui partire non è quale motore usare, ma quali componenti devono restare interrogabili. Da quella risposta discende quasi tutto il resto.
Costruiamo applicazioni XR e software 3D a partire da dati di progettazione: cosa facciamo con System, il framework Explore che usiamo per le interazioni, oppure scriveteci.