OpenGL – Difficoltà dei buffer di indice

Ho un formato di file personalizzato che ha tutte le informazioni necessarie per una mesh 3D (esportata da 3ds Max). Ho estratto i dati per vertici, indici dei vertici e normali.

Passo a OpenGL i dati dei vertici, gli indici dei vertici e i dati normali e rendo la mesh con una chiamata a glDrawElements(GL_TRIANGLES,...)

Tutto sembra giusto ma le normali. Il problema è che le normali hanno indici diversi. E poiché OpenGL può usare solo un buffer di indice, usa quel buffer di indice per i vertici e le normali.

Sarei davvero grato se potesse suggerirmi come affrontare questo problema.

È importante notare che i dati vertici / normali non sono “ordinati” e quindi non sono in grado di utilizzare la funzionalità di glDrawArrays(GL_TRIANGLES,...) – la mesh non viene visualizzata correttamente.

C’è un modo / algoritmo che posso usare per ordinare i dati in modo che la mesh possa essere disegnata correttamente con glDrawArrays(GL_TRIANGLES,..) ? Ma anche se c’è un algoritmo, c’è un altro problema – Dovrò duplicare alcuni vertici (perché il mio vertice buffer è costituito da vertici univoci – per esempio se hai un cubo il mio buffer avrà solo 8 vertici) e non sono sicuro come farlo.

I tipi di file che usano indici separati per i vertici e le normali non corrispondono al modello del vertice OpenGL molto direttamente. Come hai notato, OpenGL utilizza un singolo set di indici.

Quello che devi fare è creare un vertice OpenGL per ogni coppia univoca (indice dei vertici, indice normale) nel tuo input. Questo richiede un po ‘di lavoro, ma non è terribilmente difficile, soprattutto se si utilizzano strutture dati disponibili. Una map STL funziona bene per questo, con la coppia (indice vertice, indice normale) come chiave. Non ho intenzione di fornire un codice C ++ completo, ma posso delinearlo.

Diciamo che hai già letto i tuoi vertici in una sorta di struttura di dati array / vettoriale inVertices , dove le coordinate per vertice con indice vertice vertexIdx sono memorizzate in inVertices[vertexIdx] . Stessa cosa per le normali, dove il vettore normale con indice normalIdx è memorizzato in inNormals[normalIdx] .

Ora puoi leggere una lista di triangoli, con ogni vertexIdx di ciascun triangolo dato sia da un vertexIdx che da un normalIdx . Costruiremo un nuovo array / vettore combinedVertices che contenga sia il vertice che le normali coordinate, oltre a una nuova lista di indici combinedIndices . Pseudo codice:

 nextCombinedIdx = 0 indexMap = empty loop over triangles in input file loop over 3 corners of triangle read vertexIdx and normalIdx for the corner if indexMap.contains(key(vertexIdx, normalIdx)) then combinedIdx = indexMap.get(key(vertexIdx, normalIdx)) else combinedIdx = nextCombinedIdx indexMap.add(key(vertexIdx, normalIdx), combinedIdx) nextCombinedIdx = nextCombinedIdx + 1 combinedVertices.add(inVertices[vertexIdx], inNormals[normalIdx]) end if combinedIndices.add(combinedIdx) end loop end loop 

Sono riuscito a farlo senza passare il buffer dell’indice a OpenGL con glDrawArrays(GL_TRIANGLES,..) Quello che ho fatto è il seguente: Riempire un array di vertici, array di indici di vertici, array di ordinali e array di indici normali. Poi ho creato un nuovo vertice e array normali con dati ordinati e li ho passati ad OpenGL.

 for i = 0; i < vertexIndices.size(); ++i newVertexArray[i] = oldVertexArray[vertexIndices[i]]; for i = 0; i < normalsIndices.size(); ++i newNormalsArray[i] = oldNormalsArray[normalsIndices[i]]; 

L'ho ottimizzato un po ', senza riempire gli array di indici. Ma l'ottimizzazione dipende dal modo in cui il programmatore sta leggendo i dati della mesh.