WebGL-Grundlagen Teil II

Dieser Artikel baut auf dem in Teil 1 dieser Miniserie eingeführten Framework auf und fügt einen Modell-Importer und eine benutzerdefinierte Klasse für 3D-Objekte hinzu. Außerdem werden Sie mit Animationen und Steuerelementen vertraut gemacht. Es gibt viel zu tun, also fangen wir an!

Dieser Artikel stützt sich stark auf den ersten Artikel. Wenn Sie ihn also noch nicht gelesen haben, sollten Sie dort zuerst beginnen.

Die Art und Weise, wie WebGL Elemente in der 3D-Welt bearbeitet, ist die Verwendung mathematischer Formeln, die als bekannt sind Transformationen. Bevor wir mit dem Aufbau der 3D-Klasse beginnen, werde ich Ihnen einige der verschiedenen Arten von Transformationen und deren Implementierung zeigen.


Transformationen

Beim Arbeiten mit 3D-Objekten gibt es drei grundlegende Transformationen.

  • Ziehen um
  • Skalierung
  • Drehen

Jede dieser Funktionen kann auf der X-, Y- oder Z-Achse ausgeführt werden, sodass insgesamt neun grundlegende Transformationen möglich sind. All dies beeinflusst die 4x4-Transformationsmatrix des 3D-Objekts auf unterschiedliche Weise. Um mehrere Transformationen für dasselbe Objekt ohne überlappende Probleme durchzuführen, müssen Sie die Transformation in der Objektmatrix multiplizieren und nicht direkt auf die Objektmatrix anwenden. Das Umziehen ist am einfachsten, also fangen wir dort an.

Umzug von A.K.A. "Übersetzung"

Das Verschieben eines 3D-Objekts ist eine der einfachsten Transformationen, die Sie ausführen können, da in der 4x4-Matrix ein besonderer Platz dafür vorhanden ist. Es gibt keine Notwendigkeit für Mathe; Geben Sie einfach die X-, Y- und Z-Koordinaten in die Matrix ein und fertig. Wenn Sie die 4x4-Matrix betrachten, handelt es sich um die ersten drei Zahlen in der unteren Reihe. Außerdem sollten Sie wissen, dass sich positives Z hinter der Kamera befindet. Daher setzt ein Z-Wert von -100 das Objekt 100 Einheiten nach innen auf dem Bildschirm. Wir werden dies in unserem Code kompensieren.

Um mehrere Transformationen durchzuführen, können Sie nicht einfach die reale Matrix des Objekts ändern. Sie müssen die Transformation auf eine neue leere Matrix anwenden, die als "." Identität Matrix und multiplizieren Sie es mit der Hauptmatrix.

Die Matrixmultiplikation kann ein bisschen schwierig zu verstehen sein, aber die Grundidee ist, dass jede vertikale Spalte mit der horizontalen Reihe der zweiten Matrix multipliziert wird. Beispielsweise wäre die erste Zahl die erste Zeile, multipliziert mit der ersten Spalte der anderen Matrix. Die zweite Zahl in der neuen Matrix wäre die erste Zeile, multipliziert mit der zweiten Spalte der anderen Matrix und so weiter.

Der folgende Ausschnitt ist der Code, den ich für das Multiplizieren von zwei Matrizen in JavaScript geschrieben habe. Fügen Sie dies Ihrem hinzu .js Datei, die Sie im ersten Teil dieser Serie erstellt haben:

Funktion MH (A, B) Var Sum = 0; für (var i = 0; i < A.length; i++)  Sum += A[i] * B[i];  return Sum;  function MultiplyMatrix(A, B)  var A1 = [A[0], A[1], A[2], A[3]]; var A2 = [A[4], A[5], A[6], A[7]]; var A3 = [A[8], A[9], A[10], A[11]]; var A4 = [A[12], A[13], A[14], A[15]]; var B1 = [B[0], B[4], B[8], B[12]]; var B2 = [B[1], B[5], B[9], B[13]]; var B3 = [B[2], B[6], B[10], B[14]]; var B4 = [B[3], B[7], B[11], B[15]]; return [ MH(A1, B1), MH(A1, B2), MH(A1, B3), MH(A1, B4), MH(A2, B1), MH(A2, B2), MH(A2, B3), MH(A2, B4), MH(A3, B1), MH(A3, B2), MH(A3, B3), MH(A3, B4), MH(A4, B1), MH(A4, B2), MH(A4, B3), MH(A4, B4)]; 

