Ejemplo n.º 1
0
    /// <summary>
    /// Performs a collision correction at the specified position.
    /// </summary>
    /// <param name="entity"></param>
    /// <param name="currPos"></param>
    /// <param name="currRot"></param>
    /// <param name="controller"></param>
    /// <param name="collider"></param>
    /// <param name="collisionWorld"></param>
    private void CorrectForCollision(ref Entity entity, ref float3 currPos, ref quaternion currRot, ref CharacterControllerData controller, ref PhysicsCollider collider, ref CollisionWorld collisionWorld)
    {
        RigidTransform transform = new RigidTransform()
        {
            pos = currPos,
            rot = currRot
        };

        // Use a subset sphere within our collider to test against.
        // We do not use the collider itself as some intersection (such as on ramps) is ok.

        var offset         = -math.normalize(controller.gravity) * 0.1f;
        var sampleCollider = new PhysicsCollider()
        {
            Value = SphereCollider.Create(new SphereGeometry()
            {
                Center = currPos + offset,
                Radius = 0.1f
            })
        };

        if (PhysicsUtils.ColliderDistance(out DistanceHit smallestHit, sampleCollider, 0.1f, transform, ref collisionWorld, entity, PhysicsCollisionFilters.DynamicWithPhysical, null, ColliderData, Allocator.Temp))
        {
            if (smallestHit.Distance < 0.0f)
            {
                currPos += math.abs(smallestHit.Distance) * smallestHit.SurfaceNormal;
            }
        }
    }
Ejemplo n.º 2
0
        public void TestDistanceTwoSpheres()
        {
            // Insertion
            var tree          = new NativeBVHTree(64, Allocator.Persistent);
            int expectedIndex = tree.InsertLeaf(SphereCollider.Create(new float3(0, 2, 0), 2));

            tree.InsertLeaf(SphereCollider.Create(new float3(0, 5, 0), 2));

            // Distance query
            var rayResult = new NativeList <int>(64, Allocator.Temp);
            var query     = new NativeBVHTree.DistanceQueryInput {
                origin      = new float3(0, -1, 0),
                maxDistance = 3f
            };

            tree.DistanceQuery(query, rayResult);

            // Debug
            NativeBVHDebugDrawer.LastTree     = tree;
            NativeBVHDebugDrawer.LastTreeHits = rayResult.ToArray();

            // Assert
            Assert.AreEqual(1, rayResult.Length, "Expected only one hit");
            Assert.AreEqual(expectedIndex, rayResult[0], "Expected nearer sphere to be the result");
        }
        public void TestSphereColliderCreateInvalid()
        {
            var sphere = new SphereGeometry
            {
                Center = new float3(-10.34f, 0.0f, -1.54f),
                Radius = 1.25f
            };

            // positive inf center
            {
                var invalidSphere = sphere;
                invalidSphere.Center = new float3(float.PositiveInfinity, 0.0f, 0.0f);
                TestUtils.ThrowsException <System.ArgumentException>(() => SphereCollider.Create(invalidSphere));
            }

            // negative inf center
            {
                var invalidSphere = sphere;
                invalidSphere.Center = new float3(float.NegativeInfinity, 0.0f, 0.0f);
                TestUtils.ThrowsException <System.ArgumentException>(() => SphereCollider.Create(invalidSphere));
            }

            // nan center
            {
                var invalidSphere = sphere;
                invalidSphere.Center = new float3(float.NaN, 0.0f, 0.0f);
                TestUtils.ThrowsException <System.ArgumentException>(() => SphereCollider.Create(invalidSphere));
            }

            // negative radius
            {
                var invalidSphere = sphere;
                invalidSphere.Radius = -0.5f;
                TestUtils.ThrowsException <System.ArgumentException>(() => SphereCollider.Create(invalidSphere));
            }

            // positive inf radius
            {
                var invalidSphere = sphere;
                invalidSphere.Radius = float.PositiveInfinity;
                TestUtils.ThrowsException <System.ArgumentException>(() => SphereCollider.Create(invalidSphere));
            }

            // negative inf radius
            {
                var invalidSphere = sphere;
                invalidSphere.Radius = float.NegativeInfinity;
                TestUtils.ThrowsException <System.ArgumentException>(() => SphereCollider.Create(invalidSphere));
            }

            // nan radius
            {
                var invalidSphere = sphere;
                invalidSphere.Radius = float.NaN;
                TestUtils.ThrowsException <System.ArgumentException>(() => SphereCollider.Create(invalidSphere));
            }
        }
        protected override BlobAssetReference <Collider> ProduceColliderBlob(LegacySphere shape)
        {
            var scale = (float3)shape.transform.lossyScale;

            return(SphereCollider.Create(
                       shape.center * scale,
                       shape.radius * math.cmax(math.abs(scale)),
                       ProduceCollisionFilter(shape),
                       ProduceMaterial(shape)
                       ));
        }
Ejemplo n.º 5
0
        public void SphereCollider_Create_WhenRadiusInvalid_Throws(
            [Values(float.PositiveInfinity, float.NegativeInfinity, float.NaN, -1f)] float value
            )
        {
            var geometry = new SphereGeometry {
                Radius = value
            };

            var ex = Assert.Throws <ArgumentException>(() => SphereCollider.Create(geometry));

            Assert.That(ex.Message, Does.Match(nameof(SphereGeometry.Radius)));
        }
Ejemplo n.º 6
0
        unsafe public void TestSphereColliderCreate()
        {
            float3 center         = new float3(-8.45f, 9.65f, -0.10f);
            float  radius         = 0.98f;
            var    collider       = SphereCollider.Create(center, radius);
            var    sphereCollider = UnsafeUtilityEx.AsRef <SphereCollider>(collider.GetUnsafePtr());

            TestUtils.AreEqual(center, sphereCollider.Center, 1e-3f);
            TestUtils.AreEqual(radius, sphereCollider.Radius, 1e-3f);
            Assert.AreEqual(ColliderType.Sphere, sphereCollider.Type);
            Assert.AreEqual(CollisionType.Convex, sphereCollider.CollisionType);
        }
