WebGL med Three.js Modeller och Animation

3D-grafik i webbläsaren har varit ett hett ämne sedan de introducerades. Men om du skulle skapa dina appar med vanlig gammal WebGL skulle det ta åldrar. Det är därför som några riktigt användbara bibliotek har skett. Three.js är en av de mest populära av dem, och i denna serie kommer jag att visa dig hur du gör det bästa för att skapa fantastiska 3D-upplevelser för dina användare.

Jag förväntar dig att du har en grundläggande förståelse för 3D-rymden innan du börjar läsa den här handledningen, eftersom jag inte kommer att förklara ämnen som koordinater och vektorer.


Förberedelse

Som vanligt börjar vi från koden som du skapade tidigare. Hämta och packa ut de tillgångar jag gav och du är redo att gå.


Steg 1: Ett ord om exporterande modeller i blender

Innan vi börjar programmeringsdelen kommer jag att förklara något som många har problem med. När du har en modell skapad i Blender, och du vill exportera den till Three.js-format, bör du ha följande i åtanke:

  • Ta först bort föräldraskapet. Exportören Three.js exporterar inte några animeringar om du lämnar den (detta gäller även för Armature Modifier)
  • För det andra, grupppunktar. Om du vill att benet ska flytta några vinklar måste du gruppera dem och namnge gruppen med benets namn.
  • För det tredje kan du bara ha en animering. Det kan låta som ett stort problem, men jag kommer att förklara lösningen senare.

När du exporterar måste du också se till att dessa alternativ är valda i exportören: flås, Bones och Skelett Animation.


Steg 2: Importera modellen

Som med ganska mycket allt i Three.js är importmodeller mycket enkla. Det finns en speciell klass, THREE.JSONLoader det kommer att göra allt för oss. Självklart laddar det bara JSON-modeller, men det rekommenderas att använda dem så att jag bara täcker den här lastaren (andra fungerar ganska mycket på samma sätt). Låt oss initialisera det först:

 var loader = ny THREE.JSONLoader; var animation;

Inga argument behövs. Vi behöver också definiera en variabel för animering, så vi kan komma åt det senare. Nu kan vi ladda modellen:

 loader.load ('./ model.js', funktion (geometri, material) var skinnedMesh = nytt THREE.SkinnedMesh (geometri, nytt THREE.MeshFaceMaterial (material)); skinnedMesh.position.y = 50; skinnedMesh.scale. set (15, 15, 15); scene.add (skinnedMesh); animera (skinnedMesh););

De ladda Metoden accepterar två parametrar: en väg till modellen och en återuppringningsfunktion. Denna funktion kommer att ringas när modellen är laddad (så under tiden kan du visa en laddningsrad till användaren). En återuppringningsfunktion kommer att kallas med två parametrar: modellens geometri och dess material (dessa exporteras med den). I återuppringningen skapar vi nätet, men den här gången är det THREE.SkinnedMesh, som stöder animeringar.

Därefter flyttar vi modellen 50 enheter upp för att lägga den på toppen av kuben, skala den 15 gånger (eftersom jag brukar skapa små modeller i Blender) och lägga till den på scenen. Nästa kallar vi animera funktion som kommer att sätta upp och spela animationen.


Steg 3: Animation

Nu sätter vi upp animationen. Detta är källan till animera fungera:

 funktion animera (skinnedMesh) var materials = skinnedMesh.material.materials; för (var k i material) material [k] .skinning = true;  THREE.AnimationHandler.add (skinnedMesh.geometry.animation); animation = nya THREE.Animation (skinnedMesh, "ArmatureAction", THREE.AnimationHandler.CATMULLROM); animation.play (); 

Först måste vi aktivera skinning (animeringar) i alla material i modellen. Därefter måste vi lägga till animeringen från modell till THREE.AnimationHandler och skapa THREE.Animation objekt. Parametrarna är i följande ordning: nätet att animera, animationsnamnet i modellen och interpolationstypen (användbart när du har en komplicerad modell som en mänsklig kropp, där du vill att nätet ska böja smidigt). Slutligen spelar vi animationen.

Men om du öppnar webbläsaren nu ser du att modellen inte rör sig:

För att åtgärda detta måste vi lägga till en rad i vår göra funktion, strax under particleSystem rotation:

 om (animering) animation.update (delta);

