Hi everyone.
I’m trying to load an obj 3D model. I wrote an obj loader but the program seems draw onyl some faces. I don’t know if it’s a vertex or normal problem.
Here is the loader code:
void objLoader::readData(void)
{
ifstream input(fileName->c_str());
string buffer;
if( !input.is_open() ) {
cout << "Errore read fileName" << endl;
return;
}
while(!input.eof()) {
getline(input, buffer);
if(buffer.substr(0,2)== "vn")
theObj->NumNormal++;
else if(buffer.substr(0,2) == "vt")
theObj->NumTexCoord++;
else if(buffer.substr(0,1) == "v")
theObj->NumVertex++;
else if(buffer.substr(0,1) == "f")
theObj->NumTriangle++;
}
theObj->NormalArray = new objNormal[theObj->NumNormal];
theObj->TexCoordArray = new objTexCoord[theObj->NumTexCoord];
theObj->TriangleArray = new objTriangle[theObj->NumTriangle];
theObj->VertexArray = new objVertex[theObj->NumVertex];
input.close();
input.open(fileName->c_str());
input.clear();
if( !input.is_open() ) {
cout << "Errore read fileName" << endl;
return;
}
//contatori
int nC, vC, tC, fC;
nC = vC = tC = fC = 0;
string currMaterial;
//get the hard data, and load up our arrays...
//read one line at a time of the file...
while( !input.eof() ) {
getline(input, buffer);
istringstream line(buffer);
string temp;
string f1, f2, f3;
if(buffer.substr(0,2) == "vn") {
line >> temp >> f1 >> f2 >> f3;
theObj->NormalArray[nC].X = atof(f1.c_str());
theObj->NormalArray[nC].Y = atof(f2.c_str());
theObj->NormalArray[nC].Z = atof(f3.c_str());
nC++;
}
else if(buffer.substr(0,2) == "vt") {
line >> temp >> f1 >> f2;
theObj->TexCoordArray[tC].U = atof(f1.c_str());
theObj->TexCoordArray[tC].V = atof(f2.c_str());
tC++;
}
else if(buffer.substr(0,1) == "v") {
line >> temp >> f1 >> f2 >> f3;
theObj->VertexArray[vC].X = atof(f1.c_str());
theObj->VertexArray[vC].Y = atof(f2.c_str());
theObj->VertexArray[vC].Z = atof(f3.c_str());
vC++;
}
else if(buffer.substr(0,6) == "mtllib") {
line >> temp >> f1;
mtlL = new MtlLoader("models/"+f1);
// cout << f1 << endl;
// theObj->TriangleArray[fC].MaterialName = f1;
}
else if(buffer.substr(0,6) == "usemtl") {
line >> temp >> f1;
currMaterial = f1;
}
else if(buffer.substr(0,1) == "f") {
line >> temp >> f1 >> f2 >> f3;
int sPos = 0;
int ePos = sPos;
string temp;
ePos = f1.find_first_of("/");
//cout << currMaterial << endl;
theObj->TriangleArray[fC].MaterialName = currMaterial;
if(ePos !=string::npos) {
temp = f1.substr(sPos, ePos - sPos);
theObj->TriangleArray[fC].Vertex[0] = atoi(temp.c_str()) - 1;
// cout << temp.c_str() << endl;
sPos = ePos+1;
ePos = f1.find("/", sPos);
temp = f1.substr(sPos, ePos - sPos);
theObj->TriangleArray[fC].TexCoord[0] = atoi(temp.c_str()) -1;
// cout << temp.c_str() << endl;
sPos = ePos+1;
ePos = f1.length();
temp = f1.substr(sPos, ePos - sPos);
theObj->TriangleArray[fC].Normal[0] = atoi(temp.c_str()) -1;
// cout << temp.c_str() << endl;
}
sPos = 0;
ePos = f2.find_first_of("/");
if(ePos !=string::npos) {
temp = f2.substr(sPos, ePos - sPos);
theObj->TriangleArray[fC].Vertex[1] = atoi(temp.c_str()) - 1;
sPos = ePos +1;
ePos = f2.find("/", sPos+1);
temp = f2.substr(sPos, ePos - sPos);
theObj->TriangleArray[fC].TexCoord[1] = atoi(temp.c_str()) - 1;
sPos = ePos+1;
ePos = f2.length();
temp = f2.substr(sPos, ePos - sPos);
theObj->TriangleArray[fC].Normal[1] = atoi(temp.c_str()) - 1;
}
sPos = 0;
ePos = f3.find_first_of("/");
if(ePos !=string::npos) {
temp = f3.substr(sPos, ePos - sPos);
theObj->TriangleArray[fC].Vertex[2] = atoi(temp.c_str()) - 1;
sPos = ePos +1;
ePos = f3.find("/", sPos+1);
temp = f3.substr(sPos, ePos - sPos);
theObj->TriangleArray[fC].TexCoord[2] = atoi(temp.c_str()) - 1;
sPos = ePos+1;
ePos = f3.length();
temp = f3.substr(sPos, ePos - sPos);
theObj->TriangleArray[fC].Normal[2] = atoi(temp.c_str()) - 1;
}
fC++;
}
}
input.close();
}
the draw func:
void ObjModel::drawFace(objTriangle triangle)
{
glPushAttrib(GL_ALL_ATTRIB_BITS);
glPushMatrix();
glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//cout << triangle.MaterialName << endl;
glBegin(GL_TRIANGLES);
for(int i = 0; i< 3; ++i) {
//glColor3f(1.0f, 0.0f, 0.0f);
//std::cout << triangle.Normal[i] << ": " << NormalArray[triangle.Normal[i]].X << " " << NormalArray[triangle.Normal[i]].Y << endl;
glNormal3f(NormalArray[triangle.Normal[i]].X, NormalArray[triangle.Normal[i]].Y, NormalArray[triangle.Normal[i]].Z);
glTexCoord2f(TexCoordArray[triangle.TexCoord[i]].U, TexCoordArray[triangle.TexCoord[i]].V);
applyMaterial(triangle);
glVertex3f(VertexArray[triangle.Vertex[i]].X, VertexArray[triangle.Vertex[i]].Y, VertexArray[triangle.Vertex[i]].Z);
std::cout << VertexArray[triangle.Vertex[i]].X << " " << VertexArray[triangle.Vertex[i]].Y << " " << VertexArray[triangle.Vertex[i]].Z << endl;
}
glEnd();
glPopMatrix();
glPopAttrib();
}
void ObjModel::applyMaterial(objTriangle triangle)
{
Material *mat = getMaterialByName(triangle.MaterialName, Materials, numMaterial);
/*for(int i = 0; i < numMaterial; ++i) {
cout << "mat: " << Materials[i].name << endl;
}*/
if(mat != NULL) {
// cout << mat->name << ": " << mat->Kd[0] << " " << mat->Kd[1] << " " << mat->Kd[2] << endl;
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat->Ka);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat->Kd);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat->Ks);
glColor4f(mat->Kd[0], mat->Kd[1], mat->Kd[2], 1.0f);
//glColor3f(mat->Kd[0], mat->Kd[1], mat->Kd[2]);
}
}
The loader works only with triangles so I triangolated my 3D object (I use Maya). I print some loaded values and it seems correct.
I print