Ich denke nicht, dass dies einer Erklärung bedarf, da es nur die notwendige Mathematik für die Matrixmultiplikation ist. Lassen Sie uns zur Skalierung übergehen.

Skalierung

Das Skalieren eines Modells ist auch ziemlich einfach - es ist eine einfache Multiplikation. Sie müssen die ersten drei Diagonalen mit der Skala multiplizieren. Wiederum ist die Reihenfolge X, Y und Z. Wenn Sie also Ihr Objekt in allen drei Achsen zweimal vergrößern wollen, multiplizieren Sie das erste, sechste und elfte Element in Ihrem Array mit 2.

Drehen

Das Drehen ist die schwierigste Transformation, da es für jede der drei Achsen eine andere Gleichung gibt. Das folgende Bild zeigt die Rotationsgleichungen für jede Achse:

Machen Sie sich keine Sorgen, wenn dieses Bild für Sie keinen Sinn ergibt. Wir werden die JavaScript-Implementierung in Kürze überprüfen.

Es ist wichtig zu wissen, dass es wichtig ist, in welcher Reihenfolge Sie die Transformationen durchführen. unterschiedliche aufträge führen zu unterschiedlichen ergebnissen.

Es ist wichtig zu wissen, dass es wichtig ist, in welcher Reihenfolge Sie die Transformationen durchführen. unterschiedliche aufträge führen zu unterschiedlichen ergebnissen. Wenn Sie Ihr Objekt zuerst bewegen und dann drehen, schwenkt WebGL das Objekt wie eine Fledermaus, anstatt das Objekt an Ort und Stelle zu drehen. Wenn Sie zuerst drehen und dann Ihr Objekt verschieben, befindet sich ein Objekt an der angegebenen Position, aber es zeigt in die von Ihnen eingegebene Richtung. Dies liegt daran, dass die Transformationen um den Ursprungspunkt (0,0,0) in der 3D-Welt durchgeführt werden. Es gibt keine richtige oder falsche Reihenfolge. Es hängt alles von der gewünschten Wirkung ab.

Es können mehrere Transformationen erforderlich sein, um fortgeschrittene Animationen zu erstellen. Wenn Sie beispielsweise möchten, dass eine Tür an den Scharnieren aufschwingt, bewegen Sie die Tür so, dass sich die Scharniere auf der Y-Achse befinden (dh auf der X- und Z-Achse 0). Sie würden sich dann auf der Y-Achse drehen, so dass die Tür an ihren Scharnieren schwingt. Zum Schluss würden Sie es erneut an die gewünschte Stelle in Ihrer Szene verschieben.

Diese Art von Animationen sind für jede Situation etwas maßgeschneiderter, daher werde ich keine Funktion dafür erstellen. Ich werde jedoch eine Funktion mit der grundlegendsten Reihenfolge erstellen: Skalieren, Drehen und dann Bewegen. Dadurch wird sichergestellt, dass sich alles am angegebenen Ort befindet und in die richtige Richtung zeigt.

Nachdem Sie nun ein grundlegendes Verständnis für die Mathematik hinter all dem und die Funktionsweise von Animationen besitzen, erstellen wir einen JavaScript-Datentyp, der unsere 3D-Objekte aufnehmen soll.


GL-Objekte

Denken Sie beim ersten Teil dieser Serie daran, dass Sie drei Arrays benötigen, um ein einfaches 3D-Objekt zu zeichnen: das Vertices-Array, das Triangle-Array und das Textures-Array. Das ist die Basis unseres Datentyps. Wir brauchen auch Variablen für die drei Transformationen auf jeder der drei Achsen. Schließlich benötigen wir Variablen für das Texturbild und geben an, ob das Modell vollständig geladen wurde.

Hier ist meine Implementierung eines 3D-Objekts in JavaScript:

Funktion GLObject (VertexArr, TriangleArr, TextureArr, ImageSrc) this.Pos = X: 0, Y: 0, Z: 0; this.Scale = X: 1,0, Y: 1,0, Z: 1,0; this.Rotation = X: 0, Y: 0, Z: 0; this.Vertices = VertexArr; this.Triangles = TriangleArr; this.TriangleCount = TriangleArr.length; this.TextureMap = TextureArr; this.Image = neues Bild (); this.Image.onload = function () this.ReadyState = true; ; this.Image.src = ImageSrc; this.Ready = false; // Transformationsfunktion hier hinzufügen