Detta uppdaterar tiden på animeringen, så THREE.AnimationHandler vet vilken ram som ska göras. Öppna nu webbläsaren och du ska se toppkubens böjning åt vänster och till höger:


Steg 4: Flera animeringar

Ja, det finns en lösning för endast en animationssekvens i en modell, men det kräver att du redigerar det. Tanken är att du lägger till varje animering i en sekvens, då när den slutar börjar nästa. Därefter måste du ändra animeringskoden när du har exporterat din modell. Låt oss säga att vi har en stående animering från början till tredje sekund, och en animation från tredje sekund till slutet. Då i vår göra funktion vi måste kontrollera vilken sekund animationen är och om den når slutet av den aktuella sekvensen, stoppa den och spela den från början:

 var currentSequence = 'standing'; funktion (render) ... om (animering) animation.update (delta); om (currentSequence == 'standing') if (animation.currentTime> 4) animation.stop (); animation.play (false, 0); // spela animationen inte looped, från 0s annars om (currentSequence == 'walking') if (animation.currentTime <= 4 || animation.currentTime > 8) animation.stop (); animation.play (false, 4); // spela animationen inte looped, från 4s ...

Du måste komma ihåg att starta animationerna som inte loopade och från rätt tid. Detta kommer givetvis att vara buggy om användarens ramhastighet är väldigt låg, eftersom deltaet blir högre och animation.currentTime kan vara mycket högre än gränsen för en viss sekvens, vilket resulterar i att spela en del av nästa sekvens. Men det kommer bara att märkas om deltas är ca 300-500ms.

Nu för att ändra animera funktionen för att spela gånganimationen, lägg bara till dessa argument till animation.play fungera:

 animation.play (false, 0);

Låt oss också tillåta användaren att växla mellan animeringar med hjälp av en nyckel. Lägg till den här koden i slutet av filen, strax före göra() ring upp:

 document.addEventListener ('keyup', funktion (e) if (e.keyCode == 'A'.charCodeAt (0)) currentSequence = (currentSequence ==' stående '?' walking ':' standing '); );

Steg 5: Bifoga till ben

Denna teknik är särskilt användbar i RPG, men den kan också gälla andra genrer. Det involverar fästa Ett annat objekt mot det animerade objektets ben: kläder, vapen, etc..

Låt oss börja med att ändra vår Loader.load ring tillbaka. Lägg till den här koden under scene.add (skinnedMesh '):

 item = new THREE.Mesh (new THREE.CubeGeometry (100, 10, 10), nytt THREE.MeshBasicMaterial (color: 0xff0000)); item.position.x = 50; pivot = nytt THREE.Object3D (); pivot.scale.set (0.15, 0.15, 0.15); pivot.add (item); pivot.useQuaternion = true; skinnedMesh.add (pivot);

De Artikel nät simulerar något du kanske vill bifoga ett animerat objekt. För att rotera runt en viss punkt, och inte runt mitten, lägger vi till en svänga objekt och flytta det 50 enheter (hälften av bredden) till höger. Vi måste skala det till 0,15, eftersom det kommer att läggas till skinnedMesh som har en skala av 15. Slutligen, innan det läggs till i vårt animerade objekt, berättar vi att det ska användas quaternions.

I grund och botten är quaternions ett nummer system, men eftersom Three.js hanterar allt för oss, behöver du inte dyka in i det här ämnet om du inte vill (men om du gör det, ta en titt på Wikipedia-sidan). De används för att rotera föremål utan risk för gimballås.

Nu, i göra funktion vi måste uppdatera objektets position och rotation:

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

Låt mig förklara vad som händer här. Först ställer vi ställningen att vara densamma som på det sista benet i modellen. Vi använder skinMatrix egendom för att beräkna det. Sedan använder vi samma egenskap för att beräkna kvaternionen för svängas rotation. Därefter kan du öppna webbläsaren och du bör se den röda strålen kopplad till vår modell:


Slutsats

Jag hoppas att du har lärt dig några nya intressanta tekniker från den här handledningen. Som alltid kan du experimentera med den app som vi har skapat. I nästa (och sista) handledning i denna serie visar jag dig den verkliga kraften i OpenGL / WebGL-Shaders.