public bool IntersectsWith(Segment3D segment, out float t1, out float t2) { t1 = t2 = 0.0f; if (_length == 0.0f || segment.Length == 0.0f) { return(false); } // If the segments are parallel, they don't intersect if (segment.NormalizedDirection.IsAlignedWith(_normalizedDirection)) { return(false); } // Check if the 2 segments are coplanar Vector3 segmentPlaneNormal = Vector3.Cross(segment.NormalizedDirection, _normalizedDirection); Vector3 fromThisSegmentStartToOtherSegmentStart = segment.StartPoint - _startPoint; if (!fromThisSegmentStartToOtherSegmentStart.IsPerpendicularTo(segmentPlaneNormal)) { return(false); } // Build a plane which slices thorough the segment Vector3 slicingPlaneNormal = Vector3.Cross(segmentPlaneNormal, _normalizedDirection); slicingPlaneNormal.Normalize(); Plane slicingPlane = new Plane(slicingPlaneNormal, _startPoint); // Check if the query segment intersects the plane float t; Ray3D querySegmentRay = new Ray3D(segment.StartPoint, segment.Direction); if (querySegmentRay.IntersectsPlane(slicingPlane, out t)) { // The segment intersect the plane, but we have to ensure that the intersection point lies somewehre along 'this' segment. Vector3 intersectionPoint = querySegmentRay.Origin + t * querySegmentRay.Direction; Vector3 toIntersectionPoint = intersectionPoint - _startPoint; if (Vector3.Dot(toIntersectionPoint, _normalizedDirection) < 0.0f) { return(false); } if (toIntersectionPoint.sqrMagnitude > _sqrLength) { return(false); } t1 = toIntersectionPoint.magnitude / _length; t2 = t; return(true); } return(false); }
public bool Raycast(Ray3D ray, out float t) { if (ray.IntersectsPlane(_plane, out t)) { Vector3 intersectionPoint = ray.GetPoint(t); return(ContainsPoint(intersectionPoint)); } return(false); }
public bool IntersectsRay(Ray3D ray, out float t) { Plane circlePlane = Plane; Vector3 circleCenter = Center; float scaledRadius = ScaledRadius; // Note: 'IntersectsPlane' not enough. Also check for containment???? if (ray.IntersectsPlane(circlePlane, out t)) { return(true); } else if (ray.Direction.IsPerpendicularTo(circlePlane.normal)) { // Project the circle center onto the ray direction segment. If the distance between the circle center // and the projected center is <= the circle's radius, the ray might intersect the circle. Otherwise, // the ray can not possibly intersect the circle. Segment3D segment = new Segment3D(ray); Vector3 centerProjectedOnRayDir = circleCenter.CalculateProjectionPointOnSegment(segment.StartPoint, segment.EndPoint); Vector3 fromCenterToProjectedCenter = centerProjectedOnRayDir - circleCenter; float triAdjSideLength1 = fromCenterToProjectedCenter.magnitude; if (triAdjSideLength1 > scaledRadius) { return(false); } // At this point it is possible that the ray might intersect the circle. Calcluate how much // we have to move from the center projection to a point on the circle along the reverse of // the ray direction vector. We will store this amount in 'triAdjSideLength2'. float triAdjSideLength2 = Mathf.Sqrt(scaledRadius * scaledRadius - triAdjSideLength1 * triAdjSideLength1); // Now check if moving from the projected center along the reverse ray direction by an amount equal to // 'triAdjSideLength2', we end up on a point which resides on the ray direction segment. Vector3 normalizedRayDirection = ray.Direction; normalizedRayDirection.Normalize(); Vector3 targetPoint = centerProjectedOnRayDir - triAdjSideLength2 * normalizedRayDirection; if (targetPoint.IsOnSegment(segment.StartPoint, segment.EndPoint)) { // The point sits on the segment, which means that the ray intersects the circle. // Now we need to calculate the intersection offset. t = (targetPoint - ray.Origin).magnitude / ray.Direction.magnitude; return(true); } } return(false); }