using different textures problem...

Started by
3 comments, last by ov3r_dr1v3 16 years, 12 months ago
Hey... I'm looking for some help with this texturing problem that i am having, and I just can't seem to figure it out. Anywho, I have written .OBJ file loader which obviously loads in the geometry, aswell as read the associated .mtl file. here is the code i am using to scan through the .mtl file and store all the data...

void OBJ_Model::load_Material(string filename)
{
	model.material.numTextures = 3;
	model.material.Textures = new Texture[model.material.numTextures];	// Set the size of the Texturres Array
	int texCount = 0;							// current texture being processed
	string str;									// string used to hold the current line	
	ifstream file(filename.c_str());			// open 'filename' filestream
	istringstream line(str);
	if (file.is_open())							// check to see if filestream is open
	{
		string id, r, g, b;
		while (!file.eof())						// loop through every line in the file
		{
			getline(file, str);					// retrieve next line and store in str
			if(str.substr(0, 6) == "newmtl")	// create a new texture
			{
				cout << "new material... ";
				// store the name of the texture
				model.material.Textures[texCount].name = str.substr(7, str.length());
				cout << model.material.Textures[texCount].name << endl;
			}
			if(str.substr(0, 2) == "Ka")	// ambient data
			{
				r = str.substr(4, 3); g = str.substr(8, 3); b = str.substr(12, 3);
				sscanf(r.c_str(), "%f", &model.material.Textures[texCount].Ka[0]);
				sscanf(g.c_str(), "%f", &model.material.Textures[texCount].Ka[1]);
				sscanf(b.c_str(), "%f", &model.material.Textures[texCount].Ka[2]);
				cout << "  ambient data... " << model.material.Textures[texCount].Ka[0]
					<< " " << model.material.Textures[texCount].Ka[1] << " "
						<< model.material.Textures[texCount].Ka[2] << endl;
				r.clear(); g.clear(); b.clear();
			}
			if(str.substr(0, 2) == "Kd")	// difuse data
			{
				r = str.substr(4, 3); g = str.substr(8, 3); b = str.substr(12, 3);
				sscanf(r.c_str(), "%f", &model.material.Textures[texCount].Kd[0]);
				sscanf(g.c_str(), "%f", &model.material.Textures[texCount].Kd[1]);
				sscanf(b.c_str(), "%f", &model.material.Textures[texCount].Kd[2]);
				cout << "  diffuse data... " << model.material.Textures[texCount].Kd[0]
					<< " " << model.material.Textures[texCount].Kd[1] << " "
						<< model.material.Textures[texCount].Kd[2] << endl;
				r.clear(); g.clear(); b.clear();
			}
			if(str.substr(0, 2) == "Ks")	// specular data
			{
				r = str.substr(4, 3); g = str.substr(8, 3); b = str.substr(12, 3);
				sscanf(r.c_str(), "%f", &model.material.Textures[texCount].Ks[0]);
				sscanf(g.c_str(), "%f", &model.material.Textures[texCount].Ks[1]);
				sscanf(b.c_str(), "%f", &model.material.Textures[texCount].Ks[2]);
				cout << "  diffuse data... " << model.material.Textures[texCount].Ks[0]
					<< " " << model.material.Textures[texCount].Ks[1] << " "
						<< model.material.Textures[texCount].Ks[2] << endl;
				r.clear(); g.clear(); b.clear();
			}
			if(str.substr(0, 1) == "d")		// alpha data
			{
				r = str.substr(3, 3);
				sscanf(r.c_str(), "%f", &model.material.Textures[texCount].d);
				cout << "  alpha data... " << model.material.Textures[texCount].d << endl;
				r.clear();
			}
			if(str.substr(0, 2) == "Ns")	// shininess data
			{
				r = str.substr(4, 3);
				sscanf(r.c_str(), "%f", &model.material.Textures[texCount].Ns);
				cout << "  shininess data... " << model.material.Textures[texCount].Ns << endl;
				r.clear();
			}
			if(str.substr(0, 5) == "illum")	// illumination model
			{
				r = str.substr(6, 1);
				sscanf(r.c_str(), "%d", &model.material.Textures[texCount].illum);
				cout << "  illumination model... " << model.material.Textures[texCount].illum << endl;
				r.clear();
			}
			if(str.substr(0, 6) == "map_Kd")	// tetxure filename
			{
				char temp[50];
				model.material.Textures[texCount].filename = new char[50];
				string temp_filename = str.substr(7, str.length()-7);
				strcpy(model.material.Textures[texCount].filename, temp_filename.c_str());
				cout << "  texture filename... " << model.material.Textures[texCount].filename;

				model.material.Textures[texCount].texture = tgaLoadAndBind((model.material.Textures[texCount].filename), TGA_DEFAULT);
				cout << " loaded!" << endl;
			}
		}			
	}
}


