Loading a model

Are there any “simple” ways to load a model that I can use in OpenGL?

I’m currently trying to parse Wavefront OBJ files but it isn’t going very well.

Nothing is displayed, unless I use the console output from the program in my code instead of the loop to draw the vertices and faces. Even when this happens the model isn’t actually what it should be.


#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
#include <vector>
#include <gl/freeglut.h>
#include <boost/algorithm/string.hpp>

std::vector<float> vertexData;
std::vector<int> faceData;
std::vector<float> drawThis;
float angle = 0.1;

void display();
void framerate(int timer);

int main(int argc, char **argv)
{
	std::fstream in("cube.obj");

	std::cout.precision(6);
	in.precision(6);

	if(in.is_open())
	{
		while(!in.eof())
		{
			std::string buffer;
			std::getline(in, buffer);
			if(buffer != "")
			{ // If vertex, put in vertexData vector
				if(buffer[0] == 'v')
				{
					std::vector<std::string> splitVector;
					boost::split(splitVector, buffer, boost::is_any_of(" "));
					for(int i = 1; i < splitVector.size(); i++)
					{
						std::stringstream ss;
						float tempFloat;
						ss << splitVector[i];
						ss >> tempFloat;
						vertexData.push_back(tempFloat);
					}
				}
				else if(buffer.find("usemtl") != std::string::npos)
				{
					// Material stuff
				}
				else if(buffer[0] == 'f')
				{ // If face, put in faceData vector
					std::vector<std::string> splitVector;
					boost::split(splitVector, buffer, boost::is_any_of(" "));
					for(int i = 1; i < splitVector.size(); i++)
					{
						std::stringstream ss;
						int tempInt;
						ss << splitVector[i];
						ss >> tempInt;
						faceData.push_back(tempInt);
					}
				}
			}
		}

		for(int i = 0; i < faceData.size(); i++)
		{
			std::cout << "glVertex3f(" << vertexData[faceData[i]] << ", ";
			std::cout << vertexData[faceData[i] + 1] << ", ";
			std::cout << vertexData[faceData[i] + 2] << ");" << std::endl;
			// An object IS displayed if I use this output in my code instead of the for loop but the
			// object still isn't correct.
		}

		glutInit(&argc, argv);
		glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
		glutInitWindowSize(500, 500);
		glutInitWindowPosition(0, 0);
		glutCreateWindow("modeltest");
		glEnable(GL_DEPTH_TEST);
		glClearColor(1.0, 1.0, 1.0, 1.0);
		glutDisplayFunc(display);
		glutTimerFunc(1000/100, framerate, 1);
		glutMainLoop();
	}
	else
	{
		return 0;
	}

	system("pause");
}

void display()
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glLoadIdentity();
	glRotatef(angle, 0.5, 0.5, 0.5);
	glColor4f(1.0, 0.0, 0.0, 1.0);
	glBegin(GL_TRIANGLES);
	for(int i = 0; i < faceData.size(); i++)
	{
		glVertex3f(vertexData[faceData[i]], vertexData[faceData[i]] + 1, vertexData[faceData[i]] + 2);
	}

	// Nothing displayed
	glEnd();

	glutSwapBuffers();
}

void framerate(int timer)
{
	angle += 0.5;
	glutPostRedisplay();
	glutTimerFunc(1000/60, framerate, timer);
}

The file I’m trying to read is a triangulated cube exported from Blender.


# Blender3D v249 OBJ File: 
# 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
usemtl Material
s off
f 5 1 4
f 5 4 8
f 3 7 8
f 3 8 4
f 2 6 3
f 6 7 3
f 1 5 2
f 5 6 2
f 5 8 6
f 8 7 6
f 1 2 3
f 1 3 4

Maybe there already is a library for loading OBJ files, or would another model format be more appropriate?

change this line


glVertex3f(vertexData[faceData[i]], vertexData[faceData[i]] + 1, vertexData[faceData[i]] + 2);

to this


glVertex3f(vertexData[faceData[i]], vertexData[faceData[i]+1] , vertexData[faceData[i]+2]);

I have written a simple obj loader (will add material support soon) in opengl3.3 u may get it from here http://www.spacesimulator.net/wiki/index.php/3d_Engine_Projects

If u need a library to load your models (3ds, obj etc.) u may look at http://assimp.sourceforge.net/.

OBJ is a really nice format, but one thing that catches out most of the importers I’ve used for editors/engines is that there’s two ways of counting indices; either from zero up from the start of the file or from negative one down from the current position in the file. Exporters/importers generally seem to understand one or the other and it’s rather annoying.