0
\$\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\$
0
\$\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\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.