Ich versuche eine .obj-Datei zu laden und zeichne sie mit Hilfe von glDrawElements
.
Nun, mit glDrawArrays
funktioniert alles perfekt, aber es ist natürlich ineffizient.
Das Problem, das ich gerade habe, ist, dass eine .obj-Datei mehrere Index-Puffer (für jedes Attribut) verwendet, während OpenGL nur eine verwenden darf. Also muss ich sie entsprechend abbilden.
Es gibt viele Pseudoalgorithmen, und ich habe sogar eine C ++ - Implementierung gefunden. Ich kenne ziemlich viel C ++, aber seltsamerweise hat mir keiner bei meiner Implementierung in Scala geholfen.
Mal sehen:
%Vor% Das val indices: List[Int]
war meine erste naive Einstellung und ist natürlich falsch. Aber fangen wir ganz oben an:
Ich lade die Datei ein und gehe durch sie hindurch. (Ich nehme an, Sie wissen, wie eine .obj-Datei besteht)
Ich lese die Scheitelpunkte, Texturkoordinaten und Normalen ein. Dann komme ich zu den Gesichtern.
Nun hat jedes Gesicht in meinem Beispiel drei Werte v_x, t_y, n_z
, die vertexAtIndexX, textureCoordAtIndexY, normalAtIndexZ
definieren. So definiert jeder von diesen einen Vertex, während ein Tripel von diesen (oder eine Zeile in der Datei) ein Face / Polygon / Triangle definiert.
in val vertices: List[Vertex] = for(face <- faces) yield(new Vertex(positions(face._1-1), textureCoordinates(face._2-1)))
Ich versuche tatsächlich Vertices zu erstellen (eine Case-Klasse, die momentan nur Positionen und Texturkoordinaten enthält und die Normalen für jetzt vernachlässigt)
Das eigentliche Problem ist diese Zeile:
val indices: List[Int] = faces.map(f => f._1-1) // Wrong!
Um die echten Indizes zu erhalten, muss ich im Prinzip anstatt von
tun val vertices: List[Vertex] = for(face <- faces) yield(new Vertex(positions(face._1-1), textureCoordinates(face._2-1)))
und
val indices: List[Int] = faces.map(f => f._1-1) // Wrong!
Pseudocode:
%Vor%Aber ich bin total festgefahren. Ich habe verschiedene Dinge ausprobiert, kann aber keine schöne und saubere Lösung finden, die tatsächlich funktioniert.
Dinge wie:
%Vor% und versuchen, f.distinct
funktionieren nicht, weil es nichts zu unterscheiden gibt, alle Einträge dort sind eindeutig, was total Sinn macht, wenn ich mir die Datei anschaue und das ist es, was der Pseudo-Code mir sagt.
Natürlich müsste ich dann die Indizes entsprechend füllen (vorzugsweise in einem One-Liner und mit viel funktionaler Schönheit)
Aber ich sollte versuchen, Duplikate zu finden, also ... ich bin etwas verblüfft. Ich schätze, ich verwechsle die verschiedenen "Ecken" und "Positionen" zu sehr, mit allen Referenzen.
Also, denke ich falsch, oder ist der Algorithmus / das Denken richtig und ich muss das nur in einem netten, sauberen (und tatsächlich funktionierenden) Scala-Code implementieren?
Bitte, erleuchte mich!
Laut Kommentaren habe ich ein kleines Update vorgenommen:
%Vor%wo noch Gesichter sind:
%Vor%Lustige Tatsache Ich verstehe das natürlich immer noch nicht, weil ich auf diese Weise nie ein Duplikat bekomme!
Das bedeutet, dass combinedIndices
am Ende nur die natürlichen Zahlen wie folgt enthält:
Das ist Javascript (Sorry nicht Scala), aber es ist kommentiert und sollte ziemlich einfach zu konvertieren sein.
%Vor%Die Ausgabe
%Vor%Der JSFiddle Ссылка
Die einzige Sache, die ich ~ anders mache, ist die Verwendung der Zeichenfolge, die einen der Teile eines Gesichts als Schlüssel in meiner indexMap darstellt (zB: "25/32/5").
BEARBEITEN JSFiddle Ссылка Diese Version kombiniert wiederholte Werte für Vertex, Textur und Normal. Dies optimiert OBJ-Dateien, die die gleichen Werte wiederholen, wodurch jedes Gesicht einzigartig wird.
%Vor%Tags und Links scala algorithm opengl .obj index-buffer