If you build your cube geometry as in a right handed system, then you will have some special things to do to make it work in Babylon (which is fundamentally left handed at its core):
- add a root node to your cube with a transformation that transforms a right to a left handed system => only needed if you plan to set
scene.useRightHandedSystem = false
at some point. If you will always have scene.useRightHandedSystem = true
you can skip this step
- override the
sideOrientation
property of material so that Babylon does not tamper with it (use mesh.overrideMaterialSideOrientation
for that)
Regarding 2, Babylon is expecting that the geometry is described in a left-handed way. So, if you set scene.useRightHandedSystem = true;
, the projection matrix will be changed in a way that will invert the winding: Babylon needs to flip the side orientation of the materials to account for this, and it does this automatically. To disable this feature, you must use the mesh.overrideMaterialSideOrientation
property: if it is non-null, Babylon will use it in all circumstances, whatever the value of scene.useRightHandedSystem
.
Regarding 1, you can do what the glTF loader does, as the geometry in the .gltf/.glb files is described in a right handed system way. This loader is doing this to handle the two points above:
- create a root node with rotation.y = 180° and scaling.z = -1
- set
mesh.overrideMaterialSideOrientation = scene.useRightHandedSystem ? Material.CounterClockWiseSideOrientation : Material.ClockWiseSideOrientation;
So, you can do the same so that your code will work whatever the value of scene.useRightHandedSystem
is:
What you were doing (mat.sideOrientation = BABYLON.Material.CounterClockWiseSideOrientation
) is essentially ok if you don’t plan to change the value of scene.useRightHandedSystem
afterwards, as it achieves the same thing than mesh.overrideMaterialSideOrientation = Material.CounterClockWiseSideOrientation
.
Note that the positions and indices should be arrays of numbers, not strings => the bounding info computation fails when using array of strings. That’s why I have added some map((s) => parseFloat(s))
in the PG above.
the debug visualization of normals in the Inspector seems off (or the normals are still off).
This was because of the arrays not being arrays of numbers.
Yes, it’s what convertToFlatShadedMesh
is for, it will make sure that all faces have 3 unique vertices, not shared by other faces. Then it will set the normal of each vertex as being the normal of the face. At render time you will get a flat shaded rendering because the vertices are not shared by faces anymore, so the normals are not blended.