Wednesday, July 10, 2019

c++ - Collision detection - Smooth wall sliding, no bounce effect


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;
}

}

Answer



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;

No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...