Inverted Normals in Solid Particle System

Hi All,

Looking to use a Solid Particle System to distribute trees across a scene. I have a .glb file which is my tree mesh, and another which loads in the tree positions through a collection of transformNodes.

In doing so though, all of the tree generated via the particle system seems to have been turned inside-out, reversing their normals. The original mesh is on the left, a tree rendered with a particle system on the right.

My tree mesh is imported to the scene with:

BABYLON.SceneLoader.LoadAssetContainer(
    "assets/3d/",
    "tree_2.glb",
    scene,
    function (container) {
      const treeMesh  = container.meshes[0]
      // add our tree mesh
      container.addAllToScene()
      BABYLON.SceneLoader.LoadAssetContainer(
        "assets/3d/",
        "tree_positions.glb",
        scene,
        function (container) {

          let treeMat = treeMesh.material

          var positions = []

          for (var n in container.transformNodes) {
            let node = container.transformNodes[n];
            positions.push(node.position)
          }

          var posFcn = function (instance, i) {
            instance.rotationQuaternion = null;
            instance.rotation.x = Math.PI / 2;
            instance.rotation.y = Math.random() * Math.PI * 2;

            instance.position.x = -0.01 * positions[i].x
            instance.position.y = -0.01 * positions[i].z
            instance.position.z = 0.01 * positions[i].y
            
            let scale_factor = (Math.random() * 0.2) + 0.9

            instance.scale.x = instance.scale.x * 0.01 * scale_factor
            instance.scale.y = instance.scale.y * 0.01 * scale_factor
            instance.scale.z = instance.scale.z * 0.01 * scale_factor
          }

          var sps = new BABYLON.SolidParticleSystem('Tree Particle System', scene, {updatable: false});
          sps.addShape(treeMesh, positions.length, {
            positionFunction: posFcn
          });
          const spsMesh = sps.buildMesh();
          sps.mesh.freezeWorldMatrix();
          spsMesh.material = treeMat
        }
      );
    }
)

anything obvious I'm doing wrong here?

Could you try to repro in the playground ?

What I suspect is GLTF/B is using a special _rootNode to invert scale every thing in to convert from left handed to right handed and SPS is not taking this into account.

Maybe you could try your scene with right Handed turn on: scene.useRightHandedSystem = true;

3 Likes

Have created the following PG which shows the issue: https://playground.babylonjs.com/#TQCIJN#3

Including the scene.useRightHandedSystem = true; does work in the P/G ti display the normals correctly.

However this raises two further issues:

  1. I have many other imported models which then disappear/invert to broken normals.
  2. This seems to introduce a new bug, whereby it renders fine, until you rotate the camera, at which point all the meshes disappear. This only occurs when scene.useRightHandedSystem is set to true. If you resize the window, they re-appear (this does also occur in the P/G)

In your case you could force a negative scale on the z axis (similar to what the root node of gltf does).
https://playground.babylonjs.com/#TQCIJN#4

Or you need to rely on Babylon instancing mecanism as you do not need to update every frame anyway and attach the instances to the same Tree 2 parent.

Thanks @sebavan - I did have instancing in place, but performance (have 10k trees to render) was significantly worse than I seem to be getting with particles. Had about a 30 FPS drop with the instancing, with SPS only seeing about 5 FPS drop.

The negative scale works great in terms of the normals, but annoyingly I am noticing this odd lighting issue:

I’m guessing it’s because the lighting is basked onto the base mesh, then “instanced” for each particle. Where I then randomly rotate around the y-axis, the lighting doesn’t match that particular points in space?

Oddly, even though I’m using the exact same HDR as this new version of the PG, that doesn’t have the same effect.

Turns out it wasn’t the HDR causing the lighting issues, but a directional light I have, have added it to the PG: https://playground.babylonjs.com/#TQCIJN#6

Assume there isn’t much I can do about this, given the way particles are rendered?

Can only think I add 6-12 versions of the tree as a standard mesh which random y-rotations, then have a particle system for each of the versions with their respective rotation?

Maybe thin instances is the way to go for you ? Thin Instances | Babylon.js Documentation

@Evgeni_Popov any thoughts ?

A reasonable workaround I’ve found is reducing the impact of direct lighting on the tree material to about 0.1/02 (to give some variation) and then increase the brightness of the albedo colour, which has a decent enough effect.

it does feel pretty hacky though…

Yes, I think thin instances would be a perfect fit for your use case:
https://playground.babylonjs.com/#TQCIJN#9

BOOOM @Evgeni_Popov did it again :wink: !!!

than you so much!

Note that what I did is not particularly fast (at creation time), have a look here if you want to improve things.

1 Like