Wie kann ich ein OBJ-Modell in Arrays von Eckpunkten und Indizes konvertieren?


7

Ich schreibe einen einfachen Modelllader, um zu erfahren, wie Modelle geladen werden. Ich habe ein Programm geschrieben, um OBJ-Dateien in ein benutzerdefiniertes Format zu konvertieren. (Es ist praktisch genau das gleiche wie .OBJ, ich habe es noch einmal geschrieben, nur um zu lernen). Ich kann alle Daten in std::vectors laden, aber ich weiß nicht, wie ich sie in ein Array von Scheitelpunkten und Indizes einfügen soll, daher wird sie falsch gerendert. So stellt sich heraus, dass kein Culling und kein Drahtmodell aktiviert sind (es soll eine Kugel sein und die L-Form in der Mitte ist nicht Teil des Modells):

http://i.imgur.com/eMK4I.png

Wenn ich ihm sage, dass er eine Punktliste rendern soll, befinden sich alle Scheitelpunkte an den richtigen Stellen. Sie scheinen jedoch Gesichter nicht richtig zu formen ...

Dies ist der Code, der sie rendert:

    //=========================================================
    // 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;

Ich weiß, dass es einen Weg gibt, aber ich kann meinen Kopf nicht darum wickeln. Ich habe es wahrscheinlich 5 Mal umgeschrieben, aber ich bekomme immer das gleiche Ergebnis.

Hier ist die ModelData-Struktur:

struct ModelData
{
    int vertexCount;
    int normalCount;
    int faceCount;
    unsigned long* indices;
    EntityBase::VertexType* vertices;
    int errorCode;
};

Die FaceDefinition-Struktur enthält die Indizes der Eckpunktpositionen, Normalen und Texturkoordinaten. Ich habe jedoch noch keine Texturkoordinaten implementiert.

struct FaceDefinition
{
    int vertexIndexes[3];
    int textureIndexes[3];
    int normalIndexes[3];
};

Hier ist die gesamte Funktion, nur zur Verdeutlichung:

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;
}

Dies ist dort Kugel Modelle Datei:

#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

Was passiert, wenn Sie es an einem sehr einfachen Modell versuchen? Wie ein einzelnes Dreieck oder eine flache Ebene? Können Sie auch ein Beispiel für das veröffentlichen, von dem Sie importieren?
MichaelHouse

Das gepostete Objekt OP sieht so aus, als ob es eine Kugel sein sollte.
Exilyth

Übrigens OP: Wenn Sie Ihr Modell nicht triangulieren, bevor Sie es aus Ihrer Modellierungs-App nach .obj exportieren, kann Ihr .obj Gesichter enthalten, die durch mehr als drei Punkte definiert sind, z. B. Quads. Dies sieht jedoch nach einem Indizierungsfehler aus. OP, Sie wissen, dass Indizes in .obj von 1 ... max_vertice im Gegensatz zu Array-Indizes 0 ... [max_vertice - 1] gehen?
Exilyth

Ja, ich weiß, dass es eine Kugel sein soll. Vielleicht wird das Problem besser gelöst, wenn Sie es an einem einfachen Objekt versuchen. Angenommen, das OP versucht es in einer Ebene und nur ein Dreieck wird gerendert? Dann ist es wahrscheinlich, wie Sie sagten, ein Indizierungsfehler. Welches war auch mein Verdacht.
MichaelHouse

2
Ich könnte mich irren, aber warum ändern Sie die Positionen von Eckpunkten? Sie sollten mit einer Scheitelpunktliste (in der Reihenfolge, in der sie in der Datei angezeigt werden) und einer Indexliste (die sich auf die Scheitelpunkte bezieht) enden. Sie müssen die Scheitelpunkte überhaupt nicht neu anordnen (dies wäre tatsächlich ein Fehler).
Ravachol

Antworten:


2

Ok, ich habe es gelöst ...

