Exemplo n.º 1
0
        public void TestCalculateAabbTransformedTriangle()
        {
            float3[] vertices =
            {
                new float3(-1.8f, 2.4f, 4.6f),
                new float3(1.4f,  1.6f, 1.6f),
                new float3(0.2f,  1.2f, 3.6f)
            };

            float3     translation = new float3(3.4f, 2.5f, -1.1f);
            quaternion rotation    = quaternion.AxisAngle(math.normalize(new float3(1.1f, 10.1f, -3.4f)), 78.0f);

            var  collider = PolygonCollider.CreateTriangle(vertices[0], vertices[1], vertices[2]);
            Aabb aabb     = collider.Value.CalculateAabb(new RigidTransform(rotation, translation));

            for (int i = 0; i < 3; ++i)
            {
                vertices[i] = translation + math.mul(rotation, vertices[i]);
            }

            Aabb expected = new Aabb()
            {
                Min = math.min(math.min(vertices[0], vertices[1]), vertices[2]),
                Max = math.max(math.max(vertices[0], vertices[1]), vertices[2])
            };

            TestUtils.AreEqual(expected.Min, aabb.Min, 1e-3f);
            TestUtils.AreEqual(expected.Max, aabb.Max, 1e-3f);
        }
Exemplo n.º 2
0
        unsafe public void TestCreateTriangle()
        {
            float3[] vertices =
            {
                new float3(-1.4f, 1.4f, 5.6f),
                new float3(1.4f,  1.4f, 3.6f),
                new float3(0.2f,  1.2f, 5.6f)
            };
            float3 normal = math.normalize(math.cross(vertices[1] - vertices[0], vertices[2] - vertices[0]));

            var collider         = PolygonCollider.CreateTriangle(vertices[0], vertices[1], vertices[2]);
            var triangleCollider = UnsafeUtility.AsRef <PolygonCollider>(collider.GetUnsafePtr());

            Assert.IsTrue(triangleCollider.IsTriangle);
            Assert.IsFalse(triangleCollider.IsQuad);

            TestUtils.AreEqual(triangleCollider.Vertices[0], vertices[0], 1e-3f);
            TestUtils.AreEqual(triangleCollider.Vertices[1], vertices[1], 1e-3f);
            TestUtils.AreEqual(triangleCollider.Vertices[2], vertices[2], 1e-3f);
            Assert.AreEqual(2, triangleCollider.Planes.Length);
            TestUtils.AreEqual(normal, triangleCollider.Planes[0].Normal, 1e-3f);
            TestUtils.AreEqual(-normal, triangleCollider.Planes[1].Normal, 1e-3f);
            Assert.AreEqual(ColliderType.Triangle, triangleCollider.Type);
            Assert.AreEqual(CollisionType.Convex, triangleCollider.CollisionType);
        }
Exemplo n.º 3
0
        //[Test] // #TODO: Add test back in once we have implemented this in Physics
        unsafe public void TestMassPropertiesTriangle()
        {
            // constructing the triangle to be parallel to the xy plane so we don't have to figure out the transformations first
            float3[] vertices =
            {
                new float3(-1.1f, -0.4f, 0.0f),
                new float3(0.8f,  -0.1f, 0.0f),
                new float3(-0.2f,  1.3f, 0.0f)
            };

            var collider = PolygonCollider.CreateTriangle(vertices[0], vertices[1], vertices[2]);

            float3 inertiaTensor         = collider.Value.MassProperties.MassDistribution.InertiaTensor;
            float3 expectedInertiaTensor = calcTriangleInertiaTensor(vertices[0], vertices[1], vertices[2]);

            TestUtils.AreEqual(expectedInertiaTensor, inertiaTensor, 1e-3f);
        }
Exemplo n.º 4
0
        public void TestCalculateAabbLocalTriangle()
        {
            float3[] vertices =
            {
                new float3(-1.8f, 2.4f, 4.6f),
                new float3(1.4f,  1.6f, 1.6f),
                new float3(0.2f,  1.2f, 3.6f)
            };

            var  collider = PolygonCollider.CreateTriangle(vertices[0], vertices[1], vertices[2]);
            Aabb aabb     = collider.Value.CalculateAabb();

            Aabb expected = new Aabb()
            {
                Min = math.min(math.min(vertices[0], vertices[1]), vertices[2]),
                Max = math.max(math.max(vertices[0], vertices[1]), vertices[2])
            };

            TestUtils.AreEqual(expected.Min, aabb.Min, 1e-3f);
            TestUtils.AreEqual(expected.Max, aabb.Max, 1e-3f);
        }
