WebGL cu modelele Three.js Modele și animație

Grafica 3D în browser a fost un subiect fierbinte de când au fost introduse. Dar dacă v-ați crea aplicațiile utilizând WebGL vechi, ar fi nevoie de vârste. De aceea au apărut câteva biblioteci cu adevărat utile. Three.js este unul dintre cele mai populare dintre ele, iar în această serie vă voi arăta cum să faceți cea mai bună utilizare a acesteia pentru a crea experiențe 3D uimitoare pentru utilizatorii dvs..

Mă aștept să aveți o înțelegere de bază a spațiului 3D înainte de a începe să citiți acest tutorial, deoarece nu voi explica subiecte cum ar fi coordonatele și vectorii.


preparare

Ca de obicei, vom porni de la codul pe care l-ați creat mai devreme. Descărcați și despachetați materialele pe care le-am furnizat și veți fi gata să plecați.


Pasul 1: Un cuvânt despre exportul de modele în Blender

Înainte de a începe partea de programare, voi explica ceva cu care mulți oameni au probleme. Când aveți un model creat în Blender și doriți să-l exportați în format Three.js, trebuie să țineți cont de următoarele:

  • Mai întâi, eliminați părinții. Exportatorul Three.js nu va exporta animații dacă îl părăsiți (acest lucru se aplică și Modificatorului de Armătură)
  • În al doilea rând, vârfuri de grup. Dacă doriți ca osul să se deplaseze pe orice vârf, trebuie să-i grupați și numiți grupul cu numele osului.
  • În al treilea rând, puteți avea o singură animație. Acest lucru poate părea o mare problemă, dar voi explica mai târziu soluția.

De asemenea, atunci când exportați, trebuie să vă asigurați că aceste opțiuni sunt selectate în exportator: jupuială, Oase și Animații scheletice.


Pasul 2: Importul modelului

La fel ca în cazul a trei lucruri din Trei.js, importul de modele este foarte simplu. Există o clasă specială, THREE.JSONLoader care va face totul pentru noi. Bineînțeles că încarcă numai modele JSON, dar este recomandat să le folosiți, astfel încât să acoperim doar acest încărcător (alții funcționează cam la fel). Să o inițializăm mai întâi:

 var loader = nou THREE.JSONLoader; var animație;

Nu sunt necesare argumente. Avem de asemenea nevoie defini o variabilă pentru animație, astfel încât să putem accesa mai târziu. Acum putem încărca modelul:

 loader.load ('./ model.js', functie (geometrie, materiale) var skinnedMesh = nou THREE.SkinnedMesh (geometrie, nou material THREE.MeshFace (materiale)); skinnedMesh.position.y = 50; skinnedMesh.scale. set (15, 15, 15); scene.add (skinnedMesh); animate (skinnedMesh););

sarcină Metoda acceptă doi parametri: o cale către model și o funcție de apel invers. Această funcție va fi apelată atunci când modelul este încărcat (astfel încât între timp să puteți afișa o bară de încărcare pentru utilizator). O funcție de apel invers va fi apelată cu doi parametri: geometria modelului și a materialelor sale (acestea sunt exportate împreună cu acesta). În apelul de apel, creăm plasa - dar de data asta este THREE.SkinnedMesh, care acceptă animații.

Apoi, mutăm modelul de 50 de unități în sus pentru ao pune în partea superioară a cubului nostru, scară-l de 15 ori (pentru că am tendința de a crea modele mici în Blender) și adăugați-l la scenă. Apoi sunăm anima care va configura și va juca animația.


Pasul 3: Animație

Acum am creat animația. Aceasta este sursa pentru anima funcţie:

 funcția animate (skinnedMesh) var materials = skinnedMesh.material.materials; pentru (var k în materiale) materials [k] .skinning = true;  THREE.AnimationHandler.add (skinnedMesh.geometry.animation); animație = nouă THREE.Animation (skinnedMesh, "ArmatureAction", THREE.AnimationHandler.CATMULLROM); animation.play (); 

În primul rând trebuie să permitem jupuirea (animațiile) în toate materialele modelului. Apoi, trebuie să adăugăm animația de la model la THREE.AnimationHandler și creați THREE.Animation obiect. Parametrii sunt în ordinea următoare: mesh-ul pentru animație, numele de animație în model și tipul de interpolare (util atunci când aveți un model complicat, cum ar fi un corp uman, unde doriți ca ochiurile să se îndoaie ușor). În cele din urmă, jucăm animația.

Dar dacă deschideți browser-ul acum, ați vedea că modelul nu se mișcă:

Pentru a rezolva acest lucru, trebuie să adăugăm o linie la adresa noastră face funcția, chiar sub particleSystem rotație:

 dacă (animație) animation.update (delta);

