射線與長方體

1 Ray-AABB交叉檢測算法

1.求射線與長方體6個面的距離,確定距離最小的三個面

計算射線在這三個面上的交點。從距離最小的交點開始判定是否在AABB盒裏


2 COCOS3.3 Ray-AABB實現

Ray-AABB碰撞檢測

進行求出射線後,需要做的便是與包圍盒的碰撞檢測了,如之前的代碼所示,在做碰撞檢測時,Cocos2d-x 3.3beta0中的Ray類裏面爲我們提供了intersects()方法,該方法的參數有OBB對象和AABB對象兩種,實際上最終都是轉換成了對AABB的檢測,最後來看一下碰撞檢測相關代碼:

bool Ray::intersects(const AABB& aabb) const
{
  Vec3 ptOnPlane; //射線與包圍盒某面的交點
  Vec3 min = aabb._min; //aabb包圍盒最小點座標
  Vec3 max = aabb._max; //aabb包圍盒最大點座標
  
  const Vec3& origin = _origin; //射線起始點
  const Vec3& dir = _direction; //方向矢量
  
  float t;
  
  //分別判斷射線與各面的相交情況
  
  //判斷射線與包圍盒x軸方向的面是否有交點
  //射線x軸方向分量不爲0 若射線方向矢量的x軸分量爲0,
  //射線不可能經過包圍盒朝x
  //軸方向的兩個面
  if (dir.x != 0.f) 
  {
    /*
      使用射線與平面相交的公式求交點
     */
    if (dir.x > 0)//若射線沿x軸正方向偏移
      t = (min.x - origin.x) / dir.x;
    else  //射線沿x軸負方向偏移
      t = (max.x - origin.x) / dir.x;
    
    if (t > 0.f) //t>0時則射線與平面相交
    {
      ptOnPlane = origin + t * dir; //計算交點座標
      //判斷交點是否在當前面內
      if (min.y < ptOnPlane.y && ptOnPlane.y < max.y && min.z < ptOnPlane.z && ptOnPlane.z < max.z)
      {
        return true; //射線與包圍盒有交點
      }
    }
  }
  
  //若射線沿y軸方向有分量 判斷是否與包圍盒y軸方向有交點
  if (dir.y != 0.f)
  {
    if (dir.y > 0)
      t = (min.y - origin.y) / dir.y;
    else
      t = (max.y - origin.y) / dir.y;
    
    if (t > 0.f)
    {
      ptOnPlane = origin + t * dir;
      if (min.z < ptOnPlane.z && ptOnPlane.z < max.z && min.x < ptOnPlane.x && ptOnPlane.x < max.x)
      {
        return true;
      }
    }
  }
  
  //若射線沿z軸方向有分量 判斷是否與包圍盒y軸方向有交點
  if (dir.z != 0.f)
  {
    if (dir.z > 0)
      t = (min.z - origin.z) / dir.z;
    else
      t = (max.z - origin.z) / dir.z;
    
    if (t > 0.f)
    {
      ptOnPlane = origin + t * dir;
      
      if (min.x < ptOnPlane.x && ptOnPlane.x < max.x && min.y < ptOnPlane.y && ptOnPlane.y < max.y)
      {
        return true;
      }
    }
  }
  
  return false;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章