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: 418
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