OpenGL – dificuldades de buffer de índice

Eu tenho um formato de arquivo personalizado que contém todas as informações necessárias para uma malha 3D (exportada do 3ds Max). Eu extraí os dados para vértices, índices de vértices e normais.

Eu passo para o OpenGL os dados de vértices, índices de vértices e dados normais e eu renderizo a malha com uma chamada para glDrawElements(GL_TRIANGLES,...)

Tudo parece certo, mas as normais. O problema é que as normais têm índices diferentes. E como o OpenGL pode usar apenas um buffer de índice, ele usa esse buffer de índice para os vértices e as normais.

Eu ficaria muito grato se você pudesse me sugerir como lidar com esse problema.

É importante notar que os dados de vértice / normal não são “classificados” e, portanto, não consigo usar a funcionalidade de glDrawArrays(GL_TRIANGLES,...) – a malha não é renderizada corretamente.

Existe uma maneira / algoritmo que eu possa usar para classificar os dados para que a malha possa ser desenhada corretamente com glDrawArrays(GL_TRIANGLES,..) ? Mas mesmo que haja um algoritmo, há mais um problema – eu terei que duplicar alguns vértices (porque meu buffer de vértices consiste em vértices únicos – por exemplo, se você tiver um cubo meu buffer terá apenas 8 vértices) e não tenho certeza Como fazer isso.

Os tipos de arquivos que usam índices separados para vértices e normais não correspondem ao modelo de vértice OpenGL muito diretamente. Como você percebeu, o OpenGL usa um único conjunto de índices.

O que você precisa fazer é criar um vértice OpenGL para cada par único (índice de vértice, índice normal) em sua input. Isso requer um pouco de trabalho, mas não é muito difícil, especialmente se você usar estruturas de dados disponíveis. Um map STL funciona bem para isso, com o par (índice de vértice, índice normal) como chave. Eu não vou fornecer código C ++ completo, mas posso esboçar isso.

Digamos que você já tenha lido seus vértices em algum tipo de estrutura de dados vetoriais / matriciais em inVertices , onde as coordenadas para o vértice com o índice vertexIdx são armazenadas em inVertices[vertexIdx] . A mesma coisa para as normais, onde o vetor normal com índice normalIdx é armazenado em inNormals[normalIdx] .

Agora você pode ler uma lista de triângulos, com cada canto de cada triângulo dado por um vertexIdx e um normalIdx . Construiremos uma nova matriz / vetor combinedVertices que contém coordenadas de vértice e normal, além de uma nova lista 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 

Eu consegui fazer isso sem passar buffer de índice para OpenGL com glDrawArrays(GL_TRIANGLES,..) O que eu fiz foi o seguinte: Preencher uma matriz de vértice, matriz de índices de vértices, matriz de normais e matriz de índices de normals. Então eu criei novas matrizes de vértices e normais com dados ordenados e passei-os para o 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]]; 

Eu otimizei um pouco, sem preencher matrizes de índices. Mas a otimização depende da maneira como o programador está lendo os dados da malha.