Пример #1
0
        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);
        }
Пример #2
0
        public bool Raycast(Ray3D ray, out float t)
        {
            if (ray.IntersectsPlane(_plane, out t))
            {
                Vector3 intersectionPoint = ray.GetPoint(t);
                return(ContainsPoint(intersectionPoint));
            }

            return(false);
        }
Пример #3
0
        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);
        }