BEPUphysics.CollisionTests.CollisionAlgorithms.MPRToolbox.RayCast C# (CSharp) Метод

RayCast() публичный статический Метод

Casts a ray against a shape.
public static RayCast ( BEPUutilities.Ray ray, float maximumLength, ConvexShape shape, RigidTransform &transform, RayHit &hit ) : bool
ray BEPUutilities.Ray Ray to test against the shape.
maximumLength float Maximum length of the ray.
shape BEPUphysics.CollisionShapes.ConvexShapes.ConvexShape Shape to test with a ray.
transform BEPUutilities.RigidTransform Transform to apply to the shape.
hit BEPUutilities.RayHit Hit data of the ray on the shape, if any.
Результат bool
        public static bool RayCast(Ray ray, float maximumLength, ConvexShape shape, ref RigidTransform transform, out RayHit hit)
        {
            //Compute the local origin and direction of the ray.
            Ray localRay;
            Quaternion conjugate;
            Vector3.Subtract(ref ray.Position, ref transform.Position, out localRay.Position);
            Quaternion.Conjugate(ref transform.Orientation, out conjugate);
            Vector3.Transform(ref localRay.Position, ref conjugate, out localRay.Position);
            Vector3.Transform(ref ray.Direction, ref conjugate, out localRay.Direction);

            //Note that we will be casting the ray *backwards* against the sweep-expanded surface of the shape.
            Vector3.Negate(ref localRay.Direction, out localRay.Direction);

            //A ray cast is a special case of two-body sweeping.  This is implemented separately from the two-body sweep above almost entirely for a tiny performance boost.
            //It also allows for certain tricks to help with numerical stability.

            //Sweeping two objects against each other is very similar to the local surface cast.
            //The ray starts at the origin and goes in the sweep direction.
            //However, unlike the local surface cast, the origin may start outside of the minkowski difference.
            //Additionally, the method can early out if the length traversed by the ray is found to be longer than the maximum length, or if the origin is found to be outside the minkowski difference.

            //The support points of the minkowski difference are also modified.  By default, the minkowski difference should very rarely contain the origin.
            //Sweep tests aren't very useful if the objects are intersecting!
            //However, in order for the local surface cast to actually find a proper result (assuming there is a hit at all), the origin must be inside the minkowski difference.
            //So, expand the minkowski difference using the sweep direction with magnitude sufficient to fully include the plane defined by the origin and the sweep direction.
            //If there's going to be a hit, then the origin will be within this expanded shape.



            //If the sweep direction is found to be negative, the ray can be thought of as pointing away from the shape.
            //However, the minkowski difference may contain the shape.  In this case, the time of impact is zero.

            //If the swept (with sweep = 0 in case of incorrect direction) minkowski difference does not contain the shape, then the raycast cannot begin and we also know that the shapes will not intersect.

            //If the sweep amount is nonnegative and the minkowski difference contains the shape, then the normal raycasting process can continue.
            //Perform the usual local raycast, but use the swept minkowski difference.
            //Once the surface is found, the final t parameter of the ray is equal to the sweep distance minus the local raycast computed t parameter.


            //Given that this is a ray cast, we can make some modifications.  Rays frequently traverse large distances, but stretching the swept volume
            //a huge amount to match could manifest numerical issues.  Instead, pull the ray up close to the object.
            RayHit sphereHit;

            if (Toolbox.RayCastSphere(ref ray, ref transform.Position, shape.maximumRadius, maximumLength, out sphereHit))
            {
                //We can scoot ourselves almost all the way up to the intersection with the outer sphere.
                //Stop just short to prevent a possible erroneous 'just-barely-contained' result.
                sphereHit.T = Math.Max(sphereHit.T - .1f, 0);
                Vector3 offset;
                Vector3.Multiply(ref localRay.Direction, -sphereHit.T, out offset);
                Vector3.Add(ref localRay.Position, ref offset, out localRay.Position);
            }
            else
            {
                //If the ray cast doesn't hit the bounding sphere, it's impossible for the ray to hit the shape itself.
                hit.T = float.MaxValue;
                hit.Normal = new Vector3();
                hit.Location = new Vector3();
                return false;
            }



            //First: Compute the sweep amount along the sweep direction.
            //This sweep amount needs to expand the minkowski difference to fully intersect the plane defined by the sweep direction and origin.

            float rayLengthSquared = localRay.Direction.LengthSquared();
            float sweepLength;
            if (rayLengthSquared > Toolbox.Epsilon * .01f)
            {
                Vector3.Dot(ref localRay.Position, ref localRay.Direction, out sweepLength);
                //Ray length isn't necessarily normalized...
                sweepLength /= rayLengthSquared;
                //Scale the sweep length by the margins.  Divide by the length to pull the margin into terms of the length of the ray.
                sweepLength += shape.maximumRadius / (float)Math.Sqrt(rayLengthSquared);
            }
            else
            {
                rayLengthSquared = 0;
                sweepLength = 0;
            }
            //If the sweep direction is found to be negative, the ray can be thought of as pointing away from the shape.
            //Do not sweep backward.
            bool negativeLength;
            if (negativeLength = sweepLength < 0)
                sweepLength = 0;



            Vector3 sweep;
            Vector3.Multiply(ref localRay.Direction, sweepLength, out sweep);
            //Check to see if the origin is contained within the swept shape.
            if (!SweptShapeContainsPoint(shape, ref sweep, ref localRay.Position))
            {
                //The origin is not contained within the sweep volume.  The raycast definitely misses.
                hit.T = float.MaxValue;
                hit.Normal = new Vector3();
                hit.Location = new Vector3();
                return false;
            }
            if (negativeLength)
            {
                //The origin is contained, but we shouldn't continue.
                //The ray is facing backwards.  The time of impact would be 0 (because we already verified that we are contained in the shape volume).
                hit.T = 0;
                Vector3.Normalize(ref ray.Direction, out hit.Normal);
                hit.Location = ray.Position;
                return true;
            }

            //OKAY! We've finally finished all the pre-testing.  Cast the ray!
            if (LocalSweepCast(shape, sweepLength, rayLengthSquared, ref localRay.Direction, ref sweep, ref localRay.Position, out hit))
            {
                hit.T += sphereHit.T;
                if (hit.T <= maximumLength)
                {
                    //Get the world space hit location.
                    Vector3.Multiply(ref ray.Direction, hit.T, out hit.Location);
                    Vector3.Add(ref hit.Location, ref ray.Position, out hit.Location);
                    //Transform the normal.
                    Vector3.Transform(ref hit.Normal, ref transform.Orientation, out hit.Normal);
                    return true;
                }
            }
            return false;

        }