Jump to content
  • Advertisement
Sign in to follow this  
Optln

OpenGL Error in the .obj loader

This topic is 3581 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm trying to write an .obj file format loader for my OpenGL based engine. But models that I load aren't looking properly and I just can't find the problem. I'll be glad if someone can help me. Here's the code:
#include <iostream>
#include <fstream>
#include <vector>
#include "re_renderer.h"
#include "re_math.h"

#pragma once

class COBJModel: public CTexture
{
public:
	COBJModel();

	void load(const char *objFile);
	void loadDiffuseMap(const char *diffuseMapFile);
	void render(void);
private:
	vector <int> triangleData;
	vector <float> vertices;
	vector <float> texCoords;
	vector <float> normals;
	vector <float> vertexArray;
	vector <float> texCoordArray;
	vector <float> normalArray;
	GLuint diffuseTexture;
	
	int x, y, z, nx, ny, nz, tx, ty, tz;
	float a, b, c, na, nb, nc, u, v;
};




#include "re_objloader.h"

COBJModel::COBJModel()
{
	x = 0;
	y = 0;
	z = 0;
	nx = 0;
	ny = 0;
	nz = 0;
	tx = 0;
	ty = 0;
	tz = 0;
	a = 0;
	b = 0;
	c = 0;
	na = 0;
	nb = 0;
	nc = 0;
	u = 0;
	v = 0;
}

void COBJModel::load(const char *objFile)
{
	int i = 0;
	ifstream modelFile;
	string line;
	
	modelFile.open(objFile, ios::in);    
	if (!modelFile.fail())
    {
        while (!modelFile.eof())
        {
			getline(modelFile, line);
			const char* data = line.c_str();

			if(data[0] == 'v' && data[1] == ' ')
			{
				sscanf(data, "v %f %f %f", &a, &b, &c);
				vertices.push_back(a);
				vertices.push_back(b);
				vertices.push_back(c);
			}

			else if(data[0] == 'v' && data[1] == 'n')
			{
				sscanf(data, "vn %f %f %f", &na, &nb, &nc);
				normals.push_back(na);
				normals.push_back(nb);
				normals.push_back(nc);
			}
			
			else if(data[0] == 'v' && data[1] == 't')
			{
				sscanf(data, "vt %f %f", &u, &v);
				texCoords.push_back(u);
				texCoords.push_back(v);
			}
		
			else if(data[0] == 'f')
			{
				sscanf(data, "f %d/%d/%d %d/%d/%d %d/%d/%d", &x, &tx, &nx, &y, &ty, &ny, &z, &tz, &nz);
				triangleData.push_back(x);
				triangleData.push_back(y);
				triangleData.push_back(z);
				triangleData.push_back(tx);
				triangleData.push_back(ty);
				triangleData.push_back(tz);
				triangleData.push_back(nx);
				triangleData.push_back(ny);
				triangleData.push_back(nz);
			}

			else if(data[0] == 's')
			{
			}

			else if(data[0] == 'g')
			{
			}

			else if(data[0] == 'm')
			{
			}

			else if(data[0] == 'u')
			{
			}
		}

		for(int i = 0; i < triangleData.size() / 9; i++)
		{
			vertexArray.push_back(vertices[triangleData[9 * i]]);
			vertexArray.push_back(vertices[triangleData[(9 * i) + 1]]);
			vertexArray.push_back(vertices[triangleData[(9 * i) + 2]]);
			texCoordArray.push_back(texCoords[triangleData[(9 * i) + 3]]);
			texCoordArray.push_back(texCoords[triangleData[(9 * i) + 4]]);
			texCoordArray.push_back(texCoords[triangleData[(9 * i) + 5]]);
			normalArray.push_back(normals[triangleData[(9 * i) + 6]]);
			normalArray.push_back(normals[triangleData[(9 * i) + 7]]);
			normalArray.push_back(normals[triangleData[(9 * i) + 8]]);
		}
		cout << "Loaded model \"" << objFile << "\"" << endl;
    }
	else
		cout << "Could not load model \"" << objFile << "\"" << endl;
	modelFile.close();
}

void COBJModel::loadDiffuseMap(const char *diffuseMapFile)
{
	diffuseTexture = loadTexture(diffuseMapFile);
}

