public static bool DistanceBetween(CapsuleCollider capsule,
                                           RigidTransform capsuleTransform,
                                           SphereCollider sphere,
                                           RigidTransform sphereTransform,
                                           float maxDistance,
                                           out ColliderDistanceResult result)
        {
            var            capWorldToLocal           = math.inverse(capsuleTransform);
            var            sphereInCapSpaceTransfrom = math.mul(capWorldToLocal, sphereTransform);
            float3         sphereCenterInCapSpace    = math.transform(sphereInCapSpaceTransfrom, sphere.center);
            SphereCollider sphereInCapSpace          = new SphereCollider(sphereCenterInCapSpace, sphere.radius);
            bool           hit = DistanceQueries.DistanceBetween(capsule,
                                                                 sphereInCapSpace,
                                                                 maxDistance,
                                                                 out DistanceQueries.ColliderDistanceResultInternal localResult);

            result = new ColliderDistanceResult
            {
                hitpointA = math.transform(capsuleTransform, localResult.hitpointA),
                hitpointB = math.transform(capsuleTransform, localResult.hitpointB),
                normalA   = math.rotate(capsuleTransform, localResult.normalA),
                normalB   = math.rotate(capsuleTransform, localResult.normalB),
                distance  = localResult.distance
            };
            return(hit);
        }
        public static bool DistanceBetween(BoxCollider box,
                                           RigidTransform boxTransform,
                                           SphereCollider sphere,
                                           RigidTransform sphereTransform,
                                           float maxDistance,
                                           out ColliderDistanceResult result)
        {
            var            boxWorldToLocal        = math.inverse(boxTransform);
            float3         sphereCenterInBoxSpace = math.transform(boxWorldToLocal, sphere.center + sphereTransform.pos);
            SphereCollider sphereInBoxSpace       = new SphereCollider(sphereCenterInBoxSpace, sphere.radius);
            bool           hit = DistanceQueries.DistanceBetween(box,
                                                                 sphereInBoxSpace,
                                                                 maxDistance,
                                                                 out DistanceQueries.ColliderDistanceResultInternal localResult);

            result = new ColliderDistanceResult
            {
                hitpointA = math.transform(boxTransform, localResult.hitpointA),
                hitpointB = math.transform(boxTransform, localResult.hitpointB),
                normalA   = math.rotate(boxTransform, localResult.normalA),
                normalB   = math.rotate(boxTransform, localResult.normalB),
                distance  = localResult.distance
            };
            return(hit);
        }
        public static bool DistanceBetween(CapsuleCollider capsuleA,
                                           RigidTransform aTransform,
                                           CapsuleCollider capsuleB,
                                           RigidTransform bTransform,
                                           float maxDistance,
                                           out ColliderDistanceResult result)
        {
            var             aWorldToLocal      = math.inverse(aTransform);
            var             BinASpaceTransform = math.mul(aWorldToLocal, bTransform);
            CapsuleCollider BinASpace          = new CapsuleCollider(math.transform(BinASpaceTransform, capsuleB.pointA),
                                                                     math.transform(BinASpaceTransform, capsuleB.pointB),
                                                                     capsuleB.radius);
            bool hit = DistanceQueries.DistanceBetween(capsuleA, BinASpace, maxDistance, out DistanceQueries.ColliderDistanceResultInternal localResult);

            result = BinAResultToWorld(localResult, aTransform);
            return(hit);
        }
        public static bool DistanceBetween(BoxCollider box,
                                           RigidTransform boxTransform,
                                           CapsuleCollider capsule,
                                           RigidTransform capsuleTransform,
                                           float maxDistance,
                                           out ColliderDistanceResult result)
        {
            var boxWorldToLocal        = math.inverse(boxTransform);
            var capInBoxSpaceTransform = math.mul(boxWorldToLocal, capsuleTransform);
            var capsuleInBoxSpace      = new CapsuleCollider(math.transform(capInBoxSpaceTransform, capsule.pointA),
                                                             math.transform(capInBoxSpaceTransform, capsule.pointB),
                                                             capsule.radius);
            bool hit = DistanceQueries.DistanceBetween(box, capsuleInBoxSpace, maxDistance, out DistanceQueries.ColliderDistanceResultInternal localResult);

            result = BinAResultToWorld(localResult, boxTransform);
            return(hit);
        }
        public static bool DistanceBetween(SphereCollider sphereA,
                                           RigidTransform aTransform,
                                           SphereCollider sphereB,
                                           RigidTransform bTransform,
                                           float maxDistance,
                                           out ColliderDistanceResult result)
        {
            SphereCollider bInASpace = new SphereCollider(sphereB.center + bTransform.pos - aTransform.pos, sphereB.radius);
            bool           hit       = DistanceQueries.DistanceBetween(sphereA, bInASpace, maxDistance, out DistanceQueries.ColliderDistanceResultInternal localResult);

            result = new ColliderDistanceResult
            {
                hitpointA = localResult.hitpointA + aTransform.pos,
                hitpointB = localResult.hitpointB + aTransform.pos,
                normalA   = localResult.normalA,
                normalB   = localResult.normalB,
                distance  = localResult.distance
            };
            return(hit);
        }
        public static bool DistanceBetween(BoxCollider boxA,
                                           RigidTransform aTransform,
                                           BoxCollider boxB,
                                           RigidTransform bTransform,
                                           float maxDistance,
                                           out ColliderDistanceResult result)
        {
            var aWorldToLocal      = math.inverse(aTransform);
            var bWorldToLocal      = math.inverse(bTransform);
            var bInASpaceTransform = math.mul(aWorldToLocal, bTransform);
            var aInBSpaceTransform = math.mul(bWorldToLocal, aTransform);
            var hit = DistanceQueries.DistanceBetween(boxA,
                                                      boxB,
                                                      bInASpaceTransform,
                                                      aInBSpaceTransform,
                                                      maxDistance,
                                                      out DistanceQueries.ColliderDistanceResultInternal localResult);

            result = BinAResultToWorld(localResult, aTransform);
            return(hit);
        }
        public static bool DistanceBetween(SphereCollider sphereA,
                                           RigidTransform aTransform,
                                           SphereCollider sphereB,
                                           RigidTransform bTransform,
                                           float maxDistance,
                                           out ColliderDistanceResult result)
        {
            var            aWorldToLocal      = math.inverse(aTransform);
            var            bInASpaceTransform = math.mul(aWorldToLocal, bTransform);
            SphereCollider bInASpace          = new SphereCollider(math.transform(bInASpaceTransform, sphereB.center), sphereB.radius);
            bool           hit = DistanceQueries.DistanceBetween(sphereA, bInASpace, maxDistance, out DistanceQueries.ColliderDistanceResultInternal localResult);

            result = new ColliderDistanceResult
            {
                hitpointA = math.transform(aTransform, localResult.hitpointA),
                hitpointB = math.transform(aTransform, localResult.hitpointB),
                normalA   = math.rotate(aTransform, localResult.normalA),
                normalB   = math.rotate(aTransform, localResult.normalB),
                distance  = localResult.distance
            };
            return(hit);
        }
