Example #1
0
        public unsafe void BuildConvexHull2D()
        {
            // Build circle.
            var       expectedCom = new float3(4, 5, 3);
            const int n           = 1024;
            float3 *  points      = stackalloc float3[n];
            Aabb      domain      = Aabb.Empty;

            for (int i = 0; i < n; ++i)
            {
                float angle = (float)i / n * 2 * (float)math.PI;
                points[i] = expectedCom + new float3(math.cos(angle), math.sin(angle), 0);
                domain.Include(points[i]);
            }
            ConvexHullBuilderStorage builder = new ConvexHullBuilderStorage(8192, Allocator.Temp, domain, 0.0f, ConvexHullBuilder.IntResolution.High);

            for (int i = 0; i < n; ++i)
            {
                builder.Builder.AddPoint(points[i]);
            }
            builder.Builder.UpdateHullMassProperties();
            var massProperties = builder.Builder.HullMassProperties;

            Assert.IsTrue(math.all(math.abs(massProperties.CenterOfMass - expectedCom) < 1e-4f));
            Assert.AreEqual(math.PI, massProperties.SurfaceArea, 1e-4f);
        }
Example #2
0
        //
        // Reference implementations of queries using simple brute-force methods
        //

        static unsafe float RefConvexConvexDistance(ref ConvexHull a, ref ConvexHull b, MTransform aFromB)
        {
            bool success = false;

            if (a.NumVertices + b.NumVertices < 64) // too slow without burst
            {
                // Build the minkowski difference in a-space
                int  maxNumVertices = a.NumVertices * b.NumVertices;
                Aabb aabb           = Aabb.Empty;
                for (int iB = 0; iB < b.NumVertices; iB++)
                {
                    float3 vertexB = Math.Mul(aFromB, b.Vertices[iB]);
                    for (int iA = 0; iA < a.NumVertices; iA++)
                    {
                        float3 vertexA = a.Vertices[iA];
                        aabb.Include(vertexA - vertexB);
                    }
                }
                ConvexHullBuilderStorage diffStorage = new ConvexHullBuilderStorage(maxNumVertices, Allocator.Temp, aabb, 0.0f, ConvexHullBuilder.IntResolution.Low);
                ref ConvexHullBuilder    diff        = ref diffStorage.Builder;
                success = true;
                for (int iB = 0; iB < b.NumVertices; iB++)
                {
                    float3 vertexB = Math.Mul(aFromB, b.Vertices[iB]);
                    for (int iA = 0; iA < a.NumVertices; iA++)
                    {
                        float3 vertexA = a.Vertices[iA];
                        diff.AddPoint(vertexA - vertexB, (uint)(iA | iB << 16));
                    }
                }

                float distance = 0.0f;
                if (success && diff.Dimension == 3)
                {
                    // Find the closest triangle to the origin
                    distance = float.MaxValue;
                    bool penetrating = true;
                    foreach (int t in diff.Triangles.Indices)
                    {
                        ConvexHullBuilder.Triangle triangle = diff.Triangles[t];
                        float3 v0 = diff.Vertices[triangle.GetVertex(0)].Position;
                        float3 v1 = diff.Vertices[triangle.GetVertex(1)].Position;
                        float3 v2 = diff.Vertices[triangle.GetVertex(2)].Position;
                        float3 n  = diff.ComputePlane(t).Normal;
                        DistanceQueries.Result result = DistanceQueries.TriangleSphere(v0, v1, v2, n, float3.zero, 0.0f, MTransform.Identity);
                        if (result.Distance < distance)
                        {
                            distance = result.Distance;
                        }
                        penetrating = penetrating & (math.dot(n, -result.NormalInA) < 0.0f); // only penetrating if inside of all planes
                    }

                    if (penetrating)
                    {
                        distance = -distance;
                    }

                    distance -= a.ConvexRadius + b.ConvexRadius;
                }
                else
                {
                    success = false;
                }

                diffStorage.Dispose();

                if (success)
                {
                    return(distance);
                }
            }