Advertisement

AABB moving player outside the colliding AABB

Started by May 06, 2024 10:27 PM
3 comments, last by JoeJ 6 months, 2 weeks ago

Hi,

I am working on implementing AABB collision and I can detect collision but say if you have a player AABB and the meshes AABB, when they collide, I set the player velocity to zero. However, since they are still colliding, the player can't get out anymore since velocity is zero. I'm doing this so the player does not go into the wall. I need to somehow push the player AABB out the colliding meshes AABB so the player collides but does not go through the wall. Essentially something like this:

Image

I'm not entirely sure how you would do this and would appreciate any insight. This is my current collision handling function:

// position is the players position 
// obj1 is the players AABB
bool AABBCollision(AABB obj1, const glm::vec3 position, const AABB& obj2)
{
	obj1.min += position;
	obj1.max += position;

	return (
		obj1.max.x >= obj2.min.x &&
		obj1.min.x <= obj2.max.x &&
		obj1.max.y >= obj2.min.y &&
		obj1.min.y <= obj2.max.y &&
		obj1.max.z >= obj2.min.z &&
		obj1.min.z <= obj2.max.z
		);
}

You could find the minimum separating distance:

In 2d there are two options. the black and the grey lines, on x and y axis. Easy to calculate.
Because black is shorter, that's the minimum displacement to separate the boxes.

Ofc. that's no realistic way to resolve the penetration (it lacks rotation), but maybe it's good enough.

Advertisement

The way I learned to do this was by stepping the player one direction at a time, and checking collision between each of those steps. You start by moving the player horizontally by their horizontal velocity, and then check for collision. If there's a collision, you step back horizontally, either the same distance you tried to move, or simple the width of the overlap (so that your player hugs the wall it collided with). Then you do the same vertically.

gregory2 said:
The way I learned to do this was by stepping the player one direction at a time, and checking collision between each of those steps. You start by moving the player horizontally by their horizontal velocity, and then check for collision. If there's a collision, you step back horizontally, either the same distance you tried to move, or simple the width of the overlap (so that your player hugs the wall it collided with). Then you do the same vertically.

Why do you split it up into horizontal and vertical directions?
Finding the time of contact, then rolling back, modeling collision response and going from there for the rest of the timestep, would be the ideal solution.
But the decoupling might introduce some errors, false positives, or corner cases i expect?

Otherwise i would recommend doing this to collide player against static world. (For multi body problems it becomes unpractical, because finding the very first collision of many, and constantly rolling back the whole simulation becomes too expensive.)

It avoids some problems. For example, resolving AABox penetration along the shortest distance as proposed is unstable if the penetration is closely equal for multiple dimensions. Then the resolved state jumps wildly on minor perturbations of the initial state, which is unstable.
Using the players movement direction to resolve (or avoid) penetration does not have this problem, but ofc. only if the movement is not zero or noisy.

This topic is closed to new replies.

Advertisement