gpt4 book ai didi

c++ - 不良顶点数据的常见陷阱/原因?

转载 作者:太空宇宙 更新时间:2023-11-04 04:14:26 26 4
gpt4 key购买 nike

所以,过去一周半我一直在研究这个 .OBJ/.MTL 网格解析器。在这段时间里,我一直在追踪/修复很多错误、清理代码、记录代码等等。

问题是,每修复一个错误,仍然会出现这个问题,而且一张图片胜过一千个字......

使用 GL_LINE_LOOP

(注意:右侧的金字塔从球体向外倾斜是这里的问题)

sphere line loop

使用 GL_TRIANGLES

sphere 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 );

最佳答案

我找到了最终的罪魁祸首,结合@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 网格文件存储从 1...N 索引开始的面索引,而不是 0...N-1 索引。

索引本身也不应该用于绘制网格,而是作为从已经临时的顶点缓冲区中获取新的顶点缓冲区的一种方法:您使用索引来访问临时顶点中的元素,然后对于从临时缓冲区中获取的每个顶点,您将该顶点添加到新的缓冲区中。这样,您将获得以正确的绘制顺序指定的顶点数。因此,您只想使用顶点数组来绘制它们。

关于c++ - 不良顶点数据的常见陷阱/原因?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17333942/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com