Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

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;
    }
}
share|improve this question
    
What is "wall sliding"? Should you stop moving as you hit a wall and fall straight downward? Should you be able to slide up walls? –  Anko Feb 24 '13 at 17:43
    
A picture or video reference would really help in understanding your problem here. –  RobCurr Feb 24 '13 at 19:26
    
@Anko: I'm sorry, I thought wall sliding was a common definition in collision detection circles but appareantly it isn't. I'll edit it in my question :) –  Joey Feb 25 '13 at 15:08
    
I find the explanation even more confusing: What does it mean to "walk in a vertical slope"? What is "horizontal rotation"? How can you "walk towards the wall until you've left the wall"? –  Anko Feb 25 '13 at 16:21
    
@Anko, The player walks along the -z axis into a wall that is Y aligned and has a normal facing in the +z direction. With horizontal rotation I mean rotating around the Y axis. This video should show some visuals of wall sliding : youtube.com/watch?v=aKqBG9PAMfo Hope it helps. –  Joey Feb 25 '13 at 16:37
add comment

2 Answers

up vote 3 down vote accepted

I think you need to multiply invNormal by the length of direction before making the subtraction.

Vector invNormal = normal.Negative();
invNormal *= direction.length
Vector wallDir = direction - invNormal;
share|improve this answer
    
I'm at work now so can't test it right now but your answer gave me a moment of sudden clarity so that's probably the correct answer. I'll let you know when I'm home! –  Joey Feb 25 '13 at 15:11
    
it seemed to fix the problem when I'm only moving in one axis and colliding with my plane (for example, when falling down due to gravity and reaching a plane. I stop bouncing since the length negates the fall velocity). However, I still get a bouncy effect when I'm two axes along the wal (for example, falling and colliding with the floor plane while moving forward along the plane). Did I miss something? –  Joey Feb 25 '13 at 16:31
1  
I fixed the problem! In order to account for movement among multiple axes I also multiplied my direction by the normal (to remove the non-significant axis) invNormal = invNormal * (direction * normal).Length(); which made sure the length is calculated only among the significant axis! Thanks for your help Krazy, wouldn't have found it without your suggestion! :) –  Joey Feb 25 '13 at 16:42
    
Glad I could help. –  Krazy Feb 26 '13 at 0:24
add comment

You want to lose all the velocity in the direction of the normal of the wall. To do this, project the current direction onto the wall normal to get the wall part of the velocity/direction.

projected = normal * dot(direction, normal);
direction = direction - projected

Last line might have to have the sign flipped depending on the normals direction (in or out of the wall).

share|improve this answer
    
Isn't this just a different implementation for what I already did? The added length section might prove valuable though. I'll test it out! Thanks! –  Joey Feb 25 '13 at 15:09
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.