Physics blocks animations

I found a bug in version 4 generation. On 3rd branch it worked.

https://www.babylonjs-playground.com/#EGHC15#1

In this playground press ‘k’, to launch animation. Nothing is happenning.
Then comment the line 28. And try again. It works now. So, meshes with physics impostors can’t be animated anymore.

This is the expected behavior actually. Physics is controlling the mesh so you can’t do it simultaneously

But this throws me in a tricky situation. My case is a door that opens vertically (slides up).

Door should block all physical objects when closed. So physicsImpostor is required.
When door is in a process of opening it should pass objects that smaller than current gap, but it should block the bigger ones.

If I will drop physicsImpostor before opening animation and then will attach it again (after opening) then condition above will be violated.

Before it worked just fine.

Pinging @trevordev or @Cedric to get some thoughts

I think with BulletPhysics you can have dynamic or kinematic objects. Kinematic objects are moved by the user providing collision responses to dynamic objects. It’s a mix between dynamic and static objects. I’m searching now in Ammojs how it’s handled.

1 Like

You can do this without physics with moveWithCollision and enable collisions with mesh mesh.checkCollisions = true;

Also, you might try standard animation but it ONLY contains animationEvents. For each event, set door.physicsImpostor.setLinearVelocity(new BABYLON.Vector3(0, .1, 0)). Do no other keyframe property setting, or perhaps “dummy” property settings. The main thing… have animationEvents happen often-enough… to counteract gravity-pull trying to pull the door closed.

When door reaches top (how to know, not sure)… door.physicsImpostor.setMass(0)… so it stays up. When its time to close, first set door.physicsImpostor.setMass(1) and then you COULD keyframe animate again… each AnimationEvent of many… setting door.physicsImpostor.setLinearVelocity(new BABYLON.Vector3(0, -.1, 0)) . OR, you can let gravity take it down FOR YOU, but door will accelerate drop-rate over time (until it hits floor).

There are other ways, joints with motors, etc. I think Cedric is correct, though… about statics and dynamics. So far, it seems impossible to hook a joint to a 0-mass impostor… in AmmoJS. Works in Cannon and Oimo, though. If you look at the ropeImpostor demo… it uses a thing called addHook(), and there is another similar thing called addAnchor() (not used in rope demo). I have not studied them well, but addHook() is the way the rope is attached to the 0-mass arm. I tried attaching hinge joints to the 0-mass arm… trying to sim a chain-o-hinges instead of a rope. Works in Cannon, not in Ammo.

Do playground search for ropeImpostor and clothImpostor… to see more Ammo-only setAnchor and setHook stuff.

All that crap aside… I did a non-keyframe-anim… door lifter/dropper… using repeating setLinearVelocity calls… hung on the renderLoop. It runs on timers right now… but other methods could be used.

https://www.babylonjs-playground.com/#NYSAHQ#8

Look it over for awhile… see if there’s anything useful in there. I can explain things, if you wish. I think you can see… how a standard keyframe animation… COULD be filled with animationEvents… and each event (handler) sets linearVelocity.

That idea… is a way of using standard BJS animation… to do physics-approved force settings. Now I dunno if the keyframes need to be filled with ONLY animationEvents, or if we can actually tell a keyframe to do setLinearVelocity on a physicsImpostor. Usually, BJS animation only sets properties, and doesn’t call functions.

Exception: Let’s imagine we put a float property on door… like door.dummy = 0.0; I don’t know how to add a SET method for a property called dummy… but IF I DID, then EVERY TIME the standard keyframe animation SET mesh.dummy… it would execute the SET function for mesh.dummy property. INSIDE that setter method… you could setLinearVelocity to some value. The actual property that the animation is working with… mesh.dummy… IS being animated… but mesh ignores it. But still, for each SET of mesh.dummy, the SET DUMMY() method runs… and inside that setter… you could call a physics method like setLinearVelocity or setAngularVelocity or applyImpulse. It’s a sneaky way to have a method execute… for each value-setting that the animation does to mesh.dummy property. I’ve never tried it.

Perhaps we can convince someone to ATTEMPT an all-AnimationEvents animation… where each eventHandler does a range-limit test and setLinearVelocity. I’m not sure that anyone has EVER tried it before. I don’t think I have ever seen a standard keyframe animation… attempt to make physics calls.

In door OPENING OnAnimationEnd callback, you likely need to set door mass = 0, to keep it from falling to the ground via gravity. (when anim ends its sequence of AnimationEvents).

