How to set the normals of a polyhedron to have flat faces?

A dodecahedron can be created with 20 vertices. Do I need to duplicate the edge vertices to get the correct normals for each face and therefore correct lighting?

For a dodecahedron that would mean 12 sides x 5 vertices per side = 60 vertices, instead of the 20 I have now. Or is it possible to get the expected flat-face look with 20 vertices and 20 normals? I know I could set glShadeModel(GL_FLAT); but that would affect all objects.

technically you won’t be adding vertices, but working with the indices (60 indices, 20 vertices. each face has three indices to the three vertices making up the face)

I’m not sure if this will solve your problem, but the resolution found in this post may help: Mesh lighting / normal issues

I had similar issues with a project, and the answers for how to set normals really helped. I’m not sure if you have to do anything specific to the icosphere mesh that openframeworks can generate…

if you need flat face look, then indices won’t work, you really need to add one normal per face for each vertex that belongs to that face and for that you need to duplicate the vertices too. another possibility if you are working with open gl 3+ is to set the correct normal for each face in the provoking vertex and set the interpolation type in the varyings as flat:

I’m not sure if this will do what you want but I post it just in case you find it useful.

void ofApp::addSurfaceNormalsToMesh(ofMesh &mesh) {

for (int i=0; i<mesh.getNumVertices(); i+=3) {

    ofVec3f v0 = mesh.getVertex(i);
    ofVec3f v1 = mesh.getVertex(i+1);
    ofVec3f v2 = mesh.getVertex(i+2);

    ofVec3f U = v1 - v0;
    ofVec3f V = v2 - v0;
    
    float x = (U.y * V.z) - (U.z * V.y);
    float y = (U.z * V.x) - (U.x * V.z);
    float z = (U.x * V.y) - (U.y * V.x);
    
    ofVec3f normal(x,y,z);
    
    normal.normalize();
    
    mesh.addNormal(normal);
    mesh.addNormal(normal);
    mesh.addNormal(normal);
    }
}

Source : https://www.khronos.org/opengl/wiki/Calculating_a_Surface_Normal
also you can check ofSpherePrimitive has an opposite winding order

1 Like