Example #1
0
    protected override void OnUpdate()
    {
        Entities
        .WithName("ChangeSphereColliderRadius")
        .WithBurst()
        .ForEach((ref PhysicsCollider collider, ref ChangeSphereColliderRadius radius, ref Scale scale) =>
        {
            // make sure we are dealing with spheres
            if (collider.Value.Value.Type != ColliderType.Sphere)
            {
                return;
            }

            // tweak the physical representation of the sphere

            // NOTE: this approach affects all instances using the same BlobAsset
            // so you cannot simply use this approach for instantiated prefabs
            // if you want to modify prefab instances independently, you need to create
            // unique BlobAssets at run-time and dispose them when you are done

            float oldRadius = 1.0f;
            float newRadius = 1.0f;
            unsafe
            {
                // grab the sphere pointer
                SphereCollider *scPtr = (SphereCollider *)collider.ColliderPtr;
                oldRadius             = scPtr->Radius;
                newRadius             = math.lerp(oldRadius, radius.Target, 0.05f);
                // if we have reached the target radius get a new target
                if (math.abs(newRadius - radius.Target) < 0.01f)
                {
                    radius.Target = radius.Target == radius.Min ? radius.Max : radius.Min;
                }

                // update the collider geometry
                var sphereGeometry    = scPtr->Geometry;
                sphereGeometry.Radius = newRadius;
                scPtr->Geometry       = sphereGeometry;
            }

            // now tweak the graphical representation of the sphere
            float oldScale = scale.Value;
            float newScale = oldScale;
            if (oldRadius == 0.0f)
            {
                // avoid the divide by zero errors.
                newScale = newRadius;
            }
            else
            {
                newScale *= newRadius / oldRadius;
            }
            scale = new Scale {
                Value = newScale
            };
        }).Schedule();
    }
Example #2
0
        public static unsafe Result BoxSphere(BoxCollider *boxA, SphereCollider *sphereB, MTransform aFromB)
        {
            MTransform aFromBoxA        = new MTransform(boxA->Orientation, boxA->Center);
            float3     posBinA          = Mul(aFromB, sphereB->Center);
            float3     posBinBoxA       = Mul(Inverse(aFromBoxA), posBinA);
            float3     innerHalfExtents = boxA->Size * 0.5f - boxA->ConvexRadius;
            float3     normalInBoxA;
            float      distance;
            {
                // from hkAabb::signedDistanceToPoint(), can optimize a lot
                float3 projection = math.min(posBinBoxA, innerHalfExtents);
                projection = math.max(projection, -innerHalfExtents);
                float3 difference      = projection - posBinBoxA;
                float  distanceSquared = math.lengthsq(difference);

                // Check if the sphere center is inside the box
                if (distanceSquared < 1e-6f)
                {
                    float3 projectionLocal    = projection;
                    float3 absProjectionLocal = math.abs(projectionLocal);
                    float3 del  = absProjectionLocal - innerHalfExtents;
                    int    axis = IndexOfMaxComponent(new float4(del, -float.MaxValue));
                    switch (axis)
                    {
                    case 0: normalInBoxA = new float3(projectionLocal.x < 0.0f ? 1.0f : -1.0f, 0.0f, 0.0f); break;

                    case 1: normalInBoxA = new float3(0.0f, projectionLocal.y < 0.0f ? 1.0f : -1.0f, 0.0f); break;

                    case 2: normalInBoxA = new float3(0.0f, 0.0f, projectionLocal.z < 0.0f ? 1.0f : -1.0f); break;

                    default:
                        normalInBoxA = new float3(1, 0, 0);
                        Assert.IsTrue(false);
                        break;
                    }
                    distance = math.max(del.x, math.max(del.y, del.z));
                }
                else
                {
                    float invDistance = math.rsqrt(distanceSquared);
                    normalInBoxA = difference * invDistance;
                    distance     = distanceSquared * invDistance;
                }
            }

            float3 normalInA = math.mul(aFromBoxA.Rotation, normalInBoxA);

            return(new Result
            {
                NormalInA = normalInA,
                PositionOnAinA = posBinA + normalInA * (distance - boxA->ConvexRadius),
                Distance = distance - (sphereB->Radius + boxA->ConvexRadius)
            });
        }
            public static void AppendSphere(SphereCollider *sphere, RigidTransform worldFromCollider, ref List <DisplayResult> results)
            {
                float r = sphere->Radius;

                results.Add(new DisplayResult
                {
                    Mesh        = ReferenceSphere,
                    Scale       = new Vector4(r * 2.0f, r * 2.0f, r * 2.0f),
                    Position    = math.transform(worldFromCollider, sphere->Center),
                    Orientation = worldFromCollider.rot,
                });
            }