which as far as i can see, and when i was writing this i'd use some cout statements after everything was stored, just to make sure the right data was stored, which is was. now whenever i am scanning through the .OJB file, whenever "usemtl" is encountered, the proceeding filename will be the source of the texture used for all faces that follow...that is until anothe "usemtl" is encountered, in whcih case that texture will be use e.t.c. here is the code i used to handle this...

else if(str.substr(0, 6) == "usemtl")
{
	for(int i = 0; i < model.material.numTextures; i++)
	{
		if(model.material.Textures.name.compare(str.substr(7, str.length()-1)) == 0)
		{
			currentTexture = model.material.Textures;
		}
	}
}


As you can see i have a variable "currentTexture" which stores the tetxure, so when it come to reading in a face, i simply do this... model.TriangleArray[triCount].texture = currentTexture; so that each Triangle type will have its own texture. now when it come to actually drawing the objects i simply do this...

void OBJ_Model::draw()
{
	int numTriangles = model.NumTriangle;
	glBegin(GL_TRIANGLES);
		for(int i = 0; i < numTriangles; i++)
		{
			glBindTexture(GL_TEXTURE_2D, model.TriangleArray.texture.texture);
			glTexCoord2f(model.TriangleArray.texCoords[0].U,
				model.TriangleArray.texCoords[0].V);
			glNormal3f(model.TriangleArray.normals[0].X,
				model.TriangleArray.normals[0].Y,
				model.TriangleArray.normals[0].Z);
			glVertex3f(model.TriangleArray.vertices[0].X, 
				model.TriangleArray.vertices[0].Y,
				model.TriangleArray.vertices[0].Z);
			glTexCoord2f(model.TriangleArray.texCoords[1].U,
				model.TriangleArray.texCoords[1].V);
			glNormal3f(model.TriangleArray.normals[1].X,
				model.TriangleArray.normals[1].Y,
				model.TriangleArray.normals[1].Z);
			glVertex3f(model.TriangleArray.vertices[1].X, 
				model.TriangleArray.vertices[1].Y,
				model.TriangleArray.vertices[1].Z);
			glTexCoord2f(model.TriangleArray.texCoords[2].U,
				model.TriangleArray.texCoords[2].V);
			glNormal3f(model.TriangleArray.normals[2].X,
				model.TriangleArray.normals[2].Y,
				model.TriangleArray.normals[2].Z);
			glVertex3f(model.TriangleArray.vertices[2].X, 
				model.TriangleArray.vertices[2].Y,
				model.TriangleArray.vertices[2].Z);
		}
	glEnd();
}


calls are made to enable/disable 2D texturing and belnding before the call to draw() is made in my method responsible for drawing the scene... The problem I'm having is that everything object in teh scone is being texured using the last texure that was loaded. I'm obviously missing something stupidly obvious lol! but its getting on my nerves and been staring at this god damn screen for ages now... If any one can help me i'd be very grateful thanks
Advertisement
here is an image of my program running if it helps...as you can see each of the cubes is textured using the same texture, which coinciedntyl is the last texture loaded from the last mtl file read...

