为何我的Wavefront OBJ文件解析器无法正确排序顶点?
OBJ模型加载顶点排序错误排查
问题现象
加载OBJ模型时仅能正确渲染正面,其中一个顶部三角形预期顶点为:
-0.5, 0.5, -0.5, 0.5, 0.5, 0.5, 0.5, 0.5, -0.5
但实际得到错误的顶点数据:
-0.5, -0.5, 0.5, -0.5, 0.5, 0.5, 0.5, -0.5, 0.5
核心错误原因
顶点数据展开时的索引计算和赋值逻辑完全错误:
- 顶点分量索引错误:
verticesout数组中每个顶点以3个连续float存储(x、y、z),但代码直接用vertexindices[i]-1作为下标,这会取到该顶点序号对应的单个float(而非完整的三个分量),导致不同顶点的分量混乱。 - 展开赋值逻辑错误:没有为每个顶点分配3个连续的位置存储完整坐标,而是将三个顶点的各一个分量挤入三个位置,完全破坏了顶点结构。
错误代码片段
原顶点处理循环:
for(i = 0; i < vertexsize; i += 3){ verticesind[i] = verticesout[vertexindices[i] - 1]; verticesind[i + 1] = verticesout[vertexindices[i + 1] - 1]; verticesind[i + 2] = verticesout[vertexindices[i + 2] - 1]; verticessize += sizeof(verticesind[i]) + sizeof(verticesind[i + 1]) + sizeof(vertices[i + 2]); }
修复后的代码
修正顶点索引计算和赋值逻辑,确保每个顶点的三个分量正确存入verticesind:
// 重置初始值,避免累加错误 verticessize = 0; for(i = 0; i < vertexsize; i++){ // 转换为0-based顶点序号 int vertex_idx = vertexindices[i] - 1; // 计算该顶点在verticesout中的起始偏移 int out_offset = vertex_idx * 3; // 存入完整的顶点坐标 verticesind[i * 3] = verticesout[out_offset]; verticesind[i * 3 + 1] = verticesout[out_offset + 1]; verticesind[i * 3 + 2] = verticesout[out_offset + 2]; // 累加单个顶点的字节大小 verticessize += sizeof(float) * 3; }
额外需要修正的问题
- 纹理坐标和法线的同步修正:纹理坐标每个占2个
float,法线每个占3个float,原代码处理逻辑存在同样错误,需同步修改:- 纹理坐标修正:
texturecoordsize = 0; for(i = 0; i < texcoordsize; i++){ int tex_idx = texindices[i] - 1; int out_offset = tex_idx * 2; texturecoordsind[i * 2] = texcoordsout[out_offset]; texturecoordsind[i * 2 + 1] = texcoordsout[out_offset + 1]; texturecoordsize += sizeof(float) * 2; } - 法线修正:
normalssize = 0; for(i = 0; i < normalsize; i++){ int normal_idx = normalindices[i] - 1; int out_offset = normal_idx * 3; normalsind[i * 3] = normalsout[out_offset]; normalsind[i * 3 + 1] = normalsout[out_offset + 1]; normalsind[i * 3 + 2] = normalsout[out_offset + 2]; normalssize += sizeof(float) * 3; }
- 纹理坐标修正:
- 内存拷贝长度修正:原代码用
sizeof(verticesind)拷贝整个数组,实际应仅拷贝有效数据长度:memcpy(vertices, verticesind, verticessize); memcpy(texcoords, texturecoordsind, texturecoordsize); memcpy(normals, normalsind, normalssize);
内容的提问来源于stack exchange,提问作者RadoslavL
相关产品推荐
相关产品推荐

