Bullet - position a collision capsule for an animated character

Started by
5 comments, last by Michael Valle 7 years, 7 months ago

I am trying to implement a simple collision capsule so my animated character will be able to physically walk on the ground, bump into walls, etc.

My original approach was the following:

1. The character is positioned and animated relative to a root transform R.

2. Let the position of the capsule, P0 be either explicitly defined by the animation (via keyframes), or computed from the characters position.

3. Execute the bullet simulation step to derive the corrected capsule position, P1

4. Multiply R by Delta(P0, P1 ) to correct the position and shift the character.

Or in plain English... determine where you expect the collision capsule to be from the animation, determine where the capsule ends up (after forces, and collision resolution), and shift the character's location accordingly.

A problem arose with 2, because I found that Bullet does not easily let you just re-position a rigid body in this manner. I would have to remove and re-add the body to the simulation for this to work and i'm worried that this will be an issue with speed and stability. I don't think Bullet is meant to be used in this way.

A potential solution is to set the capsule's velocity equal to Delta(P0, P1 ) at every frame (I like this idea because then it gives the capsule the appropriate momentum and it would realistically knock another lose object around if you ran into it). But then the problem becomes friction. If I set the friction to 0, the capsule will slide everywhere and not grip the surface. But if I use non-zero friction, then the shift will be dampened and not correct.

Am I using an outlandish approach for this? Can anyone suggest a better way?

Advertisement

Havok has animated ragdolls built in (at least it was so 10 years back).

You could take a look how their stuff works (how it reacts to obstacles etc).

Personally i do it the hard way using Newton physics engine: Full simulation of the whole skeleton, balancing controller etc.

Newton allows to create powered joints that work stable enough for a walking character (but i need at least 90 Hz).

There are plans for a built in simulated character feature in the (near?) future.

Because you are only interested in animation, it's a lot easier and that should work with Bullet too (although in my experience it's the worst engine i know when it comes to stability).

The main problem is the question how simulation should affect things, how to handle feedback from physics by procedural animation.

Your question about friction may be only the first of a infinite number...

EDIT:

Oh sorry - you talk about a SINGLE capsule, not one capsule per bone as i thought :)

Have you tried not to move the capsule by character, but the other way around?

I made a simple capsule character controller by attaching a upvector constraint to keep it upright despite friction and applying forces to move it at target speed.

You can tweak this easily to your needs and then use the capsule velocity to calculate matching animation speed.

Thank you for that detailed response!

I made a simple capsule character controller by attaching a upvector constraint to keep it upright despite friction and applying forces to move it at target speed.

You can tweak this easily to your needs and then use the capsule velocity to calculate matching animation speed.

That sounds very doable for a basic walking/running animation.

I guess my concern is how precise this will all be for more complex animations, and if the physical corrections per frame are going to accumulate and mess up the look and feel that the artist creates. Or, if I ever need the animation to be precise. For example, maybe I need the character to leap a certain distance, or climb up on a ledge or something. The bounding box would be following a specific path, and I would have to accurately compute the forces to apply to the object to move it along this path.

The simplest approach for this I could think of is:

1. compute the desired change in position for the capsule at each frame of the animation, and record that as velocity.

2. compute the change in velocity for the capsule at each frame of the animation, and record that as acceleration.

3. apply force = mass*acceleration to the capsule at each frame.

The good thing is this calculation could be pre-computed for the whole animation, but this would certainly not be 100% accurate, estimating velocities and accelerations in this matter. Certainly the position of the animated character could be "corrected" at the end of each frame, but I wonder how much the resulting animation will differ, with these mild discrepancies adding up, potentially messing up the appearance of the animation.

More sophisticated, numerical approaches could be used to calculate the appropriate acceleration/force I guess, such as taking the Fast Fourier Transform, and then computing the 2nd derivative. But this all seems like overkill.

Does the above, 3 step approach seem like it would work well enough? Guess I don't yet have the experience to know if good enough is good enough..

(edit) Friction still creates a big problem with the approach above though. For a walking animation, for example, the above calculation would only produce enough force to accelerate the character to walking speed and then no more force would be applied, and the friction would quickly stop the motion. A compensating force could be added to counter-act the friction, but I'd have to calculate the exact amount of force to add, and do it only when the character is in contact with the ground....

Sheesh this is getting quite complicated for something I thought would be rather simple..

I think you should not precompute for the whole animations - stuff will drift appart not only due to friction, but also because of integration errors.

Instead i'd make the body follow the animation and allow a error threshold.

As long as the body / animation difference is smaller than the threshold, keep animation and compensate the error for physics in the next timestep,

otherwise change the animation so the difference is not larger than threshold (but keep trying to compensate physics error).

Setting force instead velocity as you say should work better (engine can fix bad input like trying to push something inside a wall),

