WebGL con Three.js modelli e animazione

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.


Preparazione

Come al solito, inizieremo dal codice che hai creato in precedenza. Scarica e spacchetta i beni che ho fornito e sarai pronto per partire.


Passo 1: una parola sull'esportazione di modelli in Blender

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:

  • Innanzitutto, rimuovi la genitorialità. L'esportatore di Three.js non esporterà alcuna animazione se la lasci (questo vale anche per il modificatore di armatura)
  • Secondo, i vertici di gruppo. Se vuoi che l'osso muri i vertici, devi raggrupparli e nominare il gruppo con il nome dell'osso.
  • Terzo, puoi avere solo un'animazione. Questo potrebbe sembrare un grosso problema, ma ti spiegherò la soluzione più avanti.

Inoltre, durante l'esportazione devi assicurarti che queste opzioni siano selezionate nell'esportatore: skinning, Ossatura e Animazione scheletrica.


Passaggio 2: importazione del modello

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.


Passaggio 3: 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:


Passaggio 4: animazioni multiple

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 '); );

Passaggio 5: allegare all'osso

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 pernoLa rotazione. Dopodiché, puoi aprire il browser e dovresti vedere il raggio rosso collegato al nostro modello:


Conclusione

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.