Ich habe zwei separate "ready" -Variablen hinzugefügt: eine für das Bild, wenn das Bild fertig ist, und eine für das Modell. Wenn das Bild fertig ist, bereite ich das Modell vor, indem ich das Bild in eine WebGL-Textur konvertiere und die drei Arrays in WebGL-Puffer puffern. Dies beschleunigt unsere Anwendung, da die Daten in jedem Ziehzyklus zwischengespeichert werden sollen. Da wir die Arrays in Puffer konvertieren, müssen Sie die Anzahl der Dreiecke in einer separaten Variablen speichern.

Fügen wir nun die Funktion hinzu, die die Transformationsmatrix des Objekts berechnet. Diese Funktion übernimmt alle lokalen Variablen und multipliziert sie in der zuvor genannten Reihenfolge (Maßstab, Drehung und dann Übersetzung). Sie können mit dieser Reihenfolge für verschiedene Effekte herumspielen. Ersetze das // Transformationsfunktion hier hinzufügen Kommentar mit folgendem Code:

this.GetTransforms = function () // Erstelle eine leere Identitätsmatrix var TMatrix = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1 ]; // Skalierung var Temp = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]; Temp [0] * = this.Scale.X; Temp [5] * = this.Scale.Y; Temp [10] * = this.Scale.Z; TMatrix = MultiplyMatrix (TMatrix, Temp); // Drehen von X Temp = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]; var X = this.Rotation.X * (Math.PI / 180.0); Temp [5] = Math.cos (X); Temp [6] = Math.sin (X); Temp [9] = -1 * Math.sin (X); Temp [10] = Math.cos (X); TMatrix = MultiplyMatrix (TMatrix, Temp); // Drehen von Y Temp = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]; var Y = this.Rotation.Y * (Math.PI / 180.0); Temp [0] = Math.cos (Y); Temp [2] = -1 * Math.sin (Y); Temp [8] = Math.sin (Y); Temp [10] = Math.cos (Y); TMatrix = MultiplyMatrix (TMatrix, Temp); // Drehen von Z Temp = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]; var Z = this.Rotation.Z * (Math.PI / 180.0); Temp [0] = Math.cos (Z); Temp [1] = Math.sin (Z); Temp [4] = -1 * Math.sin (Z); Temp [5] = Math.cos (Z); TMatrix = MultiplyMatrix (TMatrix, Temp); // Moving Temp = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]; Temp [12] = this.Pos.X; Temp [13] = this.Pos.Y; Temp [14] = this.Pos.Z * -1; return MultiplyMatrix (TMatrix, Temp); 

Da sich die Rotationsformeln überlappen, müssen sie einzeln ausgeführt werden. Diese Funktion ersetzt das MakeTransform Funktion aus dem letzten Tutorial, so dass Sie es aus Ihrem Skript entfernen können.


OBJ Importeur

Jetzt, da wir unsere 3D-Klasse erstellt haben, brauchen wir eine Möglichkeit, die Daten zu laden. Wir erstellen einen einfachen Modellimporter, der konvertiert .obj Dateien in die erforderlichen Daten, um eine unserer neu erstellten zu machen GLObject Objekte. Ich benutze die .obj Modellformat, weil es alle Daten in einem Rohformular speichert und sehr gut dokumentiert ist, wie es die Informationen speichert. Wenn Ihr 3D-Modellierungsprogramm den Export nach nicht unterstützt .obj, Dann können Sie immer einen Importer für ein anderes Datenformat erstellen. .obj ist ein Standard-3D-Dateityp; also sollte es kein problem sein. Alternativ können Sie auch Blender herunterladen, eine kostenlose, plattformübergreifende 3D-Modellierungsanwendung, die den Export nach unterstützt .obj

Im .obj Dateien, die ersten beiden Buchstaben jeder Zeile geben an, welche Art von Daten diese Zeile enthält. "v"steht für eine" Vertexkoordinatenzeile ""vt"steht für eine" Texturkoordinaten "-Zeile und"f"ist für die Mappingzeile. Mit dieser Information habe ich folgende Funktion geschrieben:

function LoadModel (ModelName, CB) var Ajax = new XMLHttpRequest (); Ajax.onreadystatechange = function () if (Ajax.readyState == 4 && Ajax.status == 200) // Parse-Modelldaten var Script = Ajax.responseText.split ("\ n"); var Scheitelpunkte = []; var VerticeMap = []; var Dreiecke = []; var Textures = []; var TextureMap = []; var Normals = []; var NormalMap = []; Var Counter = 0;

