3D-Grafik OpenGL Texturindexe

Network

Top Contributor
Hallo,

ich probiere mich derzeit mit OpenGL (ES) herum und versuche ein 3DObjekt darzustellen, dass ich aus einer OBJ-Datei lade.
In der OBJ Datei werden aber sowohl eine Indexliste für die Knotenpunkte, als auch eine Indexliste für die Texturkoordinaten angegeben, die die Oberflächen definieren sollen.

Wie kann ich in OpenGL die Texturindexliste eingeben?

Mein jetziger Code sieht so aus:
Java:
public void draw( GL10 gl ) {
		gl.glBindTexture( GL10.GL_TEXTURE_2D, tID );
		
		gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
		gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY );
		
		gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertices); //Liste der Knotenpunktkoordinaten
		gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, colors); //Liste der Texturkoordinaten
		
		//Indexliste der Dreieckoberflächen
		gl.glDrawElements(GL10.GL_TRIANGLES, indices.capacity(), GL10.GL_UNSIGNED_BYTE,indices);
		
		gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
		gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY );
	}

Das Objekt wird richtig angezeigt, die Texturen aber nicht, da die Indexe ja nicht stimmen.

Vielen Dank
Gruß
Network
 
G

Guest2

Gast
Moin,

in OpenGL gibt es nur einen gemeinsamen Index für alle Vertexattribute. Deshalb lässt sich die Datenstruktur aus dem OBJ-File an dieser Stelle leider nicht 1:1 übernehmen. Letztlich musst Du die Arrays anpassen und jedem eindeutigen Tupel (v/vt) einen neuen Index zuweisen.

Oft bietet es sich dann auch an, die Daten direkt für ein VBO und ein IBO aufzubereiten:
(Bei den OpenGL Desktop Varianten wird das so (meistens) empfohlen, bei ES vielleicht auch?)

Ein VBO mit allen Vertexattributen:
Code:
v1_x, v1_y, v1_z, vn1_x, vn1_y, vn1_z, vt1_s, vt1_t, v2_x, v2_y, ...

Und ein IBO mit den Indices:
Code:
1, 2, 3, 2, 3, 4, ...

Viele Grüße,
Fancy
 

Marco13

Top Contributor
(Hätte ich auch vermutet, hab' mich aber nicht getraut :oops: )

Letztlich musst Du die Arrays anpassen und jedem eindeutigen Tupel (v/vt) einen neuen Index zuweisen.

In diesem Satz steckt mehr, als man im ersten Moment meinen würde, wenn man ihn mit dem naiven Wunschdenken eines Anfängers liest ;) Das entscheidende ist: In der OBJ-Datei kann EIN Vertex mit ZWEI (oder mehr) verschiedenen Texturkoordinaten versehen sein.

v 1 1 1
v 2 2 2
v 3 3 3

vt 1 1
vt 2 2
vt 3 3
vt 4 4

f 1//1 2//2 3//3
f 1//1 2//2 4//4

Der Vertex (3,3,3) hat einmal die Texturkoordinaten (3,3) und einmal (4,4). Das rausrechnen ist ein bißchen eklig, hatte ich mal bei den javagl.de - Utilities mit der Methode assertUniqueTextureCoords gemacht.
 

Network

Top Contributor
Ein Danke an den anonymen anonymen Guest2 ;)
Es hilft, nur leider weiss man nie ob derjenige Gegenantworten mitbekommt ;)

@Marco13
Genau da lag auch mein Problem. Ein Vertex mit 2+ Texturekoordinaten.
Wenn man jetzt die einzelnen Vertexe vervielfacht auf die Anzahl der Faces die sie definieren, kommt natürlich die Frage, ob eine Übergabe eines Index-Buffers tatsächlich noch die erhoffte bessere Performance bringt (Wie überall im Internet angepriesen).
Denn anstatt dann ein Indexbuffer zu übergeben, kann man bei OpenGL ja auch gleich zeichnen lassen:
Java:
gl.glDrawArrays(GLXX.GL_TRIANGLES, [...], [...]);
Die Daten liegen ja dann bereits in aufgedröselter geordneter Form vor.

Wie dem auch sei. Ich hoffe durch diese einfachere Methode keine PerformanceEinbußen zu kriegen. Google widerspricht mir schonmal nicht ;)
 
G

Guest2

Gast
Es hilft, nur leider weiss man nie ob derjenige Gegenantworten mitbekommt ;)

Es ist ziemlich wahrscheinlich das ich Antworten lese. ;)


Wie dem auch sei. Ich hoffe durch diese einfachere Methode keine PerformanceEinbußen zu kriegen. Google widerspricht mir schonmal nicht ;)

Das hängt von der konkreten Geometrie ab. Bei einem Würfel mit seinen harten Kanten (senkrecht zueinander stehende vn) und seiner Texturierung (zerrissene vt) bringt der Zugriff über die Indices nur bedingt etwas. Bei einer relativ glatten Struktur, die mit einer großflächigen Textur belegt ist, ist es jedoch so, dass die Eckpunkte eines Dreieckes normalerweise dieselben Attribute aufweisen wie die Eckpunkte seiner direkten Nachbardreiecke.

Greift man dann über die Indices zu, spart das zum einen Platz im Buffer, da eben nur ein Integer zur Adressierung benötigt wird (statt immer die vollen 8 Floats (v, vn, vt)). Zum anderen hat nur dann die Grafikkarte die Möglichkeit effektiv Zwischenergebnisse wiederzuverwenden, da der Cache der Grafikkarte an dieser Stelle mit der VertexID arbeitet. Bei einer Abfolge von z.B. zwei Dreiecken

[c]1, 2, 3, 3, 2, 4[/c]

werden lediglich 4 Vertexdaten komplett durchgerechnet. Bei der Adressierung ohne Indices sind es (unter umständen) jedoch alle 6. Der Aufwand mit den Indices lohnt sich also normalerweise.

(Wenn man es drauf anlegt, sortiert man die Dreiecke innerhalb des IBO noch so, dass der Cache der Grafikkarte optimal ausgenutzt werden kann)


(Hätte ich auch vermutet, hab' mich aber nicht getraut :oops: )

Sonst liegst Du doch auch richtig! ;)


Das rausrechnen ist ein bißchen eklig, hatte ich mal bei den javagl.de - Utilities mit der Methode assertUniqueTextureCoords gemacht.

Wenn man beim Einlesen der OBJ auf OOP pfeift, lässt sich das auch relativ einfach mit ner Map und ein paar Listen dengeln... Da ist die Frage, was einem da lieber ist. ;)


Viele Grüße,
Fancy
 

Ähnliche Java Themen


Oben