예제 #1
0
        /// <summary>
        /// Estimates the proximity between a given capsule and a voxel.
        /// </summary>
        /// <param name="capsule">The capsule to test for intersection, the points must be at least one metre apart.</param>
        public static double Proximity(ref CapsuleD capsule, MyVoxelBase voxel, ref Vector3D hitPosition, double capsuleLength = -1d)
        {
            Logger.TraceLog(capsule.String());

            if (capsuleLength < 0)
            {
                Vector3D.Distance(ref capsule.P0, ref capsule.P1, out capsuleLength);
            }

            double   halfLength = capsuleLength * 0.5d;
            Vector3D temp; Vector3D.Add(ref capsule.P0, ref capsule.P1, out temp);
            Vector3D middle; Vector3D.Multiply(ref temp, 0.5d, out middle);

            if (capsuleLength < 1d)
            {
                hitPosition = middle;
                Logger.TraceLog("capsule length < 1: " + capsuleLength);
                return(capsuleLength);
            }

            double          radius      = halfLength + capsule.Radius;
            BoundingSphereD worldSphere = new BoundingSphereD()
            {
                Center = middle, Radius = radius
            };

            if (capsuleLength < Math.Max(capsule.Radius, 1f) * 8f)
            {
                if (!voxel.ContainsOrIntersects(ref worldSphere))
                {
                    Logger.TraceLog("sphere does not intersect voxel: " + worldSphere + ", capsuleLength: " + capsuleLength);
                    return(capsuleLength);
                }
            }
            else if (!voxel.PositionComp.WorldAABB.Intersects(ref worldSphere))
            {
                Logger.TraceLog("sphere does not intersect voxel AABB: " + worldSphere + ", capsuleLength: " + capsuleLength);
                return(capsuleLength);
            }

            CapsuleD halfCapsule;

            halfCapsule.P0     = capsule.P0;
            halfCapsule.P1     = middle;
            halfCapsule.Radius = capsule.Radius;

            double prox = Proximity(ref halfCapsule, voxel, ref hitPosition, halfLength);

            if (prox < 1f)
            {
                return(prox);
            }

            halfCapsule.P0 = middle;
            halfCapsule.P1 = capsule.P1;

            return(Math.Min(prox, Proximity(ref halfCapsule, voxel, ref hitPosition, halfLength)));
        }
예제 #2
0
        /// <summary>
        /// Performs a binary search for intersection using spheres.
        /// </summary>
        /// <param name="hitPosition">a point on the capsule's line close to obstruction</param>
        public static bool Intersects(ref CapsuleD capsule, MyVoxelBase voxel, out Vector3D hitPosition, double capsuleLength = -1d)
        {
            //Logger.DebugLog("P0: " + capsule.P0 + ", P1: " + capsule.P1 + ", radius: " + capsule.Radius);
            if (capsuleLength < 0)
            {
                Vector3D.Distance(ref capsule.P0, ref capsule.P1, out capsuleLength);
            }

            double   halfLength = capsuleLength * 0.5d;
            Vector3D temp; Vector3D.Add(ref capsule.P0, ref capsule.P1, out temp);
            Vector3D middle; Vector3D.Multiply(ref temp, 0.5d, out middle);

            if (capsuleLength < 1f)
            {
                hitPosition = middle;
                return(true);
            }

            double          radius      = halfLength + capsule.Radius;
            BoundingSphereD worldSphere = new BoundingSphereD()
            {
                Center = middle, Radius = radius
            };

            if (capsuleLength < Math.Max(capsule.Radius, 1f) * 8f)
            {
                if (!voxel.ContainsOrIntersects(ref worldSphere))
                {
                    hitPosition = Globals.Invalid;
                    return(false);
                }
            }
            else if (!voxel.PositionComp.WorldAABB.Intersects(ref worldSphere))
            {
                hitPosition = Globals.Invalid;
                return(false);
            }

            CapsuleD halfCapsule;

            halfCapsule.P0     = capsule.P0;
            halfCapsule.P1     = middle;
            halfCapsule.Radius = capsule.Radius;

            if (Intersects(ref halfCapsule, voxel, out hitPosition, halfLength))
            {
                return(true);
            }

            halfCapsule.P0 = middle;
            halfCapsule.P1 = capsule.P1;

            return(Intersects(ref halfCapsule, voxel, out hitPosition, halfLength));
        }