James T
James T

Reputation: 1156

Rendering .obj file in OpenGL ends up with missing vertices

I created a .obj loader by modifying some code i found online, to parse to .obj file I do the following

int mesh::getMesh(char* inputFile, std::vector<std::vector<glm::vec3>> & out_vertices,std::vector < glm::vec2 > & out_uvs,std::vector < glm::vec3 > & out_normals){
    std::cout << "Attempting to load file as model " << inputFile << "\n";

    std::vector<std::vector<unsigned int>> vertexIndices, uvIndices, normalIndices;
    std::vector<glm::vec3> temp_vertices;
    std::vector<glm::vec2> temp_uvs;
    std::vector<glm::vec3> temp_normals;

    FILE * file = fopen(inputFile, "r");
    if( file == NULL ){
        std::cout << "Impossible to open the file !\n";
        return 0;
    }
    while( 1 ){
        char lineHeader[128];
        // read the first word of the line
        int res = fscanf(file, "%s", lineHeader);
        if (res == EOF)
            break; // EOF = End Of File. Quit the loop.

         if ( strcmp( lineHeader, "v" ) == 0 ){
            glm::vec3 vertex;
            fscanf(file, "%f %f %f\n", &vertex.x, &vertex.y, &vertex.z );
            temp_vertices.push_back(vertex);
        }else if ( strcmp( lineHeader, "vt" ) == 0 ){
            glm::vec2 uv;
            fscanf(file, "%f %f\n", &uv.x, &uv.y );
            temp_uvs.push_back(uv);
        }else if ( strcmp( lineHeader, "vn" ) == 0 ){
            glm::vec3 normal;
            fscanf(file, "%f %f %f\n", &normal.x, &normal.y, &normal.z );
            temp_normals.push_back(normal);
        }else if ( strcmp( lineHeader, "f" ) == 0 ){
            unsigned int vertexIndex[3], uvIndex[3], normalIndex[3];
            int matches = fscanf(file, "%d/%d/%d %d/%d/%d %d/%d/%d\n", &vertexIndex[0], &uvIndex[0], &normalIndex[0], &vertexIndex[1], &uvIndex[1], &normalIndex[1], &vertexIndex[2], &uvIndex[2], &normalIndex[2] );
            if (matches != 9){
                std::cout << "File can't be read by the parser : ( Try exporting with other options )\n";
                return 0;
            }

            std::vector<unsigned int> vertexTriangle;
            vertexTriangle.push_back(vertexIndex[0]);
            vertexTriangle.push_back(vertexIndex[1]);
            vertexTriangle.push_back(vertexIndex[2]);
            vertexIndices.push_back(vertexTriangle);

            //uvIndices    .push_back(uvIndex[0]);
            //uvIndices    .push_back(uvIndex[1]);
            //uvIndices    .push_back(uvIndex[2]);

            //std::vector<unsigned int> normalTriangle;
            //normalTriangle.push_back(normalIndex[0]);
            //normalTriangle.push_back(normalIndex[1]);
            //normalTriangle.push_back(normalIndex[2]);
            //normalIndices.push_back(normalTriangle);
        }
    }
    for( unsigned int i=0; i<vertexIndices.size(); i++ ){
        std::vector<unsigned int> vertexIndexs=vertexIndices[i];

        //glm::vec3 vertex0 = temp_vertices[ vertexIndexs[3]-1 ];
        glm::vec3 vertex1 = temp_vertices[ vertexIndexs[0]-1 ];
        glm::vec3 vertex2 = temp_vertices[ vertexIndexs[1]-1 ];
        glm::vec3 vertex3 = temp_vertices[ vertexIndexs[2]-1 ];
        std::vector<glm::vec3> vertex;
        vertex.push_back(vertex1); vertex.push_back(vertex2); vertex.push_back(vertex3);
        out_vertices.push_back(vertex);

    }
    return 1;
}

I then draw it using

<initialization...>

std::vector<std::vector<glm::vec3>> vertices;
std::vector<glm::vec2> uvs;
std::vector<glm::vec3> normals;

mesh::getMesh("Resources/Models/cube.obj",vertices,uvs,normals);

<window handling and whatnot...>

for (unsigned i=0; i < vertices.size(); i++) {
    std::vector<glm::vec3> vertexGroup = vertices[i];
    glBegin(GL_TRIANGLES);
        glVertex3f(vertexGroup[0].x,vertexGroup[0].y,vertexGroup[0].z);
        glVertex3f(vertexGroup[1].x,vertexGroup[1].y,vertexGroup[1].z);
        glVertex3f(vertexGroup[2].x,vertexGroup[2].y,vertexGroup[2].z);
    glEnd();
}

This works fine for this .obj file

# Blender3D v249 OBJ File: untitled.blend
# www.blender3d.org
mtllib cube.mtl
v 1.000000 -1.000000 -1.000000
v 1.000000 -1.000000 1.000000
v -1.000000 -1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v 1.000000 1.000000 -1.000000
v 0.999999 1.000000 1.000001
v -1.000000 1.000000 1.000000
v -1.000000 1.000000 -1.000000
vt 0.748573 0.750412
vt 0.749279 0.501284
vt 0.999110 0.501077
vt 0.999455 0.750380
vt 0.250471 0.500702
vt 0.249682 0.749677
vt 0.001085 0.750380
vt 0.001517 0.499994
vt 0.499422 0.500239
vt 0.500149 0.750166
vt 0.748355 0.998230
vt 0.500193 0.998728
vt 0.498993 0.250415
vt 0.748953 0.250920
vn 0.000000 0.000000 -1.000000
vn -1.000000 -0.000000 -0.000000
vn -0.000000 -0.000000 1.000000
vn -0.000001 0.000000 1.000000
vn 1.000000 -0.000000 0.000000
vn 1.000000 0.000000 0.000001
vn 0.000000 1.000000 -0.000000
vn -0.000000 -1.000000 0.000000
usemtl Material_ray.png
s off
f 5/1/1 1/2/1 4/3/1
f 5/1/1 4/3/1 8/4/1
f 3/5/2 7/6/2 8/7/2
f 3/5/2 8/7/2 4/8/2
f 2/9/3 6/10/3 3/5/3
f 6/10/4 7/6/4 3/5/4
f 1/2/5 5/1/5 2/9/5
f 5/1/6 6/10/6 2/9/6
f 5/1/7 8/11/7 6/10/7
f 8/11/7 7/12/7 6/10/7
f 1/2/8 2/9/8 3/13/8
f 1/2/8 3/13/8 4/14/8

but when i move onto something more complicated, like A low poly model of a man i took from a free model site as a testbed, its missing a triangle to every face (see screenshots below)

The Cube: enter image description here

The Humanoid enter image description here

The man renders fine in blender so it must be how I'm parsing the file?

Upvotes: 0

Views: 2561

Answers (1)

Krythic
Krythic

Reputation: 4364

You need to triangulate the faces in blender while exporting the model to your format. For obj models you always export with normals attached, and the vertices triangulated. You may also need to check "Keep vertex order".

Upvotes: 3

Related Questions