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.
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å.
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:
När du exporterar måste du också se till att dessa alternativ är valda i exportören: flås
, Bones
och Skelett Animation
.
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.
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:
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 '); );
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änga
s rotation. Därefter kan du öppna webbläsaren och du bör se den röda strålen kopplad till vår modell:
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.