Ejemplo n.º 7
0
        public unsafe void RigidBodyCalculateAabb_SphereColliderTest()
        {
            Physics.RigidBody rigidbodySphere = Unity.Physics.RigidBody.Zero;
            const float       convexRadius    = 1.0f;

            rigidbodySphere.Collider = (Collider *)SphereCollider.Create(float3.zero, convexRadius).GetUnsafePtr();

            var sphereAabb = rigidbodySphere.CalculateAabb();
            var sphere     = (Collider *)SphereCollider.Create(float3.zero, convexRadius).GetUnsafePtr();

            Assert.IsTrue(sphereAabb.Equals(sphere->CalculateAabb()));
        }
            public void Execute(int i)
            {
                var shapeData = ComputeData[ToComputeTable[i]];

                switch (shapeData.ShapeType)
                {
                case ShapeType.Box:
                {
                    BlobAssets[i] = BoxCollider.Create(
                        shapeData.BoxProperties, shapeData.CollisionFilter, shapeData.Material
                        );
                    return;
                }

                case ShapeType.Capsule:
                {
                    BlobAssets[i] = CapsuleCollider.Create(
                        shapeData.CapsuleProperties, shapeData.CollisionFilter, shapeData.Material
                        );
                    return;
                }

                case ShapeType.Cylinder:
                {
                    BlobAssets[i] = CylinderCollider.Create(
                        shapeData.CylinderProperties, shapeData.CollisionFilter, shapeData.Material
                        );
                    return;
                }

                case ShapeType.Plane:
                {
                    var v = shapeData.PlaneVertices;
                    BlobAssets[i] = PolygonCollider.CreateQuad(
                        v.c0, v.c1, v.c2, v.c3, shapeData.CollisionFilter, shapeData.Material
                        );
                    return;
                }

                case ShapeType.Sphere:
                {
                    BlobAssets[i] = SphereCollider.Create(
                        shapeData.SphereProperties, shapeData.CollisionFilter, shapeData.Material
                        );
                    return;
                }

                // Note : Mesh and Hull are not computed here as they are in a separated set of jobs
                default:
                    return;
                }
            }
Ejemplo n.º 9
0
        public void TestSphereColliderMassProperties()
        {
            float3 center         = new float3(-8.4f, 5.63f, 77.2f);
            float  radius         = 2.3f;
            var    sphereCollider = SphereCollider.Create(center, radius);

            float  inertia = 2.0f / 5.0f * radius * radius;
            float3 expectedInertiaTensor = new float3(inertia, inertia, inertia);
            float3 inertiaTensor         = sphereCollider.Value.MassProperties.MassDistribution.InertiaTensor;

            Debug.Log($"Expected inertia tensor: {expectedInertiaTensor}, was: {inertiaTensor}");
            TestUtils.AreEqual(expectedInertiaTensor, inertiaTensor, 1e-3f);
        }
        public unsafe void RigidBodyCalculateDistanceTest()
        {
            const float size         = 1.0f;
            const float convexRadius = 0.0f;
            const float sphereRadius = 1.0f;

            var queryPos = new float3(-10, -10, -10);

            BlobAssetReference <Collider> boxCollider = BoxCollider.Create(new BoxGeometry
            {
                Center      = float3.zero,
                Orientation = quaternion.identity,
                Size        = size,
                BevelRadius = convexRadius
            });
            BlobAssetReference <Collider> sphereCollider = SphereCollider.Create(new SphereGeometry
            {
                Center = float3.zero,
                Radius = sphereRadius
            });

            var rigidBody = new Physics.RigidBody
            {
                WorldFromBody = RigidTransform.identity,
                Collider      = boxCollider
            };

            var colliderDistanceInput = new ColliderDistanceInput
            {
                Collider  = (Collider *)sphereCollider.GetUnsafePtr(),
                Transform = new RigidTransform(quaternion.identity, queryPos)
            };

            var closestHit = new DistanceHit();
            var allHits    = new NativeList <DistanceHit>(Allocator.Temp);

            // OK case : with enough max distance
            colliderDistanceInput.MaxDistance = 10000.0f;
            Assert.IsTrue(rigidBody.CalculateDistance(colliderDistanceInput));
            Assert.IsTrue(rigidBody.CalculateDistance(colliderDistanceInput, out closestHit));
            Assert.IsTrue(rigidBody.CalculateDistance(colliderDistanceInput, ref allHits));

            // Fail case : not enough max distance
            colliderDistanceInput.MaxDistance = 1;
            Assert.IsFalse(rigidBody.CalculateDistance(colliderDistanceInput));
            Assert.IsFalse(rigidBody.CalculateDistance(colliderDistanceInput, out closestHit));
            Assert.IsFalse(rigidBody.CalculateDistance(colliderDistanceInput, ref allHits));

            boxCollider.Dispose();
            sphereCollider.Dispose();
        }
        public void TestSphereColliderMassProperties()
        {
            float3 center         = new float3(-8.4f, 5.63f, 77.2f);
            float  radius         = 2.3f;
            var    sphereCollider = SphereCollider.Create(new SphereGeometry {
                Center = center, Radius = radius
            });

            float  inertia = 2.0f / 5.0f * radius * radius;
            float3 expectedInertiaTensor = new float3(inertia, inertia, inertia);
            float3 inertiaTensor         = sphereCollider.Value.MassProperties.MassDistribution.InertiaTensor;

            TestUtils.AreEqual(expectedInertiaTensor, inertiaTensor, 1e-3f);
        }
Ejemplo n.º 12
0
        public unsafe void RigidBodyCalculateAabb_SphereColliderTest()
        {
            var geometry = new SphereGeometry
            {
                Center = float3.zero,
                Radius = 1.0f
            };

            Physics.RigidBody rigidbodySphere = Unity.Physics.RigidBody.Zero;
            rigidbodySphere.Collider = (Collider *)SphereCollider.Create(geometry).GetUnsafePtr();

            var sphereAabb = rigidbodySphere.CalculateAabb();
            var sphere     = (Collider *)SphereCollider.Create(geometry).GetUnsafePtr();

            Assert.IsTrue(sphereAabb.Equals(sphere->CalculateAabb()));
        }
Ejemplo n.º 13
0
        public unsafe void RigidBodyCastColliderTest()
        {
            Physics.RigidBody rigidbody = Unity.Physics.RigidBody.Zero;

            const float size         = 1.0f;
            const float convexRadius = 0.0f;
            const float sphereRadius = 1.0f;

            var rayStartOK = new float3(-10, -10, -10);
            var rayEndOK   = new float3(10, 10, 10);

            var rayStartFail = new float3(-10, 10, -10);
            var rayEndFail   = new float3(10, 10, 10);

            rigidbody.Collider = (Collider *)BoxCollider.Create(new BoxGeometry
            {
                Center      = float3.zero,
                Orientation = quaternion.identity,
                Size        = size,
                BevelRadius = convexRadius
            }).GetUnsafePtr();

            var colliderCastInput = new ColliderCastInput();
            var closestHit        = new ColliderCastHit();
            var allHits           = new NativeList <ColliderCastHit>(Allocator.Temp);

            // OK case : Sphere hits the box collider
            colliderCastInput.Start    = rayStartOK;
            colliderCastInput.End      = rayEndOK;
            colliderCastInput.Collider = (Collider *)SphereCollider.Create(
                new SphereGeometry {
                Center = float3.zero, Radius = sphereRadius
            }
                ).GetUnsafePtr();

            Assert.IsTrue(rigidbody.CastCollider(colliderCastInput));
            Assert.IsTrue(rigidbody.CastCollider(colliderCastInput, out closestHit));
            Assert.IsTrue(rigidbody.CastCollider(colliderCastInput, ref allHits));

            // Fail case : wrong direction
            colliderCastInput.Start = rayStartFail;
            colliderCastInput.End   = rayEndFail;

            Assert.IsFalse(rigidbody.CastCollider(colliderCastInput));
            Assert.IsFalse(rigidbody.CastCollider(colliderCastInput, out closestHit));
            Assert.IsFalse(rigidbody.CastCollider(colliderCastInput, ref allHits));
        }