Esempio n. 8
0
        public static bool RaycastRoundedQuad(Ray ray, simdFloat3 quadPoints, float radius, out float fraction, out float3 normal)
        {
            // Make sure the ray doesn't start inside.
            if (DistanceQueries.DistanceBetween(ray.start, quadPoints, radius, out _))
            {
                fraction = 2f;
                normal   = default;
                return(false);
            }

            float3 ab         = quadPoints.b - quadPoints.a;
            float3 ca         = quadPoints.a - quadPoints.c;
            float3 quadNormal = math.cross(ab, ca);

            quadNormal = math.select(quadNormal, -quadNormal, math.dot(quadNormal, ray.displacement) > 0f);

            // Catch degenerate quad here
            bool  quadFaceHit  = math.any(quadNormal);
            float quadFraction = 2f;

            if (quadFaceHit)
            {
                quadFaceHit = RaycastQuad(ray, quadPoints + math.normalize(quadNormal) * radius, out quadFraction);
            }
            quadFraction = math.select(2f, quadFraction, quadFaceHit);
            bool4 capsuleHits = Raycast4Capsules(ray, quadPoints, quadPoints.bcda, radius, out float4 capsuleFractions, out simdFloat3 capsuleNormals);

            capsuleFractions = math.select(2f, capsuleFractions, capsuleHits);
            simdFloat3 bestNormals   = simd.select(capsuleNormals, capsuleNormals.badc, capsuleFractions.yxwz < capsuleFractions);
            float4     bestFractions = math.select(capsuleFractions, capsuleFractions.yxwz, capsuleFractions.yxwz < capsuleFractions);

            normal   = math.select(bestNormals.a, bestNormals.c, bestFractions.z < bestFractions.x);
            fraction = math.select(bestFractions.x, bestFractions.z, bestFractions.z < bestFractions.x);
            normal   = math.select(normal, quadNormal, quadFraction < fraction);
            fraction = math.select(fraction, quadFraction, quadFraction < fraction);
            return(fraction <= 1f);
        }
