I spent all yesterday struggling with collision bugs. I was able to get spinning objects in the game, but then they kept leaving the world.
My bullets and particles are all handled with ray-casts, so they never tunnel. My characters are fairly large, and don't move that fast, so they don't tunnel.
I added some hacks to the capsule collision system to try to catch the bad cases. One in particular helped, but was not 100% effective. What I did was to cast a ray from the object midpoint last frame to this frame, and see if that intersected a triangle. If so, I left the object where it was last frame, but bounced it back.
This prevented some tunnelling, but succeeded in making the character and weapons stuck at times. The problem was that this hack was interfering with normal legitimate collisions that would have been detected just fine with the regular system. When I made the hack only apply when the normal system failed, it didn't prevent the issues.
Turned out a combination of factors was causing problems. One is that the capsule collision doesn't yet handle the nastly problem of a deeply embedded capsule very well. The other issue was just things moving too fast.
Basically, you don't want to move more than a certain percentage of the object's radius in a single physics tick, or you may miss
a collision. So, I sat down and worked out exactly how fast a given object should be allowed to go without generating tunnelling problems.
It's related to how long your physics ticks are ( yet another reason to do fixed time-step physics ), and the radius of the object.
Once I figured out the speed for my knife of a 0.08 meter radius capsule was only ~ 5 m/s, I realized what the real problem was when my character was chucking it at 25 m/s, and spinning it at 20 m/s as well.
One way to fix it is to increase the object radius. Of course, that just causes the weapons to appear to float about the ground when they come to rest.
Here is a shot of some floating weapons :
Other ways of fixing it include moving your object only a fraction of his radius over and over again until the timestep is used up. This can be way more expensive than a single test.
Yet another way is changing, say, a static sphere test into a swept-sphere test. A swept-capsule test, though seems decidedly less trivial - especially if its rotating.
So, I decided to grow an object's collision radius proportionally to the speed above the safe limit. This seems to work very well, and causes no visual anomalies that I could see. What a relief. There is very little in game programming more disheartening than a system you thought was robust ( like the collision one ), suddenly catastrophically failing - like a slowly falling knife just gliding through the floor.
Here are some diagrams showing a caspule with a growing radius as well as a graph of radius vs speed.
Here is the relevant source snippet.
float32 Collidable::GetEffectiveRadius() const
const float32 speed = D3DXVec3Length( &mVelocity );
const float32 frame_time = (float32)g_pApp->GetActiveSession()->GetPhysicsFrameTime();
const float32 radius = GetRadius();
const float32 max_safe_speed = 0.5f * radius * frame_time;
if ( speed <= max_safe_speed )
return ( radius + ( speed - max_safe_speed ) / frame_time );
And here is your moment of Zen. Note the shadow of the knife on the wall.