Oops I broke it: Massless characters!

Discuss any questions about BEPUphysics or problems encountered.
Post Reply
mcmonkey
Posts: 92
Joined: Fri Apr 17, 2015 11:42 pm

Oops I broke it: Massless characters!

Post by mcmonkey »

Why do all my issues here seem to involve me overcomplicating things and simultaneously horrendously breaking them?

I've had this issue for a while, but have been ignoring it as non-priority. Might have even posted about it somewhere and forgotten by now, it's been so long...

Anyway, so:

I wanted to implement character free-noclip-flight as a quick button press for cheats-enabled users. In short, they fly around without gravity, and also don't collide with anything.

Flight part is easy: Just spam teleport the player based on move key presses, with complete disregard for physics.
No-colliding is seemingly easy: Just set mass to 0, and collisions won't cause issues! Except if a player pushes something into a wall of course.

But... there's a problem.
Every once in a while, for reasons I have yet to specify any further than 'once in a while it just happens', the player will enter flight, go wherever, exit flight... and lose traction! IE, they have no consistent surface traction, and are unable to walk. They slip about on completely flat surfaces!

So the sequence of events, if unclear, is the following:
Character moves like normal
Character mass set to 0
Character repositioned
Character mass set to a standard ( greater than zero ) value
Character has no traction on any surface.

Now I already have an idea for fixing this:

Stop setting the mass to zero! Just be sure to update the position immediately after physics tick but before render, to ensure position is always correct. Also requires external tracking of position (by which I mean, separate from my usual 'just read it off the physics object')

But, if nothing else, I'd like to understand why this happens to ensure I don't end up with similar/related issues in the future.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Oops I broke it: Massless characters!

Post by Norbo »

When changing back to dynamic, do you ensure that the inertia tensor is locked? If not, the character will tend to fall over, which isn't the best position for walking.

To lock the inertia tensor:

Code: Select all

CharacterController.Body.LocalInertiaTensorInverse = new Matrix3x3();
mcmonkey
Posts: 92
Joined: Fri Apr 17, 2015 11:42 pm

Re: Oops I broke it: Massless characters!

Post by mcmonkey »

So I tried that idea.
It didn't help much.
Then I ran with the idea a bit, and had this code:

Code: Select all

            CBody.Body.LocalInertiaTensorInverse = new Matrix3x3();
            // Set mass to 0, or stored mass value here
            CBody.Body.Orientation = Quaternion.Identity;
            CBody.Body.AngularVelocity = Vector3.Zero;
            CBody.Body.LocalInertiaTensorInverse = new Matrix3x3();
and that didn't work.

But then I remembered, my world is exactly the way I was taught as standard for most mathematics: X/Y is length and width, Z is depth.

And ... BEPU, for whatever reason, does not like this model. BEPU has Y as depth for some reason.

So: I stored the preexisting quaternion rather than setting it to identity every time (on the guess that identity orientation would be sideways to my world)...

