1
\$\begingroup\$

I have followed this tutorial and ported it to 3d with glm. Everything works fine when the collision normal is reported as positive ((1,0,0),(0,1,0),(0,0,1)) but when it is negative the player aabb gets "stuck: on the wall demonstrated here.

Here is the code used to detect collisions:

  Hit AABB::intersectSegment(glm::vec3 pos,glm::vec3 delta,glm::vec3 padding)
  {
    glm::vec3 scale = glm::vec3(1.0)/delta;
    glm::vec3 sign = glm::vec3(glm::sign(scale.x),glm::sign(scale.y),glm::sign(scale.z));
    glm::vec3 nearTime = (position - sign * (hwidth + padding) - pos) * scale;
    glm::vec3 farTime = (position + sign * (hwidth + padding) - pos) * scale;
    if ((nearTime.x > farTime.y) || (nearTime.x > farTime.z) || (nearTime.y > farTime.x) || (nearTime.y > farTime.z) || (nearTime.z > farTime.x) || (nearTime.z > farTime.y))
      return Hit(false);

    float near = glm::max(glm::max(nearTime.x,nearTime.y),nearTime.z);
    float far = glm::min(glm::min(farTime.x,farTime.y),farTime.z);

    if ((near >= 1) || (far <= 0))
      return Hit(false);

    Hit hit;
    hit.time = near;//glm::clamp(near , 0.f, 1.f);
    if ((nearTime.x > nearTime.y) && (nearTime.x > nearTime.z))
    {
      hit.normal = glm::vec3(-sign.x,0,0);
    }
    else if ((nearTime.y > nearTime.x) && (nearTime.y > nearTime.z))
    {
      hit.normal = glm::vec3(0,-sign.y,0);
    }
    else if ((nearTime.z > nearTime.y) && (nearTime.z > nearTime.x))
    {
      hit.normal = glm::vec3(0,0,-sign.z);
    }


    hit.delta = hit.time * delta;

    hit.pos = pos + hit.delta;
    hit.timeVect = nearTime;


    return hit;

  }
Sweep AABB::sweepAABB(AABB box,glm::vec3 delta)
  {
    if (delta == glm::vec3(0,0,0))
    {
      Sweep s;
      s.hit.colided = false;
      s.time = 1;
      return s;
    }
    Sweep sweep;
    sweep.hit = intersectSegment(box.position, delta, box.hwidth);



     if (sweep.hit.colided)
     {
       sweep.time = glm::clamp(sweep.hit.time - EPSILON,0.f,1.f);
       sweep.pos = box.position + (delta * sweep.time);

       glm::vec3 direction = glm::normalize(delta);

       sweep.hit.pos += direction * box.hwidth;
       sweep.item = box.getSimple();
       sweep.other = getSimple();

     }
     else
     {
       sweep.pos = box.position + delta;


       sweep.time = 1;
     }

   return sweep;
  }

Here is my recursive method for resolving the collisions:

glm::vec3 project(glm::vec3 a,glm::vec3 b)
{
  return (glm::dot(a,b)/glm::dot(b,b))*b;
}
void Player::resolveColision(math_custom::Sweep& least,math_custom::CollisionMode mode,float remTime)
{
  if (mode == math_custom::SLIDE)
  {
   velocity = velocity - project(velocity,glm::abs(least.hit.normal));
  }
  if (mode == math_custom::BOUNCE)
  {
    float dot = velocity.x * least.hit.normal.x + velocity.y * least.hit.normal.y + velocity.z * least.hit.normal.z ;
    glm::vec3 u = least.hit.normal * dot;
    glm::vec3 w = velocity - u;
    velocity = w - u;

  }
  if (mode == math_custom::TOUCH)
  {
    velocity = glm::vec3(0,0,0);
  }

  if(least.hit.normal == glm::vec3(0,-1,0))
    grounded = true;

    colided = true;
    colidedAabb = aabbs->at(least.id);



}
void Player::getCollisons(std::vector<math_custom::AABB*>* aabbs)
{
  sweeps.clear();
  for (int i =0;i < aabbs->size();i++)//for every aabb in the list
  {


    math_custom::AABB broadphase = math_custom::GetSweptBroadphaseBox(*aabb,velocity);

    if (broadphase.isColiding(*aabbs->at(i)))
    {
      math_custom::Sweep s = aabbs->at(i)->sweepAABB(*aabb,velocity);
      if (s.hit.colided)
      {
        s.id = i;
        sweeps.push_back(s);
      }

    }

  }
  std::sort(sweeps.begin(),sweeps.end(),math_custom::sortByTiAndDistance);
}

void Player::move(int iter)
{

  getCollisons(&tempaabbs);
  if ((sweeps.size() != 0))
  {


    aabb->translate(sweeps[0].pos-aabb->position);

    debug::print(sweeps[0].hit.normal);
    debug::print(velocity);
    resolveColision(sweeps[0],defaultMode,1.f);

    tempaabbs.erase(tempaabbs.begin()+(sweeps[0].id));
    move(iter + 1);
  }
  else
  {
    aabb->translate(velocity);
  }
}
\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

If you used the one in the tutorial, the value you used for epsilon is too small. I modified the JavaScript from the tutorial, and realized you problem happens there, too. Just lower the value of epsilon to about 0.000001f, and you should be fine.

\$\endgroup\$
2
  • \$\begingroup\$ @agone Extremely funny being reminded of this code 7 years later. I have since solved the overall problem (Collision Detection) but for trisoups instead of bounding boxes. \$\endgroup\$ Commented Sep 21, 2024 at 15:27
  • \$\begingroup\$ Welcome back. Sorry about the ping, this site has a bot that pings unanswered questions with zero votes. \$\endgroup\$ Commented Sep 22, 2024 at 19:14

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.