问题
I have an obj file and have succesfully loaded the object to opengl without using the normals given.
This is how it looks:
The format of the file is:
v x y z
vn x y z
f x//x' y//y' z//z'
The displaying function of the mesh is like that:
glBegin(GL_TRIANGLES);
for all faces
{
glVertex3f(.., .., ..);
glVertex3f(.., .., ..);
glVertex3f(.., .., ..);
}
glEnd();
And the result is this:
I've read that the object might look flat due to the default normal vector that OpenGL uses for lighting equations.
This could be solved with normals. The normals given are 780 and the vertices 155.
I've tried using glNorm before each glVertex3f call but the obj looks completely weird (lines, etc).
What should I do?
EDIT #1: This is how I read the file:
void loader(class mesh &tree)
{
int vx1, vx2, vx3, vn1, vn2, vn3;
ifstream file;
string line;
point vec, norm;
face tempface;
file.open("tree.obj");
if (file.is_open() == true)
{
while(getline(file, line) )
{
if (line.substr(0,2) == "") continue;
else if (line.substr(0, 2) == "v ")
{
istringstream numbers(line.substr(2));
numbers >> vec.x >> vec.y >> vec.z;
tree.vectors.push_back(vec);
}
else if (line.substr(0,2) == "vn")
{
istringstream numbers(line.substr(2));
numbers >> norm.x >> norm.y >> norm.z;
tree.normals.push_back(norm);
}
else if (line.substr(0,2) == "f ")
{
face f;
line = line.substr(2,line.length());
for (string::iterator it = line.begin(); it != line.end(); ++it)
{
if (*it == '/')
{
//erase both of the "//"
line.erase(it);
line.erase(it);
//add a space between the numbers
line.insert(it, ' ');
}
}
istringstream inp(line);
inp >> f.vert_indices[0] >> f.norm_indices[0] >> f.vert_indices[1] >> f.norm_indices[1] >> f.vert_indices[2] >> f.norm_indices[2];
tree.faces.push_back(f);
}
else
continue;
}
file.close();
}
}
And this is how I am displaying it:
void mesh::displayMesh()
{
glPushMatrix();
glBegin(GL_TRIANGLES);
for(vector<face>::const_iterator it = faces.begin();
it != faces.end(); ++it)
{
//glVertex3f(normals[it->norm_indices[0] -1 ].x, normals[it->norm_indices[0] -1 ].y, normals[it->norm_indices[0] -1 ].z);
glVertex3f(vectors[it->vert_indices[0] -1 ].x, vectors[it->vert_indices[0] -1 ].y, vectors[it->vert_indices[0] -1 ].z);
//glVertex3f(normals[it->norm_indices[1] -1 ].x, normals[it->norm_indices[1] -1 ].y, normals[it->norm_indices[1] -1 ].z);
glVertex3f(vectors[it->vert_indices[1] -1 ].x, vectors[it->vert_indices[1] -1 ].y, vectors[it->vert_indices[1] -1 ].z);
//glVertex3f(normals[it->norm_indices[2] -1 ].x, normals[it->norm_indices[2] -1 ].y, normals[it->norm_indices[2] -1 ].z);
glVertex3f(vectors[it->vert_indices[2] -1 ].x, vectors[it->vert_indices[2] -1 ].y, vectors[it->vert_indices[2] -1 ].z);
}
glEnd();
glPopMatrix();
}
The function displayMesh is called within Render function of openGL and the loader function is called into Setup OpenGL function and the mesh tree object is a global variable.
EDIT #2:
This how the tree looks with the normals:
回答1:
Shouldn't you have the following in your draw code instead?
glNormal3f(normals[it->norm_indices[0] -1 ].x, normals[it->norm_indices[0] -1 ].y, normals[it->norm_indices[0] -1 ].z);
glVertex3f(vectors[it->vert_indices[0] -1 ].x, vectors[it->vert_indices[0] -1 ].y, vectors[it->vert_indices[0] -1 ].z);
glNormal3f(normals[it->norm_indices[1] -1 ].x, normals[it->norm_indices[1] -1 ].y, normals[it->norm_indices[1] -1 ].z);
glVertex3f(vectors[it->vert_indices[1] -1 ].x, vectors[it->vert_indices[1] -1 ].y, vectors[it->vert_indices[1] -1 ].z);
glNormal3f(normals[it->norm_indices[2] -1 ].x, normals[it->norm_indices[2] -1 ].y, normals[it->norm_indices[2] -1 ].z);
glVertex3f(vectors[it->vert_indices[2] -1 ].x, vectors[it->vert_indices[2] -1 ].y, vectors[it->vert_indices[2] -1 ].z);
EDIT: oops, you realized that already
If you want to check if the normals are correct, color each vertex according to it's normal. Use glColor3f
but supply the normals.
回答2:
when you use erase it invalidates the iterator
//erase both of the "//"
it = line.erase(it);
it = line.erase(it);
//add a space between the numbers
it = line.insert(it, ' ');
however you can erase once and then replace
//erase both of the "//"
it = line.erase(it);
//add a space between the numbers
*it = ' ';
来源:https://stackoverflow.com/questions/14637498/loading-an-obj-file-how-to-use-normals-vertices-normals