void COBJModel::render()
{
	glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, diffuseTexture);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	glEnableClientState(GL_NORMAL_ARRAY);
	glEnableClientState(GL_VERTEX_ARRAY);
	glTexCoordPointer(3, GL_FLOAT, 0, &texCoordArray[0]);
	glNormalPointer(GL_FLOAT, 0, &normalArray[0]);
	glVertexPointer(3, GL_FLOAT, 0, &vertexArray[0]);
	glDrawArrays(GL_TRIANGLES, 0, vertexArray.size());
	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
	glDisableClientState(GL_NORMAL_ARRAY);
	glDisableClientState(GL_VERTEX_ARRAY);
	glDisable(GL_TEXTURE_2D);
}






And this is the result that I am getting(it's supposed to be a trash can :) ): http://img204.imageshack.us/my.php?image=newbitmapimagebm7.jpg

Share this post


Link to post
Share on other sites
Advertisement
Face indices in .obj files start at 1, IIRC, whereas you want them to start at 0, so you could try:


triangleData.push_back(x-1);
triangleData.push_back(y-1);
triangleData.push_back(z-1);
// ...

Share this post


Link to post
Share on other sites
Quote:
Original post by sprite_hound
Face indices in .obj files start at 1, IIRC, whereas you want them to start at 0, so you could try:


triangleData.push_back(x-1);
triangleData.push_back(y-1);
triangleData.push_back(z-1);
// ...


You are right, I forgot about that. Unfortunately it's still not working. I think there's another error in the code. I'll look onto it. Thanks by the way.

Share this post


Link to post
Share on other sites
You push U and V onto the texCoords-array, but you pass 3 as the number of coordinates per element as the first argument to glTexCoordPointer().

Share this post


Link to post
Share on other sites
Faces in the .obj files are like this:

f 710/107/273 711/108/273 712/105/273
(vert)/(text)/(norm)

But texture coordinates are like this:
vt 0.831538 0.449444
(u) (v)

I guessed that if there are 3 texture coordinates per face, I should initialize the pointer with 3 elements.

And I tried to draw the model with just vertices and it's still not working:

glBegin(GL_TRIANGLES);
for(unsigned int i = 0; i < vertexArray.size() - 2; i++)
{
glVertex3f(vertexArray, vertexArray[i + 1], vertexArray[i + 2]);
}
glEnd();

Share this post


Link to post
Share on other sites
Well that looks like a bit of a pickle. I'll have a guess too:
I would next try something like this(just looking at vertex indices for the moment):


for(int i = 0; i < triangleData.size() / 9; i++)
{
int vertIndex1 = triangleData[9 * i]*3;
vertexArray.push_back(vertices[vertIndex1]);
vertexArray.push_back(vertices[vertIndex1 + 1]);
vertexArray.push_back(vertices[vertIndex1 + 2]);

int vertIndex2 = triangleData[[(9 * i) + 1]*3;
vertexArray.push_back(vertices[vertIndex2]);
vertexArray.push_back(vertices[vertIndex2 + 1]);
vertexArray.push_back(vertices[vertIndex2 + 2]);

int vertIndex3 = triangleData[[(9 * i) + 2]*3;
vertexArray.push_back(vertices[vertIndex3]);
vertexArray.push_back(vertices[vertIndex3 + 1]);
vertexArray.push_back(vertices[vertIndex3 + 2]);

... //etc, etc
...
...
}



It's based on the premise that each index in triangleData is a vertex index (as we know) and vertices are not really vertices: but every set of 3 floats in vertices is actually a vertex. I won't go into details,...but IF the code does solve your problem a careful walkthru of the code should uncover/clarify, in your own mind, this type of tedious detail that can be easily overlooked.

If that doesn't help, what next then... hmmmm?

Share this post


Link to post
Share on other sites
Quote:
Original post by steven katic
Well that looks like a bit of a pickle. I'll have a guess too:
I would next try something like this(just looking at vertex indices for the moment):

*** Source Snippet Removed ***

It's based on the premise that each index in triangleData is a vertex index (as we know) and vertices are not really vertices: but every set of 3 floats in vertices is actually a vertex. I won't go into details,...but IF the code does solve your problem a careful walkthru of the code should uncover/clarify, in your own mind, this type of tedious detail that can be easily overlooked.

If that doesn't help, what next then... hmmmm?


Yes, that solved it. I didn't think that way. Thank you very much. After I do the same to TexCoords and Normals, I'll update the code in my first post so maybe it helps someone else too :)

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!