Пример #1
0
        //
        // Reference implementations of queries using simple brute-force methods
        //

        static unsafe float RefConvexConvexDistance(ref ConvexHull a, ref ConvexHull b, MTransform aFromB)
        {
            // Build the minkowski difference in a-space
            int maxNumVertices     = a.NumVertices * b.NumVertices;
            ConvexHullBuilder diff = new ConvexHullBuilder(maxNumVertices, 2 * maxNumVertices, Allocator.Temp);
            bool success           = true;
            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);
                }
            }
            diff.IntegerSpaceAabb = aabb;
            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];
                    if (!diff.AddPoint(vertexA - vertexB, (uint)(iA | iB << 16)))
                    {
                        // TODO - coplanar vertices are tripping up ConvexHullBuilder, we should fix it but for now fall back to DistanceQueries.ConvexConvex()
                        success = false;
                    }
                }
            }

            float distance;

            if (!success || diff.Triangles.GetFirstIndex() == -1)
            {
                // No triangles unless the difference is 3D, fall back to GJK
                // Most of the time this happens for cases like sphere-sphere, capsule-capsule, etc. which have special implementations,
                // so comparing those to GJK still validates the results of different API queries against each other.
                distance = DistanceQueries.ConvexConvex(ref a, ref b, aFromB).Distance;
            }
            else
            {
                // Find the closest triangle to the origin
                distance = float.MaxValue;
                bool penetrating = true;
                for (int t = diff.Triangles.GetFirstIndex(); t != -1; t = diff.Triangles.GetNextIndex(t))
                {
                    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;
            }

            diff.Dispose();
            return(distance);
        }