Ich musste einfach den Code ändern, der die Puffer füllt:

    bool isDuplicate;
    indices.clear();
    for(int i = 0; i < polygonCount; i++)
    {
        for(int i2 = 0; i2 < 3; i2++)
        {
            indices.push_back(faceDefinitions[i].vertexIndexes[i2]);
        }
    }

    modelData->indices = new unsigned long[indices.size()];
    modelData->indexCount = indices.size();

    for(int i = 0; i < vertexCount; i++)
    {
        modelData->vertices[i].position = vertexPositions[i];
    }

    for(unsigned long i = 0; i < indices.size(); i++)
    {
        modelData->indices[i]  = indices[i];
    }

Es war also am Ende ein Indizierungsfehler ...


1
Sie können Ihre Antwort auch als die richtige markieren, um diese Frage zu beantworten.
Jari Komppa

1
Das solltest du wirklich akzeptieren. Andernfalls wird der Community-Bot weiter darauf stoßen, um mehr Aufmerksamkeit zu erhalten.
DeadMG

@DeadMG Heh, ich habe das vergessen, sorry
smoth190

0

Hier sind zwei kleine C ++ - Funktionen aus meinem Projekt. Ich habe versucht, sie ohne Kenntnis meines Codes lesbar zu machen. Sie müssen nur wissen, dass die ObjImporter-Klasse ein Container für die Informationen ist, die aus der obj-Datei gelesen werden.

Sie verwenden im Wesentlichen eine Karte, um jeden eindeutigen Scheitelpunkt zu speichern, der von der Gesichtsliste generiert wird. Dazu muss aus den Indizes Position, Textur und Normal ein Hashwert generiert werden. Meine Implementierung verwendet nur zwei zufällige Konstanten, die für meine obj-Dateien funktionieren. Wenn Ihre Dateien größer sind, besteht die Möglichkeit, dass Hash-Kollisionen auftreten, die falsche Scheitelpunkte in Ihren Indexpuffer einfügen. Passen Sie sie daher nach Bedarf an. Der Hash-Schlüssel wird dem Index des Scheitelpunkts im Scheitelpunktpuffer zugeordnet.

Sobald Sie wissen, wie Sie Ihre Scheitelpunkte aus den Indizes hashen, können Sie damit überprüfen, ob in Ihrem Scheitelpunktpuffer bereits ein Scheitelpunkt vorhanden ist. Wenn dies der Fall ist, haben Sie den Index aus der Karte in den Puffer. Wenn dies nicht der Fall ist, wissen Sie, dass Sie den Scheitelpunkt an die Puffer anhängen können.

Die zweite Funktion hängt von Ihrem Scheitelpunktzeichnungstyp ab. In meiner folgenden Implementierung wird davon ausgegangen, dass Sie eine Dreiecksliste verwenden. (Zwei Dreiecke für jedes Quad)

