private float RayCastCallbackWrapper(ref RayCastInput input, int proxyId) { FixtureProxy proxy = ContactManager.BroadPhase.GetUserData(proxyId); Fixture fixture = proxy.Fixture; int index = proxy.ChildIndex; RayCastOutput output; bool hit = fixture.RayCast(out output, ref input, index); if (hit) { float fraction = output.Fraction; Vector2 point = (1.0f - fraction)*input.Point1 + fraction*input.Point2; return _rayCastCallback(fixture, point, output.Normal, fraction); } return input.MaxFraction; }
/// <summary> /// Cast a ray against this Shape. /// </summary> /// <param name="output">The ray-cast results.</param> /// <param name="input">The ray-cast input parameters.</param> /// <param name="childIndex">Index of the child.</param> /// <returns></returns> public bool RayCast(out RayCastOutput output, ref RayCastInput input, int childIndex) { return Shape.RayCast(out output, ref input, ref Body.Xf, childIndex); }
/// <summary> /// Ray-cast the world for all fixtures in the path of the ray. Your callback /// controls whether you get the closest point, any point, or n-points. /// The ray-cast ignores shapes that contain the starting point. /// </summary> /// <param name="callback">A user implemented callback class.</param> /// <param name="point1">The ray starting point.</param> /// <param name="point2">The ray ending point.</param> public void RayCast(RayCastCallback callback, Vector2 point1, Vector2 point2) { RayCastInput input = new RayCastInput(); input.MaxFraction = 1.0f; input.Point1 = point1; input.Point2 = point2; _rayCastCallback = callback; ContactManager.BroadPhase.RayCast(_rayCastCallbackWrapper, ref input); _rayCastCallback = null; }
// From Real-time Collision Detection, p179. public bool RayCast(out RayCastOutput output, ref RayCastInput input) { output = new RayCastOutput(); float tmin = -Settings.MaxFloat; float tmax = Settings.MaxFloat; Vector2 p = input.Point1; Vector2 d = input.Point2 - input.Point1; Vector2 absD = MathUtils.Abs(d); Vector2 normal = Vector2.Zero; for (int i = 0; i < 2; ++i) { float absD_i = i == 0 ? absD.X : absD.Y; float lowerBound_i = i == 0 ? LowerBound.X : LowerBound.Y; float upperBound_i = i == 0 ? UpperBound.X : UpperBound.Y; float p_i = i == 0 ? p.X : p.Y; if (absD_i < Settings.Epsilon) { // Parallel. if (p_i < lowerBound_i || upperBound_i < p_i) { return false; } } else { float d_i = i == 0 ? d.X : d.Y; float inv_d = 1.0f/d_i; float t1 = (lowerBound_i - p_i)*inv_d; float t2 = (upperBound_i - p_i)*inv_d; // Sign of the normal vector. float s = -1.0f; if (t1 > t2) { MathUtils.Swap(ref t1, ref t2); s = 1.0f; } // Push the min up if (t1 > tmin) { if (i == 0) { normal.X = s; } else { normal.Y = s; } tmin = t1; } // Pull the max down tmax = Math.Min(tmax, t2); if (tmin > tmax) { return false; } } } // Does the ray start inside the box? // Does the ray intersect beyond the max fraction? if (tmin < 0.0f || input.MaxFraction < tmin) { return false; } // Intersection. output.Fraction = tmin; output.Normal = normal; return true; }