PDA

View Full Version : GL_SMOOTH not working (was working before...)



paulg568
01-06-2012, 03:25 PM
Hi everyone, I just signed up and this is my first post.

This is my first attempt at OpenGL, writing an obj viewer. I was using glDrawElements for obj files that contained multiple objects and materials. Everything worked perfectly. Once I decided to add textures I found out that indices for the vertices and texture coordinates need to be in the correct order. So I rearranged them and recomputed normals. Now I am using glDrawArrays.

Prior to this change gl_smooth worked, now it does not. The upside is that textures now work.

I think it might have something to do with my calculation for normals.

Basically I have k objects from an obj file. So I need k arrays of uv coord, normals, faces, and vertices. All the faces have been triangulated.


void Model::calculateNormals(){
for (int k = 0; k < numberOfObjects; k++){
m_normals[k].resize(copied_points[k].size());
for (int i = 0; i < faces[k].size(); i += 3) {
const Point3d a = copied_points[k].at(i);
const Point3d b = copied_points[k].at(i+1);
const Point3d c = copied_points[k].at(i+2);
const Point3d normal = cross(b - a, c - a).normalize();

for (int j = 0; j < 3; ++j){
m_normals[k][i+j] += normal;
}
}
}
for(int k = 0; k < numberOfObjects; k++){
for (int i = 0; i < m_normals[k].size(); ++i){
m_normals[k][i] = m_normals[k][i].normalize();
}
}
}


Maybe there is something wrong with my rendering functions. Here is that also.



void Model::render() const
{
glEnable(GL_DEPTH_TEST);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnable(GL_NORMALIZE);
glShadeModel(GL_SMOOTH);

for(int i = 0; i < numberOfObjects; i++){
if(materials[objectMaterialInt[i]].d == 1){
renderHelper(i);
}
}
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glDisable(GL_DEPTH_TEST);
}

void Model::renderHelper(int i) const{
if(texture != NULL){
glEnable( GL_TEXTURE_2D );
glBindTexture( GL_TEXTURE_2D, texture->texture );
glTexCoordPointer(2, GL_FLOAT, sizeof(Point2d), copied_uv[i].data());
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
}
glMaterialfv(GL_FRONT, GL_AMBIENT, materials[objectMaterialInt[i]].Ka);
glMaterialfv(GL_FRONT, GL_DIFFUSE, materials[objectMaterialInt[i]].Kd);
glMaterialfv(GL_FRONT, GL_SPECULAR, materials[objectMaterialInt[i]].Ks);
glMaterialf(GL_FRONT, GL_SHININESS, materials[objectMaterialInt[i]].Ns);

glPushMatrix();
glTranslatef(position[0], position[1], position[2]);
glVertexPointer(3, GL_FLOAT, 0, (float *)copied_points[i].data());
glNormalPointer(GL_FLOAT, 0, (float *)m_normals[i].data());
glDrawArrays(GL_TRIANGLES, 0, faces[i].size());
glPopMatrix();

if(texture != NULL){
glDisable(GL_TEXTURE_2D);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
}


Let me know if you need more information. Thanks.

paulg568
01-06-2012, 04:21 PM
So I printed out the values of the normals. Each face is a triangel, and the 3 vertices of a triangle have the same normal vector. Shouldn't the normals be averaged with the points around it? I thought that was what I was doing but I guess not. Can someone help me with this?

paulg568
01-06-2012, 05:11 PM
I calculated the normals before reordering everything. This allowed me to calculate the normals of each vertex based on surround vertices instead of calculating normals based on a single face.