Ejemplo n.º 14
0
        public void TestSphereColliderCalculateAabbLocal()
        {
            float3 center         = new float3(-8.4f, 5.63f, -7.2f);
            float  radius         = 2.3f;
            var    sphereCollider = SphereCollider.Create(center, radius);

            Aabb expected = new Aabb();

            expected.Min = center - new float3(radius, radius, radius);
            expected.Max = center + new float3(radius, radius, radius);

            Aabb actual = sphereCollider.Value.CalculateAabb();

            Debug.Log($"Expected aabb: Min: {expected.Min} Max: {expected.Max}, was Min: {actual.Min} Max: {actual.Max}");
            TestUtils.AreEqual(expected.Min, actual.Min, 1e-3f);
            TestUtils.AreEqual(expected.Max, actual.Max, 1e-3f);
        }
        public void TestSphereColliderCalculateAabbLocal()
        {
            float3 center         = new float3(-8.4f, 5.63f, -7.2f);
            float  radius         = 2.3f;
            var    sphereCollider = SphereCollider.Create(new SphereGeometry {
                Center = center, Radius = radius
            });

            Aabb expected = new Aabb();

            expected.Min = center - new float3(radius, radius, radius);
            expected.Max = center + new float3(radius, radius, radius);

            Aabb actual = sphereCollider.Value.CalculateAabb();

            TestUtils.AreEqual(expected.Min, actual.Min, 1e-3f);
            TestUtils.AreEqual(expected.Max, actual.Max, 1e-3f);
        }
        unsafe public void TestSphereColliderCreate()
        {
            var sphere = new SphereGeometry
            {
                Center = new float3(-8.45f, 9.65f, -0.10f),
                Radius = 0.98f
            };

            var collider       = SphereCollider.Create(sphere);
            var sphereCollider = UnsafeUtilityEx.AsRef <SphereCollider>(collider.GetUnsafePtr());

            TestUtils.AreEqual(sphere.Center, sphereCollider.Center, 1e-3f);
            TestUtils.AreEqual(sphere.Center, sphereCollider.Geometry.Center, 1e-3f);
            TestUtils.AreEqual(sphere.Radius, sphereCollider.Radius, 1e-3f);
            TestUtils.AreEqual(sphere.Radius, sphereCollider.Geometry.Radius, 1e-3f);
            Assert.AreEqual(ColliderType.Sphere, sphereCollider.Type);
            Assert.AreEqual(CollisionType.Convex, sphereCollider.CollisionType);
        }
        protected override BlobAssetReference <Collider> ProduceColliderBlob(LegacySphere shape)
        {
            var worldCenter    = math.mul(shape.transform.localToWorldMatrix, new float4(shape.center, 1f));
            var shapeFromWorld = math.inverse(
                new float4x4(new RigidTransform(shape.transform.rotation, shape.transform.position))
                );
            var center = math.mul(shapeFromWorld, worldCenter).xyz;

            var linearScale = (float3)shape.transform.lossyScale;
            var radius      = shape.radius * math.cmax(math.abs(linearScale));

            return(SphereCollider.Create(
                       new SphereGeometry {
                Center = center, Radius = radius
            },
                       ProduceCollisionFilter(shape),
                       ProduceMaterial(shape)
                       ));
        }
Ejemplo n.º 18
0
        public void TestSphereColliderCalculateAabbTransformed()
        {
            float3 center         = new float3(-3.4f, 0.63f, -17.2f);
            float  radius         = 5.3f;
            var    sphereCollider = SphereCollider.Create(center, radius);

            float3     translation = new float3(8.3f, -0.5f, 170.0f);
            quaternion rotation    = quaternion.AxisAngle(math.normalize(new float3(1.1f, 4.5f, 0.0f)), 146.0f);

            Aabb expected = new Aabb();

            expected.Min = math.mul(rotation, center) + translation - new float3(radius, radius, radius);
            expected.Max = math.mul(rotation, center) + translation + new float3(radius, radius, radius);

            Aabb actual = sphereCollider.Value.CalculateAabb(new RigidTransform(rotation, translation));

            Debug.Log($"Expected aabb: Min: {expected.Min} Max: {expected.Max}, was Min: {actual.Min} Max: {actual.Max}");
            TestUtils.AreEqual(expected.Min, actual.Min, 1e-3f);
            TestUtils.AreEqual(expected.Max, actual.Max, 1e-3f);
        }
Ejemplo n.º 19
0
    public static async void SpawnBall(float3 position, float radius)
    {
        Material whiteMaterial = await Addressables.LoadAssetAsync <Material>(
            PRC.Addressables.Materials.White
            ).Task;

        BlobAssetReference <Collider> collider = SphereCollider.Create(new SphereGeometry()
        {
            Radius = radius
        });

        DOTools.Physics.CreateDynamicBody(
            position,
            quaternion.identity,
            collider,
            float3.zero,
            float3.zero,
            1f,
            whiteMaterial
            );
    }
Ejemplo n.º 20
0
        public unsafe void RigidBodyCastColliderTest()
        {
            Physics.RigidBody rigidbody = Unity.Physics.RigidBody.Zero;

            const float size         = 1.0f;
            const float convexRadius = 0.0f;
            const float sphereRadius = 1.0f;

            var rayStartOK = new float3(-10, -10, -10);
            var rayEndOK   = new float3(10, 10, 10);

            var rayStartFail = new float3(-10, 10, -10);
            var rayEndFail   = new float3(10, 10, 10);

            rigidbody.Collider = (Collider *)BoxCollider.Create(float3.zero, quaternion.identity, new float3(size), convexRadius).GetUnsafePtr();

            var colliderCastInput = new ColliderCastInput();
            var closestHit        = new ColliderCastHit();
            var allHits           = new NativeList <ColliderCastHit>(Allocator.Temp);

            // OK case : Sphere hits the box collider
            float3 rayDir = rayEndOK - rayStartOK;

            colliderCastInput.Position  = rayStartOK;
            colliderCastInput.Direction = rayDir;
            colliderCastInput.Collider  = (Collider *)SphereCollider.Create(float3.zero, sphereRadius).GetUnsafePtr();

            Assert.IsTrue(rigidbody.CastCollider(colliderCastInput));
            Assert.IsTrue(rigidbody.CastCollider(colliderCastInput, out closestHit));
            Assert.IsTrue(rigidbody.CastCollider(colliderCastInput, ref allHits));

            // Fail case : wrong direction
            rayDir = rayEndFail - rayStartFail;
            colliderCastInput.Position  = rayStartFail;
            colliderCastInput.Direction = rayDir;

            Assert.IsFalse(rigidbody.CastCollider(colliderCastInput));
            Assert.IsFalse(rigidbody.CastCollider(colliderCastInput, out closestHit));
            Assert.IsFalse(rigidbody.CastCollider(colliderCastInput, ref allHits));
        }
