OpenGL – El índice amortigua las dificultades

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 utilizar 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 triangularjs, 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 progtwigdor está leyendo los datos de malla.