0

それで、私はこの .OBJ/.MTL メッシュ パーサーにこの 1 週間半取り組んできました。この間、私は多くのバグの追跡/修正、コードのクリーンアップ、ドキュメント化などを行ってきました.

問題は、私がバグを修正するたびに、この問題がまだ発生していることです。写真は千の言葉に値するので...

GL_LINE_LOOP の使用

(注: 右側のピラミッドが球体から外側に傾いているのが問題です)

球体ラインループ

GL_TRIANGLES の使用

球三角形

さらに興味深いのは、この「悪い」頂点データは、シーン内を浮遊しているときにカメラとともに移動しているように見えるということです...ただし、スケールしてメッシュの外側にくっつきます。

ここで奇妙なことは、問題がメモリに関係していることは確かですが、解析アルゴリズムが適切に機能するかどうかと矛盾する問題をチェックしていたことです。いくつかの単体テストの後、正常に動作しているようです。

したがって、Linux nVidia ドライバーの問題である可能性があると考えました。ドライバーを次のバージョンに更新し、再起動しましたが、まだダイスはありません。

よく考えた後、次のコードのエラーを見つけようとしました。

            //! every 3 vertices should represent a triangle, therefore we'll want to
            //! use the indices to grab their corresponding vertices. Since the cross product
            //! of two sides of every triangle (where one side = Vn - Vm, 'n' and 'm' being on the range of 1..3),
            //! we first grab the three vertices, and then compute the normal using the their differences.

            const uInt32 length = mesh->vertices.size();

            //! declare a pointer to the vector so we can perform simple
            //! memory copies to get the indices for each triangle within the
            //! iteration.

            GLuint* const pIndexBuf = &mesh->indices[ 0 ];

            for ( uInt32 i = 0; i < length; i += 3 )
            {
                GLuint thisTriIndices[ 3 ];

                memcpy( thisTriIndices, pIndexBuf + i, sizeof( GLuint ) * 3 );

                vec3 vertexOne   = vec3( mesh->vertices[ thisTriIndices[ 0 ] ] );
                vec3 vertexTwo   = vec3( mesh->vertices[ thisTriIndices[ 1 ] ] );
                vec3 vertexThree = vec3( mesh->vertices[ thisTriIndices[ 2 ] ] );

                vec3 sideOne        = vertexTwo - vertexOne;
                vec3 sideTwo        = vertexThree - vertexOne;

                vec3 surfaceNormal  = glm::cross( sideOne, sideTwo );

                mesh->normals.push_back( surfaceNormal );
            }

写真に示されている現在のものには法線データすらありません。そのため、表面の法線を計算することを目的としているため、上記のコードが使用されます。インデックス データがループ内で適切にロードされているかどうかを確認するためにいくつかのチェックを行いましたが、まだ何も見つけることができませんでした。

私の記憶のレイアウト方法にも問題があると思いますが、何が問題なのかはっきりとはわかりません。何かを見逃した場合に備えて、glVertexAttribPointer 呼び出しをスローします。

//! Gen some buf handles

    glGenBuffers( NUM_BUFFERS_PER_MESH, mesh->buffers );

    //! Load the respective buffer data for the mesh

    __LoadVec4Buffer( mesh->buffers[ BUFFER_VERTEX ], mesh->vertices );      //! positons
    __LoadVec4Buffer( mesh->buffers[ BUFFER_COLOR ], mesh->colors );         //! material colors
    __LoadVec3Buffer( mesh->buffers[ BUFFER_NORMAL ], mesh->normals );       //! normals
    __LoadIndexBuffer( mesh->buffers[ BUFFER_INDEX ], mesh->indices );       //! indices

    //! assign the vertex array a value

    glGenVertexArrays( 1, &mesh->vertexArray );

    //! Specify the memory layout for each attribute

    glBindVertexArray( mesh->vertexArray );

    //! Position and color are both stored in BUFFER_VERTEX.

    glBindBuffer( GL_ARRAY_BUFFER, mesh->buffers[ BUFFER_VERTEX ] );

    glEnableVertexAttribArray( meshProgram->attributes[ "position" ] );
    glVertexAttribPointer( meshProgram->attributes[ "position" ],               //! index
                           4,                                                   //! num vals
                           GL_FLOAT, GL_FALSE,                                  //! value type, normalized?
                           sizeof( vec4 ),                                      //! number of bytes until next value in the buffer
                           ( void* ) 0 );                                       //! offset of the memory in the buffer

    glBindBuffer( GL_ARRAY_BUFFER, mesh->buffers[ BUFFER_COLOR ] );

    glEnableVertexAttribArray( meshProgram->attributes[ "color" ] );
    glVertexAttribPointer( meshProgram->attributes[ "color" ],
                           4,
                           GL_FLOAT, GL_FALSE,
                           sizeof( vec4 ),
                           ( void* ) 0 );

    //! Now we specify the layout for the normals

    glBindBuffer( GL_ARRAY_BUFFER, mesh->buffers[ BUFFER_NORMAL ] );

    glEnableVertexAttribArray( meshProgram->attributes[ "normal" ] );
    glVertexAttribPointer( meshProgram->attributes[ "normal" ],
                           3,
                           GL_FLOAT, GL_FALSE,
                           sizeof( vec3 ),
                           ( void* )0 );

    //! Include the index buffer within the vertex array

    glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, mesh->buffers[ BUFFER_INDEX ] );

    glBindVertexArray( 0 );