Ejemplo n.º 21
0
        public static unsafe BlobAssetReference <Collider> GenerateRandomConvex(ref Random rnd)
        {
            ColliderType colliderType = (ColliderType)rnd.NextInt((int)ColliderType.Box);
            float        radius       = (rnd.NextInt(4) > 0) ? rnd.NextFloat(0.5f) : 0.0f;

            switch (colliderType)
            {
            case ColliderType.Convex:
            {
                int numPoints = rnd.NextInt(1, 16);
                if (numPoints == 3)     // TODO - hull builder doesn't build faces for flat shapes, work around it for now to run the test
                {
                    numPoints++;
                }
                var points = new NativeArray <float3>(numPoints, Allocator.Temp);
                for (int i = 0; i < numPoints; i++)
                {
                    points[i] = rnd.NextFloat3(-1.0f, 1.0f);
                }
                var collider = ConvexCollider.Create(points, radius);
                points.Dispose();
                return(collider);
            }

            case ColliderType.Sphere:
            {
                float3 center = (rnd.NextInt(4) > 0) ? float3.zero : rnd.NextFloat3(-0.5f, 0.5f);
                return(SphereCollider.Create(center, rnd.NextFloat(0.01f, 0.5f)));
            }

            case ColliderType.Capsule:
            {
                float3 point0 = rnd.NextFloat3(0.0f, 1.0f);
                float3 point1 = (rnd.NextInt(4) > 0) ? -point0 : rnd.NextFloat3(-1.0f, 1.0f);
                return(CapsuleCollider.Create(point0, point1, rnd.NextFloat(0.01f, 0.5f)));
            }

            case ColliderType.Triangle:
            {
                return(PolygonCollider.CreateTriangle(rnd.NextFloat3(-1.0f, 1.0f), rnd.NextFloat3(-1.0f, 1.0f), rnd.NextFloat3(-1.0f, 1.0f)));
            }

            case ColliderType.Quad:
            {
                // Pick 3 totally random points, then choose a fourth that makes a flat and convex quad
                float3 point0 = rnd.NextFloat3(-1.0f, 1.0f);
                float3 point1 = rnd.NextFloat3(-1.0f, 1.0f);
                float3 point3 = rnd.NextFloat3(-1.0f, 1.0f);
                float  t0     = rnd.NextFloat(0.0f, 1.0f);
                float  t1     = rnd.NextFloat(0.0f, 1.0f);
                float3 e      = point1 + point1 - point0;
                float3 a      = math.lerp(point1, e, t0);
                float3 b      = math.lerp(point3, point3 + point3 - point0, t0);
                float3 point2 = math.lerp(a, b, t1);

                return(PolygonCollider.CreateQuad(point0, point1, point2, point3));
            }

            case ColliderType.Box:
            {
                float3     center      = (rnd.NextInt(4) > 0) ? float3.zero : rnd.NextFloat3(-0.5f, 0.5f);
                quaternion orientation = (rnd.NextInt(4) > 0) ? quaternion.identity : rnd.NextQuaternionRotation();
                return(BoxCollider.Create(center, orientation, rnd.NextFloat3(0.01f, 1.0f), radius));
            }

            default: throw new System.NotImplementedException();
            }
        }
        protected override BlobAssetReference <Collider> ProduceColliderBlob(PhysicsShape shape)
        {
            var material        = ProduceMaterial(shape);
            var collisionFilter = ProduceCollisionFilter(shape);

            var blob = new BlobAssetReference <Collider>();

            shape.GetBakeTransformation(out var linearScalar, out var radiusScalar);
            switch (shape.ShapeType)
            {
            case ShapeType.Box:
                shape.GetBoxProperties(out var center, out var size, out quaternion orientation);
                blob = BoxCollider.Create(
                    center * linearScalar,
                    orientation,
                    math.abs(size * linearScalar),
                    shape.ConvexRadius * radiusScalar,
                    collisionFilter,
                    material);
                break;

            case ShapeType.Capsule:
                shape.GetCapsuleProperties(out var v0, out var v1, out var radius);
                blob = CapsuleCollider.Create(
                    v0 * linearScalar,
                    v1 * linearScalar,
                    radius * radiusScalar,
                    collisionFilter,
                    material);
                break;

            case ShapeType.Sphere:
                shape.GetSphereProperties(out center, out radius, out orientation);
                blob = SphereCollider.Create(
                    center * linearScalar,
                    radius * radiusScalar,
                    collisionFilter,
                    material);
                break;

            case ShapeType.Cylinder:
                shape.GetCylinderProperties(out center, out var height, out radius, out orientation);
                var s = math.abs(math.mul(math.inverse(orientation), linearScalar));
                blob = CylinderCollider.Create(
                    center * linearScalar,
                    height * s.z,
                    radius * math.cmax(s.xy),
                    orientation,
                    shape.ConvexRadius * radiusScalar,
                    collisionFilter,
                    material);
                break;

            case ShapeType.Plane:
                shape.GetPlaneProperties(out v0, out v1, out var v2, out var v3);
                blob = PolygonCollider.CreateQuad(
                    v0 * linearScalar,
                    v1 * linearScalar,
                    v2 * linearScalar,
                    v3 * linearScalar,
                    collisionFilter,
                    material);
                break;

            case ShapeType.ConvexHull:
                var pointCloud = new NativeList <float3>(65535, Allocator.Temp);
                shape.GetConvexHullProperties(pointCloud);
                if (pointCloud.Length == 0)
                {
                    pointCloud.Dispose();
                    throw new InvalidOperationException(
                              $"No vertices associated with {shape.name}. Add a {typeof(MeshFilter)} component or assign {nameof(PhysicsShape.CustomMesh)}."
                              );
                }
                blob = ConvexCollider.Create(
                    pointCloud,
                    shape.ConvexRadius * radiusScalar,
                    linearScalar,
                    collisionFilter,
                    material);
                pointCloud.Dispose();
                break;

            case ShapeType.Mesh:
                // TODO: no convex radius?
                var mesh = shape.GetMesh();
                if (mesh == null)
                {
                    throw new InvalidOperationException(
                              $"No mesh associated with {shape.name}. Add a {typeof(MeshFilter)} component or assign {nameof(PhysicsShape.CustomMesh)}."
                              );
                }
                else
                {
                    blob = MeshCollider.Create(mesh.GetScaledVertices(linearScalar), mesh.triangles, collisionFilter, material);
                }
                break;

            default:
                throw new UnimplementedShapeException(shape.ShapeType);
            }
            return(blob);
        }