// Description -
// Given an index to a vertex, that vertex is then checked using a map to determine if
// it is in the vertex buffer already. If it is then it's index is just appended to the index
// buffer, if it isn't than the vertex is appended to the map and both the index and vertex buffers
// Parameters -
// _vBuffer - Vector containing the vertex buffer you are building.
// _iBuffer - Vector containing the index buffer you are building.
// _vMap    - Map that uses a hash value to determine if a vertex is already in the buffer. <Key,Value> = <HashValue, vertexBufferIndex>
// _faceIndex   - Index into an array of faces containing position, normal, and texture value indices. Face list provided by obj file.
// _vertexIndex - Index into the face object.
// _import - Container object for the face and vertex array from the obj file. Class was responsible for reading and storing the obj file. 
void ImportVertex(std::vector<VERTEX> &_vBuffer, std::vector<unsigned int> &_iBuffer, std::map<unsigned int, unsigned int> &_vMap,
    const unsigned int _faceIndex, const unsigned int _vertexIndex, const ObjImporter &_import) {

    // Vertex that will be pushed onto the vertex buffer vector.
    static VERTEX _vTemp;

    // Get the indices from the face for the vertex.
    int _vPosIndex = _import.GetFaceIndexPtr(_faceIndex)->GetVertexPositionIndex(_vertexIndex);
    int _vNorIndex = _import.GetFaceIndexPtr(_faceIndex)->GetVertexNormalIndex(_vertexIndex);
    int _vTexIndex = _import.GetFaceIndexPtr(_faceIndex)->GetVertexTextureIndex(_vertexIndex);

    // Initially build the key from just the position.
    unsigned int _vKey = _vPosIndex;

    // Set the position using the index from the face.
    _vTemp.SetPosition(_import.GetVertexPositionPtr(_vPosIndex));

    // If you have a normal index and value.
    // My importer fills the indices with -1 if they don't exist.
    if (_vNorIndex >= 0) {
        _vTemp.SetNormal(_import.GetVertexNormalPtr(_vNorIndex));
        // Append the key value multiplied by a constant.
        // This constant is dependent upon the size of your obj file and it must be unique for
        // each different vertex. 
        _vKey += _vNorIndex * 1000;
    } else _vTemp.SetNormal(0.0f, 0.0f, 0.0f);

    if (_vTexIndex >= 0) {
        _vTemp.SetTexture(_import.GetVertexTexturePtr(_vTexIndex));
        // Append the key value with the texture index scaled by
        // a higher constant.
        _vKey += _vTexIndex * 1000000;
    } else _vTemp.SetTexture(0.0f, 0.0f, 0.0f);

    // Check to see if the map already contains the key generated.
    if (_vMap.count(_vKey) == 0) {
        // Since the vertex is new it will be at the end of the vector.
        // Map it's key to it's position.
        _vMap[_vKey] = _vBuffer.size();
        // Push back the vertex onto the vertex buffer vector.
        _iBuffer.push_back(_vBuffer.size());
        // Push back the index of this vertex onto the index buffer.
        _vBuffer.push_back(_vTemp);
    // If the vertex is already in the map and hence in the vertex buffer,
    // then just add it's index to the index buffer.                    
    } else _iBuffer.push_back(_vMap[_vKey]);
}

// Description -
// Given an obj file, the faces are iterated through and used to build a triangle list
// vertex buffer.
void Import(const ObjImporter &_import) {
    // Vectors are used to build the index and vertex buffers
    std::vector<RENDEROBJECT_DEFAULT_VERTEX>  _vAggregateBuffer; 
    std::vector<unsigned int> _iAggregateBuffer;
    std::map<unsigned int, unsigned int> _vMap;

    // Iterate through every face in the obj file.
    for (unsigned int i = 0; i < _import.GetFaceCount(); ++i) {
        // If it's a triangle.
        if (_import.GetFaceIndexPtr(i)->GetVertexCount() == 3)
            // Grab each vertex
            for (int k = 0; k < 3; ++k)
                ImportVertex(_vAggregateBuffer, _iAggregateBuffer, _vMap, i, k, _import);                   
        // Else assumes a quad was provided.
        else {
            // Grab each vertex. This is dependent upon vertex drawing type.
            // The order below assumes a triangle list.
            ImportVertex(_vAggregateBuffer, _iAggregateBuffer, _vMap, i, 0, _import);
            ImportVertex(_vAggregateBuffer, _iAggregateBuffer, _vMap, i, 1, _import);
            ImportVertex(_vAggregateBuffer, _iAggregateBuffer, _vMap, i, 2, _import);
            ImportVertex(_vAggregateBuffer, _iAggregateBuffer, _vMap, i, 2, _import);
            ImportVertex(_vAggregateBuffer, _iAggregateBuffer, _vMap, i, 3, _import);
            ImportVertex(_vAggregateBuffer, _iAggregateBuffer, _vMap, i, 0, _import);               
        }
    }
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.