Jondolf / avian

ECS-driven 2D and 3D physics engine for the Bevy game engine.
https://crates.io/crates/avian3d
Apache License 2.0
1.22k stars 95 forks source link

Dominance for joints? #180

Open mattdm opened 9 months ago

mattdm commented 9 months ago

Since you were so amazingly responsive with my last request, I will punish you by making another. :)

Rapier3d has an (barely documented, yay!) "Rope Joint", which enforces distance between two bodies. (Despite the name, it has both a minimum and maximum, so it's not really a "rope".) Leaving aside actually actually adding such a joint to xpbd, in playing with this in Rapier3d, I ended up with something funny.... I had an object I wanted to follow "leashed" to my camera, but instead of stopping at the limit, the camera lifted the object off the ground, like a UFO abduction. Obvious in retrospect!

In real life, of course, both ends of the rope can pull the other one — anyone who has walked a big dog on a leash knows how this goes. In a game, it is often useful to say "this thing needs to follow the other one, no matter what", like my camera experiment, or, say, the hands of a clock or a fan (the clock body or fan mount should never spin the other way). One can increase the mass, but that has other implications (the dog walker shouldn't need to weigh 2 tons just to be sure...).

From what I can see this should be doable with a custom constraint, but it would be handy to have a parameter to the "preassembled" joints which would make one of the anchors "fixed" -- effectively treating the body attached to that anchor as RigidBody::Static for the purposes of that joint alone.

Something like fixed_body: Option<Entity>?

Or, anchor1_locked: bool, anchor2_locked: bool?

Jondolf commented 9 months ago

We already have a DistanceJoint, which is roughly equivalent to Rapier's RopeJoint. This is only on the main branch though, which is why it doesn't show up in the docs yet.

In the dominance PR, I actually made the dominance also apply to joints (didn't test properly though, mainly tried collisions). If a dog walker has a higher dominance than a dog attached to a leash, the dog should follow the dog walker as if the dog walker was kinematic/static. Maybe this should also be configurable at the joint level like you're suggesting? That way, you could make the bodies collide normally, but the joint could be configured to make one of the bodies fixed/dominant

mattdm commented 9 months ago

Oh, that's cool. However, I think there's a problem there. It works for my "leashed camera" idea, where I don't want the camera to push anything. But for the dog and dog-walker, there's a problem if there are more things in the world. Let's say there's a car -- ooh, this is getting grim, but I'm going to stick with it. Say the dog walker is at dominance 0 (default) and the dog at dominance -1 (it's a tiny dog). This should work perfectly for the dog walker always pulling the dog, or keeping the dog from pulling past the limit.

But now, enter the car. The hapless walker and dog are in a crosswalk, and the car runs the light. Here, all three should be at the same level.

This could possibly be solved by some kind of complicated layering approach, but to me it's simpler to keep the dog, dog walker, and car all on the same dominance level for collisions -- and have the joint-level fixed/dominant property just controlling that interaction.