static BlobAssetReference <Collider> CreateMeshTerrain(NativeArray <float> heights, int2 size, float3 scale)
    {
        var vertices    = new NativeList <float3>(Allocator.Temp);
        var triangles   = new NativeList <int3>(Allocator.Temp);
        var vertexIndex = 0;

        for (int i = 0; i < size.x - 1; i++)
        {
            for (int j = 0; j < size.y - 1; j++)
            {
                int    i0 = i;
                int    i1 = i + 1;
                int    j0 = j;
                int    j1 = j + 1;
                float3 v0 = new float3(i0, heights[i0 + size.x * j0], j0) * scale;
                float3 v1 = new float3(i1, heights[i1 + size.x * j0], j0) * scale;
                float3 v2 = new float3(i0, heights[i0 + size.x * j1], j1) * scale;
                float3 v3 = new float3(i1, heights[i1 + size.x * j1], j1) * scale;

                vertices.Add(v1);
                vertices.Add(v0);
                vertices.Add(v2);
                vertices.Add(v1);
                vertices.Add(v2);
                vertices.Add(v3);

                triangles.Add(new int3(vertexIndex++, vertexIndex++, vertexIndex++));
                triangles.Add(new int3(vertexIndex++, vertexIndex++, vertexIndex++));
            }
        }

        return(MeshCollider.Create(vertices, triangles));
    }
        protected override BlobAssetReference <Collider> ProduceColliderBlob(LegacyMesh shape)
        {
            if (shape.sharedMesh == null)
            {
                throw new InvalidOperationException(
                          $"No {nameof(LegacyMesh.sharedMesh)} assigned to {typeof(MeshCollider)} on {shape.name}."
                          );
            }

            var filter   = ProduceCollisionFilter(shape);
            var material = ProduceMaterial(shape);

            using (var pointCloud = new NativeList <float3>(shape.sharedMesh.vertexCount, Allocator.Temp))
            {
                // transform points into world space and back into shape space
                shape.sharedMesh.GetVertices(m_Vertices);
                var shapeFromWorld = math.inverse(
                    new float4x4(new RigidTransform(shape.transform.rotation, shape.transform.position))
                    );
                for (int i = 0, count = m_Vertices.Count; i < count; ++i)
                {
                    var worldPt = math.mul(shape.transform.localToWorldMatrix, new float4(m_Vertices[i], 1f));
                    pointCloud.Add(math.mul(shapeFromWorld, worldPt).xyz);
                }

                return(shape.convex
                    ? ConvexCollider.Create(pointCloud, PhysicsShape.k_DefaultConvexRadius, new float3(1f), filter, material)
                    : MeshCollider.Create(pointCloud.ToArray(), shape.sharedMesh.triangles, filter, material));
            }
        }
            public void Execute(int index)
            {
                var inputParameters = InputValues[index];

                var vertices = new NativeArray <float3>(
                    inputParameters.VertexCount, Allocator.Temp, NativeArrayOptions.UninitializedMemory
                    );

                UnsafeUtility.MemCpy(
                    vertices.GetUnsafePtr(),
                    (float3 *)AllVertices.GetUnsafeReadOnlyPtr() + inputParameters.VerticesStart,
                    UnsafeUtility.SizeOf <float3>() * inputParameters.VertexCount
                    );

                var triangles = new NativeArray <int3>(
                    inputParameters.TriangleCount, Allocator.Temp, NativeArrayOptions.UninitializedMemory
                    );

                UnsafeUtility.MemCpy(
                    triangles.GetUnsafePtr(),
                    (int3 *)AllIndices.GetUnsafeReadOnlyPtr() + inputParameters.TrianglesStart,
                    UnsafeUtility.SizeOf <int3>() * inputParameters.TriangleCount
                    );

                Output[index] = new KeyValuePair <Hash128, BlobAssetReference <Collider> >(
                    InputKeys[index],
                    MeshCollider.Create(vertices, triangles, inputParameters.Filter, inputParameters.Material)
                    );
            }
            public unsafe void Execute()
            {
                if (DummyRun)
                {
                    return;
                }

                MeshCollider.Create(Vertices, Indices);
            }
            public void Execute()
            {
                if (DummyRun)
                {
                    return;
                }

                MeshCollider.Create(Vertices, Triangles);
            }
            public void Execute(int index)
            {
                var inputParameters = InputValues[index];

                Output[index] = new KeyValuePair <Hash128, BlobAssetReference <Collider> >(
                    InputKeys[index],
                    MeshCollider.Create(
                        AllVertices.GetSubArray(inputParameters.VerticesStart, inputParameters.VertexCount),
                        AllIndices.GetSubArray(inputParameters.TrianglesStart, inputParameters.TriangleCount),
                        inputParameters.Filter, inputParameters.Material
                        )
                    );
            }
    public static unsafe BlobAssetReference <Collider> Create(float3 *vertices, int *indices, int numVertices, int numIndices, CollisionFilter?filter = null, Material?material = null)
    {
        var v    = new NativeArray <float3>(numVertices, Allocator.Temp);
        var vptr = NativeArrayUnsafeUtility.GetUnsafePtr(v);

        UnsafeUtility.MemCpy(vptr, vertices, numVertices * sizeof(float3));

        var i    = new NativeArray <int>(numIndices, Allocator.Temp);
        var iptr = NativeArrayUnsafeUtility.GetUnsafePtr(i);

        UnsafeUtility.MemCpy(iptr, indices, numIndices * sizeof(int));

        var collider = MeshCollider.Create(v, i);

        v.Dispose();
        i.Dispose();
        return(collider);
    }
