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

从OBJ文件导入模型渲染时部分多边形消失的技术求助

OBJ模型导入渲染后部分多边形消失的解决方法

导入OBJ模型并渲染时出现部分多边形消失的情况,但使用glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)切换为线框模式后模型显示正常。

导入器代码

void load_m(string filename)
{
    string line;
    char c;
    int i, j, k;
    double x, y, z;
    double xt, yt, zt;
    string si, sj, sk;

    ifstream in(filename);
    while (getline(in, line))                     
    {
        if (line.find_first_of("vVfFtT") == string::npos) continue;

        std::istringstream ss(line);                            
        ss >> c;

        switch (c)
        {
        case 'v':                                         
        case 'V':                                         
            ss >> x >> y >> z;                               
            vertices.push_back({ x, y, z });               
            break;

        case 't':
        case 'T':
            ss >> xt >> yt >> zt;
            texture.push_back({ xt, yt, zt });
            break;

        case 'f':                                         
        case 'F':                                         
            ss >> si >> sj >> sk;                            
            i = stoi(si);  j = stoi(sj);  k = stoi(sk);   
            faces.push_back({ i, j, k });                 
            break;
        }
    }
    in.close();
}

渲染代码

string draw_model()
{
    sf::Texture::bind(&tt);
    glEnable(GL_TEXTURE_2D);
    glColor3f(1, 1, 1);

    glBegin(GL_TRIANGLES);

    for (int i = 0; i < faces.size(); i++)
    {
        Point v1 = vertices[faces[i].v1 - 1];
        Point v2 = vertices[faces[i].v2 - 1];
        Point v3 = vertices[faces[i].v3 - 1];

        glVertex3f(v1.x, v1.z, v1.y);
        glVertex3f(v2.x, v2.z, v2.y);
        glVertex3f(v3.x, v3.z, v3.y);

        glTexCoord3f(texture[i].xt, texture[i].yt, texture[i].zt); //Draw texture
    }

    return "123";
    glEnd();
}

错误显示效果

错误模型显示效果

已尝试的方法

  • 自行编写模型加载器,加载速度更快但模型瑕疵更多
  • 修改顶点坐标顺序为glVertex3f(v1.x, v1.z, v1.y),修正了模型方向但未解决多边形消失问题

问题原因及解决办法

1. 渲染代码中glEnd()位置错误

glEnd()放在了return "123";之后,这行代码永远不会被执行。glBegin(GL_TRIANGLES)必须和glEnd()配对使用,否则OpenGL的渲染状态会混乱,导致部分三角形无法正确渲染。

修正后的渲染代码:

string draw_model()
{
    sf::Texture::bind(&tt);
    glEnable(GL_TEXTURE_2D);
    glColor3f(1, 1, 1);

    glBegin(GL_TRIANGLES);

    for (int i = 0; i < faces.size(); i++)
    {
        Point v1 = vertices[faces[i].v1 - 1];
        Point v2 = vertices[faces[i].v2 - 1];
        Point v3 = vertices[faces[i].v3 - 1];

        // 每个顶点对应一个纹理坐标,需先设置纹理坐标再调用glVertex
        glTexCoord3f(texture[faces[i].t1 - 1].xt, texture[faces[i].t1 - 1].yt, texture[faces[i].t1 - 1].zt);
        glVertex3f(v1.x, v1.z, v1.y);
        
        glTexCoord3f(texture[faces[i].t2 - 1].xt, texture[faces[i].t2 - 1].yt, texture[faces[i].t2 - 1].zt);
        glVertex3f(v2.x, v2.z, v2.y);
        
        glTexCoord3f(texture[faces[i].t3 - 1].xt, texture[faces[i].t3 - 1].yt, texture[faces[i].t3 - 1].zt);
        glVertex3f(v3.x, v3.z, v3.y);
    }

    glEnd(); // 移到return之前
    return "123";
}

2. 纹理坐标绑定与加载错误

当前加载器只读取了顶点的索引,但OBJ文件的面格式通常是f v/t/vn(顶点/纹理/法线索引),直接用stoi(si)读取整个字符串会得到错误索引;同时渲染时每个三角形只设置一次纹理坐标,不符合OpenGL“每个顶点对应一个纹理坐标”的要求。

修改加载器的面解析部分,拆分顶点、纹理索引:

case 'f':                                         
case 'F':                                         
    // 拆分面索引,处理"v/t/vn"格式
    auto parse_face_index = [](const string& s) {
        vector<int> indices;
        stringstream ss(s);
        string part;
        while (getline(ss, part, '/')) {
            indices.push_back(part.empty() ? 0 : stoi(part));
        }
        return indices;
    };

    ss >> si >> sj >> sk;                            
    auto idx1 = parse_face_index(si);
    auto idx2 = parse_face_index(sj);
    auto idx3 = parse_face_index(sk);
    // 假设faces结构体包含v1/v2/v3(顶点索引)和t1/t2/t3(纹理索引)字段
    faces.push_back({ idx1[0], idx2[0], idx3[0], idx1[1], idx2[1], idx3[1] });                 
    break;

3. 开启深度测试(可选但推荐)

若模型存在遮挡关系,未开启深度测试会导致后面的面错误覆盖前面的面,开启后可正确剔除被遮挡的面:

// 在初始化阶段调用
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 18:47:09