glTF & Basic Physics

I’ve created a very basic model in Blender 2.92.

It contains the basic types of meshes (Cone, Cube, Cylinder, Icosphere, Plane, Sphere & Torus). Each mesh also has its own ‘Collider’ mesh, which is either a Cube, Cylinder or Sphere.

Having exported & loaded ‘test.gltf’ into a Babylon.js scene, I’m using the Ammo.js plugin to drop spheres onto each mesh in the model. ‘ballOnCone’ is dropped onto the Cone mesh & so on.

I’m trying to follow the steps described here but, I’m having quite a few issues:

  1. PhysicsViewer is showing all ‘test.gltf’ impostors as boxes.

  1. Some impostors don’t seem to work - the sphere falls or rolls through or even gets stuck inside.

  1. The spheres don’t come to rest unless I ‘help them’, by scaling down their angular velocity.

Is this necessary or am I masking some other issue? They either roll (very VERY slowly) off the plane, or in the case of the 3 spheres against the long cylinder near the top, they sit there constantly jiggling!?

  1. When I try to registerOnPhysicsCollide to display a collision counter for firstBall I get an error in Ammo.js as soon as it collides with another impostor.

I’m new to Babylon & 3D in general, so hopefully I’m just missing something basic, but I’d really appreciate some help or advice.

I have been wondering whether I’d have more success if I created the collider meshes in Babylon.js rather than in Blender, but was unsure how feasible that would be, especially for more complex models.

I haven’t created a playground (yet), but I’m happy to do so, or post source code if it helps.

Thanks in advance!

Hi @richm welcome to the forum!

A playground will be more than helpful to understand the situation and provide a good answer :slight_smile: . There are quite a few issues here that we will need to address, so would be also great if you made a few line comments (or add a few flags) for us to be able to play with and understand what went wrong.

Thanks!!

Thanks @RaananW !

I’ve created a playground.

There are a bunch of flags at the top, the most important ones being:

  • SHOW_IMPOSTORS: Set this to use the PhysicsViewer to show wireframes of impostors.
  • TARGET_SHAPE (sphere, icosphere, cylinder, cone, torus, cube): Which object you want to drop the ball onto.
  • COLLIDER_REGISTER_ON_COLLIDE: Set this to see the Ammo.js error I mentioned.
  • FIX_PERPETUAL_MOTION: Set this to use deterministic lockstep & cause the ball to stop moving.

There’s quite a lot of code (sorry…!).

Thanks for your help!

1 Like

Ok!

  1. Ball is rolling constantly - this is a known issue with physics engines. Friction is only taken into account when colliding, and the ball technically collides against the floor only once. Cannon.js supports linearDamping and angularDamping which you can apply to emulate such a behavior (https://www.babylonjs-playground.com/#UFVU18#177). I have to say I don’t know if Ammo supports such a feature. When @Cedric is back from his time off I am sure he will be able to answer that
  2. Physics Viewer showing only boxes - Interesting catch :slight_smile: It seems to show only bounding boxes, and they are not calculated correctly. We will have to check that.
  3. Callback on collision - hmmm… This seems to be an issue with the ammo plugin. @Cedric will look into it when he is back,

The rest (the problem with the colliders) seems to be related to the GLTF itself. More specific - the transformation of the child meshes. Which is a known bug that we will tackle for 5.0. The github issue is here - Physics imposters are not created correctly for negatively scaled meshes. · Issue #10283 · BabylonJS/Babylon.js (github.com)

1 Like

If I’m importing models (.gltf, .glb, .babylon etc) into Babylon, then I have to use Ammo right!?

I haven’t tried any other plugins based on this section of the docs.

Or, is there an example of how to create the colliders in code instead of in Blender? I know there’s the skull example in the docs, but that doesn’t need to scale, rotate or position the colliders so will only take me so far down the road…

Or, am I just going about this all wrong?

Should I import (and position) each object separately in the scene, rather than importing everything as a single glTF?

In other words, import cylinder.gltf, sphere.gltf, torus.gltf, … instead of test.gltf. To give a slightly more realistic example, this could be house.gltf, wall.gltf, tree.gltf, … instead of my-home.gltf !?

Regarding the open issue about negatively scaled meshes. Is there something I might have done or missed when exporting the model from Blender?

Should I try exporting as .babylon instead of .gltf ?

I’ve created another version of the playground where the ball DOES stop, BUT it still doesn’t stop on the imported model. I had to create a ground plane underneath, only on there do these functions to work:

    // Check if the ball's impostor is moving up or down.
    const isMovingUpDown = function(ballImpostor) {
        return Math.abs(ballImpostor.getLinearVelocity().y) > 
            BABYLON.PhysicsEngine.Epsilon;
    }

    // Check if the ball's impostor is static/stationary.
    const isStatic = function(ballImpostor) {
        return ballImpostor.getLinearVelocity().length() < 
            BABYLON.PhysicsEngine.Epsilon;
    }

Hopefully that all made sense! :wink:

Hi @RaananW,

I’ve made some progress. The Ammo error was a bug in my code. I was calling ball.physicsImpostor.registerOnPhysicsCollide for each collider mesh, rather than just for the physics root mesh. This new version of the playground shows it working.

Interestingly, collision events are being raised while the ball is rolling and at rest… Unique to the Ammo.js plugin maybe!?

Thanks!

Very much unique. I find it odd that collisions are constantly triggered even when the ball is at rest. I sadly never found the time to fully explore Ammo.js, so I can’t say whether it’s an issue with us, with ammo, or the expected behavior.

Thanks @RaananW .

I forgot to include you directly in my reply yesterday.

As someone learning the ropes, I’d really appreciate any thoughts you might have.

All the best!

Let me check first the physics debug display.
I think the callback thing is expected. Each frame there is a collision/response thanks to the gravity. So it seems pretty normal to me with ammo. Maybe when the body is sleeping, you won’t get new callbacks.

Thanks for your help @Cedric & @RaananW !

I decided to have a go at creating the colliders manually in code & so I’m working on several new playgrounds; one for cubes, one for spheres, planes, cylinders & so on (to keep things simple! :wink:).

glTF Cubes & Manually Added Physics Colliders works OK, but:

  1. The scene looks different depending on which physics engine I use.
  2. There’s something interesting going on in the glTF, where the __root__ node is negatively scaled along the Z axis, causing the cubes to face into the scene. Simple enough to rotate it I guess (I’ve cheated by moving the camera), but maybe I’m missing something!?

p.s. I intend to post links to the other playgrounds once they’re working, in case they’re useful to anyone.

PR is live for improved physics debug viewer : Scale gizmo & physics debug view fix by CedricGuillemet · Pull Request #10411 · BabylonJS/Babylon.js · GitHub

1 Like

I’ve created glTF Spheres & Manually Added Physics Colliders, which drops balls on imported spheres at intervals.

There’s an issue when using Cannon.js - the balls fall through two of the six imported spheres.

I also noticed that the first time the balls are dropped, they miss the spheres (they always hit after that).
I’m wondering whether some internal state of the spheres needs to be explicitly updated in the playground. Or is it a bug?

I’ve already mention that imported meshes are being loaded facing the wrong way - I had to rotate the ‘physics root’ 180 degrees to correct that.

Finally, the imported meshes appear translated to the left when using Oimo.js (Ammo & Cannon seem OK).

I’m happy to raise issues on github for any of these, but to be honest I thought I’d mention them here first as it could be something I’m doing… :persevere:

Thanks!