c++ - OpenGL-El índice amortigua las dificultades
3d rendering (2)
Tengo un formato de archivo personalizado que tiene toda la información necesaria para una malla 3D (exportada desde 3ds Max). Extraje los datos para vértices, índices de vértices y normales.
Paso a OpenGL los datos de vértice, índices de vértices y datos normales y glDrawElements(GL_TRIANGLES,...)
la malla con una llamada a glDrawElements(GL_TRIANGLES,...)
Todo se ve bien, pero las normales. El problema es que las normales tienen diferentes índices. Y debido a que OpenGL puede usar solo un buffer de índice, usa ese buffer de índice tanto para los vértices como para los normales.
Estaría muy agradecido si pudieras sugerirme cómo resolver ese problema.
Lo importante a tener en cuenta es que los datos de vértice / normal no están "ordenados" y, por lo tanto, no puedo usar la funcionalidad de glDrawArrays(GL_TRIANGLES,...)
: la malla no se procesa correctamente.
¿Hay alguna forma / algoritmo que pueda usar para ordenar los datos para que la malla se pueda dibujar correctamente con glDrawArrays(GL_TRIANGLES,..)
? Pero incluso si hay un algoritmo, hay un problema más: tendré que duplicar algunos vértices (porque mi búfer de vértices consiste en vértices únicos, por ejemplo, si tienes cubo mi búfer solo tendrá 8 vértices) y no estoy seguro como hacer eso.
Los tipos de archivos que usan índices separados para vértices y normales no coinciden con el modelo de vértices de OpenGL de manera muy directa. Como habrás notado, OpenGL usa un solo conjunto de índices.
Lo que necesita hacer es crear un vértice OpenGL para cada par único (índice de vértice, índice normal) en su entrada. Eso requiere un poco de trabajo, pero no es terriblemente difícil, especialmente si usa estructuras de datos disponibles. Un map
STL funciona bien para esto, con el par (índice de vértice, índice normal) como la clave. No voy a proporcionar un código completo de C ++, pero puedo esbozarlo.
Digamos que ya ha leído sus vértices en algún tipo de estructura de datos matriz / vector en inVertices
, donde las coordenadas para vértice con índice vertexIdx
se almacenan en inVertices[vertexIdx]
. Lo mismo para las normales, donde el vector normal con índice normalIdx
se almacena en inNormals[normalIdx]
.
Ahora puedes leer una lista de triángulos, con cada esquina de cada triángulo dada por un vertexIdx
y un normalIdx
. Construiremos una nueva matriz / vectorVertices combinedVertices
que contenga coordenadas tanto de vértices como normales, más una nueva lista de índices de índices combinedIndices
. Pseudo código:
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
glDrawArrays(GL_TRIANGLES,..)
hacerlo sin pasar el buffer de índice a OpenGL con glDrawArrays(GL_TRIANGLES,..)
Lo que hice fue lo siguiente: Llenar una matriz de vértices, matriz de índices de vértices, matriz de índices normales y matriz de índices normales. Luego creé nuevos vértices y matrices normales con datos ordenados y los pasé a 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]];
Lo optimicé un poco, sin llenar los cuadros de índices en absoluto. Pero la optimización depende de la forma en que el programador está leyendo los datos de malla.