Jump to content
  • Advertisement
Sign in to follow this  
ov3r_dr1v3

using different textures problem...

This topic is 4173 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

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

Share this post


Link to post
Share on other sites
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!

Share this post


Link to post
Share on other sites
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...

Share this post


Link to post
Share on other sites
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 Type
typedef struct _Normal {float X, Y, Z;} Normal; // Normals Type
typedef struct _TexCoord {float U, V;} TexCoord; // TexCoord Type
typedef 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

Share this post


Link to post
Share on other sites
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?

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!