/// <summary> /// Performs a ray cast on the polygon given an optional tmax value /// Only process the information in the rayHit structure if Intersection = true, /// which is specified in the gxtRayHit instance and the return value. If the ray origin is /// inside the Polygon it is not considered an intersection /// </summary> /// <param name="ray">Ray</param> /// <param name="polygon">Polygon</param> /// <param name="rayHit">Ray Hit Info</param> /// <param name="tmax">Max T Value</param> /// <returns>If Intersecting</returns> public virtual bool RayCast(gxtRay ray, ref gxtPolygon polygon, out gxtRayHit rayHit, float tmax = float.MaxValue) { rayHit = new gxtRayHit(); rayHit.Distance = tmax; // if a crossing is within tmax bool intersection = false; // temp holder for segment distance float distance; // number of crossings, regardless of tmax int crossings = 0; // log a message when we run a raycast on a very detailed polygon // to indicate that the results may not be perfect int testIterations = polygon.NumVertices; if (MaxIterations < polygon.NumVertices) { gxtLog.WriteLineV(gxtVerbosityLevel.WARNING, "Polygon vertices exceeds max collider iterations. Not all segments will be tested!"); testIterations = MaxIterations; } for (int j = polygon.NumVertices - 1, i = 0; i < testIterations; j = i, i++) { if (RayIntersectsSegment(ray, polygon.v[j], polygon.v[i], out distance)) { crossings++; if (distance <= rayHit.Distance) { intersection = true; rayHit.Distance = distance; rayHit.Point = ray.GetPoint(distance); // right perp assumes CCW polygon winding Vector2 edge = polygon.v[j] - polygon.v[i]; rayHit.Normal = Vector2.Normalize(gxtMath.RightPerp(edge)); } } } // raycast algorithm rayHit.Intersection = intersection && crossings > 0 && crossings % 2 == 0; return rayHit.Intersection; }
public static bool RayCast(gxtRay ray, gxtPolygon polygon, float tmax, out float t, out Vector2 pt, out Vector2 normal) { t = float.MaxValue; pt = ray.Origin; normal = ray.Direction; bool intersection = false; // temp holder for segment distance float distance; int crossings = 0; for (int j = polygon.NumVertices - 1, i = 0; i < polygon.NumVertices; j = i, i++) { if (RayIntersectsSegment(ray, polygon.v[j], polygon.v[i], float.MaxValue, out distance)) { crossings++; if (distance < t && distance <= tmax) { intersection = true; t = distance; pt = ray.GetPoint(t); Vector2 edge = polygon.v[i] - polygon.v[j]; normal = Vector2.Normalize(gxtMath.RightPerp(edge)); //normal = gxtMath.GetReflection(ray.Direction, edgeNormal); } } } return intersection && crossings > 0 && crossings % 2 == 0; }