Inconsistent face visibility even though normals are facing the same direction

Hello Babylonians!

So i am working on this triangulated mesh, triangulated with an delaunay algorithm implementation:

My issue is now that the faces ‘face’ in different directions.
Here a view w/o wireframe from the top:

Here a view from the bottom:

The thing is: I am not creating normals with VertexData.ComputeNormals but by creating a buffer with 0.0, 1.0, 0.0 x the amount of vertices i have.
So i guess my normals are fine. I am wondering if it might have to do with the cw or ccw definition of the triangles in the indices buffer (this is the next thing i am gonna check). Even though i am wondering if cw/ccw triangles and normals may interfere somehow?
And i know i could use backfaceculling = true but that wouldn’t work when texturing i guess. And it is a hacky solution in my opinion.

Btw. Long time no see! I am very happy to work with Babylon.js again. Hope you all are doing well…
Greetings from Thuringia, Germany.

Welcome back. CW and CCW difference is the problem, in the following PG facet 0, 1, 2 is CCW and 3, 4, 5 CW, both have normals in same direction.


Before i (try to) implement a solution. Is there some function to recompute index order based on normals?

Not that I know of, you would need to create your own.

Did you know about Use PolygonMeshBuilder - Babylon.js Documentation or even Create Parametric Shapes - Babylon.js Documentation

Yes i know about those. I used those in an earlier version of the project.

1 Like

Are you happy to create a function that would recompute index order based on normals?

I guess that might be a rabbit hole. Changing from ccw to cw is easy. You just need to swap a pair of indices. But how do i find out that an index order ist ccw?!

I will try out earcut instead of the other triangulation algorithm to see if its results have no need for recomputing index order.

Above PG will recalculate index order if needed. It is based on all vertices of all triangles having the same normal (0, 0, -1), some tweaking needed if the normals are in a different direction


Thanks John! In my implementation i used normal.equalsWithEpsilon(Vector3.Down()) (see API). To see which indices are the ones being ordered ccw. But i may could also use if(normal.equalsWithEpsilon(Vector3.Up()) == false).

One new thing ocurred that i don’t understand: some of my normals are (0,0,0). How could that happen?

I made a playground Version #14 is the “default” scene without any index reordering.

Update on playground version 32
I added the code to compute the normals and there are no 0,0,0 normals (check the console, i console.log() the values). Weird.
Update: This issue is resolved!! :crazy_face:

Update on playground 52:
Determine wether facet is cw or ccw based on the normal. I realize that the facets that i am looking at from above are the facets that are ccw. After the reordering you don’t see anything because all facets are facing to negative y.

Update on playground 53:
So if i am reordering facets that are similar to Vector3.Up() then i see my mesh from above. That is a little confusing because in my mind it should be exactly the opposite. I must have some knot in my head.

1 Like

Swap the cross product over Since the cross product is non commutative order of vectors matter.

Note I changed to an ArcRotateCamera because I like to see all around the mesh easily during construction.

Also note from my PG that I declared my vectors prior to using them in a loop and then calculated their values using set, subtractToRef and CrossToRef. By reusing the same variables I cut down on how often Garbage Collection is called.

Could not see where you got (0, 0, 0) for any normals so cannot comment on this.


Ah okay. I used the equation from Does he assume some other coordiante system?

Will keep in mind the ArcRotateCamera for future PGs of that manner :wink:

Ah thanks for noting that. I was wondering why you wrote your code like this. Now it makes totally sense. I will apply that to my implementation. Surely there are some other places i can apply this to.

Anyways, i mark your last answer as a solution to my post, since all issues are resolved. Thanks a lot John!

1 Like