Thursday, October 9, 2014

This is a simple tutorial to load a .obj file (wavefront .obj) using OpenGL. I came up with this loader during my university project, where I had a requirement to load various objects into my OpenGL scene. The aim of the project was to build a 3D environment containing various objects around which one could roam about in first person view as in free roaming games.

I wanted to include objects like cars, air-crafts, boats etc in my OpenGL scene. It was then that I stumbled upon wavefront .obj files. I realized that there were plenty of cool and complex objects available all over the internet in wavefront .obj file format. But I could not put them to use as I did not have a loader that loaded these .obj files into my scene.

Then I thought I must understand the wavefront .obj file format. I spent a few minutes understanding the obj format and a few more minutes to write a code that reads the vertex information from it and renders the object defined in the .obj file using GL_Points. After a few minutes of coding, what I got was a clean loader which was capable of displaying the object in the .obj file.

You can read about wavefront .obj file from here: http://en.wikipedia.org/wiki/Wavefront_.obj_file

A simple wavefront .obj loader in OpenGL using C



//headers
#include<GL/gl.h>
#include<GL/glut.h>
#include<stdio.h>
//globals
GLuint elephant;
float elephantrot;
char ch='1';
//other functions and main
//wavefront .obj loader code begins
void loadObj(char *fname)
{
    FILE *fp;
    int read;
    GLfloat x, y, z;
    char ch;
    elephant=glGenLists(1);
    fp=fopen(fname,"r");
    if (!fp)
    {
        printf("can't open file %s\n", fname);
        exit(1);
    }
    glPointSize(2.0);
    glNewList(elephant, GL_COMPILE);
    {
        glPushMatrix();
        glBegin(GL_POINTS);
        while(!(feof(fp)))
        {
            read=fscanf(fp,"%c %f %f %f",&ch,&x,&y,&z);
            if(read==4&&ch=='v')
            {
                glVertex3f(x,y,z);
            }
        }
        glEnd();
    }
    glPopMatrix();
    glEndList();
    fclose(fp);
}
//wavefront .obj loader code ends here
void reshape(int w,int h)
{
    glViewport(0,0,w,h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective (60, (GLfloat)w / (GLfloat)h, 0.1, 1000.0);
    //glOrtho(-25,25,-2,2,0.1,100);
    glMatrixMode(GL_MODELVIEW);
}
void drawElephant()
{
    glPushMatrix();
    glTranslatef(0,-40.00,-105);
    glColor3f(1.0,0.23,0.27);
    glScalef(0.1,0.1,0.1);
    glRotatef(elephantrot,0,1,0);
    glCallList(elephant);
    glPopMatrix();
    elephantrot=elephantrot+0.6;
    if(elephantrot>360)elephantrot=elephantrot-360;
}
void display(void)
{
    glClearColor (0.0,0.0,0.0,1.0);
    glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    drawElephant();
    glutSwapBuffers(); //swap the buffers
}
int main(int argc,char **argv)
{
    glutInit(&argc,argv);
    glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB|GLUT_DEPTH);
    glutInitWindowSize(800,450);
    glutInitWindowPosition(20,20);
    glutCreateWindow("ObjLoader");
    glutReshapeFunc(reshape);
    glutDisplayFunc(display);
    glutIdleFunc(display);
    loadObj("data/elepham.obj");//replace elepham.obj withp orsche.obj or radar.obj or any other .obj to display it
    glutMainLoop();
    return 0;
}


Screenshots of the .obj loader loading objects into a OpenGL scene

You can also download the complete repository from my github page at https://github.com/nanosmooth/opengl_objloader