Question on Animation and Collision

Hi folks,

I´ve been struggeling with something simple that apparently isn´t that simple for me.

What I need:

  1. Everytime the User presses a button a new box will be spawned.
  2. In JS the created mesh gets some more values like moveToDirection, velocity, etc.
  3. I need something like an auto-creation of an Animation that uses these values.
  4. When the created box collides with another mesh, it has to stop until I tell BJS anything else.
  5. Therefore I need something like a callback on anything

Basically this:

All PG examples I´ve studied are based on already existing meshes and predefined static functions that are applied to the render loop:

var box = BABYLON.Mesh.CreateBox("mybox", 3, scene);

var animate = function() {
    var scene = engine.scenes[0];
    var mybox = scene.getMeshByName("mybox");
    mybox.rotation.y += .01;
    mybox.mydiv.textContent = "mybox.rotation.y = " +
        mybox.rotation.y.toFixed(2);
}

scene.registerBeforeRender(animate);

It´s like an event-triggered start and stop of animations for arbitrary meshes which are not pre-defined.

What is the prefered way to get this done?

Any help appreciated.

BR,
Topper

Well, I’m no coder, Topper, but maybe this playground could maybe give you some ideas. Instead of changing the colour of the spheres when they intersect a second mesh - just stop the animation?

Mesh intersect Playground

Maybe after the initial intersection, reverse the animation for one frame to avoid any potential overlap, then stop the animation?

cheers, gryff :slight_smile:

@ gryff

I know this PG. My pain is to get this dynamic, since I don´t have three balloons:

    // Balloons
var balloon1 = BABYLON.Mesh.CreateSphere("balloon1", 10, 2.0, scene);
var balloon2 = BABYLON.Mesh.CreateSphere("balloon2", 10, 2.0, scene);
var balloon3 = BABYLON.Mesh.CreateSphere("balloon3", 10, 2.0, scene);
balloon1.material = new BABYLON.StandardMaterial("matBallon", scene);
balloon2.material = new BABYLON.StandardMaterial("matBallon", scene);
balloon3.material = new BABYLON.StandardMaterial("matBallon", scene);

balloon1.position = new BABYLON.Vector3(6, 5, 0);
balloon2.position = new BABYLON.Vector3(-6, 5, 0);
balloon3.position = new BABYLON.Vector3(-30, 5, 0);

//Animation
scene.registerBeforeRender(function () {

    //Balloon 1 intersection -- Precise = false
    if (balloon1.intersectsMesh(plan1, false)) {
        balloon1.material.emissiveColor = new BABYLON.Color3(1, 0, 0);
    } else {
        balloon1.material.emissiveColor = new BABYLON.Color3(1, 1, 1);
    }

    //Balloon 2 intersection -- Precise = true
    if (balloon2.intersectsMesh(plan2, true)) {
        balloon2.material.emissiveColor = new BABYLON.Color3(1, 0, 0);
    } else {
        balloon2.material.emissiveColor = new BABYLON.Color3(1, 1, 1);
    }

    //balloon 3 intersection on single point
    if (balloon3.intersectsPoint(pointToIntersect)) {
        balloon3.material.emissiveColor = new BABYLON.Color3(1, 0, 0);
    } else {
        balloon3.material.emissiveColor = new BABYLON.Color3(1, 1, 1);
    }

    alpha += 0.01;
    balloon1.position.y += Math.cos(alpha) / 10;
    balloon2.position.y = balloon1.position.y;
    balloon3.position.y = balloon1.position.y;
});

Actually I think my main problem is that I don´t know how to structure my code (and my JS skills lol).

Can I register as many functions as I like with scene.registerBeforeRender(function(){}) ?

How can I remove a registered function from the scene (like unregister)?

Like everytime the User spawns a new mesh I register a new (mesh-specific) function to the scene.

BR,
Topper

Hello Topper, you can register as much as you want.

But if you want to remove it you have to use this form:

var foo = function(){...}
scene.registerBeforeRender(foo);
scene unregisterBeforeRender(foo)

Also you can consider using observables:
https://doc.babylonjs.com/how_to/observables

Hi Topper/others.

Take a look at this thing, Topper…
https://www.babylonjs-playground.com/#HH1U5#89

It is a little animation demo that I once created. It makes heavy-use of the powerful but many-parameter’d BABYLON.Animation.CreateAndStartAnimation call. I love that thing. It is a “derive-the-keyframes-with-math” type-of animation tool.

Note: Anims that DO use keyframes, also derive their steps… with “programmer-marshalled” math. Deriving animation steps… is often called “interpolation” and sometimes “LERP” (linear interpolation).

Notice HOW I “added” these 8 animation funcs (spin, spinTo, move, moveTo, scale, scaleTo, color, colorTo) …to the scene. They are sometimes called “over-loads” or “over-loading”. They are added to the “factory” that makes BJS mesh… BEFORE we begin making mesh. We asked the factory to PREPARE to produce “custom mesh”, and the factory said “Gladly”. :slight_smile:

(some say that overloading is not a healthy/wise thing, for various reasons, but I still do it and so can you)

Those 8 animators… are ‘method’ overloads. You can also do ‘property’ overloads… like seen in line 54.

The NAME of the added/overloaded property or method… is important. For FULL POWER… use “custom” property and function names which ARE NOT already ‘members’ of the default BJS Mesh class.

Take careful note of lines 56-59, where I TRIED to force all factory-made mesh.isPickable to FALSE. If you look at JS console output, we can see that… fail. The factory set mesh.isPickable to ITS preference, no matter what we wanted.

In this case, perhaps wait-for scene isReady, and THEN take over the world, like this:

scene.onReadyObservable.add( function() {
     for (mesh of scene.meshes) { mesh.isPickable = false }
});

That way, we modify factory-made meshes… AFTER their construction. :slight_smile: All these methods can be used on all “nodes”… including Nodes, TransformNodes, Cameras, Lights, and Mesh. Also available on many non-node BJS objects.

Ok, I hope this gets your idea-juices flowing. scene.onReadyObservable can be very useful/powerful for adding post-construction overloads, and lots of other things.

Sometimes programmers do the very first scene.render(), FIRST THING, inside scene.onReadyObservable. I think this makes mesh.boundingInfo() “flesh-out”, so that its many measuring tools will be accurate. It also first-renders any GUI controls/widgets that the scene might use, and fleshes-out their GUI currentMeasure and measureForChildren (and similar) properties. (in case you need to do some accurate measurements and last-moment tweaks to your GUI).

Lots of things wait for the first-render… before they “flesh-out”, and you might need things fleshed-out (rendered at least once) before you can do the custom/personal measurements and tweaks you wish to do.

All in all, scene.onReadyObservable is your personal place to doFinalStuffBeforeGO().

We COULD have added my 8 animation functions to each/select mesh… within onReadyObservable, if wanted (probably wiser). But, I wanted to show you both ways, so you have all the tools you need to blow up the planet. :smiley: I hope I have been helpful. Party On!

Thanks guys.

@ Wingnut

I put some of my code in a PG:

https://www.babylonjs-playground.com/#KQ54LE#26

You´ve a conveyor (with a light sensor as separate mesh) and an animated simple box (moving along z-axis).

Can you please complete the code as follows:

When box intersects with sensor create new animation moving the box along x-axis.

thanks a lot man, I really appreciate it.

BR,
Topper

Hi T. Cool conveyor! Let’s make this into a little contest… let some other forum users have a try.

And don’t forget about the FUN of “figuring it out”, too. Some of the BEST fun of programming… is coding/testing various solutions. Be sure to save plenty of fun for yourself, Topper. :wink:

What if line 50 used step variable… instead of hard-coded 0.01? Then, what if you did step *= -1; when the intersect happens, which would “toggle the sign” of the value of step? Hmm. :wink:

1 Like

:joy::joy::joy::joy:

OK,

here´s my latest try:

https://www.babylonjs-playground.com/#KQ54LE#29

My current problem is how to end the initial animation in z and create (or call) a new (or another) one
that moves the box in x (and no longer in z).

What would be yout suggestion, Wingnut?

Actually I´m considering four default animation functions:

mesh.position.x +=
mesh.position.x -=
mesh.position.z +=
mesh.position.z -=

and four arrays that hold the meshes that need animations:

var meshesMovingXPlus = []
var meshesMovingXMinus = []
var meshesMovingZPlus = []
var meshesMovingZMinus = []

based on mesh intersection I would do the math (based on routing information) to
remove meshes from source arrays and put meshes into destination arrays.

Still struggeling with BJS and its capabilities and functionalities, though.

@ Wingnut

Feel like helping me or giving me a jump start?

BR,
Topper

1 Like

You sound motivated. :slight_smile:

Yep, all good ideas, you are having. Your box could have tools on it… for moving ANY direction.

Perhaps… box might have… moveLeftUntilIntersect() and similar funcs. Anything is possible.

Here’s a solve for your turn-at-beam.

https://www.babylonjs-playground.com/#KQ54LE#30

Notice line 172… putting a STRING inside [here]… and we change that string from “z” to “x”… at intersect.

We could also do step *= -1; when intersect, if we want the box to turn left. LOTS of options. Fun, huh?

Notice I waited for scene isREADY in line 152… before I set scene.onBeforeRenderObservable in line 155. This is because… box was showing intersectWIthBeam == true AT SCENE START. No good. This is because… box and sensorBeam had not yet been positioned when the first observation happened.

Both box and sensorBeam were positioned at 0,0,0 still… so there WAS an intersect at scene-start. I had to wait for mesh to be positioned, and then everything worked great.

Keep in mind that sensorBeam.visibility = 0; … will give you an invisible beam… that will STILL intersect ok. sensorBeam.setEnabled(false) will make it disappear, and NOT be intersect-ready anymore. :slight_smile:

Yupp, that did the trick.

Thanks a lot man.

Actually a really good foundation.

:kissing_heart:

1 Like

pg #32

These playgrounds have an “interesting anomaly”.

Try activating line #160… to cause the box to turn LEFT at intersection.

Stuck and jiggling? Yep. I think it is STUCK in intersection “state”… and so step is toggling its sign… back and forth.

Now activate line 158. Upon intersect, it “backs-out” the box… away-from the sensorBeam… TWO steps.

After that, the left-turn works fine.

One might ask WHY is back-away line 158… needed for LEFT turns, but not for RIGHT turns? Is our sensorBeam… bent or rotated somehow? hmm. A mystery, indeed. :smiley:

rounding error?

Yeah, maybe. But TWO steps of rounding error? 0.04

That’s too much… me thinx. hmm.

This is kinda responding a few comments back, but here’s another general pattern. This is mostly pseudocode:

let collisionResult = new CollisionResult()

class Example {
    constructor() {
        this.mesh = new BABYLON.Whatever(args)
        this.heading = new BABYLON.Vector3(0, 0, 0)
        this.speed = 50
    }

    update(delta) {
        // some very classic movement code
        this.mesh.position.x += this.heading.x * this.speed * delta
        this.mesh.position.y += this.heading.y * this.speed * delta
        this.mesh.position.z += this.heading.z * this.speed * delta
        // note: depending on the game heading should be a unit vector

        // hypothetical DIY collision logic:
        // this code could live elsewhere as well
        collisionResult.clear()
        CollisionSystem.checkStuff(this, collisionResult)

        if (collisionResult.collision) {
            // a collision!
            
            if (collisionResult.blahblah === 'sensor:xPos') {
                // made up stuff.. after colliding with Whatever
                // this is, the object travels in the x direction
                this.heading.x = 1
                this.heading.y = 0
                this.heading.z = 0
            }
        }
    }

    dispose() {
        this.mesh.dispose()
    }
}

So that’s just a class and a somewhat OOP style. It doesn’t have to be though, the update function can just be a freestanding function that operates on an object that possesses a mesh,heading, speed. Then one can do away with the this keyword if that is a stylistic preference.

And then actually using the pseudo “entity” defined above consists of creating it (or creating many) and then invoking update every frame.

// somewhere else in the application...

// creation
const entity = new Example()
entities.add(entity)

// removal
entities.delete(entity)

// running behavior on every entity, this code probably belongs in beforeRender
entities.forEach(entity => {
    entity.update(delta)
})

In a game with more physics one generally does not apply the collision logic right after moving one object as the pseudocode above does. Instead all objects move first i(nto a potentially collided state) and then after they’ve all been moved the physics is applied that collides them or raises any kind of collision-related logic.

Here’s some pseudocode for that…

function engineUpdate(delta) {

    entities.forEach(entity => {
        entity.update(delta) // removed collision logic, tho
        // OR
        // doMovementStuff(entity, delta) 
    })

   doCollisionStuff(entities)
    
}

Either way logic like the update on the Example class above, followed by collision checks, presents an alternative to using animations, observables, and potential callbacks. I find this format to be easier mentally when thinking about creating and adding a whole bunch of stuff to a game that doesn’t exist when the scene initially loads. That said I’m new to babylon, and my proposed code would end up doing the exact same stuff as the animations + observables + etc, so perhaps the difference is just semantics.

Here’s how I’d think of it: every frame every object runs its update which moves itself based on some state variables attached to the entity such as speed and heading (and anything else). After movement occurs we do some specific collision checks, perhaps seeing if any box has hit a sensor or fallen off the conveyor belt. If it hits a sensor perhaps we changing the heading which changes the direction of travel or stops the box. If it falls off the end of the conveyor belt perhaps we destroy the object (not shown in the pseudocode). Similarly new boxes (or other things such as more track or more sensors) can be added on any frame per user input.

Hi @Topper, in my model train game I’m using conveyors as well. E.g. a conveyor is used to load goods on/off the train. I don’t know if this will help your case but I experimented with the Physics engine.

The Physics engine has callback functions on collision (e.g. between boxes). And I gave the conveyor surface an (invisible) box with mass 0 and some (world space) linear velocity. That created the effect of a force when a non-zero-mass object collided with it. When a box mesh crosses a laser mesh (the laser mesh doesn’t have a rigid body e.g. the box moves through the laser) you can set the onIntersectionEnter action trigger right from the BabylonJS engine itself.

If I have finished a nice isolated working example later on, then I might be able to post it on the forum.

https://doc.babylonjs.com/how_to/using_the_physics_engine

https://doc.babylonjs.com/how_to/using_advanced_physics_features

https://doc.babylonjs.com/babylon101/intersect_collisions_-_mesh

https://doc.babylonjs.com/how_to/how_to_use_actions