Diese Funktion akzeptiert den Namen eines Modells und eine Rückruffunktion. Der Callback akzeptiert vier Arrays: den Scheitelpunkt, das Dreieck, die Textur und normale Arrays. Ich habe noch keine Normale behandelt, also kannst du sie einfach ignorieren. Ich werde sie in dem Folgeartikel durchgehen, wenn wir über Beleuchtung sprechen.

Der Importer beginnt mit der Erstellung eines XMLHttpRequest Objekt und definieren seine onreadystatechange Eventhandler. Im Handler teilen wir die Datei in ihre Zeilen auf und definieren einige Variablen. .obj Dateien definieren zuerst alle eindeutigen Koordinaten und definieren dann ihre Reihenfolge. Deshalb gibt es zwei Variablen für die Scheitelpunkte, Texturen und Normalen. Die Zählervariable wird zum Ausfüllen des Dreiecks-Arrays verwendet, weil .obj Dateien definieren die Dreiecke in der Reihenfolge.

Als nächstes müssen wir jede Zeile der Datei durchgehen und prüfen, um welche Art von Zeile es sich handelt:

 for (var I im Skript) var Line = Skript [I]; // If Vertice Line if (LineSubstring (0, 2) == "v") var Zeile = LineSubstring (2) .split (""); Vertices.push (X: parseFloat (Zeile [0]), Y: parseFloat (Zeile [1]), Z: parseFloat (Zeile [2]));  // Texture Line Andernfalls if (LineSubstring (0, 2) == "vt") var Row = LineSubstring (3) .split (""); Textures.push (X: parseFloat (Zeile [0]), Y: parseFloat (Zeile [1]));  // Normalen Zeile else if (LineSubstring (0, 2) == "vn") var Zeile = LineSubstring (3) .split (""); Normals.push (X: parseFloat (Zeile [0]), Y: parseFloat (Zeile [1]), Z: parseFloat (Zeile [2]); 

Die ersten drei Linientypen sind ziemlich einfach. Sie enthalten eine Liste eindeutiger Koordinaten für die Scheitelpunkte, Texturen und Normalen. Alles, was wir tun müssen, ist, diese Koordinaten in ihre jeweiligen Arrays zu schieben. Die letzte Art von Zeile ist etwas komplizierter, da sie mehrere Dinge enthalten kann. Es könnte nur Scheitelpunkte oder Scheitelpunkte und Texturen oder Scheitelpunkte, Texturen und Normalen enthalten. Daher müssen wir für jeden dieser drei Fälle prüfen. Der folgende Code macht dies:

 // Zuordnungszeile else if (LineSubstring (0, 2) == "f") var Row = LineSubstring (2) .split (""); for (var T in Row) // Leere Einträge entfernen if (Row [T]! = "") // Wenn dies ein mehrwertiger Eintrag ist, wenn (Row [T] .indexOf ("/")! = -1) // Die verschiedenen Werte aufteilen var TC = Row [T] .split ("/"); // Increment The Triangles Array Triangles.push (Counter); Counter ++; // füge die Scheitelpunkte ein var index = parseInt (TC [0]) - 1; VerticeMap.push (Vertices [Index] .X); VerticeMap.push (Vertices [Index] .Y); VerticeMap.push (Vertices [Index] .Z); // füge die Texturen ein index = parseInt (TC [1]) - 1; TextureMap.push (Texturen [Index] .X); TextureMap.push (Texturen [Index] .Y); // Wenn dieser Eintrag Normaldaten enthält if (TC.length> 2) // Normalen einfügen index = parseInt (TC [2]) - 1; NormalMap.push (Normalen [Index] .X); NormalMap.push (Normalen [Index] .Y); NormalMap.push (Normalen [Index] .Z);  // Für Zeilen mit nur Scheitelpunkten else Triangles.push (Counter); // Inkrementiere den Triangles Array Counter ++; var index = parseInt (Zeile [T]) - 1; VerticeMap.push (Vertices [Index] .X); VerticeMap.push (Vertices [Index] .Y); VerticeMap.push (Vertices [Index] .Z); 

Dieser Code ist länger als kompliziert. Obwohl ich das Szenario behandelt habe, wo die .obj Datei enthält nur Scheitelpunktdaten, unser Framework erfordert Scheitelpunkte und Texturkoordinaten. Wenn eine .obj Wenn die Datei nur Scheitelpunktdaten enthält, müssen Sie die Texturkoordinatendaten manuell hinzufügen.