texture problem


very frustrating, don't understand ahhhh!
I'm not sure about all your code, but first thing you should correct is:

glBegin();
glBindTexture(GL_TEXTURE_2D, model.TriangleArray.texture.texture);
// your code
glEnd();


should be

glBindTexture(GL_TEXTURE_2D, model.TriangleArray.texture.texture);
glBegin();
// your code
glEnd();

Never use glBindTexture(....); function
between glBegin(); and glEnd(); functions.

Hope this helps...
jesus christ what a bloody idiot! I tell you, about a day ive been trying to solve this, so so stupid lol.

thanks buddy!!!

well now, this works perfectly for objects which only have one texture, however when i have objects that have multiple tetxures, i get a similar problem.

texture_problem2

The brown cube to the far left is meant to be tetxured with three materials, however is only textured with one, the last one. So this makes me think that there is a problem when i am storing the current texture...

Just for reference, here are the data structures im using to hold the data loaded in from the file

typedef struct _Vertex {float X, Y, Z;} Vertex;		// Vertex Typetypedef struct _Normal {float X, Y, Z;} Normal;		// Normals Type	typedef struct _TexCoord {float U, V;} TexCoord;	// TexCoord Typetypedef struct _Texture								// Texture type...will be used to{													// hold all the data read in	string name;		// reference name			// from a material file	char* filename;		// filename of texture	GLuint texture;		// OpenGL texture object	float Ka[3];		// ambience data	float Kd[3];		// diffuse data	float Ks[3];		// specular data	float d;			// alpha data	float Ns;			// shininess data	int illum;			// illumination model} Texture;typedef struct _Triangle							// Triangle data type... consists{													// of 3 vertices, 3 normals,	Vertex vertices[3];								// 3 texCoords and a texture	Normal normals[3];	TexCoord texCoords[3];	Texture texture;} Triangle;typedef struct _Material							// Material library data...{	string filename;	// filename of material library	int numTextures;	// Number of Textures	Texture *Textures;	// Array of textures in the library} Material;typedef struct _Model		// model type... kind of encapsulates all of the above{							// data types	int NumVertex, NumNormal, NumTexCoord, NumTriangle, NumGroups;    Vertex *VertexArray;    Normal *NormalArray;    TexCoord *TexCoordArray;    Triangle *TriangleArray;	Material material;} Model;


now here is the code i use when a nwe material is supposed to be used...firstly i created a new Texture object to hold the 'currentTexture', which i would obviously update

Texture currentTexture;blah blah blah...handle other stuff			else if(str.substr(0, 6) == "usemtl")			{				// string containing the name of the material				string temp = str.substr(7, str.length());				// loop through all the materials and find the appropriate one				for(int i = 0; i < model.material.numTextures; i++)				{										if(model.material.Textures.name.compare(temp) == 0)					{						// set the current material to the appropriate one						currentTexture = model.material.Textures;											}				}			}


I'm really confused...I think the problme may lie with the string compare() method, not really sure...

Is there a better way to implement a solution to this problem, this is the only way i could think of doing this since when "usemtl" is encountered in a OBJ file, the only piece of reference iformation provided with it is the material name


any help would be greatly appreciated

thanks
update on the problem...the problem definelty lies here...

			else if(str.substr(0, 6) == "usemtl")			{				// string containing the name of the material				string temp = str.substr(7, str.length());				// loop through all the materials and find the appropriate one				for(int i = 0; i < model.material.numTextures; i++)				{						if(temp.compare(model.material.Textures.name) == 0)					{							// set the current material to the appropriate one						currentTexture = model.material.Textures;											}				}			}


the program will only match the strings once for some reason, so the current texture is set for the first texture, and is never reset when its suppose to be...I don't understand this?

This topic is closed to new replies.

Advertisement