Ejemplo n.º 23
0
        private BlobAssetReference <Collider> CreateCollider(UnityEngine.Mesh mesh, ColliderType type)
        {
            switch (type)
            {
            case ColliderType.Sphere:
            {
                Bounds bounds = mesh.bounds;
                return(SphereCollider.Create(bounds.center, math.cmax(bounds.extents)));
            }

            case ColliderType.Triangle:
            {
                return(PolygonCollider.CreateTriangle(mesh.vertices[0], mesh.vertices[1], mesh.vertices[2]));
            }

            case ColliderType.Quad:
            {
                // We assume the first 2 triangles of the mesh are a quad with a shared edge
                // Work out a correct ordering for the triangle
                int[] orderedIndices = new int[4];

                // Find the vertex in first triangle that is not on the shared edge
                for (int i = 0; i < 3; i++)
                {
                    if ((mesh.triangles[i] != mesh.triangles[3]) &&
                        (mesh.triangles[i] != mesh.triangles[4]) &&
                        (mesh.triangles[i] != mesh.triangles[5]))
                    {
                        // Push in order or prev, unique, next
                        orderedIndices[0] = mesh.triangles[(i - 1 + 3) % 3];
                        orderedIndices[1] = mesh.triangles[i];
                        orderedIndices[2] = mesh.triangles[(i + 1) % 3];
                        break;
                    }
                }

                // Find the vertex in second triangle that is not on a shared edge
                for (int i = 3; i < 6; i++)
                {
                    if ((mesh.triangles[i] != orderedIndices[0]) &&
                        (mesh.triangles[i] != orderedIndices[1]) &&
                        (mesh.triangles[i] != orderedIndices[2]))
                    {
                        orderedIndices[3] = mesh.triangles[i];
                        break;
                    }
                }

                return(PolygonCollider.CreateQuad(
                           mesh.vertices[orderedIndices[0]],
                           mesh.vertices[orderedIndices[1]],
                           mesh.vertices[orderedIndices[2]],
                           mesh.vertices[orderedIndices[3]]));
            }

            case ColliderType.Box:
            {
                Bounds bounds = mesh.bounds;
                return(BoxCollider.Create(bounds.center, quaternion.identity, 2.0f * bounds.extents, 0.0f));
            }

            case ColliderType.Capsule:
            {
                Bounds bounds  = mesh.bounds;
                float  min     = math.cmin(bounds.extents);
                float  max     = math.cmax(bounds.extents);
                int    x       = math.select(math.select(2, 1, min == bounds.extents.y), 0, min == bounds.extents.x);
                int    z       = math.select(math.select(2, 1, max == bounds.extents.y), 0, max == bounds.extents.x);
                int    y       = math.select(math.select(2, 1, (1 != x) && (1 != z)), 0, (0 != x) && (0 != z));
                float  radius  = bounds.extents[y];
                float3 vertex0 = bounds.center; vertex0[z] = -(max - radius);
                float3 vertex1 = bounds.center; vertex1[z] = (max - radius);
                return(CapsuleCollider.Create(vertex0, vertex1, radius));
            }

            case ColliderType.Cylinder:
                // TODO: need someone to add
                throw new NotImplementedException();

            case ColliderType.Convex:
            {
                NativeArray <float3> points = new NativeArray <float3>(mesh.vertices.Length, Allocator.Temp);
                for (int i = 0; i < mesh.vertices.Length; i++)
                {
                    points[i] = mesh.vertices[i];
                }
                return(ConvexCollider.Create(points, 0.0f));
            }

            default:
                throw new System.NotImplementedException();
            }
        }
            public unsafe void Execute(int index)
            {
                Results.BeginForEachIndex(index);
                int numRows = (Request.ImageResolution + Results.ForEachCount - 1) / Results.ForEachCount;

                const float sphereRadius = 0.005f;
                BlobAssetReference <Collider> sphere;

                if (Request.CastSphere)
                {
                    sphere = SphereCollider.Create(float3.zero, sphereRadius, Request.CollisionFilter);
                }

                for (int yCoord = index * numRows; yCoord < math.min(Request.ImageResolution, (index + 1) * numRows); yCoord++)
                {
                    for (int xCoord = 0; xCoord < Request.ImageResolution; xCoord++)
                    {
                        float xFrac = 2.0f * ((xCoord / (float)Request.ImageResolution) - 0.5f);
                        float yFrac = 2.0f * ((yCoord / (float)Request.ImageResolution) - 0.5f);

                        float3 targetImagePlane = Request.ImageCenter + Request.Up * Request.PlaneHalfExtents * yFrac + Request.Right * Request.PlaneHalfExtents * xFrac;
                        float3 rayDir           = Request.RayLength * (Request.PinHole - targetImagePlane);

                        RaycastHit hit;
                        bool       hasHit;
                        if (Request.CastSphere)
                        {
                            var input = new ColliderCastInput
                            {
                                Collider    = (Collider *)sphere.GetUnsafePtr(),
                                Orientation = quaternion.identity,
                                Start       = Request.PinHole,
                                End         = Request.PinHole + rayDir
                            };
                            hasHit = World.CastCollider(input, out ColliderCastHit colliderHit);
                            hit    = new RaycastHit
                            {
                                Fraction       = colliderHit.Fraction,
                                Position       = colliderHit.Position,
                                SurfaceNormal  = colliderHit.SurfaceNormal,
                                RigidBodyIndex = colliderHit.RigidBodyIndex,
                                ColliderKey    = colliderHit.ColliderKey
                            };
                        }
                        else
                        {
                            var rayCastInput = new RaycastInput
                            {
                                Start  = Request.PinHole,
                                End    = Request.PinHole + rayDir,
                                Filter = Request.CollisionFilter
                            };
                            hasHit = World.CastRay(rayCastInput, out hit);
                        }

                        Color hitColor = Color.black;
                        if (hasHit)
                        {
                            if (hit.RigidBodyIndex < NumDynamicBodies)
                            {
                                hitColor = Color.yellow;
                            }
                            else
                            {
                                hitColor = Color.grey;
                            }

                            // Lighten alternate keys
                            if (Request.AlternateKeys && !hit.ColliderKey.Equals(ColliderKey.Empty))
                            {
                                Collider *collider = World.Bodies[hit.RigidBodyIndex].Collider;
                                hit.ColliderKey.PopSubKey(collider->NumColliderKeyBits, out uint key);
                                if (key % 2 == 0)
                                {
                                    Color.RGBToHSV(hitColor, out float h, out float s, out float v);
                                    hitColor = Color.HSVToRGB(h, s, v + 0.25f);
                                }
                            }

                            if (Request.Shadows)
                            {
                                float3 hitPos    = Request.PinHole + rayDir * hit.Fraction + hit.SurfaceNormal * 0.001f;
                                bool   shadowHit = false;

                                if (Request.CastSphere)
                                {
                                    var start = hitPos + hit.SurfaceNormal * sphereRadius;
                                    var input = new ColliderCastInput
                                    {
                                        Collider    = (Collider *)sphere.GetUnsafePtr(),
                                        Orientation = quaternion.identity,
                                        Start       = start,
                                        End         = start + (Request.LightDir * Request.RayLength),
                                    };
                                    ColliderCastHit colliderHit;
                                    shadowHit = World.CastCollider(input, out colliderHit);
                                }
                                else
                                {
                                    var rayCastInput = new RaycastInput
                                    {
                                        Start  = hitPos,
                                        End    = hitPos + (Request.LightDir * Request.RayLength),
                                        Filter = Request.CollisionFilter
                                    };
                                    RaycastHit shadowOutput;
                                    shadowHit = World.CastRay(rayCastInput, out shadowOutput);
                                }

                                if (shadowHit)
                                {
                                    hitColor *= 0.4f;
                                }
                            }
                        }

                        float lighting = math.min(1.0f, math.max(Request.AmbientLight, Vector3.Dot(hit.SurfaceNormal, Request.LightDir)));

                        Results.Write(xCoord);
                        Results.Write(yCoord);
                        Results.Write(hitColor * lighting);
                    }
                }

                Results.EndForEachIndex();
            }
