Multiple planes on collision detection sliding

Hello everybody

I’ve got working collision detection and “sliding” response to it. Everything is working just fine, but when there is only one wall to collide (I’m ignoring collisions with terrain yet). When there is second wall, problems begin to emerge.
Following picture demonstrates what I’m talking about.

[ATTACH=CONFIG]704[/ATTACH]

Part A is the situation, in which everything works fine, the character (circle) simply slides along it.
What I need to achieve is when we reach the corner, the character should stop, as there is nowhere to go, but instead it ignores the first wall, and moves through it.

Here’s simplified code of my move function:


void ObjMobile::Move(glm::vec3 velocity)
{
  if (FindCollisions(velocity))
  {
    for (Collision &c : collisions)
      velocity -= coll.Normal() * glm::dot(velocity, coll.Normal());
  }

  position += velocity;
}

Collision is simply struct that contains colliding wall’s normal, and collision point.

So, putting everything short: I want to prevent movement against all the walls, when there are multiple collisions. What am I missing in my code?

This is because you don’t check the resulting velocity-vector after the second collision again versus the first wall. I’m not sure ad-hoc how this could be solved. Maybe using the same velocity-vector for all calculations, collecting the vectors that have to be subtracted from it for each wall, would help. I’m too lazy to prove this right now, but I bet it has to do with using the resulting vector of a collision handling as input for the next.

So basically, I cannot use one formula to check each wall at once, and instead I have to check each previous wall?
This may seem to be it. It’s just pity that there is no “one formula to rule them all”, it would make it way more performance-effective.
I will check this solution. Thanks for answer!

What i meant to say is to accumulate the subtrahends in the loop and to subtract this result from velocity, instead from subtracting them in-place. This should not be very much less permant.

So, if I understand you correctly, the code would look something like this:


void ObjMobile::Move(glm::vec3 velocity)
{
  glm::vec3 collisionVector(0.0f);
  if (FindCollisions(velocity))
  {
    for (Collision &c : collisions)
      collisionVector -= coll.Normal() * glm::dot(velocity, coll.Normal());
  }
 
  position += velocity + collisionVector;
}

Correct me if I’m wrong.

This code does not make any change however.

Then I have lost my bet, I guess. I’d have supposed the result is not the same.
Another idea I’d try is to accumulate the collision-normals from each wall to get the overall-collision-normal and work with that. But again this is just a guess - I’ve never implemented such a Thing. Sorry for my mistake. No idea.

I have re-checked my code, and I found an error - there was break in loop that was searching for collisions, which resulted only in one collision allowed.

I’ve fixed that, and now it works, but sometimes glitches happen, which allow to move through certain walls. I haven’t yet checked what might be the source of the error, but I think it is going in the right way.

That’s likely because the handling of a collision in one frame sets you in or beyond a wall in the next frame. The resulting velocity-vector is not checked for where it takes you. Imagine a huge velocity in the first example. It’s possible to be thrown right through the second wall.