Esempio n. 9
0
        public static bool RaycastRoundedBox(Ray ray, BoxCollider box, float radius, out float fraction, out float3 normal)
        {
            // Early out if inside hit
            if (DistanceQueries.DistanceBetween(ray.start, box, radius, out _))
            {
                fraction = default;
                normal   = default;
                return(false);
            }

            var outerBox = box;

            outerBox.halfSize += radius;
            bool hitOuter = RaycastBox(ray, outerBox, out fraction, out normal);
            var  hitPoint = math.lerp(ray.start, ray.end, fraction);

            if (hitOuter && math.all(normal > 0.5f & (hitPoint >= box.center - box.halfSize | hitPoint <= box.center + box.halfSize)))
            {
                // We hit a flat surface of the box. We have our result already.
                return(true);
            }
            else if (!hitOuter && !math.all(ray.start >= outerBox.center - outerBox.halfSize & ray.start <= outerBox.center + outerBox.halfSize))
            {
                // Our ray missed the outer box.
                return(false);
            }

            // Our ray either hit near an edge of the outer box or started inside the box. From this point it must hit a capsule surrounding an edge.
            simdFloat3 bTopPoints    = default;
            simdFloat3 bBottomPoints = default;

            bTopPoints.x    = math.select(-box.halfSize.x, box.halfSize.x, new bool4(true, true, false, false));
            bBottomPoints.x = bTopPoints.x;
            bBottomPoints.y = -box.halfSize.y;
            bTopPoints.y    = box.halfSize.y;
            bTopPoints.z    = math.select(-box.halfSize.z, box.halfSize.z, new bool4(true, false, true, false));
            bBottomPoints.z = bTopPoints.z;
            bTopPoints     += box.center;
            bBottomPoints  += box.center;

            simdFloat3 bLeftPoints = simd.shuffle(bTopPoints,
                                                  bBottomPoints,
                                                  math.ShuffleComponent.LeftZ,
                                                  math.ShuffleComponent.LeftW,
                                                  math.ShuffleComponent.RightZ,
                                                  math.ShuffleComponent.RightW);
            simdFloat3 bRightPoints = simd.shuffle(bTopPoints,
                                                   bBottomPoints,
                                                   math.ShuffleComponent.LeftX,
                                                   math.ShuffleComponent.LeftY,
                                                   math.ShuffleComponent.RightX,
                                                   math.ShuffleComponent.RightY);
            simdFloat3 bFrontPoints = simd.shuffle(bTopPoints,
                                                   bBottomPoints,
                                                   math.ShuffleComponent.LeftY,
                                                   math.ShuffleComponent.LeftW,
                                                   math.ShuffleComponent.RightY,
                                                   math.ShuffleComponent.RightW);
            simdFloat3 bBackPoints = simd.shuffle(bTopPoints,
                                                  bBottomPoints,
                                                  math.ShuffleComponent.LeftX,
                                                  math.ShuffleComponent.LeftZ,
                                                  math.ShuffleComponent.RightX,
                                                  math.ShuffleComponent.RightZ);

            var topBottomHits = Raycast4Capsules(ray, bTopPoints, bBottomPoints, radius, out float4 topBottomFractions, out simdFloat3 topBottomNormals);
            var leftRightHits = Raycast4Capsules(ray, bLeftPoints, bRightPoints, radius, out float4 leftRightFractions, out simdFloat3 leftRightNormals);
            var frontBackHits = Raycast4Capsules(ray, bFrontPoints, bBackPoints, radius, out float4 frontBackFractions, out simdFloat3 frontBackNormals);

            topBottomFractions = math.select(2f, topBottomFractions, topBottomHits);
            leftRightFractions = math.select(2f, leftRightFractions, leftRightHits);
            frontBackFractions = math.select(2f, frontBackFractions, frontBackHits);

            simdFloat3 bestNormals   = simd.select(topBottomNormals, leftRightNormals, leftRightFractions < topBottomFractions);
            float4     bestFractions = math.select(topBottomFractions, leftRightFractions, leftRightFractions < topBottomFractions);

            bestNormals   = simd.select(bestNormals, frontBackNormals, frontBackFractions < bestFractions);
            bestFractions = math.select(bestFractions, frontBackFractions, frontBackFractions < bestFractions);
            bestNormals   = simd.select(bestNormals, bestNormals.badc, bestFractions.yxwz < bestFractions);
            normal        = math.select(bestNormals.a, bestNormals.c, bestFractions.z < bestFractions.x);
            fraction      = math.select(bestFractions.x, bestFractions.z, bestFractions.z < bestFractions.x);
            return(fraction <= 1f);
        }