TexCoords gone mad with the help of VBO's

Hello I have a problem with VBO’s. Everything is working great except texture coordinates, they are nowhere near where they should be.

This image might help you understand my problem:

I use 4 separate VBO’s, I have heard using two is better but I have also heard nVidia recommending not to. Anyhow I don’t think that is my problem here, but you tell me…

The following is the code I use to render my models

void Model::Render() {
	if(Materials.at(0).TexMat.texture)
		glBindTexture(GL_TEXTURE_2D,Materials.at(0).TexMat.texture); //Don't ask

	glBindBufferARB(GL_ARRAY_BUFFER_ARB,vBuffer[3]);
	glNormalPointer(GL_FLOAT,0,0);

	glBindBufferARB(GL_ARRAY_BUFFER_ARB,vBuffer[2]);
	glTexCoordPointer(2,GL_FLOAT,0,0);

	glBindBufferARB(GL_ARRAY_BUFFER_ARB,vBuffer[0]);
	glVertexPointer(3,GL_FLOAT,0,0);

	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	glEnableClientState(GL_VERTEX_ARRAY);
	glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB,vBuffer[1]);
	glDrawRangeElements(GL_TRIANGLES,0,0,Stats.nTriangles,GL_UNSIGNED_SHORT,0);
	glDisableClientState(GL_VERTEX_ARRAY);
	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}

For the record here is my OBJ loader

void Model::Load(string tmp) {
	vector<unsigned short> Triangles;
	vector<GLfloat> Vertices;
	vector<GLfloat> Coords;
	vector<GLfloat> Normals;

	ifstream f(tmp.c_str());

	if(!f) {
		cerr<<"ERROR: Model \""<<tmp<<"\" was not found"<<endl;
		exit(1);
	}

	tmp.erase(tmp.size()-4,0); //Remove file extension
	Stats.Name=tmp; //Save the name to model stats

	while(f>>tmp) {
		if(tmp=="mtllib") {
			f>>tmp;
			ifstream matfile((TexDir+tmp).c_str());

			while(matfile>>tmp) {
				if(tmp=="newmtl") {
					matfile>>tmp;
					mat tmp_mat;
					tmp_mat.Name=tmp;
					Materials.push_back(tmp_mat);
				}

				else if(tmp=="Ns") {
					matfile>>tmp;
					Materials.back().Specular2=atof(tmp.c_str());
				}

				else if(tmp=="Ka") {
					for(int i=0; i<3; i++) {
						matfile>>tmp;
						Materials.back().Ambient[i]=atof(tmp.c_str());
					}
				}

				else if(tmp=="Kd") {
					for(int i=0; i<3; i++) {
						matfile>>tmp;
						Materials.back().Diffuse[i]=atof(tmp.c_str());
					}
				}

				else if(tmp=="Ks") {
					for(int i=0; i<3; i++) {
						matfile>>tmp;
						Materials.back().Specular[i]=atof(tmp.c_str());
					}
				}

				else if(tmp=="map_Kd") {
					matfile>>tmp;
					Materials.back().TexMat.Load(TexDir+tmp);
				}
			}
		}

		else if(tmp=="v") {
			for(int i=0; i<3; i++) {
				f>>tmp;
				Vertices.push_back(atof(tmp.c_str()));
			}
		}

		else if(tmp=="vn") {
			for(int i=0; i<3; i++) {
				f>>tmp;
				Normals.push_back(atof(tmp.c_str()));
			}
		}

		else if(tmp=="vt") {
			for(int i=0; i<2; i++) {
				f>>tmp;
				Coords.push_back(atof(tmp.c_str()));
			}
			f>>tmp; //No Z
		}

		else if(tmp=="f") {
			int vertices[4];
			int texcoords[4];
			int normals[4];

			for(int i=0; i<3; i++) {
				f>>tmp;
				GetFaces(tmp,vertices[i],texcoords[i],normals[i]);
			}

			if(f.peek()==' ') {
				f>>tmp;
				//Convert quad to triangles
			}
			else {
				for(int i=0; i<3; Triangles.push_back(vertices[i++]-1));
			}
		}
	}

	glGenBuffersARB(4,vBuffer);

	//Vertices
	glBindBufferARB(GL_ARRAY_BUFFER_ARB,vBuffer[0]);
	glBufferDataARB(GL_ARRAY_BUFFER_ARB,Vertices.size()*sizeof(GLfloat),&Vertices[0],GL_STATIC_DRAW_ARB);

	//Vertex Indices
	glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB,vBuffer[1]);
	glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB,Triangles.size()*sizeof(unsigned short),&Triangles[0],GL_STATIC_DRAW_ARB);

	//Tex Coords
	glBindBufferARB(GL_ARRAY_BUFFER_ARB,vBuffer[2]);
	glBufferDataARB(GL_ARRAY_BUFFER_ARB,Coords.size()*sizeof(GLfloat),&Coords[0],GL_STATIC_DRAW_ARB);

	//Vertex Normals
	glBindBufferARB(GL_ARRAY_BUFFER_ARB,vBuffer[3]);
	glBufferDataARB(GL_ARRAY_BUFFER_ARB,Normals.size()*sizeof(GLfloat),&Normals[0],GL_STATIC_DRAW_ARB);

	//Remember the properties
	Stats.nVertices=Vertices.size();
	Stats.nTriangles=Triangles.size();
	Stats.nCoords=Coords.size();
	Stats.nNormals=Normals.size();
}

I know that I have gotten the data from my vectors to work with immediate mode, even textures if that’s any help.

Hoping for answers, I have been struggling with this for a long time!

The OBJ file has separate indices for vertex positions, normals and texture coordinates. The OpenGL supports only one index stream used by all of them. You need to create vertex for each combination of position&normal&coordinate indices used by face inside the OBJ file.

I heard that from another person, just wanted to make sure. Is there any tutorial about this? I find it hard to imagine the solution.

I don’t think there are any tutorial about this.
What you have to do is index one characteristic of your geometry and then duplicate the rest of the data relating to these indices.

I mean, usually your indices are vertex indices. Then you have to generate normals and texture coordinates arrays thinking that vertex indices are the ones that will be used to index these arrays.
Practically you loop on each triangle vertices, you read texture coordinates and normals at each vertex and build the new texture coordinates and normals arrays at the same time.
So you will end with a lot of duplicated data, but you don’t have the choice for now.

I hope I am clear. Don’t hesitate to ask more questions. :slight_smile:

Some pseudocode would not be bad, really :slight_smile:

update
I now have a vector of sorted vertices

struct sorted_vertex {
	GLfloat x, y, z;
	GLfloat s, t;
	GLfloat nx, ny, nz;
};

they are matching the vertices used in OBJ files

Thanks for explaining more in depth dletozeun

4600 FPS… :slight_smile:

Now, what would be the next step in my render?

It’s a shield. Now you should add a sword.

CatDog

And a knight to carry this stuff. :slight_smile:

:slight_smile:
Guess I’ll be looking into GLSL next.

you will put some metal reflection? That would be nice

It’s not just a shield, it’s the master shield.