SO much stuff to think about, eh? I agree with Deltakosh… physics-impostor-active mesh (p-mesh) should NOT allow standard keyframe animating. The impostor is the boss, not the keyframe. Sorry if you were fooled by incorrect behavior in BJS 3.x series. We all try to prevent that… but it’s a big job with many fingers in the pie, and with physics engines evolving fast.

Using forces to push door upwards seems more close to reality. Because in real life we also have engine that literally pulls the door up. But turning to zero mass breaks all reality :laughing: If we want to implement door this way it will be fair to use brakes (additional meshes that will block door from falling).
Anyway I think that it is too much logic for such pretty simple thing.

If we are creating hacks we can go some other way. We can create invisible parent mesh and animate it while the child mesh will keep the physicsImpostor.

https://www.babylonjs-playground.com/#EGHC15#4 - press ‘k’ to animate.

My solution fulfills what I need however it is still a little bit weird. :laughing:

Of course we can write some kind of DoorManager that will hide all our magic code and will offer the simpler door creating interface. But I still can’t stop having fun about how we are trying to solve it. :laughing:

1 Like

Hi s27… welcome back :slight_smile:

https://www.babylonjs-playground.com/#EGHC15#5

Sorry, I accidentally removed the physics… but I wanted to show you the world famous moveTo abstractMesh overload function. It removes ugly keyframes code-lines and other animation stuff.

j/k keys active, there. Not very exciting, but little PG. :slight_smile:

That BABYLON.Animation.CreateAndStartAnimation in line 4 is sweet, but, I don’t think it allows an onAnimationEnd callback, which you might need.

Have you tried a Compound Collider Setup ???

Im just guessing… But

You can actually have a separate Collision Mesh Volume as the child of the the object…

So your Door or Wall and have a separate child BOX mesh… Setup the Primary Door as a NoImpostor and and the child as a box impostor… You should still be able to FORCE MOVE the door and still get Collisions from the compound.

If still not clear or something you wanna try … let me know i will try in the Babylon Toolkit :slight_smile:

Fortunately it supports onAnimationEnd. But this is a last argument, so if I want to use it I will need to pass ease function anyway. But I don’t get it how to pass linear function there to keep it working like in default case (without argument).

(Splash is talking about CreateAndStartAnimation() method/feature.)

Oh, cool discovery, thx for info. I have a need for this… in another project: PG #97 - installed onEnd at end of lines 8, 14, 20, 27, works good.

PG #98 tests onEnd(this)… which passes-along WHICH animation ended… to our onEnd handler. Good good good, considering we might have 2-10 move() animations running at the same time.

A great question. You need a “noEase” easing to fill-in the slot in the parameters (just before the callback func name/args). Yuh yuh yuh. You could try “undefined” or null in that easing-parameter slot… might work.

But also, a bezier-curve ease with all 4 of ITS values… set to 0… MIGHT work. I tested:

https://www.babylonjs-playground.com/#3AYOL#2 line 47.

Seems pretty linear/default, but my eyes could be fooling me. :slight_smile:

Useful comments, s27, thanks!

Update test: Yes, null works in that easing slot… https://www.babylonjs-playground.com/#HH1U5#97 near end of lines 8, 14, 20, 27. Good deal. The core-coders are taking good care of us, eh? (hugs)

Using null to “skip-over” optional parameter slots… is likely common in MANY areas of BJS. I think I have used it to skip-over “noMipmap” on Texture Trail… because that is an ugly mud-puddle that I don’t understand, and so it might contain alligators that could bite my foot-off. heh. Someday, I should simply learn what a mipmap is… so I’m not so scared of it. :slight_smile:

I wonder how many JS users… worldwide… have tried using a question mark… as a param slot skipper. Or perhaps a $ to indicate “ignore/work-AROUND this sanctioning device”. :open_mouth: (ahem)

ANYway, keep in mind that trolls sometimes live under (null) parameter-slot bridges. No matter what they try/say, charging tolls (or rolls - see Robin Hood - Men In Tights movie) for crossing BJS bridges… is quite illegal. hah.

1 Like

Well…

Looks like the approach with parenting will not work.
Parenting disables physics on child mesh.
Take a look at this playground: https://www.babylonjs-playground.com/#EGHC15#6
Sphere just goes through myBox. But if I comment the line 34, this will work as expected. :cry:

Actually it does not but you have to declare parent AFTER physics:
https://www.babylonjs-playground.com/#EGHC15#7

doc: Use Advanced Physics Features - Babylon.js Documentation

1 Like