Exemple #1
0
   bool Intersects(const Ray2 &ray, const Circle &circle, float *distance)
   {
      const Vector2 &rayDir = ray.GetDirection();

      // Adjust ray origin relative to circle center
      const Vector2 &rayOrig = ray.GetOrigin() - circle.GetCentre();
      float radius = circle.GetRadius();

      // Check origin inside first
      if (rayOrig.MagnitudeSquared() <= radius * radius)
      {
         SetPtrValue(distance, 0.0f);
         return true;
      }

      // Mmm, quadratics
      // Build coeffs which can be used with std quadratic solver
      // ie t = (-b +/- sqrt(b * b + 4ac)) / 2a
      float a = Vector2::DotProduct(rayDir, rayDir);
      float b = 2 * Vector2::DotProduct(rayOrig, rayDir);
      float c = Vector2::DotProduct(rayOrig, rayOrig) - radius * radius;

      // Calc determinant
      float d = (b * b) - (4 * a * c);
      if (d < 0)
      {
         // No intersection
         SetPtrValue(distance, 0.0f);
         return false;
      }
      else
      {
         // BTW, if d=0 there is one intersection, if d > 0 there are 2
         // But we only want the closest one, so that's ok, just use the 
         // '-' version of the solver

         float negB(-b);
         float sqrtD(Sqrt(d));
         float twoA(2 * a);

         float t = (negB - sqrtD) / twoA;

         if (t < 0)
         {
            t = (negB + sqrtD) / twoA;
         }

         if (t > 0)
         {
            SetPtrValue(distance, t);
            return true;
         }

         return false;
      }
   }
Exemple #2
0
   bool Intersects(const LineSegment2 &lineSegment, bool singleSided, const Ray2 &ray, float *distance)
   {
      if (singleSided && Vector2::DotProduct(ray.GetDirection(), lineSegment.GetNormal()) >= 0.0f)
      {
         // Ray is pointing in the same direction as the line normal
         return false;
      }

      const Vector2 &P0 = ray.GetOrigin();
      const Vector2 &D0 = ray.GetDirection();
      const Vector2 &P1 = lineSegment.GetTail();
      const Vector2 &D1 = lineSegment.GetVector();

      Vector2 perpD0 = Perp(D0);
      Vector2 perpD1 = Perp(D1);

      if (Dot(perpD1, D0) != 0.0f)
      {
         Vector2 P1MinusP0 = P1 - P0;
         float s = Dot(perpD1, P1MinusP0) / Dot(perpD1,D0);
         float t = Dot(perpD0, P1MinusP0) / Dot(perpD1,D0);
         bool intersects = s >= 0.0f && 0.0f <= t && t <= 1.0f;

         if (intersects)
         {
            if (distance)
            {
               // We've probably already calculated the nearest point in terms of s & t but
               // I can't figure it out.
               
               *distance = s; // ((lineSegment.GetTail() + lineSegment.GetDirection() * t) - ray.GetOrigin()).Magnitude();
               // *distance = (nearestPoint - ray.GetOrigin()).Magnitude();
            }

            return true;
         }
      }

      return false;
   }
Exemple #3
0
 Vector2 operator*(const Ray2 &ray, float distance)
 {
    return Vector2(ray.GetOrigin() + ray.GetDirection() * distance);
 }
Exemple #4
0
   // Ray Intersection
   bool Intersects(const Ray2 &ray, const AARect &rect, float *distance)
   {
      if (rect.IsNull()) 
      {
         SetPtrValue(distance, 0.0f);
         return false;
      }

      float lowt = 0.0f;
      float t;
      bool hit = false;
      Vector2 hitpoint;
      const Vector2 &rectMin = rect.GetMinimum();
      const Vector2 &rectMax = rect.GetMaximum();
      const Vector2 &rayOrig = ray.GetOrigin();
      const Vector2 &rayDir = ray.GetDirection();

      // Check origin inside first
      if (rayOrig.x > rectMin.x && rayOrig.y > rectMin.y && rayOrig.x < rectMax.x && rayOrig.y < rectMax.y)
      {
         SetPtrValue(distance, 0.0f);
         return true;
      }

      // Check each face in turn, only check closest 3
      // Min x
      if (rayOrig.x < rectMin.x && rayDir.x > 0)
      {
         t = (rectMin.x - rayOrig.x) / rayDir.x;

         if (t > 0)
         {
            // Substitute t back into ray and check bounds and dist
            hitpoint = rayOrig + rayDir * t;
            if (hitpoint.y >= rectMin.y && hitpoint.y <= rectMax.y /* && (!hit || t < lowt) */)
            {
               if (distance == NULL)
               {
                  return true;
               }

               hit = true;
               lowt = t;
            }
         }
      }
      // Max x
      if (rayOrig.x > rectMax.x && rayDir.x < 0)
      {
         t = (rectMax.x - rayOrig.x) / rayDir.x;
         if (t > 0)
         {
            // Substitute t back into ray and check bounds and dist
            hitpoint = rayOrig + rayDir * t;
            if (hitpoint.y >= rectMin.y && hitpoint.y <= rectMax.y &&
               (!hit || t < lowt))
            {
               if (distance == NULL)
               {
                  return true;
               }

               hit = true;
               lowt = t;
            }
         }
      }
      // Min y
      if (rayOrig.y < rectMin.y && rayDir.y > 0)
      {
         t = (rectMin.y - rayOrig.y) / rayDir.y;
         if (t > 0)
         {
            // Substitute t back into ray and check bounds and dist
            hitpoint = rayOrig + rayDir * t;
            if (hitpoint.x >= rectMin.x && hitpoint.x <= rectMax.x &&
               (!hit || t < lowt))
            {
               if (distance == NULL)
               {
                  return true;
               }

               hit = true;
               lowt = t;
            }
         }
      }
      // Max y
      if (rayOrig.y > rectMax.y && rayDir.y < 0)
      {
         t = (rectMax.y - rayOrig.y) / rayDir.y;
         if (t > 0)
         {
            // Substitute t back into ray and check bounds and dist
            hitpoint = rayOrig + rayDir * t;
            if (hitpoint.x >= rectMin.x && hitpoint.x <= rectMax.x &&
               (!hit || t < lowt))
            {
               if (distance == NULL)
               {
                  return true;
               }

               hit = true;
               lowt = t;
            }
         }
      }

      SetPtrValue(distance, lowt);
      return hit;
   }