And it still loses traction and even support sometimes :(

So, I'm fresh out of tricks here.
mcmonkey
Posts: 92
Joined: Fri Apr 17, 2015 11:42 pm

Re: Oops I broke it: Massless characters!

Post by mcmonkey »

Oh also, if it helps: It seems to be relevant that the player is moving forward when they switch to dynamic (>0 mass).
If a player is perfectly still before hitting the disable-flight button, there's a much better chance of not having the traction loss.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Oops I broke it: Massless characters!

Post by Norbo »

I can't replicate the issue in the BEPUphysicsDemos when the inertia tensor is properly locked after switching back to dynamic. Is the inertia tensor being set only before making the object dynamic? If it's set before, the conversion to dynamic will overwrite the inertia tensor with a recomputed (and unlocked) one. (The code block you posted earlier suggests that you already tried this, but just making sure.)

If that's not it, could you try to recreate it in the demos so I can take a look?
mcmonkey
Posts: 92
Joined: Fri Apr 17, 2015 11:42 pm

Re: Oops I broke it: Massless characters!

Post by mcmonkey »

This is magical... I actually replicated it in your demos! I've never broken something so hard it's replicable even in demos. Yay!

Here's a gif to show what's happening first: http://i.imgur.com/OHUaia7.gifv

Basically, I fly up, land, and walk into the spinny thing... at which point I get knocked right over and lose the ability to walk.

It looks like the character controller is losing it's "don't fall over ever" lock when I play with its mass like that.

Anyway, here's CharacterControllerInput.cs http://pastebin.com/xXjUeH5L

That's the only thing I had to modify. I remapped the controls to sanity (WASD and space to move), deleted unrelated scrap, and added the X key to toggle flight.
mcmonkey
Posts: 92
Joined: Fri Apr 17, 2015 11:42 pm

Re: Oops I broke it: Massless characters!

Post by mcmonkey »

... Huh. I was entirely wrong to celebrate.

I figured it out.

Let's look at my code from earlier.

Code: Select all

            CBody.Body.LocalInertiaTensorInverse = new Matrix3x3();
            // Set mass to 0, or stored mass value here
            CBody.Body.Orientation = Quaternion.Identity;
            CBody.Body.AngularVelocity = Vector3.Zero;
            CBody.Body.LocalInertiaTensorInverse = new Matrix3x3();
See anything?

Code: Select all

LocalInertiaTensorInverse 
...

I accidentally edited the Inverse.

Autocomplete, damn you to hell!

It works perfectly fine in both demos and my actual environment when I correct that typo.

And now I'm going to go hang my head in shame a while.

As always, thanks for the help, and the great work on BEPU in general!
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Oops I broke it: Massless characters!

Post by Norbo »

For reference, the inverse is actually the property most conceptually appropriate to set to all zeroes. The way to 'lock' rotation is to make it so no dynamic force can introduce any angular velocity, which means effectively infinite inertia. One over something-approaching-infinity approaches zero, so that's why I generally say set the local inverse to all zeroes. That said, setting the LocalInertiaTensor happens to work as well due to the way the adaptive invert works, it's just a bit of a happy accident.

If you have a situation where setting the LocalInertiaTensorInverse to all zeroes doesn't work and setting the LocalInertiaTensor to all zeroes does, that's weird and likely a bug.

The edited CharacterControllerInput, as posted, doesn't seem to have any references to the inertia tensor at all, which would be why it didn't work.
mcmonkey
Posts: 92
Joined: Fri Apr 17, 2015 11:42 pm

Re: Oops I broke it: Massless characters!

Post by mcmonkey »

I just realized your example used the Inverse too, I thought it was just a typo on my part.

... Huh.

Well, something's wrong, because setting the non-inverse tensor fixes the bug in quick testing and the inverse one doesn't.

You can easily add either one into the example code yourself to see it happen.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Oops I broke it: Massless characters!

Post by Norbo »

Both the LocalInertiaTensorInverse and the LocalInertiaTensor appear to work as expected. Are you testing in an old version? Is something else overwriting the inertia tensors after they're being set to zero?
mcmonkey
Posts: 92
Joined: Fri Apr 17, 2015 11:42 pm

Re: Oops I broke it: Massless characters!

Post by mcmonkey »

... Huh. Rather than fixing it, it /temporarily/ fixed it. I was wrong.

I'm not touching the inertia tensors by hand anywhere outside this code.

Is there anywhere else it'd be adjusted that might be relevant?
mcmonkey
Posts: 92
Joined: Fri Apr 17, 2015 11:42 pm

Re: Oops I broke it: Massless characters!

Post by mcmonkey »

I seem to have unbroken it, by ENFORCING a correct orientation.
As orientation seems to be inherently linked to the inertia tensor, based on a quick glance at the code.

Code: Select all

        public static readonly Quaternion PreFlyOrient = Quaternion.CreateFromAxisAngle(Vector3.UnitX, Math.PI * 0.5);
^ the setup

Code: Select all

            CBody.Body.LocalInertiaTensorInverse = new Matrix3x3();
            CBody.Body.Orientation = PreFlyOrient;
^ The usage

That seems to so far produce consistent not-fally-over results, if by no other reason than it fixes orientation every time it has potential to fall over!
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Oops I broke it: Massless characters!

Post by Norbo »

Notably, there is no way for it to fall down (or even begin to change orientation) between making it dynamic and setting the inertia to all zeroes unless a timestep occurs between the two, or if the velocity/orientation is manually set to fall-ish values.

Is the space being updated asynchronously with this modification? That would cause all kinds of problems. Is anything else modifying the angular velocity or orientation during previous transitions? Is it ever potentially dynamic while 'flying'?

Reproducing the behavior in the demos would be helpful, since I'm still just guessing.
Post Reply