Collision detection - Smooth wall sliding, no bounce effect

Posted by Joey on Game Development See other posts from Game Development or by Joey
Published on 2013-02-24T15:16:33Z Indexed on 2013/11/13 4:16 UTC
Read the original article Hit count: 423

Filed under:
|
|

I'm working on a basic collision detection system that provides point - OBB collision detection. I have around 200 cubes in my environment and I check (for now) each of them in turn and see if it collides. If it does I return the colliding face's normal, save the old player position and do some trigonometry to return a new player position for my wall sliding.

edit
I'll define my meaning of wall sliding: If a player walks in a vertical slope and has a slight horizontal rotation to the left or the right and keeps walking forward in the wall the player should slide a little to the right/left while continually walking towards the wall till he left the wall. Thus, sliding along the wall.

Everything works fine and with multiple objects as well but I still have one problem I can't seem to figure out: smooth wall sliding. In my current implementation sliding along the walls make my player bounce like a mad man (especially noticable with gravity on and moving forward).

I have a velocity/direction vector, a normal vector from the collided plane and an old and new player position. First I negate the normal vector and get my new velocity vector by substracting the inverted normal from my direction vector (which is the vector to slide along the wall) and I add this vector to my new Player position and recalculate the direction vector (in case I have multiple collisions).

I know I am missing some step but I can't seem to figure it out.

Here is my code for the collision detection (run every frame):

Vector direction;
Vector newPos(camera.GetOriginX(), camera.GetOriginY(), camera.GetOriginZ());
direction = newPos - oldPos; // Direction vector
// Check for collision with new position
for(int i = 0; i < NUM_OBJECTS; i++)
{
    Vector normal = objects[i].CheckCollision(newPos.x, newPos.y, newPos.z, direction.x, direction.y, direction.z);
    if(normal != Vector::NullVector())
    {
        // Get inverse normal (direction STRAIGHT INTO wall)
        Vector invNormal = normal.Negative();
        Vector wallDir = direction - invNormal; // We know INTO wall, and DIRECTION to wall. Substract these and you got slide WALL direction
        newPos = oldPos + wallDir;
        direction = newPos - oldPos;
    }
}

Any help would be greatly appreciated!


FIX I eventually got things up and running how they should thanks to Krazy, I'll post the updated code listing in case someone else comes upon this problem!

for(int i = 0; i < NUM_OBJECTS; i++)
{
    Vector normal = objects[i].CheckCollision(newPos.x, newPos.y, newPos.z, direction.x, direction.y, direction.z);
    if(normal != Vector::NullVector())
    {
        Vector invNormal = normal.Negative();
        invNormal = invNormal * (direction * normal).Length(); // Change normal to direction's length and normal's axis
        Vector wallDir = direction - invNormal;
        newPos = oldPos + wallDir;
        direction = newPos - oldPos;
    }
}

© Game Development or respective owner

Related posts about c++

Related posts about 3d