La grafica 3D nel browser è stata un tema caldo da quando sono stati introdotti. Ma se dovessi creare le tue app utilizzando la vecchia WebGL normale, ci vorranno anni. Ecco perché sono state create delle librerie davvero utili. Three.js è uno dei più popolari e in questa serie ti mostrerò come utilizzarlo al meglio per creare incredibili esperienze 3D per i tuoi utenti.
Mi aspetto che tu abbia una conoscenza di base dello spazio 3D prima di iniziare a leggere questo tutorial, poiché non spiegherò argomenti come coordinate e vettori.
Come al solito, inizieremo dal codice che hai creato in precedenza. Scarica e spacchetta i beni che ho fornito e sarai pronto per partire.
Prima di iniziare la parte di programmazione, spiegherò qualcosa con cui molte persone hanno problemi. Quando hai creato un modello in Blender e desideri esportarlo nel formato Three.js, tieni presente quanto segue:
Inoltre, durante l'esportazione devi assicurarti che queste opzioni siano selezionate nell'esportatore: skinning
, Ossatura
e Animazione scheletrica
.
Come con praticamente tutto in Three.js, l'importazione di modelli è molto semplice. C'è una classe speciale, THREE.JSONLoader
quello farà tutto per noi. Naturalmente carica solo i modelli JSON, ma si consiglia di usarli in modo da coprire solo questo caricatore (altri funzionano più o meno allo stesso modo). Inizializziamolo prima:
var loader = new THREE.JSONLoader; animazione var;
Non sono necessari argomenti. Abbiamo anche bisogno di definire una variabile per l'animazione, quindi possiamo accedervi in seguito. Ora possiamo caricare il modello:
loader.load ('./ model.js', function (geometry, materials) var skinnedMesh = new THREE.SkinnedMesh (geometry, new THREE.MeshFaceMaterial (materiali)); skinnedMesh.position.y = 50; skinnedMesh.scale. set (15, 15, 15); scene.add (skinnedMesh); animate (skinnedMesh););
Il caricare
metodo accetta due parametri: un percorso per il modello e una funzione di callback. Questa funzione verrà chiamata quando il modello viene caricato (quindi nel frattempo è possibile visualizzare una barra di caricamento per l'utente). Una funzione di callback sarà chiamata con due parametri: la geometria del modello e dei suoi materiali (questi vengono esportati con esso). Nel callback, stiamo creando la mesh, ma questa volta lo è THREE.SkinnedMesh
, che supporta le animazioni.
Successivamente, spostiamo il modello 50 unità per metterlo in cima al nostro cubo, ridimensionarlo 15 volte (perché tendo a creare piccoli modelli in Blender) e aggiungerlo alla scena. Quindi chiamiamo il animare
funzione che configurerà e riprodurrà l'animazione.
Ora impostiamo l'animazione. Questa è la fonte per il animare
funzione:
funzione animata (skinnedMesh) var materials = skinnedMesh.material.materials; for (var k in materials) materials [k] .skinning = true; THREE.AnimationHandler.add (skinnedMesh.geometry.animation); animation = new THREE.Animation (skinnedMesh, "ArmatureAction", THREE.AnimationHandler.CATMULLROM); animation.play ();
Per prima cosa dobbiamo abilitare skinning (animazioni) in tutti i materiali del modello. Successivamente, dobbiamo aggiungere l'animazione dal modello a THREE.AnimationHandler
e creare il THREE.Animation
oggetto. I parametri sono nel seguente ordine: la mesh da animare, il nome dell'animazione nel modello e il tipo di interpolazione (utile quando si ha un modello complicato come un corpo umano, in cui si desidera che la mesh si pieghi uniformemente). Infine, suoniamo l'animazione.
Ma se apri il browser ora, vedresti che il modello non si muove:
Per risolvere questo problema, dobbiamo aggiungere una linea al nostro rendere
funzione, appena sotto il Particlesystem
rotazione:
if (animation) animation.update (delta);
Questo aggiornerà il tempo sull'animazione, quindi THREE.AnimationHandler
sa quale frame rendere. Ora apri il browser e dovresti vedere il cubo in alto piegato a sinistra ea destra:
Sì, esiste una soluzione alternativa per una sola sequenza di animazione in un modello, ma richiede di modificarla. L'idea è di aggiungere ciascuna animazione a una sequenza, quindi, quando termina quella, inizia la successiva. Successivamente, dopo aver esportato il modello, è necessario modificare il codice di animazione. Diciamo che abbiamo un'animazione permanente dal primo al terzo secondo e un'animazione a piedi dal terzo alla fine. Quindi nel nostro rendere
funzione dobbiamo controllare su quale secondo l'animazione è, e se raggiunge l'ora di fine della sequenza corrente, fermarla e riprodurla dall'inizio:
var currentSequence = 'in piedi'; function (render) ... if (animation) animation.update (delta); if (currentSequence == 'standing') if (animation.currentTime> 4) animation.stop (); animation.play (false, 0); // riproduce l'animazione non in loop, da 0s else if (currentSequence == 'walking') if (animation.currentTime <= 4 || animation.currentTime > 8) animation.stop (); animation.play (false, 4); // riproduce l'animazione non in loop, da 4s ...
Devi ricordarti di avviare le animazioni non in loop e dall'ora corretta. Ovviamente questo sarà bug se il frame rate dell'utente è veramente basso, perché il delta sarà più alto e animation.currentTime
potrebbe essere molto più alto del limite per ogni particolare sequenza, risultando in alcune parti della sequenza successiva. Ma sarà evidente solo se i delta sono circa 300-500ms.
Ora per cambiare il animare
funzione per riprodurre l'animazione a piedi, basta aggiungere questi argomenti al animation.play
funzione:
animation.play (false, 0);
Inoltre, permettiamo all'utente di passare da un'animazione usando il un chiave. Aggiungi questo codice alla fine del file, appena prima del render ()
chiamata:
document.addEventListener ('keyup', function (e) if (e.keyCode == 'A'.charCodeAt (0)) currentSequence = (currentSequence ==' standing '?' walking ':' standing '); );
Questa tecnica è particolarmente utile nei giochi di ruolo, ma può essere applicata anche ad altri generi. Implica allegando un altro oggetto all'osso dell'oggetto animato: vestiti, armi, ecc.
Iniziamo modificando il nostro Loader.load
richiama. Aggiungi questo codice sotto il scene.add (skinnedMesh ')
:
item = new THREE.Mesh (new THREE.CubeGeometry (100, 10, 10), new THREE.MeshBasicMaterial (color: 0xff0000)); item.position.x = 50; pivot = new THREE.Object3D (); pivot.scale.set (0,15, 0,15, 0,15); pivot.add (voce); pivot.useQuaternion = true; skinnedMesh.add (perno);
Il articolo
mesh simula qualcosa che potresti voler collegare a un oggetto animato. Per farlo ruotare attorno a un punto specifico, e non attorno al centro, lo aggiungeremo a perno
oggetto e spostalo di 50 unità (metà della larghezza) a destra. Dobbiamo ridimensionarlo 0.15
, perché sarà aggiunto al skinnedMesh
che ha una scala di 15
. Infine, prima che venga aggiunto al nostro oggetto animato, gli diciamo di usare i quaternioni.
Fondamentalmente, i quaternioni sono un sistema numerico, ma dal momento che Three.js gestisce tutto per noi, non è necessario approfondire questo argomento se non si desidera (ma se lo si fa, dare un'occhiata alla sua pagina di Wikipedia). Sono utilizzati per ruotare gli oggetti senza il rischio di bloccare il giunto cardanico.
Ora, nel rendere
funzione dobbiamo aggiornare la posizione e la rotazione dell'oggetto:
pivot.position = new THREE.Vector3 (). getPositionFromMatrix (skinnedMesh.bones [2] .skinMatrix); pivot.quaternion.setFromRotationMatrix (skinnedMesh.bones [2] .skinMatrix);
Lascia che ti spieghi cosa sta succedendo qui. Innanzitutto, impostiamo la posizione sullo stesso punto dell'ultimo osso nel modello. Stiamo usando il skinMatrix
proprietà per calcolarlo. Quindi usiamo la stessa proprietà per calcolare il quaternion per il perno
La rotazione. Dopodiché, puoi aprire il browser e dovresti vedere il raggio rosso collegato al nostro modello:
Spero che tu abbia imparato alcune nuove tecniche interessanti da questo tutorial. Come sempre, sentiti libero di sperimentare con l'app che abbiamo creato. Nel prossimo (e ultimo) tutorial di questa serie, ti mostrerò il vero potere di OpenGL / WebGL-Shaders.