少なくとも正しい方向へのあらゆる種類のポイントをいただければ幸いです。これらの問題の一般的な原因が何であるかはわかりません。

編集:リクエストに応じてドローコードを投稿

glBindVertexArray( mMeshes[ i ]->vertexArray );

UBO::LoadMatrix4( UBO::MATRIX_MODELVIEW, modelView.top() );
UBO::LoadMatrix4( UBO::MATRIX_PROJECTION, camera.projection() );

glDrawElements( GL_TRIANGLES, mMeshes[ i ]->indices.size(), GL_UNSIGNED_INT, ( void* )0 );

glBindVertexArray( 0 );
4

1 に答える 1

0

@radical7の提案と組み合わせて、最終的な原因を見つけました。これらは、ほとんどの問題を修正しました。

            // round mesh->indices.size() down if it's not already divisible by 3.
            // the rounded value is stored in numTris

        std::vector< vec4 > newVertices;

        uInt32 indicesLen = Math_FloorForMultiple( mesh->indices.size(), 3 );

            // declare a pointer to the vector so we can perform simple
            // memory copies to get the indices for each triangle within the
            // iteration.

        newVertices.reserve( indicesLen );

        const GLuint* const pIndexBuf = &mesh->indices[ 0 ];

        for ( uInt32 i = 0; i < indicesLen; i += 3 )
        {
            const GLuint* const thisTriIndices = pIndexBuf + i;

            vec4 vertexOne   = mesh->vertices[ thisTriIndices[ 0 ] - 1 ];
            vec4 vertexTwo   = mesh->vertices[ thisTriIndices[ 1 ] - 1 ];
            vec4 vertexThree = mesh->vertices[ thisTriIndices[ 2 ] - 1 ];

            vec4 sideOne     = vertexTwo - vertexOne;
            vec4 sideTwo     = vertexThree - vertexOne;

            vec3 surfaceNormal = glm::cross( vec3( sideOne ), vec3( sideTwo ) );

            mesh->normals.push_back( surfaceNormal );
            mesh->normals.push_back( surfaceNormal + vec3( sideOne ) );
            mesh->normals.push_back( surfaceNormal + vec3( sideTwo ) );

            newVertices.push_back( vertexOne );
            newVertices.push_back( vertexTwo );
            newVertices.push_back( vertexThree );
        }


        mesh->vertices.clear();
        mesh->vertices = newVertices;

への呼び出しを介してループ内で頂点が取得される場合mesh->vertices[ thisTriIndices[ x ] - 1 ]- 1が非常に重要であることに注意してください。OBJ メッシュ ファイルは、0....N-1 インデックスではなく、1...N インデックスから始まる面インデックスを保存します。

インデックス自体も、メッシュを描画するために使用するのではなく、頂点の既に一時的なバッファーから頂点の新しいバッファーを取得する手段として使用する必要があります。インデックスを使用して、一時的な頂点内の要素にアクセスします。一時バッファから取得した各頂点を、その頂点を新しいバッファに追加します。このようにして、正しい描画順序で指定された数の頂点を取得します。したがって、頂点配列のみを使用してそれらを描画する必要があります。

于 2013-06-29T19:14:45.120 に答える