Lassen Sie uns nun die Arrays an die Callback-Funktion übergeben und die LoadModel Funktion:

  // Rückgabe der Arrays CB (VerticeMap, Triangles, TextureMap, NormalMap);  Ajax.open ("GET", ModelName + ".obj", true); Ajax.Send (); 

Sie sollten aufpassen, dass unser WebGL-Framework relativ einfach ist und nur Modelle zeichnet, die aus Dreiecken bestehen. Möglicherweise müssen Sie Ihre 3D-Modelle entsprechend bearbeiten. Glücklicherweise verfügen die meisten 3D-Anwendungen über eine Funktion oder ein Plug-In, um Ihre Modelle für Sie zu triangulieren. Ich habe ein einfaches Modell eines Hauses mit meinen grundlegenden Modellierungsfähigkeiten erstellt, und ich werde es in die Quelldateien aufnehmen, die Sie verwenden können, wenn Sie dazu neigen.

Jetzt lass uns das ändern Zeichnen Funktion aus dem letzten Tutorial, um unseren neuen 3D-Objektdatentyp zu integrieren:

this.Draw = Funktion (Modell) if (Model.Image.ReadyState == true && Model.Ready == false) this.PrepareModel (Model);  if (Model.Ready) this.GL.bindBuffer (this.GL.ARRAY_BUFFER, Model.Vertices); this.GL.vertexAttribPointer (this.VertexPosition, 3, this.GL.FLOAT, false, 0, 0); this.GL.bindBuffer (this.GL.ARRAY_BUFFER, Model.TextureMap); this.GL.vertexAttribPointer (this.VertexTexture, 2, this.GL.FLOAT, false, 0, 0); this.GL.bindBuffer (this.GL.ELEMENT_ARRAY_BUFFER, Model.Triangles); // Generate The Perspective Matrix var PerspectiveMatrix = MakePerspective (45, this.AspectRatio, 1, 1000.0); var TransformMatrix = Model.GetTransforms (); // Setze Slot 0 als aktive Textur this.GL.activeTexture (this.GL.TEXTURE0); // Lade die Textur in den Speicher this.GL.bindTexture (this.GL.TEXTURE_2D, Model.Image); // Aktualisieren Sie den Texture Sampler im Fragment-Shader, um Steckplatz 0 zu verwenden. This.GL.uniform1i (this.GL.getUniformLocation (this.ShaderProgram, "uSampler"), 0); // Setze die Perspektive und die Transformationsmatrizen var pmatrix = this.GL.getUniformLocation (this.ShaderProgram, "PerspectiveMatrix"); this.GL.uniformMatrix4fv (pmatrix, false, neuer Float32Array (PerspectiveMatrix)); var tmatrix = this.GL.getUniformLocation (this.ShaderProgram, "TransformationMatrix"); this.GL.uniformMatrix4fv (tmatrix, false, neuer Float32Array (TransformMatrix)); // Draw The Triangles this.GL.drawElements (this.GL.TRIANGLES, Model.TriangleCount, this.GL.UNSIGNED_SHORT, 0); ;

Die neue Zeichenfunktion prüft zunächst, ob das Modell für WebGL vorbereitet wurde. Wenn die Textur geladen wurde, wird das Modell für das Zeichnen vorbereitet. Wir kommen zum PrepareModel Funktion in einer Minute. Wenn das Modell fertig ist, verbindet es seine Puffer mit den Shader und lädt die Perspektiven- und Transformationsmatrizen wie zuvor. Der einzige echte Unterschied besteht darin, dass nun alle Daten aus dem Modellobjekt übernommen werden.

Das PrepareModel Die Funktion konvertiert lediglich die Textur- und Daten-Arrays in WebGL-kompatible Variablen. Hier ist die Funktion; Fügen Sie es direkt vor der Draw-Funktion hinzu:

