Game Development Community

Clamp Collision Response

by Gary Preston · in Torque Game Builder · 11/14/2006 (4:11 pm) · 7 replies

I've a player with a rectangular collision box which collides with a scene object again with a simple rectangular collision box. Both objects are set to "CLAMP" response type and most of the time everything works fine.

With the debug banner enabled, contacts shows as 0. When the player is moved into contact with the scene object and the movement keys are kept held down, contacts shows 2 as expected, upon releasing the keys contacts returns to 0 as expected. The player can then be moved left/right/up without problem, and trying to move down will once more cause the clamp response and contacts becomes 2 until release.

However, occasionally after releasing the keys contacts remains at 2 and from that time on, the player can only move parallel to the scene objects surface, any attempt to move off it results in the Y velocity been reset to 0 by the collision response code.

I've had a quick look in the engine in t2dPhysics.cc and the culprit appears to be "resolveClampCollision"

// Solve Source?
    if ( solveSrc )
    {
        // Fetch Linear Velocity / Collision Normal.
        const t2dVector linearVelocity = pCollisionStatus->mpSrcPhysics->getGrossLinearVelocity();
        t2dVector collisionNormal = pCollisionStatus->mCollisionNormal;
        // Normalise Collision Normal.
        collisionNormal.normalise();

        // Calculate Dot Velocity Normal.
        const F32 dotVelocityNormal = collisionNormal * linearVelocity;

        // Any velocity to clamp?
        if ( mNotZero(dotVelocityNormal) )
        {
           // Set new Linear Velocity.
           // NOTE:-   vO = vI - ((N*vI)N) 
           pCollisionStatus->mpSrcPhysics->setGrossLinearVelocity( linearVelocity-(collisionNormal*dotVelocityNormal) );
        }
    }
.. solveDst snipped ..

When the bug occurs, the collisionNormal is (-0, -1.0) and linearVelocity is (0, -3.25), dot velocity ends up as (0, 3.25) and thus in set new linear velocity we end up setting the Y velocity to -3.25 - (-1*3.25) = 0.

If the above is instead modified to test for velocity been in the same direction as the collision normal, then when the bug occurs and we normally end up stuck to the sceneobject, we can now move away from it.

// Solve Source?
    if ( solveSrc )
    {
        // Fetch Linear Velocity / Collision Normal.
        const t2dVector linearVelocity = pCollisionStatus->mpSrcPhysics->getGrossLinearVelocity();
        t2dVector collisionNormal = pCollisionStatus->mCollisionNormal;
        // Normalise Collision Normal.
        collisionNormal.normalise();

        // Any velocity to clamp?

        const F32 dotVelocityNormal = collisionNormal.dot(linearVelocity);
        if ( dotVelocityNormal < 0 )
        {
            // Set new Linear Velocity.
            // NOTE:-   vO = vI - ((N*vI)N) 
            pCollisionStatus->mpSrcPhysics->setGrossLinearVelocity( linearVelocity-(collisionNormal*dotVelocityNormal) );
        }
    }
... same fix in the solveDst too ...

This is the first time I've really looked at the TGB source and I've only had a 5 minute glance over things, but even so this "fix" does not feel right. Although it solves the problem, it doesn't really address the cause.

The player shouldn't be getting stuck in the first place. I.E after releasing the movement keys contacts is remaining at 2 when normally it should return to 0 until we try to move into the sceneobject again. Why this is occurring though, I'm not sure.

Anyone have any ideas?

EDIT: Updated "fix" in case anyone reads this without reading all the thread.

#1
11/14/2006 (4:33 pm)
I believe this is a (very well known) bug and will be fixed at some point ;)
#2
11/14/2006 (4:44 pm)
I think the fix is going into the next release (1.1.3), but don't quote me on that. Seriously.. please don't quote me on that.
#3
11/14/2006 (4:46 pm)
Dude - you're supposed to say something vague and then wink ;)
#4
11/14/2006 (6:14 pm)
In that case, I'll just ignore it :)
#5
11/16/2006 (3:55 am)
Oh noes! I forgot to wink...

I'll do it bold so there's no mistaking it: ;)

Seriously though, there's absolutely no guaranty that the fix will go into the 1.1.3 release. There is a lot of discussion internally about collision and physics in general and some of the bigger fixes might be held off on until a later release for the sake of allowing them time to be fully tested. We don't want to put in changes that break things. The same applies doubly for 'fixes'.

In the meantime, change that (>) to a (>=) in the dot product check and you'll be on our same page, as far as clamp response. The effect is essentially the same, but the >= gives you the added benefit of skipping the rest in the case of velocity parallel to the collision normal. You could also just lose the if and change the else to "if(dot < 0)" for the same effect.

To give a little history on the subject, that check was initially there, but was taken out as a fix for a specific problem. The problem that the fix was supposed to solve was overlaps not being entirely resolved. An overlap would be detected and not entirely resolved because clamp was only checking for velocity into the object. The idea was that if clamp tried to resolve regardless of the velocity of the object then the overlap would eventually take care of itself. The result of the change was that overlaps would still sometimes only partially resolve, but now when they weren't entirely resolved, clamp would cancel velocity away from the collision normal. This is almost a tired topic in-house because we've run it into the ground and the root of the problem is well known and called for some major changes as to how overlaps are resolved in general.

The issue with clamp sticking was a freak side-effect of a fix that uncovered a deeper problem with collision that I can promise you is being addressed.
#6
11/16/2006 (5:03 am)
Quote: You could also just lose the if and change the else to "if(dot < 0)" for the same effect.

Yes that's how I finally left it. Well, I had "<=" hadn't occurred to me to exclude parallel too.
#7
11/18/2006 (6:07 pm)
Just a quick update for those concerned that don't have the Pro version and are unable to make this change: I just confirmed in a meeting the other day that this fix will in fact be in the 1.1.3 binary. The bigger physics and collision changes will be held off for a later release.