Triangles and quads don't check for degenerate faces (where the normal might be zero), while ngons already set the Z component to 1 for that, which is also what we do for vertex normals. Also reorder the face size checks to put quads and triangles before N-gons, since they are typically more common on high-poly meshes. And change the check for 2 sided faces into an assert.