this.PrepareModel = function (Model) Model.Image = this.LoadTexture (Model.Image); // Konvertiere Arrays in Puffer var Buffer = this.GL.createBuffer (); this.GL.bindBuffer (this.GL.ARRAY_BUFFER, Puffer); this.GL.bufferData (this.GL.ARRAY_BUFFER, neuer Float32Array (Model.Vertices), this.GL.STATIC_DRAW); Model.Vertices = Puffer; Puffer = this.GL.createBuffer (); this.GL.bindBuffer (this.GL.ELEMENT_ARRAY_BUFFER, Puffer); this.GL.bufferData (this.GL.ELEMENT_ARRAY_BUFFER, neuer Uint16Array (Model.Triangles), this.GL.STATIC_DRAW); Model.Triangles = Puffer; Puffer = this.GL.createBuffer (); this.GL.bindBuffer (this.GL.ARRAY_BUFFER, Puffer); this.GL.bufferData (this.GL.ARRAY_BUFFER, neuer Float32Array (Model.TextureMap), this.GL.STATIC_DRAW); Model.TextureMap = Puffer; Model.Ready = true; ;

Nun ist unser Framework fertig und wir können zur HTML-Seite übergehen.


Die HTML-Seite

Sie können alles löschen, was sich im Inneren befindet Skript Tags, da wir den Code dank unseres neuen jetzt noch präziser schreiben können GLObject Datentyp.

Dies ist das vollständige JavaScript:

var GL; var Gebäude; function Ready () GL = neuer WebGL ("GLCanvas", "FragmentShader", "VertexShader"); LoadModel ("House", Funktion (VerticeMap, Triangles, TextureMap) Building = neues GLObject (VerticeMap, Triangles, TextureMap, "House.png"); Building.Pos.Z = 650; // Mein Modell war etwas zu groß Building.Scale.X = 0,5; Building.Scale.Y = 0,5; Building.Scale.Z = 0,5; // Und Rückwärts Building.Rotation.Y = 180; setInterval (Update, 33););  Funktion Update () Building.Rotation.Y + = 0.2 GL.Draw (Gebäude); 

Wir laden ein Modell und teilen der Seite mit, sie etwa dreißig Mal pro Sekunde zu aktualisieren. Das Aktualisieren Diese Funktion dreht das Modell um die Y-Achse, was durch Aktualisierung des Y-Objekts des Objekts erreicht wird Drehung Eigentum. Mein Modell war für die WebGL-Szene etwas zu groß und es war rückwärts, daher musste ich einige Anpassungen im Code vornehmen.

Wenn Sie keine filmische WebGL-Präsentation erstellen, möchten Sie wahrscheinlich einige Steuerelemente hinzufügen. Sehen wir uns an, wie wir unserer Anwendung einige Tastatursteuerungen hinzufügen können.


Tastatursteuerungen

Dies ist nicht wirklich eine WebGL-Technik wie eine native JavaScript-Funktion, aber sie ist praktisch zum Steuern und Positionieren von 3D-Modellen. Sie müssen lediglich einen Ereignis-Listener zu den Tastaturen hinzufügen Taste nach unten oder keyup Ereignisse und prüfen Sie, welche Taste gedrückt wurde. Jeder Schlüssel hat einen speziellen Code. Um herauszufinden, welcher Code dem Schlüssel entspricht, können Sie die Schlüsselcodes beim Auslösen des Ereignisses in der Konsole protokollieren. Gehen Sie zu dem Bereich, in den ich das Modell geladen habe, und fügen Sie den folgenden Code direkt nach dem ein setInterval Linie:

document.onkeydown = handleKeyDown;

Damit wird die Funktion eingestellt handleKeyDown mit dem zu tun haben Taste nach unten Veranstaltung. Hier ist der Code für die handleKeyDown Funktion:

function handleKeyDown (event) // Sie können die nächste Zeile auskommentieren, um den Code der einzelnen Schlüssel herauszufinden. //alert(event.keyCode); if (event.keyCode == 37) // Linke Pfeiltaste Gebäude.Pos.X - = 4;  else if (event.keyCode == 38) // Pfeiltasten nach oben erstellen.Pos.Y + = 4;  else if (event.keyCode == 39) // Rechte Pfeiltaste Gebäude.Pos.X + = 4;  else if (event.keyCode == 40) // Abwärtspfeiltaste Gebäude.Pos.Y - = 4; 

Diese Funktion muss lediglich die Eigenschaften des Objekts aktualisieren. Das WebGL-Framework kümmert sich um den Rest.


Fazit

Wir sind noch nicht fertig! Im dritten und letzten Teil dieser Miniserie werden verschiedene Beleuchtungsarten beschrieben, und Sie erfahren, wie Sie alles mit 2D-Elementen verbinden können!

Vielen Dank für das Lesen und wie immer, wenn Sie Fragen haben, können Sie unten einen Kommentar hinterlassen!