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); }
// // 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); } }