Exemplo n.º 5
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();
            }
        }
Exemplo n.º 6
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();
            }
        }
Exemplo n.º 7
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();
            }
        }
Exemplo n.º 8
0
 public void Execute() =>
 PolygonCollider.CreateTriangle(new float3(-1f, 1f, 0f), new float3(1f, 1f, 0f), new float3(1f, -1f, 0f)).Dispose();
Exemplo n.º 9
0
        public void TestCreateInvalid()
        {
            // +inf vertex
            {
                float3[] vertices =
                {
                    new float3(-4.5f, float.PositiveInfinity, 1.0f),
                    new float3(3.4f,                    2.7f, 1.0f),
                    new float3(3.4f,                    0.7f, 1.0f),
                    new float3(-3.4f,                   1.2f, 1.1f)
                };
                TestUtils.ThrowsException <System.ArgumentException>(
                    () => PolygonCollider.CreateTriangle(vertices[0], vertices[1], vertices[2])
                    );
                TestUtils.ThrowsException <System.ArgumentException>(
                    () => PolygonCollider.CreateQuad(vertices[0], vertices[1], vertices[2], vertices[3])
                    );
            }

            // -inf vertex
            {
                float3[] vertices =
                {
                    new float3(-4.5f, float.NegativeInfinity, 1.0f),
                    new float3(3.4f,                    2.7f, 1.0f),
                    new float3(3.4f,                    0.7f, 1.0f),
                    new float3(-3.4f,                   1.2f, 1.1f)
                };
                TestUtils.ThrowsException <System.ArgumentException>(
                    () => PolygonCollider.CreateTriangle(vertices[0], vertices[1], vertices[2])
                    );
                TestUtils.ThrowsException <System.ArgumentException>(
                    () => PolygonCollider.CreateQuad(vertices[0], vertices[1], vertices[2], vertices[3])
                    );
            }

            // nan vertex
            {
                float3[] vertices =
                {
                    new float3(-4.5f, float.NaN, 1.0f),
                    new float3(3.4f,       2.7f, 1.0f),
                    new float3(3.4f,       0.7f, 1.0f),
                    new float3(-3.4f,      1.2f, 1.1f)
                };
                TestUtils.ThrowsException <System.ArgumentException>(
                    () => PolygonCollider.CreateTriangle(vertices[0], vertices[1], vertices[2])
                    );
                TestUtils.ThrowsException <System.ArgumentException>(
                    () => PolygonCollider.CreateQuad(vertices[0], vertices[1], vertices[2], vertices[3])
                    );
            }

            // non-planar quad
            {
                float3[] nonPlanarQuad =
                {
                    new float3(-4.5f, 0.0f, 1.0f),
                    new float3(3.4f,  0.7f, 1.0f),
                    new float3(3.4f,  2.7f, 1.0f),
                    new float3(-3.4f, 1.2f, 1.1f)
                };
                TestUtils.ThrowsException <System.ArgumentException>(
                    () => PolygonCollider.CreateQuad(nonPlanarQuad[0], nonPlanarQuad[1], nonPlanarQuad[2], nonPlanarQuad[3])
                    );
            }

            // non-planar quad unsorted
            {
                float3[] nonPlanarQuad =
                {
                    new float3(-4.5f, -0.30f, 1.0f),
                    new float3(3.4f,    2.7f, 1.0f),
                    new float3(3.4f,   -0.7f, 1.0f),
                    new float3(-3.4f,   1.2f, 1.1f)
                };
                TestUtils.ThrowsException <System.ArgumentException>(
                    () => PolygonCollider.CreateQuad(nonPlanarQuad[0], nonPlanarQuad[1], nonPlanarQuad[2], nonPlanarQuad[3])
                    );
            }
        }
        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);
        }