Estou escrevendo um carregador de modelo simples apenas para aprender como os modelos são carregados. Eu escrevi um programa para converter arquivos .OBJ em um formato personalizado. (É praticamente exatamente o mesmo que .OBJ, escrevi mais uma vez apenas para aprender). Posso carregar todos os dados em std::vector
s, mas não sei como colocá-los em uma matriz de vértices e índices; portanto, está renderizando errado. Veja como isso acontece sem a seleção e o wireframe ativados (deveria ser uma esfera e que a forma de L no meio não faz parte do modelo):
Quando eu digo para renderizar uma lista de pontos, todos os vértices estão nos lugares certos. No entanto, eles não parecem formar rostos corretamente ...
Este é o código que os renderiza:
//=========================================================
// CONVERT THE DATA INTO SOMETHING USABLE
//=========================================================
bool isDuplicate;
for(int i = 0; i < polygonCount; i++)
{
for(int i2 = 0; i2 < 3; i2++)
{
isDuplicate = false;
isCreated = false;
selectedVertex = faceDefinitions[i].vertexIndexes[i2];
for(int i3 = 0; i3 < vertexCount; i3++)
{
if(modelData->vertices[i3].position == vertexPositions[selectedVertex])
{
if(modelData->vertices[i3].texture == D3DXVECTOR2(0,0))
{
indices[selectedVertex] = i3;
isDuplicate = true;
break;
}
}
}
if(isDuplicate)
continue;
indices[selectedVertex] = selectedVertex;
modelData->vertices[selectedVertex].position = vertexPositions[selectedVertex];
modelData->vertices[selectedVertex].normal = vertexNormals[faceDefinitions[i].normalIndexes[i2]];
modelData->vertices[selectedVertex].texture = D3DXVECTOR2(0,0);
}
}
modelData->indices = indices;
Eu sei que há uma maneira de fazê-lo, mas não consigo envolver minha cabeça nisso. Eu o reescrevi provavelmente 5 vezes, mas sempre obtenho o mesmo resultado.
Aqui está a estrutura ModelData:
struct ModelData
{
int vertexCount;
int normalCount;
int faceCount;
unsigned long* indices;
EntityBase::VertexType* vertices;
int errorCode;
};
A estrutura FaceDefinition contém os índices das posições dos vértices, normais e cordas de textura. Ainda não implementei cordões de textura.
struct FaceDefinition
{
int vertexIndexes[3];
int textureIndexes[3];
int normalIndexes[3];
};
Aqui está toda a função, apenas para maior clareza:
ModelData* CModelLoader::LoadModel(WCHAR* modelName)
{
ifstream loaderStream(Application::FileSystem::GetFileLocation(FILE_TYPE_MODEL,modelName));
ModelData* modelData = new ModelData;
vector<D3DXVECTOR3> vertexPositions;
vector<D3DXVECTOR3> vertexNormals;
vector<D3DXVECTOR3> vertexTextureCoords;
vector<int> setVertices;
vector<FaceDefinition> faceDefinitions;
vector<string> tokens;
vector<string> faceToken;
int vertexCount = 0, normalCount = 0, polygonCount = 0;
unsigned long *indices;
int selectedVertex;
bool isCreated;
string input;
string currentToken;
string currentFaceToken;
std::istringstream streamReader;
std::istringstream faceReader;
D3DXVECTOR3 tempVector;
FaceDefinition tempFace;
modelData->errorCode = ERR_NO_ERROR;
if(!loaderStream)
modelData->errorCode = ERR_COULD_NOT_OPEN;
else
{
while(std::getline(loaderStream, input))
{
streamReader.clear();
streamReader.str(input);
tokens.clear();
while(std::getline(streamReader, currentToken, ' '))
{
tokens.push_back(currentToken);
}
if(tokens.size() < 1)
continue;
if(tokens[0] == "VERTEX")
{
vertexCount++;
if(tokens.size() >= 4)
{
tempVector = D3DXVECTOR3(0,0,0);
tempVector.x = (float) atof(tokens[1].c_str());
tempVector.y = (float) atof(tokens[2].c_str());
tempVector.z = (float) atof(tokens[3].c_str());
vertexPositions.push_back(tempVector);
continue;
}
else
{
vertexPositions.push_back(D3DXVECTOR3(0,0,0)); //give it a bad vertex, because we received a bad vertex
}
}
if(tokens[0] == "VERTEX_NORMAL")
{
normalCount++;
if(tokens.size() >= 4)
{
tempVector = D3DXVECTOR3(0,0,0);
tempVector.x = (float) atof(tokens[1].c_str());
tempVector.y = (float) atof(tokens[2].c_str());
tempVector.z = (float) atof(tokens[3].c_str());
vertexNormals.push_back(tempVector);
continue;
}
else
{
vertexNormals.push_back(D3DXVECTOR3(0,0,0)); //give it a bad normal, because we received a bad normal
}
}
if(tokens[0] == "FACE")
{
polygonCount++;
if(tokens.size() == 4) //sorry, but non triangles aren't worth the time
{
tempFace = FaceDefinition();
//vertex 1
faceReader.clear();
faceReader.str(tokens[1]);
faceToken.clear();
while(std::getline(faceReader, currentFaceToken, ','))
{
faceToken.push_back(currentFaceToken);
}
if(faceToken.size() == 3) //should have all the info, or, same as above, its not worth the time
{
tempFace.vertexIndexes[0] = atoi(faceToken[0].c_str()) - 1;
tempFace.textureIndexes[0] = atoi(faceToken[1].c_str()) - 1;
tempFace.normalIndexes[0] = atoi(faceToken[2].c_str()) - 1;
}
//vertex 2
faceReader.clear();
faceReader.str(tokens[2]);
faceToken.clear();
while(std::getline(faceReader, currentFaceToken, ','))
{
faceToken.push_back(currentFaceToken);
}
if(faceToken.size() == 3) //should have all the info, or, same as above, its not worth the time
{
tempFace.vertexIndexes[1] = atoi(faceToken[0].c_str()) - 1;
tempFace.textureIndexes[1] = atoi(faceToken[1].c_str()) - 1;
tempFace.normalIndexes[1] = atoi(faceToken[2].c_str()) - 1;
}
//vertex 3
faceReader.clear();
faceReader.str(tokens[3]);
faceToken.clear();
while(std::getline(faceReader, currentFaceToken, ','))
{
faceToken.push_back(currentFaceToken);
}
if(faceToken.size() == 3) //should have all the info, or, same as above, its not worth the time
{
tempFace.vertexIndexes[2] = atoi(faceToken[0].c_str()) - 1;
tempFace.textureIndexes[2] = atoi(faceToken[1].c_str()) - 1;
tempFace.normalIndexes[2] = atoi(faceToken[2].c_str()) - 1;
}
faceDefinitions.push_back(tempFace);
}
//if we receive a bad face, we just wont read it
}
}
}
indices = new unsigned long[vertexCount];
modelData->faceCount = polygonCount;
modelData->normalCount = normalCount;
modelData->vertexCount = vertexCount;
modelData->vertices = new EntityBase::VertexType[vertexCount];
//< ^^everything up here works^^ >
//=========================================================
// CONVERT THE DATA INTO SOMETHING USABLE
//=========================================================
//now is the boring part, creating the vertex list...
bool isDuplicate;
for(int i = 0; i < polygonCount; i++)
{
for(int i2 = 0; i2 < 3; i2++)
{
isDuplicate = false;
isCreated = false;
selectedVertex = faceDefinitions[i].vertexIndexes[i2];
for(int i3 = 0; i3 < vertexCount; i3++)
{
if(modelData->vertices[i3].position == vertexPositions[selectedVertex])
{
if(modelData->vertices[i3].texture == D3DXVECTOR2(0,0))
{
indices[selectedVertex] = i3;
isDuplicate = true;
break;
}
}
}
if(isDuplicate)
continue;
indices[selectedVertex] = selectedVertex;
modelData->vertices[selectedVertex].position = vertexPositions[selectedVertex];
modelData->vertices[selectedVertex].normal = vertexNormals[faceDefinitions[i].normalIndexes[i2]];
modelData->vertices[selectedVertex].texture = D3DXVECTOR2(0,0);
}
}
modelData->indices = indices;
return modelData;
}
Este é o arquivo de modelos de esfera:
#Vertex Info
VERTEX_COUNT:62
NORMAL_COUNT:62
FACE_COUNT:120
VERTEX 0 19.5 0
VERTEX 0 -19.5 0
VERTEX 9.75 -16.887495 0
VERTEX 8.443748 -16.887495 4.875
VERTEX 4.875 -16.887495 8.443748
VERTEX 0 -16.887495 9.75
VERTEX -4.875 -16.887495 8.443748
VERTEX -8.443748 -16.887495 4.875
VERTEX -9.75 -16.887495 0
VERTEX -8.443748 -16.887495 -4.875
VERTEX -4.875 -16.887495 -8.443748
VERTEX 0 -16.887495 -9.75
VERTEX 4.875 -16.887495 -8.443748
VERTEX 8.443748 -16.887495 -4.875
VERTEX 16.887497 -9.75 0
VERTEX 14.625001 -9.75 8.443748
VERTEX 8.443748 -9.75 14.625
VERTEX 0 -9.75 16.887497
VERTEX -8.443748 -9.75 14.625
VERTEX -14.625001 -9.75 8.443748
VERTEX -16.887497 -9.75 0
VERTEX -14.625001 -9.75 -8.443748
VERTEX -8.443748 -9.75 -14.625
VERTEX 0 -9.75 -16.887497
VERTEX 8.443748 -9.75 -14.625
VERTEX 14.625001 -9.75 -8.443748
VERTEX 19.5 1E-06 0
VERTEX 16.887495 1E-06 9.75
VERTEX 9.75 1E-06 16.887495
VERTEX 0 1E-06 19.5
VERTEX -9.75 1E-06 16.887495
VERTEX -16.887495 1E-06 9.75
VERTEX -19.5 1E-06 0
VERTEX -16.887495 1E-06 -9.75
VERTEX -9.75 1E-06 -16.887497
VERTEX 0 1E-06 -19.5
VERTEX 9.75 1E-06 -16.887497
VERTEX 16.887495 1E-06 -9.75
VERTEX 16.887495 9.750001 0
VERTEX 14.624999 9.750001 8.443748
VERTEX 8.443748 9.750001 14.625
VERTEX 0 9.750001 16.887495
VERTEX -8.443748 9.750001 14.625
VERTEX -14.624999 9.750001 8.443748
VERTEX -16.887495 9.750001 0
VERTEX -14.624999 9.750001 -8.443748
VERTEX -8.443748 9.750001 -14.625
VERTEX 0 9.750001 -16.887497
VERTEX 8.443748 9.750001 -14.625
VERTEX 14.624999 9.750001 -8.443748
VERTEX 9.750001 16.887495 0
VERTEX 8.443748 16.887495 4.875
VERTEX 4.875 16.887495 8.443748
VERTEX 0 16.887495 9.750001
VERTEX -4.875 16.887495 8.443748
VERTEX -8.443748 16.887495 4.875
VERTEX -9.750001 16.887495 0
VERTEX -8.443748 16.887495 -4.875
VERTEX -4.875 16.887495 -8.443748
VERTEX 0 16.887495 -9.750002
VERTEX 4.875 16.887495 -8.443748
VERTEX 8.443748 16.887495 -4.875
# Vertex Normals!
VERTEX_NORMAL 0 -1 0
VERTEX_NORMAL 0.573584 -0.819147 0
VERTEX_NORMAL 0.431481 -0.867044 0.249116
VERTEX_NORMAL 0 1 0
VERTEX_NORMAL 0.431481 0.867044 0.249116
VERTEX_NORMAL 0.573584 0.819147 0
VERTEX_NORMAL 0.286792 -0.819147 0.496738
VERTEX_NORMAL 0.286792 0.819147 0.496738
VERTEX_NORMAL 0 -0.867044 0.498231
VERTEX_NORMAL 0 0.867044 0.498231
VERTEX_NORMAL -0.286792 -0.819147 0.496738
VERTEX_NORMAL -0.286792 0.819147 0.496738
VERTEX_NORMAL -0.431481 -0.867044 0.249116
VERTEX_NORMAL -0.431481 0.867044 0.249116
VERTEX_NORMAL -0.573584 -0.819147 0
VERTEX_NORMAL -0.573584 0.819147 0
VERTEX_NORMAL -0.431481 -0.867044 -0.249116
VERTEX_NORMAL -0.431481 0.867044 -0.249116
VERTEX_NORMAL -0.286792 -0.819147 -0.496738
VERTEX_NORMAL -0.286792 0.819147 -0.496738
VERTEX_NORMAL 0 -0.867044 -0.498231
VERTEX_NORMAL 0 0.867044 -0.498231
VERTEX_NORMAL 0.286792 -0.819147 -0.496738
VERTEX_NORMAL 0.286792 0.819147 -0.496738
VERTEX_NORMAL 0.431481 -0.867044 -0.249116
VERTEX_NORMAL 0.431481 0.867044 -0.249116
VERTEX_NORMAL 0.865033 -0.501714 0
VERTEX_NORMAL 0.749141 -0.501714 0.432517
VERTEX_NORMAL 0.432517 -0.501714 0.749141
VERTEX_NORMAL 0 -0.501714 0.865033
VERTEX_NORMAL -0.432517 -0.501714 0.749141
VERTEX_NORMAL -0.749141 -0.501714 0.432517
VERTEX_NORMAL -0.865033 -0.501714 0
VERTEX_NORMAL -0.749141 -0.501714 -0.432517
VERTEX_NORMAL -0.432517 -0.501714 -0.749141
VERTEX_NORMAL 0 -0.501714 -0.865033
VERTEX_NORMAL 0.432517 -0.501714 -0.749141
VERTEX_NORMAL 0.749141 -0.501714 -0.432517
VERTEX_NORMAL 1 0 0
VERTEX_NORMAL 0.866025 0 0.5
VERTEX_NORMAL 0.5 0 0.866025
VERTEX_NORMAL 0 0 1
VERTEX_NORMAL -0.5 0 0.866025
VERTEX_NORMAL -0.866025 0 0.5
VERTEX_NORMAL -1 0 0
VERTEX_NORMAL -0.866025 0 -0.5
VERTEX_NORMAL -0.5 0 -0.866025
VERTEX_NORMAL 0 0 -1
VERTEX_NORMAL 0.5 0 -0.866025
VERTEX_NORMAL 0.866025 0 -0.5
VERTEX_NORMAL 0.865033 0.501714 0
VERTEX_NORMAL 0.749141 0.501714 0.432517
VERTEX_NORMAL 0.432517 0.501714 0.749141
VERTEX_NORMAL 0 0.501714 0.865033
VERTEX_NORMAL -0.432517 0.501714 0.749141
VERTEX_NORMAL -0.749141 0.501714 0.432517
VERTEX_NORMAL -0.865033 0.501714 0
VERTEX_NORMAL -0.749141 0.501714 -0.432517
VERTEX_NORMAL -0.432517 0.501715 -0.749141
VERTEX_NORMAL 0 0.501714 -0.865033
VERTEX_NORMAL 0.432517 0.501715 -0.749141
VERTEX_NORMAL 0.749141 0.501714 -0.432517
# Face Definitions!
FACE 2,1,1 3,2,2 4,3,3
FACE 1,4,4 52,5,5 51,6,6
FACE 2,7,1 4,3,3 5,8,7
FACE 1,9,4 53,10,8 52,5,5
FACE 2,11,1 5,8,7 6,12,9
FACE 1,13,4 54,14,10 53,10,8
FACE 2,15,1 6,12,9 7,16,11
FACE 1,17,4 55,18,12 54,14,10
FACE 2,19,1 7,16,11 8,20,13
FACE 1,21,4 56,22,14 55,18,12
FACE 2,23,1 8,20,13 9,24,15
FACE 1,25,4 57,26,16 56,22,14
FACE 2,27,1 9,24,15 10,28,17
FACE 1,29,4 58,30,18 57,26,16
FACE 2,31,1 10,28,17 11,32,19
FACE 1,33,4 59,34,20 58,30,18
FACE 2,35,1 11,32,19 12,36,21
FACE 1,37,4 60,38,22 59,34,20
FACE 2,39,1 12,36,21 13,40,23
FACE 1,41,4 61,42,24 60,38,22
FACE 2,43,1 13,40,23 14,44,25
FACE 1,45,4 62,46,26 61,42,24
FACE 2,47,1 14,44,25 3,48,2
FACE 1,49,4 51,50,6 62,46,26
FACE 3,2,2 15,51,27 16,52,28
FACE 3,2,2 16,52,28 4,3,3
FACE 4,3,3 16,52,28 5,8,7
FACE 16,52,28 17,53,29 5,8,7
FACE 5,8,7 17,53,29 18,54,30
FACE 5,8,7 18,54,30 6,12,9
FACE 6,12,9 18,54,30 7,16,11
FACE 18,54,30 19,55,31 7,16,11
FACE 7,16,11 19,55,31 20,56,32
FACE 7,16,11 20,56,32 8,20,13
FACE 8,20,13 20,56,32 9,24,15
FACE 20,56,32 21,57,33 9,24,15
FACE 9,24,15 21,57,33 22,58,34
FACE 9,24,15 22,58,34 10,28,17
FACE 10,28,17 22,58,34 11,32,19
FACE 22,58,34 23,59,35 11,32,19
FACE 11,32,19 23,59,35 24,60,36
FACE 11,32,19 24,60,36 12,36,21
FACE 12,36,21 24,60,36 13,40,23
FACE 24,60,36 25,61,37 13,40,23
FACE 13,40,23 25,61,37 26,62,38
FACE 13,40,23 26,62,38 14,44,25
FACE 14,44,25 26,62,38 3,48,2
FACE 26,62,38 15,63,27 3,48,2
FACE 15,51,27 27,64,39 16,52,28
FACE 27,64,39 28,65,40 16,52,28
FACE 16,52,28 28,65,40 29,66,41
FACE 16,52,28 29,66,41 17,53,29
FACE 17,53,29 29,66,41 18,54,30
FACE 29,66,41 30,67,42 18,54,30
FACE 18,54,30 30,67,42 31,68,43
FACE 18,54,30 31,68,43 19,55,31
FACE 19,55,31 31,68,43 20,56,32
FACE 31,68,43 32,69,44 20,56,32
FACE 20,56,32 32,69,44 33,70,45
FACE 20,56,32 33,70,45 21,57,33
FACE 21,57,33 33,70,45 22,58,34
FACE 33,70,45 34,71,46 22,58,34
FACE 22,58,34 34,71,46 35,72,47
FACE 22,58,34 35,72,47 23,59,35
FACE 23,59,35 35,72,47 24,60,36
FACE 35,72,47 36,73,48 24,60,36
FACE 24,60,36 36,73,48 37,74,49
FACE 24,60,36 37,74,49 25,61,37
FACE 25,61,37 37,74,49 26,62,38
FACE 37,74,49 38,75,50 26,62,38
FACE 26,62,38 38,75,50 27,76,39
FACE 26,62,38 27,76,39 15,63,27
FACE 27,64,39 39,77,51 40,78,52
FACE 27,64,39 40,78,52 28,65,40
FACE 28,65,40 40,78,52 29,66,41
FACE 40,78,52 41,79,53 29,66,41
FACE 29,66,41 41,79,53 42,80,54
FACE 29,66,41 42,80,54 30,67,42
FACE 30,67,42 42,80,54 31,68,43
FACE 42,80,54 43,81,55 31,68,43
FACE 31,68,43 43,81,55 44,82,56
FACE 31,68,43 44,82,56 32,69,44
FACE 32,69,44 44,82,56 33,70,45
FACE 44,82,56 45,83,57 33,70,45
FACE 33,70,45 45,83,57 46,84,58
FACE 33,70,45 46,84,58 34,71,46
FACE 34,71,46 46,84,58 35,72,47
FACE 46,84,58 47,85,59 35,72,47
FACE 35,72,47 47,85,59 48,86,60
FACE 35,72,47 48,86,60 36,73,48
FACE 36,73,48 48,86,60 37,74,49
FACE 48,86,60 49,87,61 37,74,49
FACE 37,74,49 49,87,61 50,88,62
FACE 37,74,49 50,88,62 38,75,50
FACE 38,75,50 50,88,62 27,76,39
FACE 50,88,62 39,89,51 27,76,39
FACE 39,77,51 51,6,6 40,78,52
FACE 51,6,6 52,5,5 40,78,52
FACE 40,78,52 52,5,5 53,10,8
FACE 40,78,52 53,10,8 41,79,53
FACE 41,79,53 53,10,8 42,80,54
FACE 53,10,8 54,14,10 42,80,54
FACE 42,80,54 54,14,10 55,18,12
FACE 42,80,54 55,18,12 43,81,55
FACE 43,81,55 55,18,12 44,82,56
FACE 55,18,12 56,22,14 44,82,56
FACE 44,82,56 56,22,14 57,26,16
FACE 44,82,56 57,26,16 45,83,57
FACE 45,83,57 57,26,16 46,84,58
FACE 57,26,16 58,30,18 46,84,58
FACE 46,84,58 58,30,18 59,34,20
FACE 46,84,58 59,34,20 47,85,59
FACE 47,85,59 59,34,20 48,86,60
FACE 59,34,20 60,38,22 48,86,60
FACE 48,86,60 60,38,22 61,42,24
FACE 48,86,60 61,42,24 49,87,61
FACE 49,87,61 61,42,24 50,88,62
FACE 61,42,24 62,46,26 50,88,62
FACE 50,88,62 62,46,26 51,50,6
FACE 50,88,62 51,50,6 39,89,51
Respostas:
Ok, eu resolvi isso ...
Eu simplesmente tive que mudar o código que preenche os buffers para isso:
Então foi um erro de indexação no final ...
fonte
Aqui estão duas pequenas funções c ++ do meu projeto. Tentei torná-los legíveis sem o conhecimento do meu código. Apenas saiba que a classe ObjImporter é um contêiner para as informações lidas no arquivo obj.
Eles essencialmente usam um mapa para armazenar todos os vértices exclusivos gerados pela lista de faces. Para fazer isso, um valor de hash deve ser gerado a partir da posição, textura e índices normais. Minha implementação usa apenas duas constantes aleatórias que funcionam para meus arquivos obj. Se seus arquivos forem maiores, é possível que você tenha colisões de hash que colocarão vértices incorretos no buffer do índice, para ajustá-los conforme necessário. A chave de hash é mapeada para o índice do vértice no buffer do vértice.
Depois de saber como hash seus vértices dos índices, você pode usá-lo para verificar se já existe um vértice no seu buffer de vértices. Se isso acontecer, você terá o índice no buffer do mapa e, se não estiver, sabe que pode anexar o vértice aos buffers.
A segunda função depende do seu tipo de desenho de vértice. Minha implementação abaixo assume que você está usando a lista de triângulos. (Dois triângulos para cada quad)
fonte