CannonJS joint collision-flag problem... and more

Hi gang!

(Hey, it IS a simple playground. You should see version #71 - omg) :slight_smile:

This is continued Lunar Lander-like “landing gear” work, but it’s unrecognizable as such, so far. :slight_smile:

Issue: collision is a parameter on BJS physics joints, and in lines 124, 132, 140, and 148 of my 4 hinge joints on the lander legs… I set it to false. You can “impulse” the 4 lander legs with x/z keys, or shifted x/z keys. AND, you can see that they collide with the greenbox lander body.

The lander’s legs will also collide with each other, but that might not be see-able in this demo.

In short, collision parameter on CannonJS joints… might not be working.

Want to see another “oddity”? I knew ya did. :slight_smile: The “L” key is also active (lines 223-228). All it does is setMass on the greenbox impostor… to .1… which should start the greenbox sinking to the ground.

Pressing “L”… appears to do more than that. It appears to fire an impulse, sideways.

In lines 233-236, when scene isReady… I ensure that the greenbox has no angular or linear velocities, and set its mass to 0 (so I can “hang” the lander legs from it, nicely).

I wonder why the “L” key is causing sideways movement. hmm.

Also, although no leg-to-greenbox parenting is done, legs are fastened to greenbox by hinge joints. So, if greenbox moves, so should legs (I would think). After pressing “L”… how are the legs still hanging in mid-air… when they each have mass? hmm.

Disable line 236 to see greenbox fall on its own… keeping its legs WITH it. But after that, a press of “L” goes berserk and leaves legs behind. Weird.

Ok, all help/ideas… welcome. THANKS!

A little update:

I went touring in the CannonJS plugin and I saw some TODO’s in there… regarding collisions.

Then I decided to tour CannonJS github site… and take a little look at Schteppe’s collisionFilter demo.

And there they were, our old friends collisionFilterGroup and collisionFilterMask. As you can see, they are not really JOINT-related like our collision parameter (on BJS joints). Instead, they are CannonJS physics BODY-related.

Hey, I can do that… using greenbox.physicsImpostor.physicsBody.collisionFilterGroup and collisionFilterMask. Wingnut is headed to CannonJS “native” lands! :slight_smile: Look out!

See lines 238-262… quite a pile of grouping and masking (commented).

AND… it works. Tapping x/z wobbles the legs… without collision with the greenbox. YAY! Disable line 236… and she falls to the ground with legs-to-ground impact collision… nicely.

So, there IS a work-around method for the possibly-non-functioning collision parameter on BJS-Cannon joints.

In this #75 playground, on the joints… I tried collideConnected: false… instead of collision (because of things I had seen while examining the latest cannon plugin)… but that didn’t work, either. More about that… in next post.

Somebody has been busy in the CannonJS plugin… and work is still in progress, it seems.

Other reported problems (like the “L” key issue)… not much progress, yet. With line 236 disabled (auto-fall = true)… AFTER landing, the “L” key acts SLIGHTLY better… but really NOT. The greenbox should NOT fall to the floor (when the “L” key sets its mass = .1)… as its legs and joints should hold it above the ground.

It appears at this time… that ANY greenbox.physicsImpostor.setMass(non-zero-val)… might disconnect the joints from the greenbox (a bad thing).

Fun Note: Is anyone asking theirself WHY these hinge joints are SO INCLINED to NOT-swing-freely and why they tend to point straight-up or straight-down (somewhat firmly)? It is because the mainAxis and connectedAxis on the hinges… is Y.

To get nice x/z “free swing”, I should probably use a Hinge2Joint (x and z axis pivots?) or a “BallAndSocketJoint”. Both would likely swing more smoothly with the x and z keys… and swing for longer residual periods… and NEVER get stuck aimed-upward (gravity would tip them over - the legs have mass). Early ballAndSocket test on one leg… here.

Ok, just some further tests:

Our CannonJSPlugin, and Cannon’s Constraint class both show collideConnected being used, but I can’t tell if it should be standard param or nativeParam. So… for each of my joints in lines 119-169, I did it all.

    var joint1 = new BABYLON.HingeJoint({  
        mainPivot: new BABYLON.Vector3(-legSpacing, greenboxHeightOffset, -legSpacing),
        connectedPivot: new BABYLON.Vector3(0, greenboxYpos-legHeightOffset, 0),
        mainAxis: new BABYLON.Vector3(0, 1, 0),
        connectedAxis: new BABYLON.Vector3(0, 1, 0),
            collideConnected: false,  // attempt #1
            collision: false,  // attempt #2
        nativeParams: {
            collideConnected: false, // attempt #3
            collision: false // attempt #4

No joy in PG #78. x/z key tapping… still shows legs colliding with greenbox. Not supposed-to do that.

If I tour-around in our CannonJSPlugin, I can see some occurrences of both collision and collideConnected. There are a few “double bangs” in there… you know… these things… !!.

Line 204: collideConnected: !!jointData.collision
Line 234: constraint.collideConnected = !!jointData.collision;

I’ve just begun studying the not-not (double-bang)… here: What is the !! (not not) operator in JavaScript? - Stack Overflow Still foggy, but I’ll fig it. If anyone wishes to explain to me, in a gentle hand-holding way… what the double-bang in the two lines above… DOES… that would be great (thx). Meanwhile, I’ll keep reading.

Later today, I will examine the joints of the #78 playground… at native levels… to see if the collideConnected is ACTUALLY getting set on the native-level jointData and/or jointParams. (…to see IF the setting made-the-trip thru the plugin and down to native level).

Early tests:

Object { collideConnected: false, collision: false, nativeParams: Object { collideConnected: false, collision: false, ... }

Object {  collideConnected: false, … }

collideConnected IS making the trip to native level (the CannonJS joint objects). SO… hmm… now the question becomes… why is CannonJS ignoring the setting. hmm.

The joint has a BodyA and BodyB (the shapes on each end of the joint). On BOTH of those body objects…

collisionFilterGroup: 1
​​collisionFilterMask: 1
​​collisionResponse: true

collisionResponse = true? hmm. This might be normal, though. I am not asking the shapes on each end of the joint… to STOP doing collision response. I just want them to stop doing collision response WITH EACH OTHER. (any leg-to-greenbox). A collision parameter on a joint SHOULD ONLY be able to set collision characteristics… on the shapes/bodies THAT joint is connected-to. Any further “reach” (scope)… would be imposing on the shape’s OTHER collision characteristics (with shapes NOT connected to this joint).

But now… both bodyA and bodyB ARE members of the same filterGroup #1… so they are quite likely to collide. It appears… that the joint (construct/world-install) has not made proper adjustments… to avoid bodyA and bodyB collisions. OR… I don’t understand Cannon’s collideConnected joint option (quite possible). :slight_smile:

It might be time to TRY some “forcings” on these ends-of-the-joint body objects… to see if I can blow-up the planet. :slight_smile:

Possible interesting note seen in line 233 of CannonJS plugin// set the collideConnected flag after the creation, since DistanceJoint ignores it.

Does this “after creation” setting… affect the HINGE joint, too? Possibly, does it cause the Hinge joint to ignore collideConnected because it was not set till AFTER hinge joint construction? hmm.

Pinging @Cedric FYI :slight_smile:

1 Like

That’s interesting! I’ll take a look at it

1 Like

I didn’t know what the !! what used for before. Basically, it’s a conversion to Boolean.
In this case:
myboolean = !!object
object can be false, null, 0, a valid object… anything. the first ! will return true if the object is false, null, 0,… and false otherwise. The second will invert that bool.
It’s like doing :
myboolean = (object != false )&&(object != 0)&&(object != null)…

I’ve seen that line Babylon.js/cannonJSPlugin.ts at master · BabylonJS/Babylon.js · GitHub and it’s unclear for me as well. I will dig deeper.

AFAIK, there is no generic system for filtering collision. You have to use the nativeparam that the physics engine provides. I know ammojs/bullet physics manages that pretty well.
Maybe it’s possible to add some api to expose that in a more generic manner.

1 Like

Hey, thx for the boolean info. You said it well!

Well, that’s what we’re doing, but we’re trying to get the BJS Cannon plugin to do that native setting FOR us… via BJS joint collision parameter. I’m not sure of your background, Cedric, but the collision parameter has been part of our BJS joint-making for quite a while (Oimo and Cannon). That param has always indicated… if/not the shapes on each end of the joint… are allowed to collide. And I think… Cannon’s joints are using collideConnected for exactly the same purpose. I could be wrong, though.

Look at Cannon’s constraint class… cannon.js/Constraint.js at master · schteppe/cannon.js · GitHub Line 49… .collideConnected is used in the joint constructor. It defaults to true.

The plugin is supposed-to use the joint collision param… to set Cannon constraint’s collideConnected… so that it is FALSE during that construction.

Dollars to doughnuts (chances-are)… if we could monitor line 49 of the constraint constructor, we would see options.collideConnected being incorrectly true… for all 4 of my joint-constructs.

This is why I question that comment line #233

// set the collideConnected flag after the creation, since DistanceJoint ignores it .

I don’t think we should EVER late-set collideConnected. I think… it has to be set as a joint option… BEFORE the joint is constructed, no matter which type of joint.

BUT… I think line 204 DOES do that… for ALL joint data (a good thing).

And so… I think maybe… lines 233 and 234… are old code debris… needing removal.

And then… somehow… WATCH line 49 of the Cannon constraint construction during my collision: false hinge-making scene… and make sure it is receiving options.collideConnected; = false.

We have to make sure the value of collision… is arriving at the constructor… as intended (false).

Thoughts? Cedric (or anyone)… is there an easy way to “watch” options that arrive at Cannon joint constructor (during a hinge-joint creation)? I suppose we need to overload something? :slight_smile:

Just maybe… maybe… removing lines 233 and 234 from plugin… fixes everything. I’m not sure that they are supposed to be there. But, I’m “in over my head” a bit, here.

Easiest way to “watch” is by using the browser debugger and put a breakpoint on those lines

Ok, new info. setMass might be an issue… or Wingnut being stupid… might be an issue.

Here, one ball&socket joint is attached to corner of greenbox. Collision param on joint is set false. Greenbox has dflt mass = 1.0, and THIS TIME, I DO NOT set its mass to 0… at scene-ready. I let it all fall.

Watch for a moment, and you can see… collision IS false… no colliding… all working.

Except, after 10 seconds… I set greenbox mass to zero. Collision instantly activates.

Then, 10 seconds later, I set greenbox mass to 1.0 again. Anything can happen, there. Greenbox could fly-away and leave leg1 hanging onto SOMETHING, but certainly not onto greenbox. OR, greenbox can stay connected to leg1, but collisions won’t turn OFF again.

Use keys x, z, shifted-x, shifted-z… to do some impulsing upon leg and greenbox at same time. When mass = 0 on greenbox, impulses don’t work on it (normal). Impulses WILL work on leg, no matter greenbox mass.

Side: Some might say that an impulse on leg1 SHOULD be able to “drag” a 0-mass box, easily (via the connected B&S joint). Others might say that a 0-mass p-body… should be frozen in-place, no matter the forces/joint-torques. Your masses may vary :wink:

Anyway, this “chase” is getting ugly. The mass of greenbox, or the calling of bjsImpostor.setMass() and/or CannonBody.updateMassProperties()… is definitely a factor. Lots more setMass tests coming.

Although I’m predominantly clueless, I’m starting to smell something rotten… near the “let’s add softbodies for AmmoJS”-area… of BJS impostor class. It is something that recently changed. The impostor class mods needed to satisfy Ammo… were quite extensive, me thinks.

My brain hurts.

Hey, thx for the boolean info. You said it well!

Well, that’s what we’re doing, but we’re trying to get the BJS Cannon plugin to do that native setting FOR us… via BJS joint collision or collideConnected parameter.

Look at Cannon’s constraint class… cannon.js/Constraint.js at master · schteppe/cannon.js · GitHub Line 49… .collideConnected is used in the joint constructor. It defaults to true.

The plugin is supposed-to use the joint collision param… to set Cannon constraint’s collideConnected… so that it is FALSE during that construction.

Dollars to doughnuts (chances-are)… if we could monitor line 49 of the constraint constructor, we would see options.collideConnected being true… for all 4 of my joint-constructs.

This is why I question that comment line…

// set the collideConnected flag after the creation, since DistanceJoint ignores it .

I don’t think we should EVER late-set collideConnected. I think… it has to be set as a joint option… BEFORE the joint is constructed, no matter which type of joint.

I started a new PG to understand what’s going on
it should look like what you want (let me know if I’m wrong).
So, in this PG, if you make small presses on s key until the box begins to move, you’ll see the cylinder freely moves, without collision. (collision is commented, so as it’s not present, considered false thanks to the famous !!)
if you uncomment line 79, the collision is activated and the behavior is different…well with collision now :smiley:

Nod. You’re impulsing directly up the Y axis in line 109? Are you trying to crush the trunnion on my ball-socket? Huh? :smiley:

Yeah, as long as we never do setMass() on either shape’s impostor, all is working.

But let’s turn on the timers and do some periodic setMass calls.

At 2 seconds, start us swinging - line 116
At 10 seconds, set greenbox mass = 0 - line 120 - collision activates
At 15 seconds, set greenbox mass = 1.0 - line 124 - greenbox moves without taking joint along.
At 20 seconds, impulse leg1 hard on z-axis… to try to hit box for collision test. Collision still active.

So, yes, I agree… initial collision testing is working… just don’t touch the mass on greenbox.

Should I try changing the mass on leg1, periodically? I’m scared.

If someone wants to “sign-off on this” as “fixed” or “no problem”… it’s fine with me. I’m not buying it, though.

With physic engine, in general, it’s a bad idea to change the mass at runtime.
The physics engine treats bodies with mass == 0 as kinetic objects: not dynamic, no joints, static object that collides with the dynamic bodies(mass > 0)

What do you want to achieve? I think it’s possible without touching the mass

Why did Schteppe do this, then? cannon.js/Body.js at master · schteppe/cannon.js · GitHub Our setMass() calls that. I wonder if we are giving it indigestion, somehow. :slight_smile:

Finding the (probable) bug in setMass(), of course. :slight_smile:

Less-bluntly, try to get lines 124, 132, 140, 148 collision parameter settings… to work correctly. But, that scene isReady line 236 (keeping greenbox from falling WITHOUT needing to set scene.gravity.y)… is a no-no, you think?

ok, thanks for your input/help.

I see. You will always have collision between the greenbox and the legs. It’s not because the joints parameters are not taken into account, it’s because the green box mass is 0. And when it’s 0, it becomes a static kinematic object that will collide with other dynamic objects. Like the ground. The only way to get it working is to set a mass to the greenbox

In this iteration, everything looks fine. No collision between legs and greenbox. an impulse on Y is fine as well.
But if you uncomment line 124, you’ll see the collision for that leg.

Yeah, that works ok… no collision by default… lookin’ good.

BUT… greenbox started as mass 1.0. At scene isReady, you set it to 1.0 again.

Now press “L” key to set greenbox mass at 0.5. Ugly. :slight_smile:

Or, you can turn on the 5 second timer 238-240… sets .5 mass… same results.

In short… late-setting of mass to same value… no problems. Change to different value, and a pet could get hurt. :slight_smile: During that sequence of events, we never set mass = 0, so it should not have become a “static kinematic object” that might automatically change its collision characteristics. (some kind of automatic type-casting, based upon mass=0? interesting. I have SO MUCH to learn, erf.)

Dinner time? Quittin’ time? I’m kind-of fried. Thanks for the interchange, Cedric… sorry if I’m being a pain-in-the-butt. We have quite a tutorial being built, here. :slight_smile:

Another try then
Y impulse and mass change seem to work. I tweaked badly the values to show the mass difference.
I change the method to set the mass and that one calls the update for the inertia matrix on the rigid body.

1 Like

scene.getPhysicsEngine().getPhysicsPlugin().setBodyMass(greenbox.physicsImpostor, .1); // works
greenbox.physicsImpostor.setMass(.1); // goes berserk

Interesting! Nicely found! hmm.

Ok, here we go again…

I have hijacked-in 3 core funcs… in lines 1-26. They are over-riding default funcs properly (see console), and all 3 are involved in our issue, here.

Line 265… I’m calling LOCAL setMass(0) when scene isReady… just like other tests we’ve done. Cedric’s setBodyMass(0) work-around line is at line 264… handy for alternative testing. SetBodyMass() is one of the local funcs, too… lines 21-25.

The “L” key currently uses Cedric’s setBodyMass(.1) work-around (line 253)… with a setMass(.1) in line 254, handy for alternative testing.

The only significant difference between setMass() and setBodyMass()… is lines 6-7 impostor param adjusting. SetParam() is also a local func, (lines 15-19), and line 17… this._bodyUpdateRequired = true; … is the root of all evil. :slight_smile: That is the ONLY significant difference between impostor.setMass() and plugin.setBodyMass().

Whatever happens during a “bodyUpdate”… is disrupting our impostor.setMass() calls… making them act differently than plugin.setBodyMass() calls. hmm.

Ok, that’s all I have so far. I’m heading out to try to determine what happens… during a body update.

Anyone want to bet… that the bodyUpdate does an impostor/body replacement, but forgets to re-add the joints that were previously-attached to the original body? :wink: (just guessing)

Maybe more precise, perhaps it re-adds the joints ok, but it forgets to set the original collideConnected values FOR those joints? hmm. Help welcome, as always. :slight_smile:

Sidenotes: We have a physics method laying around… called… umm… .updateForScaling() or something like that. THAT function… is supposed to be called after you scale a mesh that has an impostor assigned. IT… uses a replace-the-impostor-with-a-new-one operation, which I always thought was a bit dangerous. I wonder if THAT function… re-adds the joints and honors the collideConnected values previously put-onto those joints… so they act the same after the mesh scaling.

I’m not sure that “install a replacement impostor” is EVER a good idea. I know @RaananW somewhat disliked it, but was unable to find a more sane way of updating the scaling on a physics-active mesh.

Cannon might “see” those impostor replacements… and say “ok, i saw an impostor replacement, so all previous joint collideConnected settings for joints attached to the original impostor… are now null and void.” Essentially, Cannon could be erasing all collideConnected data… when it sees the impostor be replaced.

IF… CannonJS stores its collideConnected settings… via .collisionFilterGroup and .collisionFilterMask properties… then OUR setMass->setParam->bodyUpdate must adjust pEngine.collisionFilterGroup and .collisionFilterMask… so that it honors the newly-installed impostor (IF bodyUpdate IS doing a replacement).

---- Update ----

Four occurrences of _bodyUpdateRequired found on BJS impostor class. One of them… takes us to the plugin… .isBodyInitRequired() area… line 99.

There, yep, old body, new body, all sorts of “fresh init” stuff, which could easily kill any collideConnected settings that WERE on the joints, which are/were attached to the original body.

So, impostor.setMass() calls impostor.setParam()… which sets impostor._bodyUpdateRequired = true… which causes cannonPlugin.isBodyInitRequired() to return true, which causes a replacement of the p-body… which causes our joints to lose their collideConnected settings, which makes impostor.setMass() act differently than plugin.setBodyMass(). Yuh, yuh, yuh. Ugly. :slight_smile:

Impostor.setParam() should probably NOT set impostor._bodyUpdateRequired = true… for all param settings… especially not for changes to mass. But maybe more, too (friction, restitution). We don’t have setFriction() and setRestitution() funcs, yet, but, we probably should/could. Maybe impostor.setParam() should NEVER EVER set impostor._bodyUpdateRequired = true.

Disabling line 17 in the above PG… makes the legs “lay flat” better… as they should, but the model slowly sinks thru the ground for some reason. Interesting.

Cannon’s physics body has a .updateMassProperties(), but no .updateFrictionProperties() or .updateRestitutionProperties(). So I suspect Schteppe wants us to avoid on-the-fly friction and resty adjustments. :slight_smile:

Hi again. A little break… doing some work on the ACTUAL project… thanks to Cedric’s findings.

This is all for fun… a little Wingnut pride/show’n’tell. After 10 seconds… the lander lands… using its new spring-loaded-ball-and-socket joints (2 joints per leg). YAY! Fun bounce!

umm… all the old x/y/z /shiftedX/shiftedY/shiftedZ keys work, and the “L” key now does what it’s supposed-to… (L)ift-off! (Y-key does it, too, of course. SHIFTED-Y is… just TOO much fun. :slight_smile:

All working quite nicely, it seems. I still have stiffness, damping, restLength, tons of other tweaks to try on the springJoints. Still… it’s looking pretty good, I think.

Only 3 more bone-sections for each leg… and we’re done. And then, the motors… to make each 4-bone leg… fold/unfold into the belly pan of greenbox. Yikes!

Anyway, sorry for off-topic. But this is easier reading/thinking than my previous posts, eh? nod. :slight_smile:

1 Like