You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何我的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

核心错误原因

顶点数据展开时的索引计算和赋值逻辑完全错误:

  1. 顶点分量索引错误:verticesout数组中每个顶点以3个连续float存储(x、y、z),但代码直接用vertexindices[i]-1作为下标,这会取到该顶点序号对应的单个float(而非完整的三个分量),导致不同顶点的分量混乱。
  2. 展开赋值逻辑错误:没有为每个顶点分配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;
}

额外需要修正的问题

  1. 纹理坐标和法线的同步修正:纹理坐标每个占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;
      }
      
  2. 内存拷贝长度修正:原代码用sizeof(verticesind)拷贝整个数组,实际应仅拷贝有效数据长度:
    memcpy(vertices, verticesind, verticessize);
    memcpy(texcoords, texturecoordsind, texturecoordsize);
    memcpy(normals, normalsind, normalssize);
    

内容的提问来源于stack exchange,提问作者RadoslavL

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 22:18:29