I feel a bit silly to ask such a question, but I want to dynamically create Geoms which have flat shading, that is face normals and not vertex normals.

I get the list of vertices and triangles from a thrid-party library, but unfortunately without any normals. Triangles share vertices, i. e. a cube has 8 vertices and not 24.

I create a Geom using GeomVertexWriter and the GeomTriangles primitive. I know how to compute face normals, but I wonder how/where to store them.

Ok, I could add a “normal” collumn to the GeomVertexData, and compute vertex normals. But I explicitly want to have face normals.

Face normals are stored on the vertices of the face. This means that in order to have face normals, you just need to make sure that vertices are unique to every individual face. If the model data has vertices shared among connected triangles, you will need to duplicate these vertices so that every triangle has its own set of 3 vertices. (The number of vertices in the final model should be three times the amount of triangles).

It should be easy to do this; iterate over the source data triangles, for every triangle, get the position of the vertices, and then write a Panda triangle with three new vertices.

Then, you can compute the face normals (should be a simple (b - a).cross(c - a), where a b and c are the positions of the vertices), and assign them to the three vertices of that triangle.

Well, thank you for the explanation. This is what I have been afraid of, since I have shared vertices, and I don’t want to duplicate vertices (vertices have identity in my case). I think I will go for vertex normals then.

You can also have face vertices where you have shared vertices between triangles. This uses OpenGL’s glShadeModel(GL_FLAT) state.

To do this, you must arrange your vertices such that the last vertex of each triangle holds the key face vertex (the first two vertices don’t matter). When you have shared vertices, you can always arrange your triangles so that each different triangle has a different last vertex.

Then you call GeomTriangles.setShadeModel(Geom.SMFlatLastVertex), and NodePath.setAttrib(ShadeModelAttrib.make(ShadeModelAttrib.MFlat)).

The egg loader will do this automatically if you create polygon normals and have “egg-flat-shading 1” in your Config.prc file. (The default is egg-flat-shading 0, which means the egg loader will replicate vertices instead. This is usually preferable because it avoids the extra state change required by the ShadeModelAttrib.)