Example #4
0
 // Create a contact point for a pair of spheres in world space.
 public static unsafe void SphereSphere(
     SphereCollider *sphereA, SphereCollider *sphereB,
     MTransform worldFromA, MTransform aFromB, float maxDistance,
     out Manifold manifold)
 {
     DistanceQueries.Result convexDistance = DistanceQueries.SphereSphere(sphereA, sphereB, aFromB);
     if (convexDistance.Distance < maxDistance)
     {
         manifold = new Manifold(convexDistance, worldFromA);
     }
     else
     {
         manifold = new Manifold();
     }
 }
Example #5
0
 // Create a single point manifold between a capsule and a sphere in world space.
 public static unsafe void CapsuleSphere(
     CapsuleCollider *capsuleA, SphereCollider *sphereB,
     MTransform worldFromA, MTransform aFromB, float maxDistance,
     out Manifold manifold)
 {
     DistanceQueries.Result convexDistance = DistanceQueries.CapsuleSphere(
         capsuleA->Vertex0, capsuleA->Vertex1, capsuleA->Radius, sphereB->Center, sphereB->Radius, aFromB);
     if (convexDistance.Distance < maxDistance)
     {
         manifold = new Manifold(convexDistance, worldFromA);
     }
     else
     {
         manifold = new Manifold();
     }
 }
        public unsafe void Execute(ref PhysicsCollider collider, ref ChangeSphereColliderRadius radius, ref Scale scale)
        {
            // make sure we are dealing with spheres
            if (collider.ColliderPtr->Type != ColliderType.Sphere)
            {
                return;
            }

            //
            // tweak the physical representation of the sphere
            // grab the sphere pointer
            SphereCollider *scPtr     = (SphereCollider *)collider.ColliderPtr;
            float           oldRadius = scPtr->Radius;
            float           newRadius = math.lerp(oldRadius, radius.Target, 0.05f);

            // if we have reached the target radius get a new target
            if (math.abs(newRadius - radius.Target) < 0.01f)
            {
                radius.Target = radius.Target == radius.Min ? radius.Max : radius.Min;
            }

            // update the collider geometry
            var sphereGeometry = scPtr->Geometry;

            sphereGeometry.Radius = newRadius;
            scPtr->Geometry       = sphereGeometry;

            //
            // now tweak the graphical representation of the sphere
            float oldScale = scale.Value;
            float newScale = oldScale;

            if (oldRadius == 0.0f)
            {
                // avoid the divide by zero errors.
                newScale = newRadius;
            }
            else
            {
                newScale *= newRadius / oldRadius;
            }
            scale = new Scale()
            {
                Value = newScale
            };
        }
Example #7
0
        // Create a single point manifold between a triangle and sphere in world space.
        public static unsafe void TriangleSphere(
            PolygonCollider *triangleA, SphereCollider *sphereB,
            MTransform worldFromA, MTransform aFromB, float maxDistance,
            out Manifold manifold)
        {
            Assert.IsTrue(triangleA->Vertices.Length == 3);

            DistanceQueries.Result convexDistance = DistanceQueries.TriangleSphere(
                triangleA->Vertices[0], triangleA->Vertices[1], triangleA->Vertices[2], triangleA->Planes[0].Normal,
                sphereB->Center, sphereB->Radius, aFromB);
            if (convexDistance.Distance < maxDistance)
            {
                manifold = new Manifold(convexDistance, worldFromA);
            }
            else
            {
                manifold = new Manifold();
            }
        }
