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