3D-grafikk i nettleseren har vært et varmt emne siden de ble introdusert. Men hvis du skulle lage appene dine ved å bruke vanlig gammel WebGL, ville det ta aldre. Det er derfor noen virkelig nyttige biblioteker har kommet. Three.js er en av de mest populære av dem, og i denne serien vil jeg vise deg hvordan du får det beste ut av det for å skape fantastiske 3D-opplevelser for brukerne dine.
Jeg forventer at du skal ha en grunnleggende forståelse av 3D-plass før du begynner å lese denne opplæringen, da jeg ikke vil forklare emner som koordinater og vektorer.
Som vanlig starter vi fra koden du opprettet tidligere. Last ned og pakk ut de eiendelene jeg har gitt, og du vil være klar til å gå.
Før vi starter programmeringsdelen, vil jeg forklare noe som mange mennesker har problemer med. Når du har en modell opprettet i Blender, og du vil eksportere den til Three.js-format, bør du huske følgende:
Når du eksporterer, må du også kontrollere at disse alternativene er valgt i eksportøren: Skinning
, Bones
og Skjelett Animasjon
.
Som med stort sett alt i Three.js, er det veldig enkelt å importere modeller. Det er en spesiell klasse, THREE.JSONLoader
det vil gjøre alt for oss. Selvfølgelig laster det bare JSON-modeller, men det anbefales å bruke dem så jeg vil bare dekke denne lasteren (andre jobber ganske mye på samme måte). La oss initialisere det først:
var loader = ny THREE.JSONLoader; var animasjon;
Ingen argumenter nødvendig. Vi må også definere en variabel for animasjon, så vi kan få tilgang til det senere. Nå kan vi laste modellen:
loader.load ('./ model.js', funksjon (geometri, materialer) var skinnedMesh = nytt THREE.SkinnedMesh (geometri, nytt THREE.MeshFaceMaterial (materials)); skinnedMesh.position.y = 50; skinnedMesh.scale. sett (15, 15, 15); scene.add (skinnedMesh); animere (skinnedMesh););
De laste
Metoden aksepterer to parametre: En bane til modellen og en tilbakeringingsfunksjon. Denne funksjonen vil bli kalt når modellen er lastet (så i mellomtiden kan du vise en lastelinje til brukeren). En tilbakeringingsfunksjon vil bli kalt med to parametre: geometri av modellen og dens materialer (disse eksporteres med den). I tilbakekallingen lager vi nettverket, men denne gangen er det THREE.SkinnedMesh
, som støtter animasjoner.
Deretter flytter vi modellen 50 enheter opp for å sette den på toppen av kuben, skala den 15 ganger (fordi jeg pleier å lage små modeller i Blender) og legge den til scenen. Neste kaller vi animere
funksjon som vil sette opp og spille animasjonen.
Nå setter vi opp animasjonen. Dette er kilden til animere
funksjon:
funksjon animere (skinnedMesh) var materials = skinnedMesh.material.materials; for (var k i materialer) materialer [k] .skinning = true; THREE.AnimationHandler.add (skinnedMesh.geometry.animation); animasjon = ny THREE.Animation (skinnedMesh, "ArmatureAction", THREE.AnimationHandler.CATMULLROM); animation.play ();
Først må vi aktivere skinning (animasjoner) i alle materialene i modellen. Deretter må vi legge til animasjonen fra modell til THREE.AnimationHandler
og opprett THREE.Animation
gjenstand. Parametrene er i følgende rekkefølge: masken for å animere, animasjonsnavnet i modellen og interpoleringstypen (nyttig når du har en komplisert modell som en menneskekropp, hvor du vil at nettverket skal bøyes jevnt). Til slutt spiller vi animasjonen.
Men hvis du åpner nettleseren nå, ser du at modellen ikke beveger seg:
For å fikse dette må vi legge til en linje til vår gjengi
funksjon, like under particleSystem
rotasjon:
hvis (animasjon) animasjon.update (delta);
Dette vil oppdatere tiden på animasjonen, så THREE.AnimationHandler
vet hvilken ramme som skal gjengis. Nå åpner du nettleseren, og du bør se toppkubens bøyning til venstre og til høyre:
Ja, det er en løsning for bare en animasjonssekvens i en modell, men det krever at du redigerer det. Tanken er at du legger til hver animasjon til en sekvens, da når den ene ender, begynner den neste. Etter at du har eksportert modellen din, må du endre animasjonskoden. La oss si at vi har en stående animasjon fra begynnelsen til tredje sekund, og en vandrende animasjon fra tredje sekund til slutt. Så i vår gjengi
funksjon vi må sjekke hvilket sekund animasjonen er, og hvis den når slutten av den nåværende sekvensen, stopper den og spiller den fra begynnelsen:
var currentSequence = 'standing'; funksjon (gjengiv) ... hvis (animasjon) animasjon.update (delta); hvis (currentSequence == 'standing') if (animation.currentTime> 4) animation.stop (); animasjon.spill (false, 0); // spille animasjonen ikke looped, fra 0s annet hvis (currentSequence == 'walking') if (animation.currentTime <= 4 || animation.currentTime > 8) animation.stop (); animasjon.spill (falsk, 4); // spille animasjonen ikke looped, fra 4s ...
Du må huske å starte animasjonene som ikke er sløyfet og fra riktig tid. Dette vil selvfølgelig være buggy hvis brukerens rammeprofil er veldig lav, fordi deltaet blir høyere og animation.currentTime
kan være mye høyere enn grensen for en bestemt sekvens, noe som resulterer i å spille en del av den neste sekvensen. Men det vil bare være merkbart hvis deltasene er omtrent 300-500ms.
Nå for å endre animere
fungere for å spille gangav animasjon, bare legg til disse argumentene til animation.play
funksjon:
animasjon.spill (false, 0);
La oss også la brukeren bytte mellom animasjoner ved hjelp av en nøkkel. Legg til denne koden på slutten av filen, like før render ()
anrop:
document.addEventListener ('keyup', funksjon (e) if (e.keyCode == 'A'.charCodeAt (0)) currentSequence = (currentSequence ==' stående '?' walking ':' standing '); );
Denne teknikken er spesielt nyttig i RPG, men det kan også gjelde for andre sjangere. Det involverer feste et annet objekt til beinet i det animerte objektet: klær, våpen osv.
La oss begynne med å endre vår loader.load
Ring tilbake. Legg til denne 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 (pos); pivot.useQuaternion = true; skinnedMesh.add (pivot);
De punkt
mesh simulerer noe du kanskje vil legge ved et animert objekt. For å få det til å rotere rundt et bestemt punkt, og ikke rundt sentrum, legger vi det til a dreie
objekt og flytte det 50 enheter (halvparten av bredden) til høyre. Vi må skala den til 0,15
, fordi det vil bli lagt til i skinnedMesh
som har en skala av 15
. Til slutt, før det legges til vårt animerte objekt, forteller vi det å bruke quaternions.
I utgangspunktet er quaternions et talesystem, men siden Three.js håndterer alt for oss, trenger du ikke å dykke inn i dette emnet hvis du ikke vil (men hvis du gjør det, ta en titt på Wikipedia-siden). De er vant til å rotere gjenstander uten risiko for gimbal lås.
Nå, i gjengi
funksjon vi må oppdatere objektets posisjon og rotasjon:
pivot.position = nytt THREE.Vector3 (). getPositionFromMatrix (skinnedMesh.bones [2] .skinMatrix); pivot.quaternion.setFromRotationMatrix (skinnedMesh.bones [2] .skinMatrix);
La meg forklare hva som skjer her. Først setter vi stillingen til å være den samme som på det siste benet i modellen. Vi bruker skinMatrix
eiendom for å beregne det. Da bruker vi den samme egenskapen til å beregne kvaternionen for dreie
s rotasjon. Deretter kan du åpne nettleseren, og du bør se den røde strålen som er festet til vår modell:
Jeg håper du har lært noen nye, interessante teknikker fra denne opplæringen. Som alltid, vær så snill å eksperimentere med appen som vi har opprettet. I den neste (og siste) opplæringen i denne serien, viser jeg deg den virkelige kraften til OpenGL / WebGL-Shaders.