GL_SMOOTH not working (was working before...)

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.

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?

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.