Example #8
0
 // Create a contact point for a pair of spheres in world space.
 public static unsafe void SphereSphere(
     SphereCollider *sphereA, SphereCollider *sphereB,
     [NoAlias] in MTransform worldFromA, [NoAlias] in MTransform aFromB, float maxDistance,
Example #9
0
        // Dispatch any pair of convex colliders
        public static unsafe Result ConvexConvex(Collider *convexA, Collider *convexB, MTransform aFromB)
        {
            Result result;
            bool   flip = false;

            switch (convexA->Type)
            {
            case ColliderType.Sphere:
                SphereCollider *sphereA = (SphereCollider *)convexA;
                switch (convexB->Type)
                {
                case ColliderType.Sphere:
                    result = SphereSphere(sphereA, (SphereCollider *)convexB, aFromB);
                    break;

                case ColliderType.Capsule:
                    CapsuleCollider *capsuleB = (CapsuleCollider *)convexB;
                    result = CapsuleSphere(capsuleB->Vertex0, capsuleB->Vertex1, capsuleB->Radius, sphereA->Center, sphereA->Radius, Inverse(aFromB));
                    flip   = true;
                    break;

                case ColliderType.Triangle:
                    PolygonCollider *triangleB = (PolygonCollider *)convexB;
                    result = TriangleSphere(
                        triangleB->Vertices[0], triangleB->Vertices[1], triangleB->Vertices[2], triangleB->Planes[0].Normal,
                        sphereA->Center, sphereA->Radius, Inverse(aFromB));
                    flip = true;
                    break;

                case ColliderType.Quad:
                    PolygonCollider *quadB = (PolygonCollider *)convexB;
                    result = QuadSphere(
                        quadB->Vertices[0], quadB->Vertices[1], quadB->Vertices[2], quadB->Vertices[3], quadB->Planes[0].Normal,
                        sphereA->Center, sphereA->Radius, Inverse(aFromB));
                    flip = true;
                    break;

                case ColliderType.Box:
                    result = BoxSphere((BoxCollider *)convexB, sphereA, Inverse(aFromB));
                    flip   = true;
                    break;

                case ColliderType.Cylinder:
                case ColliderType.Convex:
                    result = ConvexConvex(ref sphereA->ConvexHull, ref ((ConvexCollider *)convexB)->ConvexHull, aFromB);
                    break;

                default:
                    throw new NotImplementedException();
                }
                break;

            case ColliderType.Capsule:
                CapsuleCollider *capsuleA = (CapsuleCollider *)convexA;
                switch (convexB->Type)
                {
                case ColliderType.Sphere:
                    SphereCollider *sphereB = (SphereCollider *)convexB;
                    result = CapsuleSphere(capsuleA->Vertex0, capsuleA->Vertex1, capsuleA->Radius, sphereB->Center, sphereB->Radius, aFromB);
                    break;

                case ColliderType.Capsule:
                    result = CapsuleCapsule(capsuleA, (CapsuleCollider *)convexB, aFromB);
                    break;

                case ColliderType.Triangle:
                    result = CapsuleTriangle(capsuleA, (PolygonCollider *)convexB, aFromB);
                    break;

                case ColliderType.Box:
                case ColliderType.Quad:
                case ColliderType.Cylinder:
                case ColliderType.Convex:
                    result = ConvexConvex(ref capsuleA->ConvexHull, ref ((ConvexCollider *)convexB)->ConvexHull, aFromB);
                    break;

                default:
                    throw new NotImplementedException();
                }
                break;

            case ColliderType.Triangle:
                PolygonCollider *triangleA = (PolygonCollider *)convexA;
                switch (convexB->Type)
                {
                case ColliderType.Sphere:
                    SphereCollider *sphereB = (SphereCollider *)convexB;
                    result = TriangleSphere(
                        triangleA->Vertices[0], triangleA->Vertices[1], triangleA->Vertices[2], triangleA->Planes[0].Normal,
                        sphereB->Center, sphereB->Radius, aFromB);
                    break;

                case ColliderType.Capsule:
                    result = CapsuleTriangle((CapsuleCollider *)convexB, triangleA, Inverse(aFromB));
                    flip   = true;
                    break;

                case ColliderType.Box:
                case ColliderType.Triangle:
                case ColliderType.Quad:
                case ColliderType.Cylinder:
                case ColliderType.Convex:
                    result = ConvexConvex(ref triangleA->ConvexHull, ref ((ConvexCollider *)convexB)->ConvexHull, aFromB);
                    break;

                default:
                    throw new NotImplementedException();
                }
                break;

            case ColliderType.Box:
                BoxCollider *boxA = (BoxCollider *)convexA;
                switch (convexB->Type)
                {
                case ColliderType.Sphere:
                    result = BoxSphere(boxA, (SphereCollider *)convexB, aFromB);
                    break;

                case ColliderType.Capsule:
                case ColliderType.Box:
                case ColliderType.Triangle:
                case ColliderType.Quad:
                case ColliderType.Cylinder:
                case ColliderType.Convex:
                    result = ConvexConvex(ref boxA->ConvexHull, ref ((ConvexCollider *)convexB)->ConvexHull, aFromB);
                    break;

                default:
                    throw new NotImplementedException();
                }
                break;

            case ColliderType.Quad:
            case ColliderType.Cylinder:
            case ColliderType.Convex:
                result = ConvexConvex(ref ((ConvexCollider *)convexA)->ConvexHull, ref ((ConvexCollider *)convexB)->ConvexHull, aFromB);
                break;

            default:
                throw new NotImplementedException();
            }

            if (flip)
            {
                result.PositionOnAinA = Mul(aFromB, result.PositionOnBinA);
                result.NormalInA      = math.mul(aFromB.Rotation, -result.NormalInA);
            }

            return(result);
        }
Example #10
0
        public static unsafe Result SphereSphere(SphereCollider *sphereA, SphereCollider *sphereB, MTransform aFromB)
        {
            float3 posBinA = Mul(aFromB, sphereB->Center);

            return(PointPoint(sphereA->Center, posBinA, sphereA->Radius, sphereA->Radius + sphereB->Radius));
        }