Example #8
0
        public void MeshCollider_Create_WhenTriangleIndexOutOfRange_Throws()
        {
            int numTriangles = 10;
            var vertices     = new NativeArray <float3>(numTriangles * 3, Allocator.Persistent);
            var triangles    = new NativeArray <int3>(numTriangles, Allocator.Persistent);

            try
            {
                for (int i = 0; i < numTriangles; i++)
                {
                    int firstVertexIndex = i * 3;

                    vertices[firstVertexIndex]     = new float3(firstVertexIndex, 1f * (firstVertexIndex % 2), firstVertexIndex + 1);
                    vertices[firstVertexIndex + 1] = new float3(firstVertexIndex + 1, 1f * ((firstVertexIndex + 1) % 2), firstVertexIndex + 2);
                    vertices[firstVertexIndex + 2] = new float3(firstVertexIndex + 2, 1f * ((firstVertexIndex + 2) % 2), firstVertexIndex + 3);
                    triangles[i] = new int3(firstVertexIndex, firstVertexIndex + 1, firstVertexIndex + 2);
                }

                Random rnd = new Random(0x12345678);

                for (int i = 0; i < 100; i++)
                {
                    int indexToChange = rnd.NextInt(0, triangles.Length * 3 - 1);

                    int triangleIndex    = indexToChange / 3;
                    int vertexInTriangle = indexToChange % 3;
                    int invalidValue     = rnd.NextInt() * (rnd.NextBool() ? -1 : 1);

                    var triangle = triangles[triangleIndex];
                    triangle[vertexInTriangle] = invalidValue;
                    triangles[triangleIndex]   = triangle;

                    Assert.Throws <ArgumentException>(() => MeshCollider.Create(vertices, triangles));

                    triangle[vertexInTriangle] = indexToChange;
                    triangles[triangleIndex]   = triangle;
                }
            }
            finally
            {
                triangles.Dispose();
                vertices.Dispose();
            }
        }
        public void Execute(int index)
        {
            var inputParameters = InputParameters[index];
            var vertices        = new NativeArray <float3>(
                inputParameters.VertexCount, Allocator.Temp, NativeArrayOptions.UninitializedMemory
                );

            UnsafeUtility.MemCpy(
                vertices.GetUnsafePtr(),
                (float3 *)AllVertices.GetUnsafeReadOnlyPtr() + inputParameters.VerticesStart,
                UnsafeUtility.SizeOf <float3>() * inputParameters.VertexCount
                );
            var indices = new NativeArray <int>(
                inputParameters.IndexCount, Allocator.Temp, NativeArrayOptions.UninitializedMemory
                );

            UnsafeUtility.MemCpy(
                indices.GetUnsafePtr(),
                (int *)AllIndices.GetUnsafeReadOnlyPtr() + inputParameters.IndicesStart,
                UnsafeUtility.SizeOf <int>() * inputParameters.IndexCount
                );
            Output[index] = new KeyValuePair <Entity, LeafShapeData>(
                inputParameters.BodyEntity,
                new LeafShapeData
            {
                LeafEntity           = inputParameters.LeafEntity,
                ColliderBlobInstance = new CompoundCollider.ColliderBlobInstance
                {
                    CompoundFromChild = inputParameters.CompoundFromChild,
                    Collider          = MeshCollider.Create(
                        vertices, indices, inputParameters.Filter, inputParameters.Material
                        )
                }
            }
                );
        }
