Top ↑

Class Header File (Geometry)

This object loader uses the standard .cpp/.h structure, where the header file is included in whatever other source files that need it.

Here, I'll explain all the parts of the header file for loading geometry only (no materials or textures).

Header files

There aren't many, but these are required for things like string manipulation.

#include <iostream>
#include <fstream>
#include <vector>
#include <cstring>
using namespace std;

#include <GL/gl.h>

It goes without saying that you should have the correct OpenGL development headers installed, along with a functioning 3D driver for your graphics card. This loader doesn't use any strange or non-core OpenGL commands, so should be widely supported.

Types

There are only two types defined for the basic implementation of this class:

typedef struct
{
    float x;
    float y;
    float z;
}
Vector;

typedef struct
{
    int v1, v2, v3;
    int vn1, vn2, vn3;
}
Face;

The Vector type defines a simple X, Y, Z vector with floating point values. You could replace float with double for extra precision, but it's not really necessary unless you're doing collision detection/response.

The Face type holds the indices for a face's vertices and vertex normals. Unfortunately, this loader only supports triangle meshes. There are plans to support polygonal meshes, but most 3D modelling programs allow you to triangulate meshes anyway.

Class definition

This is a pretty simple class, with only a couple of functions and variables.

class WFObject
{
    private:
        // Dynamic variables to keep our object data in
        vector<Vector> vertices;
        vector<Vector> normals;
        vector<Face> faces;

        void parseLine(char *line);

        void parseVertex(char *line);
        void parseNormal(char *line);
        void parseFace(char *line);

    public:
        WFObject();
        ~WFObject();

        int load(char *filename);
        void draw();
};

Here, a WFObject class is defined with two public functions: load() and draw(). These should be pretty self explanatory, other than noting that load() takes the .OBJ file's filename as it's only argument.

To store the object data in memory, we make use of vector<>. These are, put simply, dynamic arrays (reference, tutorial. Here, we create 3 vectors to hold the vertex, normal and face data. These are given a sensible type of Vector (note the capital V) for the former two, and Face for the latter.

Finally, we have 4 private functions.

  • void parseLine() takes a line from the loaded file and decides what to do with it.
  • void parseVertex() parses the coordinates for a vertex from the line passed to it.
  • void parseNormal(), likewise, parses the coordinates for a vertex's normal.
  • void parseFace() parses a more complex face definition line into the faces array.

And that's it. After the header file listing (below), let's move on to the .cpp file, with all the meat in it.

Complete code listing

#ifndef _WAVEFRONT_LOADER_H_
#define _WAVEFRONT_LOADER_H_

#include <iostream>
#include <fstream>
#include <vector>
#include <cstring>
using namespace std;

#include <GL/gl.h>

typedef struct
{
    float x;
    float y;
    float z;
}
Vector;

typedef struct
{
    int v1, v2, v3;
    int vn1, vn2, vn3;
}
Face;

class WFObject
{
    private:
        // Dynamic variables to keep our object data in
        vector<Vector> vertices;
        vector<Vector> normals;
        vector<Face> faces;

        void parseLine(char *line);

        void parseVertex(char *line);
        void parseNormal(char *line);
        void parseFace(char *line);

    public:
        WFObject();
        ~WFObject();

        int load(char *filename);
        void draw();
};

#endif