It depends on physics engine and maybe the selected solver, but you should see improvements using forces, like less jitter on the wall example.

Here's some code to get the force from a target velocity.

currentVel is the actual body velocity.

Finally you should clamp resulting force to a maximum magnitude to prevent supermen and physics blow ups.

If you set this maximum large enough, the capsule should follow also with ground friction and it will push light weighted obstacles out of the way.

E.g. for the friction case it will automatically calculate a larger force because actual measured velocity will be initially low.

There will be some lag, oszillations or even jitter, but the error threshold talked above should be able to hide those things.

inline sVec3 ConvertLinVelToForce ( sVec3 &targetVel, sVec3 &currentVel, float timestep, float mass)
{
    sVec3 force ((targetVel - currentVel) * (mass / timestep));
    return force;
}

That sounds reasonable..

As long as the body / animation difference is smaller than the threshold, keep animation and compensate the error for physics in the next timestep,

otherwise change the animation so the difference is not larger than threshold (but keep trying to compensate physics error).

What's the difference between "compensate for the error in physics" and "change the animation" in what you describe above?

My only other concern is moving platforms when computing the target velocity. I suppose I could compute this as (target animation velocity ) + (velocity of platform). By clamping the resulting force within some threshold, this would allow for some realistic sliding of the character if they were to land on a platform with a considerable difference in velocity.

Do you think this would work with the approach you described?

I'll try to giv an example. Say AI wants to have the initially still standing character walk a straight line from a to b with constant velocity 5.

We then calculate the force necessery to change capsule velocity from zero to 5.

But we don't take ground friction into account, so we reach only a velocity of 3,

and because of that the capsule position is between the predicted animation target and its initial position.

Let's call this the position error and assume this error is smaller than our threshold,

so we render the character at predicted position and use the animation to set our next simulation target.

After some simulation steps the error becomes smaller and smaller and everything is fine.

So this is the compensation part of the example.

Then something bad happens: There is a heavy big crate in the way and AI was not aware of this - character tries to walk through which is impossible.

The capsule gets stuck, and the difference beween capsule and animation becomes larger and larger each step, and when it's larger than the threshold (10cm or something),

it's time to change the animation (keep a max distance of 10cm from rendered character to capsule), notify AI of the obstacle to stop walking and whatever.

This should work for the moving platform example as you expect (although the trick might filter out some of the cool sliding you expect, similar to how a low pass filter removes details).

Clamping force should be done always, also to prevent the capsule from moving too heavy crates and to keep simulation stable.

I think you can get some robust mechanics from that, but will not help to get life like animations - combining animation and simulation always makes this harder :)

Thank you for that detailed response!

I am still doing some research and piecing together an approach, using elements of what you described and some others.

Here are some good details of an approach using ray casting. This is described as "the general approach" which is what I'm more or less looking for here. I'm wanting to implement a "tried and true" technique, not something too original.

https://groups.google.com/forum/#!topic/ode-users/mkbwSymDRm8

The general approach to this is to model the player with a capsule geom,
suspended over the ground with a downward facing ray geom. The bottom
cap of the capsule should roughly be at knee height. The capsule should
only collide with walls and ceilings, the ray only with the ground. You
may find it necessary to use more than one ray to prevent the character
falling into small gaps and getting stuck (e.g. the gap between two
planks bridging a trench).

What I'm not sure about with this is how they resolve the ray cast collision. Do they just apply forces to adjust the height of the capsule so its always suspended at the appropriate height above the ground?

I wonder if it would make sense to suspend gravity on the capsule and just have a check to see if there is ground beneath the object, and apply gravity forces only if not.

Here is some pseudo code for the general approach I'm thinking of so far. It is intended to support moving platforms. I leave out some of the logic you describe about updating the animation, and the threshhold, etc. Just thinking about the capsule physics mainly, at the moment... It is assumed that gravity is disabled on the capsule object.


heightOffFLoor = doRayCastToGround();
desiredHeight =  getDesiredHeight();
delta = desiredHeight-heightOffFloor;
applyForcesToShiftHeight(delta); // apply just enough force to move the body up by delta


target_velocity = base_velocity + (isOnGround ? groundSpaceTransform: Identiy) * getVelocityFromAnimation();
current_velocity = body->getLinearVelocity();
applyForcesToChangeVelocity(current_velocity,target_velocity);

if (isOnGround)
{
	base_velociy = groundBody.getVelocity();
}
else
{
	base_velocity += gravity;
}

Note I use "base_velocity" to control both the added velocity of a moving platform, and also gravity when there is no platform. I also make use of the ground transform (derived from the contact normal in the ray cast) to make sure that the motion follows the slant of the terrain.

Does this seem like a reasonable approach?

(edit) Also, not sure exactly how multiple ray casts would be handled, since it mentions that using just one ray can get the object stuck....

This topic is closed to new replies.

Advertisement