Search code examples
c++openglwavefront

Problem when importing model from object file or drawing model


When I import model from object file and render it, some polygons disappers.

Importer code:

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();
}

Render code:

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

}

And something else, if I change polygon mode from solid to mesh, using this command:

glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

Model drawing normal. I think it's happening because renders only edges of polygons.

Maybe anyone have such problem and can help me?

What I tried to do:

  1. I tried to write own model loader. It works faster but load model with more artifacts.

  2. Then in this line:

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

I change y and z indexes like this:

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

This turned the model normally, but don't fix my problem at all...

Screenshot of wrong model: Screenshot of wrong model


Solution

  • Your obj file has:

    f 1/1/1 2/2/2 3/3/3 4/4/4
    

    This is a 4-sided face (4 vertices, a.k.a. "quad"). But it appears that your code only uses the first 3 vertices. Perhaps you only anticipated 3-sided faces (a.k.a. "triangles").

    Your data structure for the faces seems to have manually-crafted variable names for 3 vertices per face. e.g. faces[i].v1 .v2 .v3. But faces can have more than 3 vertices in the obj file format.

    This piece of code is inadequate to support the complexity of an obj-file that contains quads because it only uses the first 3 vertices of the face.

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

    If you want to keep your faces as triangles (hard-coded to have 3 vertices) then you'll need to correctly convert faces to triangles when reading in your obj file. That means tessellating the face into triangles. A quad would become 2 triangles, for example.