Example #10
0
        //
        // Random generation
        //

        public static unsafe BlobAssetReference <Collider> GenerateRandomMesh(ref Random rnd)
        {
            int numTriangles = rnd.NextInt(1, 250);

            float3[] vertices  = new float3[numTriangles * 3];
            int[]    indices   = new int[numTriangles * 3];
            int      nextIndex = 0;

            while (numTriangles > 0)
            {
                int featureTriangles = math.min(rnd.NextInt(1, 100), numTriangles);

                int featureType = rnd.NextInt(0, 3);
                switch (featureType)
                {
                case 0:
                {
                    // Soup
                    for (int i = 0; i < featureTriangles; i++)
                    {
                        float size = rnd.NextFloat(0.1f, 2.5f);
                        size *= size;

                        float3 center = rnd.NextFloat3(-10.0f, 10.0f);
                        for (int j = 0; j < 3; j++)
                        {
                            vertices[nextIndex++] = center + rnd.NextFloat3(-size, size);
                        }
                    }
                    break;
                }

                case 1:
                {
                    // Fan
                    float3 center = rnd.NextFloat3(-10.0f, 10.0f);
                    float3 arm    = rnd.NextFloat3Direction() * rnd.NextFloat(0.1f, 1.0f);
                    float3 axis;
                    {
                        float3 unused;
                        Math.CalculatePerpendicularNormalized(math.normalize(arm), out axis, out unused);
                    }
                    float arc = rnd.NextFloat(0.1f, 2.0f * (float)math.PI);
                    arc = math.min(arc, featureTriangles * (float)math.PI / 2.0f);      // avoid degenerate triangles
                    featureTriangles = math.min(featureTriangles, (int)(arc / 0.025f)); // avoid degenerate triangles
                    quaternion q = Unity.Mathematics.quaternion.AxisAngle(axis, arc / numTriangles);
                    for (int i = 0; i < featureTriangles; i++)
                    {
                        vertices[nextIndex++] = center;
                        vertices[nextIndex++] = center + arm;
                        arm = math.mul(q, arm);
                        vertices[nextIndex++] = center + arm;
                    }
                    break;
                }

                case 2:
                {
                    // Strip
                    float3 v0 = rnd.NextFloat3(-10.0f, 10.0f);
                    float3 v1 = v0 + rnd.NextFloat3(-0.5f, 0.5f);
                    float3 dir;
                    {
                        float3 unused;
                        Math.CalculatePerpendicularNormalized(math.normalize(v1 - v0), out dir, out unused);
                    }
                    for (int i = 0; i < featureTriangles; i++)
                    {
                        float3 v2 = v0 + rnd.NextFloat(0.25f, 0.5f) * dir;
                        dir = math.mul(Unity.Mathematics.quaternion.AxisAngle(rnd.NextFloat3Direction(), rnd.NextFloat(0.0f, 0.3f)), dir);

                        vertices[nextIndex++] = v0;
                        vertices[nextIndex++] = v1;
                        vertices[nextIndex++] = v2;

                        v0 = v1;
                        v1 = v2;
                    }
                    break;
                }

                case 3:
                {
                    // Grid
                    int quads = featureTriangles / 2;
                    if (quads == 0)
                    {
                        featureTriangles = 0;     // Too small, try again for a different feature
                        break;
                    }

                    int rows = rnd.NextInt(1, (int)math.sqrt(quads));
                    int cols = quads / rows;
                    quads            = rows * cols;
                    featureTriangles = quads * 2;

                    float3 origin = rnd.NextFloat3(-10.0f, 10.0f);
                    float3 x      = rnd.NextFloat3(-0.5f, 0.5f);
                    float3 y      = rnd.NextFloat3(-0.5f, 0.5f);
                    for (int i = 0; i < rows; i++)
                    {
                        for (int j = 0; j < cols; j++)
                        {
                            vertices[nextIndex++] = origin + x * (i + 0) + y * (j + 0);
                            vertices[nextIndex++] = origin + x * (i + 0) + y * (j + 1);
                            vertices[nextIndex++] = origin + x * (i + 1) + y * (j + 1);

                            vertices[nextIndex++] = origin + x * (i + 0) + y * (j + 0);
                            vertices[nextIndex++] = origin + x * (i + 1) + y * (j + 1);
                            vertices[nextIndex++] = origin + x * (i + 0) + y * (j + 1);
                        }
                    }

                    break;
                }
                }

                numTriangles -= featureTriangles;
            }

            for (int i = 0; i < indices.Length; i++)
            {
                indices[i] = i;
            }

            return(MeshCollider.Create(vertices, indices));
        }
        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);
        }
Example #12
0
 public void Execute() => Output[0] = MeshCollider.Create(Points, Indices);
        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);
        }