Acest lucru va actualiza timpul de pe animație, deci THREE.AnimationHandler știe care cadru să facă. Acum, deschideți browser-ul și ar trebui să vedeți îndoiala cubului de sus spre stânga și spre dreapta:


Pasul 4: Animații multiple

Da, există o soluție pentru o singură secvență de animație într-un model, dar vă cere să o editați. Ideea este că adăugați fiecare animație într-o singură secvență, atunci când aceasta se termină, începe următoarea. Apoi, după ce ați exportat modelul, trebuie să modificați codul de animație. Să presupunem că avem o animație în picioare de la început până la cea de-a treia secundă și o animație plimbantă de la a treia secundă până la sfârșit. Apoi, în nostru face trebuie să verificăm ce secundă este animația și dacă ajunge la sfârșitul secvenței actuale, opriți-o și jucați-o de la început:

 var currentSequence = 'standing'; funcția (render) ... if (animație) animation.update (delta); dacă (currentSequence == 'în picioare') if (animation.currentTime> 4) animation.stop (); animație.play (false, 0); // redați animația care nu este cuplată, de la 0s altfel dacă (currentSequence == 'mersul') if (animation.currentTime <= 4 || animation.currentTime > 8) animation.stop (); animație.play (falsă, 4); // redați animația care nu este loopată, de la 4s ...

Trebuie să vă amintiți să începeți animațiile care nu au fost derulate și de la momentul potrivit. Acest lucru va fi, desigur, buggy în cazul în care rata cadrelor utilizatorului este foarte scăzută, deoarece delta va fi mai mare și animation.currentTime poate fi mult mai mare decât limita pentru o anumită secvență, ducând la redarea unei părți din secvența următoare. Dar va fi vizibilă numai dacă deltele sunt de aproximativ 300-500ms.

Acum pentru a schimba anima pentru a juca animația de mers pe jos, trebuie doar să adăugați aceste argumente la animation.play funcţie:

 animație.play (false, 0);

De asemenea, permiteți utilizatorului să comute între animații utilizând A cheie. Adăugați acest cod la sfârșitul fișierului, chiar înainte de face() apel:

 document.addEventListener ('keyup', funcția (e) if (e.keyCode == 'A'.charCodeAt (0)) currentSequence = (currentSequence ==' stă în picioare ' );

Pasul 5: Atașați la oase

Această tehnică este utilă în special în RPG-uri, dar se poate aplica și altor genuri. Implica atașare un alt obiect la osul obiectului animat: haine, arme, etc.

Să începem prin modificarea noastră loader.load suna inapoi. Adăugați acest cod sub scene.add (skinnedMesh '):

 item = nou TREI.Mesh (noua THREE.CubeGeometrie (100, 10, 10), nou THREE.MeshBasicMaterial (culoare: 0xff0000)); item.position.x = 50; pivot = nou TREI.Object3D (); pivot.scale.set (0.15, 0.15, 0.15); pivot.add (element); pivot.useQuaternion = adevărat; skinnedMesh.add (pivot);

articol ochiurile de plasă simulează ceva pe care ați putea dori să-l atașați unui obiect animat. Pentru a face să se rotească în jurul unui anumit punct, și nu în jurul centrului, îl vom adăuga la pivot obiect și mutați 50 de unități (jumătate din lățime) spre dreapta. Trebuie să-l ajustăm 0,15, deoarece va fi adăugată la skinnedMesh care are o scară de 15. În cele din urmă, înainte de a fi adăugat la obiectul animat, îi spunem să folosească quaternioane.

Practic, quaternionele sunt un sistem numeric, dar din moment ce Three.js se ocupă de tot ceea ce este pentru noi, nu trebuie să vă plictisiți în acest subiect dacă nu vreți (dar dacă o faceți, aruncați o privire la pagina Wikipedia). Acestea sunt folosite pentru a roti obiectele fără riscul de a fi blocat.

Acum, în face trebuie să actualizăm poziția și rotația obiectului:

 pivot.position = nou THREE.Vector3 (). getPositionFromMatrix (skinnedMesh.bones [2] .skinMatrix); pivot.quaternion.setFromRotationMatrix (skinnedMesh.bones [2] .skinMatrix);

Permiteți-mi să vă explic ce se întâmplă aici. În primul rând, am stabilit poziția să fie aceeași ca pe ultimul os din model. Noi folosim skinMatrix proprietate pentru ao calcula. Apoi folosim aceeași proprietate pentru a calcula cuaternionul pentru pivotde rotație. După aceea, puteți deschide browserul și ar trebui să vedeți fasciculul roșu atașat modelului nostru:


Concluzie

Sper că ați învățat câteva tehnici interesante din acest tutorial. Ca întotdeauna, nu ezitați să experimentați aplicația pe care am creat-o. În următoarea (și ultima) tutorial din această serie, vă voi arăta adevărata putere a OpenGL / WebGL-Shaders.

Cod