Ejemplo n.º 25
0
        public static unsafe BlobAssetReference <Collider> GenerateRandomConvex(ref Random rnd)
        {
            ColliderType colliderType = (ColliderType)rnd.NextInt((int)ColliderType.Cylinder + 1);
            float        convexRadius = (rnd.NextInt(4) > 0) ? rnd.NextFloat(0.5f) : 0.0f;

            switch (colliderType)
            {
            case ColliderType.Convex:
            {
                int numPoints = rnd.NextInt(1, 16);
                if (numPoints == 3)     // TODO - hull builder doesn't build faces for flat shapes, work around it for now to run the test
                {
                    numPoints++;
                }
                var points = new NativeArray <float3>(numPoints, Allocator.TempJob);
                for (int i = 0; i < numPoints; i++)
                {
                    points[i] = rnd.NextFloat3(-1.0f, 1.0f);
                }
                var generationParameters = ConvexHullGenerationParameters.Default;
                generationParameters.BevelRadius = convexRadius;
                var collider = ConvexCollider.Create(points, generationParameters, CollisionFilter.Default);
                points.Dispose();
                return(collider);
            }

            case ColliderType.Sphere:
            {
                return(SphereCollider.Create(new SphereGeometry
                    {
                        Center = (rnd.NextInt(4) > 0) ? float3.zero : rnd.NextFloat3(-0.5f, 0.5f),
                        Radius = rnd.NextFloat(0.01f, 0.5f)
                    }));
            }

            case ColliderType.Capsule:
            {
                float3 point0 = rnd.NextFloat3(0.0f, 1.0f);
                float3 point1 = (rnd.NextInt(4) > 0) ? -point0 : rnd.NextFloat3(-1.0f, 1.0f);
                return(CapsuleCollider.Create(new CapsuleGeometry
                    {
                        Vertex0 = point0,
                        Vertex1 = point1,
                        Radius = rnd.NextFloat(0.01f, 0.5f)
                    }));
            }

            case ColliderType.Triangle:
            {
                return(PolygonCollider.CreateTriangle(rnd.NextFloat3(-1.0f, 1.0f), rnd.NextFloat3(-1.0f, 1.0f), rnd.NextFloat3(-1.0f, 1.0f)));
            }

            case ColliderType.Quad:
            {
                // Pick 3 totally random points, then choose a fourth that makes a flat and convex quad
                float3 point0 = rnd.NextFloat3(-1.0f, 1.0f);
                float3 point1 = rnd.NextFloat3(-1.0f, 1.0f);
                float3 point3 = rnd.NextFloat3(-1.0f, 1.0f);
                float  t0     = rnd.NextFloat(0.0f, 1.0f);
                float  t1     = rnd.NextFloat(0.0f, 1.0f);
                float3 e      = point1 + point1 - point0;
                float3 a      = math.lerp(point1, e, t0);
                float3 b      = math.lerp(point3, point3 + point3 - point0, t0);
                float3 point2 = math.lerp(a, b, t1);

                return(PolygonCollider.CreateQuad(point0, point1, point2, point3));
            }

            case ColliderType.Box:
            {
                float minSize     = 0.05f; // TODO - work around hull builder problems with small faces, sometimes doesn't extend 1D->2D based on face area
                var   boxGeometry = new BoxGeometry
                {
                    Center      = (rnd.NextInt(4) > 0) ? float3.zero : rnd.NextFloat3(-0.5f, 0.5f),
                    Orientation = (rnd.NextInt(4) > 0) ? quaternion.identity : rnd.NextQuaternionRotation(),
                    Size        = rnd.NextFloat3(minSize, 1.0f)
                };

                float maxBevelRadius = math.max(math.cmin((boxGeometry.Size - minSize) / (2.0f * (1.0f + float.Epsilon))), 0.0f);
                boxGeometry.BevelRadius = math.min(maxBevelRadius, convexRadius);

                return(BoxCollider.Create(boxGeometry));
            }

            case ColliderType.Cylinder:
            {
                float minSize          = 0.01f; // TODO - cylinder gets degenerate faces if radius-convexRadius=0 or height/2-convexRadius=0, decide how to handle this in CylinderCollider
                var   cylinderGeometry = new CylinderGeometry
                {
                    Center      = (rnd.NextInt(4) > 0) ? float3.zero : rnd.NextFloat3(-0.5f, 0.5f),
                    Orientation = (rnd.NextInt(4) > 0) ? quaternion.identity : rnd.NextQuaternionRotation(),
                    Height      = rnd.NextFloat(2.0f * minSize, 1f),
                    Radius      = rnd.NextFloat(minSize, 1.0f),
                    SideCount   = 20
                };

                var maxBevelRadius = math.max(math.min(cylinderGeometry.Height / 2, cylinderGeometry.Radius) - minSize, 0.0f);
                cylinderGeometry.BevelRadius = math.min(maxBevelRadius, convexRadius);

                return(CylinderCollider.Create(cylinderGeometry));
            }

            default:
                throw new NotImplementedException();
            }
        }
        private BlobAssetReference <Collider> CreateCollider(ColliderType type)
        {
            int numMeshes = type == ColliderType.Compound ? 2 : 1;

            ColliderMeshes = new Mesh[numMeshes];
            BlobAssetReference <Collider> collider = default;

            switch (type)
            {
            case ColliderType.Sphere:
                collider = SphereCollider.Create(new SphereGeometry
                {
                    Center = float3.zero,
                    Radius = 0.5f
                });
                break;

            case ColliderType.Triangle:
                collider = PolygonCollider.CreateTriangle(k_TriangleVertices[0], k_TriangleVertices[1], k_TriangleVertices[2]);
                break;

            case ColliderType.Quad:
                collider = PolygonCollider.CreateQuad(k_QuadVertices[0], k_QuadVertices[1], k_QuadVertices[2], k_QuadVertices[3]);
                break;

            case ColliderType.Box:
                collider = BoxCollider.Create(new BoxGeometry
                {
                    Center      = float3.zero,
                    Orientation = quaternion.identity,
                    Size        = new float3(1.0f),
                    BevelRadius = 0.0f
                });
                break;

            case ColliderType.Capsule:
                collider = CapsuleCollider.Create(new CapsuleGeometry
                {
                    Vertex0 = new float3(0, -0.5f, 0),
                    Vertex1 = new float3(0, 0.5f, 0),
                    Radius  = 0.5f
                });
                break;

            case ColliderType.Cylinder:
                // TODO: need someone to add
                throw new NotImplementedException();

            case ColliderType.Convex:
                // Tetrahedron
                NativeArray <float3> points = new NativeArray <float3>(k_TetraherdonVertices, Allocator.TempJob);
                collider = ConvexCollider.Create(points, ConvexHullGenerationParameters.Default, CollisionFilter.Default);
                points.Dispose();
                break;

            case ColliderType.Compound:

                var child1 = SphereCollider.Create(new SphereGeometry
                {
                    Center = float3.zero,
                    Radius = 0.5f
                });
                ChildrenColliders.Add(child1);

                var child2 = BoxCollider.Create(new BoxGeometry
                {
                    Center      = float3.zero,
                    Orientation = quaternion.identity,
                    Size        = new float3(1.0f),
                    BevelRadius = 0.0f
                });
                ChildrenColliders.Add(child2);

                NativeArray <ColliderBlobInstance> childrenBlobs = new NativeArray <ColliderBlobInstance>(2, Allocator.TempJob);
                childrenBlobs[0] = new ColliderBlobInstance
                {
                    Collider          = child1,
                    CompoundFromChild = new RigidTransform
                    {
                        pos = new float3(0.5f, 0, 0),
                        rot = quaternion.identity
                    }
                };

                childrenBlobs[1] = new ColliderBlobInstance
                {
                    Collider          = child2,
                    CompoundFromChild = new RigidTransform
                    {
                        pos = new float3(-0.5f, 0, 0),
                        rot = quaternion.identity
                    }
                };

                ColliderMeshes[0] = SceneCreationUtilities.CreateMeshFromCollider(child1);
                ColliderMeshes[1] = SceneCreationUtilities.CreateMeshFromCollider(child2);

                collider = CompoundCollider.Create(childrenBlobs);
                childrenBlobs.Dispose();
                break;

            case ColliderType.Mesh:
                // Tetrahedron mesh
                NativeArray <float3> meshVertices  = new NativeArray <float3>(k_TetraherdonVertices, Allocator.TempJob);
                NativeArray <int3>   meshTriangles = new NativeArray <int3>(k_TetrahedronMeshTriangles, Allocator.TempJob);

                collider = MeshCollider.Create(meshVertices, meshTriangles);
                meshVertices.Dispose();
                meshTriangles.Dispose();
                break;

            case ColliderType.Terrain:
                int2   size  = 2;
                float3 scale = 1;
                Random rand  = new Random(0x9739);

                int numSamples = size.x * size.y;
                var heights    = new NativeArray <float>(numSamples, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
                for (int i = 0; i < numSamples; i++)
                {
                    heights[i] = rand.NextFloat(0, 1);
                }
                collider = TerrainCollider.Create(heights, size, scale, TerrainCollider.CollisionMethod.VertexSamples);
                heights.Dispose();
                break;

            default:
                throw new System.NotImplementedException();
            }

            if (ColliderType != ColliderType.Compound)
            {
                ColliderMeshes[0] = SceneCreationUtilities.CreateMeshFromCollider(collider);
            }

            return(collider);
        }
Ejemplo n.º 27
0
        public unsafe void CreateCompound_WithRepeatedInputs_ChildrenAreInstances()
        {
            BlobAssetReference <Collider> boxBlob      = default;
            BlobAssetReference <Collider> capsuleBlob  = default;
            BlobAssetReference <Collider> sphereBlob   = default;
            BlobAssetReference <Collider> compoundBlob = default;

            try
            {
                // 3 unique instance inputs
                boxBlob = BoxCollider.Create(new BoxGeometry {
                    Orientation = quaternion.identity, Size = new float3(1)
                });
                capsuleBlob = CapsuleCollider.Create(new CapsuleGeometry {
                    Radius = 0.5f, Vertex0 = new float3(1f), Vertex1 = new float3(-1f)
                });
                sphereBlob = SphereCollider.Create(new SphereGeometry {
                    Radius = 0.5f
                });
                var children = new NativeArray <CompoundCollider.ColliderBlobInstance>(8, Allocator.Temp)
                {
                    [0] = new CompoundCollider.ColliderBlobInstance {
                        Collider = boxBlob, CompoundFromChild = new RigidTransform(quaternion.identity, new float3(0f))
                    },
                    [1] = new CompoundCollider.ColliderBlobInstance {
                        Collider = capsuleBlob, CompoundFromChild = new RigidTransform(quaternion.identity, new float3(1f))
                    },
                    [2] = new CompoundCollider.ColliderBlobInstance {
                        Collider = boxBlob, CompoundFromChild = new RigidTransform(quaternion.identity, new float3(2f))
                    },
                    [3] = new CompoundCollider.ColliderBlobInstance {
                        Collider = sphereBlob, CompoundFromChild = new RigidTransform(quaternion.identity, new float3(3f))
                    },
                    [4] = new CompoundCollider.ColliderBlobInstance {
                        Collider = boxBlob, CompoundFromChild = new RigidTransform(quaternion.identity, new float3(4f))
                    },
                    [5] = new CompoundCollider.ColliderBlobInstance {
                        Collider = capsuleBlob, CompoundFromChild = new RigidTransform(quaternion.identity, new float3(5f))
                    },
                    [6] = new CompoundCollider.ColliderBlobInstance {
                        Collider = boxBlob, CompoundFromChild = new RigidTransform(quaternion.identity, new float3(6f))
                    },
                    [7] = new CompoundCollider.ColliderBlobInstance {
                        Collider = sphereBlob, CompoundFromChild = new RigidTransform(quaternion.identity, new float3(7f))
                    }
                };

                compoundBlob = CompoundCollider.Create(children);

                var compound       = (CompoundCollider *)compoundBlob.GetUnsafePtr();
                var uniqueChildren = new HashSet <long>();
                for (var i = 0; i < compound->Children.Length; i++)
                {
                    uniqueChildren.Add((long)compound->Children[i].Collider);
                }
                Assert.That(uniqueChildren.Count, Is.EqualTo(3));
            }
            finally
            {
                boxBlob.Dispose();
                capsuleBlob.Dispose();
                sphereBlob.Dispose();
                if (compoundBlob.IsCreated)
                {
                    compoundBlob.Dispose();
                }
            }
        }
 public void Execute() => SphereCollider.Create(new SphereGeometry {
     Radius = 1f
 }).Release();
Ejemplo n.º 29
0
        protected override BlobAssetReference <Collider> ProduceColliderBlob(PhysicsShapeAuthoring shape)
        {
            var material        = ProduceMaterial(shape);
            var collisionFilter = ProduceCollisionFilter(shape);

            BlobAssetReference <Collider> blob = default;

            switch (shape.ShapeType)
            {
            case ShapeType.Box:
                blob = BoxCollider.Create(
                    shape.GetBakedBoxProperties(),
                    collisionFilter,
                    material);
                break;

            case ShapeType.Capsule:
                blob = CapsuleCollider.Create(
                    shape.GetBakedCapsuleProperties(out var center, out var height, out var orientation),
                    collisionFilter,
                    material);
                break;

            case ShapeType.Sphere:
                blob = SphereCollider.Create(
                    shape.GetBakedSphereProperties(out orientation),
                    collisionFilter,
                    material);
                break;

            case ShapeType.Cylinder:
                blob = CylinderCollider.Create(
                    shape.GetBakedCylinderProperties(),
                    collisionFilter,
                    material);
                break;

            case ShapeType.Plane:
                shape.GetBakedPlaneProperties(out var v0, out var v1, out var v2, out var v3);
                blob = PolygonCollider.CreateQuad(
                    v0,
                    v1,
                    v2,
                    v3,
                    collisionFilter,
                    material);
                break;

            case ShapeType.ConvexHull:
                var pointCloud = new NativeList <float3>(65535, Allocator.Temp);
                shape.GetConvexHullProperties(pointCloud);
                if (pointCloud.Length == 0)
                {
                    throw new InvalidOperationException(
                              $"No vertices associated with {shape.name}. Add a {typeof(MeshFilter)} component or assign a readable {nameof(PhysicsShapeAuthoring.CustomMesh)}."
                              );
                }
                shape.GetBakedConvexProperties(pointCloud, out var hullGenerationParameters);
                RegisterConvexColliderDeferred(
                    shape, pointCloud, hullGenerationParameters.ToRunTime(), collisionFilter, material
                    );
                pointCloud.Dispose();
                break;

            case ShapeType.Mesh:
                const int defaultVertexCount = 2048;
                pointCloud = new NativeList <float3>(defaultVertexCount, Allocator.Temp);
                var triangles = new NativeList <int>((defaultVertexCount - 2) * 3, Allocator.Temp);
                shape.GetBakedMeshProperties(pointCloud, triangles);

                if (pointCloud.Length == 0 || triangles.Length == 0)
                {
                    triangles.Dispose();
                    pointCloud.Dispose();
                    throw new InvalidOperationException(
                              $"Invalid mesh data associated with {shape.name}. " +
                              $"Add a {typeof(MeshFilter)} component or assign a {nameof(PhysicsShapeAuthoring.CustomMesh)}. " +
                              "Ensure that you have enabled Read/Write on the mesh's import settings."
                              );
                }

                RegisterMeshColliderDeferred(shape, pointCloud, triangles, collisionFilter, material);
                triangles.Dispose();
                pointCloud.Dispose();
                break;

            default:
                throw new UnimplementedShapeException(shape.ShapeType);
            }
            return(blob);
        }
Ejemplo n.º 30
0
        protected unsafe override void OnUpdate()
        {
            PhysicsWorld physicsWorld = _worldBuildSystem.PhysicsWorld;
            NativeMultiHashMap <Entity, HitboxCollision> collisions = _collisions;

            collisions.Clear();
            var collisionWriter = collisions.AsParallelWriter();

            Entities
            .WithName("QueryHitboxCollisons")
            .WithReadOnly(physicsWorld)
            .ForEach((Entity entity, ref Hitbox hitbox, ref HitboxState state, in LocalToWorld transform) => {
                if (!state.Enabled)
                {
                    return;
                }

                BlobAssetReference <Collider> collider =
                    SphereCollider.Create(new SphereGeometry {
                    Center = float3.zero,
                    Radius = hitbox.Radius
                }, new CollisionFilter {
                    BelongsTo    = (uint)PhysicsLayers.HITBOX,
                    CollidesWith = (uint)PhysicsLayers.HITBOX,
                });

                float3 position = math.transform(transform.Value, float3.zero);
                var hits        = new NativeList <ColliderCastHit>(Allocator.Temp);
                physicsWorld.CastCollider(new ColliderCastInput {
                    Collider    = (Collider *)collider.GetUnsafePtr(),
                    Start       = state.PreviousPosition ?? position,
                    End         = position,
                    Orientation = float4.zero
                }, ref hits);
                collider.Dispose();

                state.PreviousPosition = position;

                for (var i = 0; i < hits.Length; i++)
                {
                    var hit = hits[i];
                    if (!HasComponent <Hurtbox>(hit.Entity))
                    {
                        continue;
                    }
                    var hurtbox = GetComponent <Hurtbox>(hit.Entity);
                    if (!hurtbox.Enabled || hurtbox.Player == Entity.Null || hurtbox.Player == state.Player)
                    {
                        continue;
                    }

                    collisionWriter.Add(hurtbox.Player, new HitboxCollision {
                        OriginPlayer = entity,
                        Hitbox       = hitbox,
                        Hurtbox      = hurtbox,
                    });
                }
            }).ScheduleParallel();

            Entities
            .WithName("ApplyCollisions")
            .WithReadOnly(collisions)
            .ForEach((Entity entity, ref PlayerComponent player, in PlayerConfig config, in CharacterFrame frame) => {
                NativeArray <HitboxCollision>?playerCollisions = collisions.CopyValuesForKey(entity);
                if (playerCollisions == null)
                {
                    return;
                }

                // Sort collisions
                playerCollisions.Value.Sort();
            }).Schedule();