buildingSMART Forums

IfcPolygonalFaceSet and face winding.

IfcPolygonalFaceSet and face winding.

Hello, I’m a bit confused about the winding of faces in IfcPolygonalFaceSet.

According to the spec:

NOTE If the IfcPolygonalFaceSet is closed, the face vertices of the IfcIndexedPolygonalFace’s shall connect counterclock-wise when seen from the outside of the closed shell to guarantee that the face normal points away from the material of the shell. Inner loops, provided by the IfcIndexedPolygonalFaceWithVoids, shall connect clock-wise.

Which makes sense, however I am unsure as to how to resolve the normal direction if the vertex ordering is not supplied (as I expect) correctly. The example on that page also highlights my problem.

According to the example (specifically Figure 342)…


Face #6 (the ‘top’ of the cube) is defined 6, 7, 8, 5… which prodcues a winding which (by cross product) gives a normal of the face pointing upwards (0,0,1), assuming z up.

Face #1 (the ‘bottom’ of the cube) is defined 1, 2, 3, 4… which prodcues a winding which (by cross product) gives a normal of the face pointing upwards (0,0,1) as well… same as Face #6 [6,7,8,5]).

The windings are the same, yet I would thought the winding of face 1 should be reversed (to produce a normal 0,0,-1 by cross product)… e.g. 4, 3, 2, 1

How can I know to reverse certain windings and not others when two (horizontal) faces have windings producing the same direction when (I assume, perhaps incorrectly) that they should be different?

I’m in a catch 22, as in order to understand what is ‘inside’ or ‘outside’ of the closed shell, I need to know the correct normal in the first place. :frowning:

Also to add to my confusion, when checking IfcIndexedPolygonalFace…


… according to figures 338 and 339 (which show to different windings) it seems that the winding should be reversed simply if the indexes are provided by a PnIndex or not. This seems a really subtle behaviour trait, is this by design? why would simply having an extra ‘indexed’ layer suddenly imply the windings are opposite?

Many thanks.

The bottom face seems to be mentioned twice (1, 2, 3, 4) & (1, 4, 3, 2) (which contradicts the informal proposition about unique faces). And “front” face is not found. :thinking:

Guess it should be

-#1 IfcIndexedPolygonalFace: ((1, 2, 3, 4)
+#1 IfcIndexedPolygonalFace: ((1, 2, 6, 5)
#2 IfcIndexedPolygonalFace: ((6, 2, 3, 7)
#3 IfcIndexedPolygonalFace: ((7, 3, 4, 8)
#4 IfcIndexedPolygonalFace: ((8, 4, 1, 5)
#5 IfcIndexedPolygonalFace: ((1, 4, 3, 2)
#6 IfcIndexedPolygonalFace: ((6, 7, 8, 5)

1 Like

Apologies, posted the same link twice. The first link should be:

I have updated OP…

Ah yes hadn’t noticed that :rofl:. So there is actually a correctly wound face in that list…

The example file:

While having correct faces and indexing, also exhibits the winding issues I am having problems with.

Note the ‘bottom’ face is pointing up like the floor of the opening and top face.

I have seen examples of this in real world data too, windings not as expected (most things seem to point up +ve z, even when they should be pointing down), which makes me think this is not a one off.

Note the top of the door opening and window… in fact all ‘horizontal’ faces have windings producuing normals facing upwards.

IFC viewers don’t seem to have a problem with this.

I can circumvent the problem myself by not backface culling when drawing (which would produce visually correct results), however when I come to use CSG operations on these shells, the normals being wrong, result in bad/incorrect tessellated openings :(.

So there must be something that I am missing in order to know when to correct these windings (reversing the index ordering so to speak). Or is this just badly implemented in IFC exporters? … I suspect the former but am at a loss as to what I can do to fix this. :confused:

Embarrassingly… turned out to be a slight case of gimbal lock in one of my routines.

So the example polygonal-face-tessellation.ifc is actually correct.

As are the real world data examples I have so far re-tested.


In my defence, the example ( is definately wrong and threw me off at first.

1 Like