Accurately get velocity of btKinematicCharacterController

Post Reply
Silverlan
Posts: 27
Joined: Thu Oct 30, 2014 9:15 pm

Accurately get velocity of btKinematicCharacterController

Post by Silverlan »

I need to keep track of the velocity of my btKinematicCharacterController, but it seems that's not such an easy task.
Since it's kinematic, it doesn't have any internal velocity, so I store the velocity inside my player class.
After the simulation step I need to update the velocity, in case a collision occurred. (Otherwise I'd run into problems, such as the downwards velocity continuously increasing due to gravity)
To do that, I figured I could just store the controller's position before the simulation step, then subtract it from the new position after the simulation step, to get the delta velocity. This would work fine in principle if it wasn't for a small problem:
When the character falls downwards (due to gravity or any other force) and hits the ground, there is a small moment of penetration with the ground. (I've compiled bullet with 'double' precision already)
After that, the character's position immediately shifts to the ground level, to resolve the penetration.
This, however, is interpreted as upwards velocity, because the character was slightly below the ground before the simulation step, and is now ON it, which leads to a kind of 'bouncing' effect:
http://youtu.be/ZkmyrGCgshE

That's of course not acceptable at all, so I was wondering, what is the 'proper' way of keeping track of a character's velocity, while still keeping things like collisions into account?
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: Accurately get velocity of btKinematicCharacterControlle

Post by drleviathan »

I don't think there is a general "proper" way to do this. You'll just have to write special case code for your particular situation.

Here's an idea: call btKinematicCharacterController::onGround() and combine that with knowledge about previous state and new velocity: if it was falling fast not on ground AND is now on ground with new velocity pointing up then zero the new velocity's up component.
Silverlan
Posts: 27
Joined: Thu Oct 30, 2014 9:15 pm

Re: Accurately get velocity of btKinematicCharacterControlle

Post by Silverlan »

drleviathan wrote:I don't think there is a general "proper" way to do this. You'll just have to write special case code for your particular situation.

Here's an idea: call btKinematicCharacterController::onGround() and combine that with knowledge about previous state and new velocity: if it was falling fast not on ground AND is now on ground with new velocity pointing up then zero the new velocity's up component.
Gravity was just an example, it could be any force, in any direction, I need it to be accurate in all cases.

Is there perhaps some collision callback for kinematic objects? If there is, maybe there's something that can be done with that?
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: Accurately get velocity of btKinematicCharacterControlle

Post by drleviathan »

Bullet doesn't provide collision callbacks as a fundamental feature (unlike other physics engines such as Havok). Instead you need to scan the contact manifolds and keep track of contact pairs yourself. See this thread for more information:

http://www.bulletphysics.org/Bullet/php ... sion+event

My questions would be: What are you using the measured velocity of the character for? and Why does it need to be so accurate?

If it doesn't really need to be super accurate you could filter or average the velocity for a smoothed but slightly lagged measure. For example you could keep track of three distinct velocities: this frame's exact, last frame's exact, and the average of the two exacts. This would provide a slightly smoothed measure that is only one frame older than the one you've already got.

You can enhance the two-sample filter by also computing the acceleration between those two samples and comparing with the last acceleration. If this acceleration is the same as last, then use this exact velocity. If the two accelerations are different then use the average of the two previous velocities. In other words, use the measured velocity during smooth acceleration and the averaged during moments of non-zero "jerk".

This idea looks a lot cheaper to me than scanning the contact manifolds every frame.
Silverlan
Posts: 27
Joined: Thu Oct 30, 2014 9:15 pm

Re: Accurately get velocity of btKinematicCharacterControlle

Post by Silverlan »

drleviathan wrote:Bullet doesn't provide collision callbacks as a fundamental feature (unlike other physics engines such as Havok). Instead you need to scan the contact manifolds and keep track of contact pairs yourself. See this thread for more information:

http://www.bulletphysics.org/Bullet/php ... sion+event

My questions would be: What are you using the measured velocity of the character for? and Why does it need to be so accurate?
I'm working on an engine which is very highly focused around modding.
If someone needs to retrieve the player's or a NPC's velocity (or any other kinematic actor), for whatever reason, the result should be accurate, not some vague estimate.
If I could completely prevent the character controller from penetrating other objects on contact in the first place, it wouldn't be an issue at all.
drleviathan wrote:If it doesn't really need to be super accurate you could filter or average the velocity for a smoothed but slightly lagged measure. For example you could keep track of three distinct velocities: this frame's exact, last frame's exact, and the average of the two exacts. This would provide a slightly smoothed measure that is only one frame older than the one you've already got.
The 'bouncing'-effect you can see in the video can be rather severe at times, so even with averaging it would still be there, albeit less intense.


How is this usually handled in games with kinematic actors?
Characters don't just start moving at full speed instantly, there's always some form of acceleration until they get to full movement speed. To do that, I need to keep track of the velocity.
Post Reply