どうすればOBJモデルを頂点とインデックスの配列に変換できますか?


7

モデルのロード方法を学ぶためだけに、単純なモデルローダーを作成しています。.OBJファイルをカスタム形式に変換するプログラムを作成しました。(それは事実上.OBJとまったく同じです、私は学習のためだけにもう一度書いた)。すべてのデータをに読み込むことはできますstd::vectorが、頂点とインデックスの配列にデータを配置する方法がわからないため、正しくレンダリングされません。カリングなしでワイヤーフレームを有効にした場合の結果は次のとおりです(球体であることが想定されており、中央のL形はモデルの一部ではありません)。

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

ポイントリストをレンダリングするように指示すると、すべての頂点が適切な場所にあります。ただし、顔が正しく形成されていないようです...

これはそれらをレンダリングするコードです:

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

それをする方法があることを私は知っていますが、私はそれに頭を包むようには見えません。おそらく5回は書き直しましたが、常に同じ結果が得られます。

これがModelData構造です。

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

FaceDefinition構造には、頂点の位置、法線、およびテクスチャ座標のインデックスが含まれています。ただし、テクスチャコードはまだ実装していません。

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

わかりやすくするために、ここに関数全体を示します。

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

これは球モデルファイルです:

#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

非常に単純なモデルで試してみるとどうなるでしょうか。単一の三角形または平らな平面のように?また、インポート元のサンプルを投稿できますか?
MichaelHouse

OPが投稿したオブジェクトは、球のように見えます。
Exilyth、2011

ちなみに、OP:モデリングアプリから.objにエクスポートする前にモデルを三角形分割しない限り、.objには4つ以上の点で定義された面(四角形など)を含めることができます。しかし、これは索引付けエラーのように見えます。OP、あなたは.objのインデックスが1 ... max_verticeであるのを知っていますか?配列インデックス0 ... [max_vertice-1]とは異なりますか?
Exilyth、2011

ええ、私はそれが球であることになっていることを知っています。おそらく、単純なオブジェクトで試してみると、目前の問題が明らかになります。OPが平面上で試してみて、三角形のみがレンダリングされるとしますか?次に、あなたが言ったように、索引付けエラーです。それも私の疑いでした。
MichaelHouse

2
私は間違っているかもしれませんが、なぜ頂点の位置を変更するのですか?頂点リスト(ファイルに表示される順序)とインデックスリスト(頂点を参照)で終わる必要があります。頂点を並べ替える必要はまったくありません(そうすると、実際にはエラーになります)。
Ravachol、2011

回答:


2

はい、解決しました...

バッファを埋めるコードを次のように変更するだけです。

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

結局のところ、それは索引付けエラーでした...


1
この質問に回答させるには、正しい回答としてマークすることもできます。
Jari Komppa、2012

1
あなたは本当にこれを受け入れるべきです。そうでなければ、コミュニティボットはもっと注目を集めるためにそれをぶつけ続けます。
DeadMG 2012年

@DeadMG Heh忘れてしまいました、申し訳ありません
smoth190 2012年

0

これが私のプロジェクトの2つの小さなc ++関数です。私は自分のコードの知識なしでそれらを読みやすくしようとしました。ObjImporterクラスがobjファイルから読み取った情報のコンテナであることを知っておいてください。

それらは基本的にマップを使用して、フェイスリストによって生成されたすべての一意の頂点を格納します。これを行うには、位置、テクスチャ、および通常のインデックスからハッシュ値を生成する必要があります。私の実装では、objファイルで機能する2つのランダム定数を使用しています。ファイルが大きい場合、ハッシュコリジョンが発生してインデックスバッファーに不正な頂点が配置される可能性があるため、必要に応じて調整してください。ハッシュキーは、頂点バッファー内の頂点のインデックスにマップされます。

インデックスから頂点をハッシュする方法がわかったら、これを使用して、頂点が頂点バッファーに既に存在するかどうかを確認できます。含まれている場合は、マップからバッファーへのインデックスがあり、それがわからない場合は、バッファーに頂点を追加できることがわかりません。

2番目の関数は、頂点の描画タイプによって異なります。以下の私の実装では、三角形のリストを使用していることを前提としています。(各クワッドに2つの三角形)

// 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);               
        }
    }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.