public static void CollideCircles(ref Manifold manifold, CircleShape circle1, XForm xf1, CircleShape circle2, XForm xf2)
        {
            manifold.PointCount = 0;

            Vector2 p1 = CommonMath.Mul(xf1, circle1.GetLocalPosition());
            Vector2 p2 = CommonMath.Mul(xf2, circle2.GetLocalPosition());

            Vector2 d         = p2 - p1;
            float   distSqr   = Vector2.Dot(d, d);
            float   r1        = circle1.GetRadius();
            float   r2        = circle2.GetRadius();
            float   radiusSum = r1 + r2;

            if (distSqr > radiusSum * radiusSum)
            {
                return;
            }

            float separation;

            if (distSqr < Settings.FLT_EPSILON)
            {
                separation      = -radiusSum;
                manifold.Normal = new Vector2(0.0f, 1.0f);
            }
            else
            {
                float dist = CommonMath.Sqrt(distSqr);
                separation = dist - radiusSum;
                float a = 1.0f / dist;
                manifold.Normal.X = a * d.X;
                manifold.Normal.Y = a * d.Y;
            }

            manifold.PointCount           = 1;
            manifold.Points[0].ID.Key     = 0;
            manifold.Points[0].Separation = separation;

            p1 += r1 * manifold.Normal;
            p2 -= r2 * manifold.Normal;

            Vector2 p = 0.5f * (p1 + p2);

            manifold.Points[0].LocalPoint1 = CommonMath.MulT(xf1, p);
            manifold.Points[0].LocalPoint2 = CommonMath.MulT(xf2, p);
        }
        public static float DistanceGeneric <T1, T2>(out Vector2 x1, out Vector2 x2, T1 shape1_, XForm xf1, T2 shape2_, XForm xf2)
        {
            IGenericShape shape1 = shape1_ as IGenericShape;
            IGenericShape shape2 = shape2_ as IGenericShape;

            if (shape1 == null || shape2 == null)
            {
                //Box2DXDebug.Assert(false, "Can not cast some parameters to IGenericShape");
            }

            Vector2[] p1s        = new Vector2[3], p2s = new Vector2[3];
            Vector2[] points     = new Vector2[3];
            int       pointCount = 0;

            x1 = shape1.GetFirstVertex(xf1);
            x2 = shape2.GetFirstVertex(xf2);

            float vSqr          = 0.0f;
            int   maxIterations = 20;

            for (int iter = 0; iter < maxIterations; ++iter)
            {
                Vector2 v  = x2 - x1;
                Vector2 w1 = shape1.Support(xf1, v);
                Vector2 w2 = shape2.Support(xf2, -v);

                vSqr = Vector2.Dot(v, v);
                Vector2 w  = w2 - w1;
                float   vw = Vector2.Dot(v, w);
                if (vSqr - vw <= 0.01f * vSqr || InPoints(w, points, pointCount)) // or w in points
                {
                    if (pointCount == 0)
                    {
                        x1 = w1;
                        x2 = w2;
                    }
                    //GJKIterations = iter;
                    return(CommonMath.Sqrt(vSqr));
                }

                switch (pointCount)
                {
                case 0:
                    p1s[0]    = w1;
                    p2s[0]    = w2;
                    points[0] = w;
                    x1        = p1s[0];
                    x2        = p2s[0];
                    ++pointCount;
                    break;

                case 1:
                    p1s[1]     = w1;
                    p2s[1]     = w2;
                    points[1]  = w;
                    pointCount = ProcessTwo(out x1, out x2, ref p1s, ref p2s, ref points);
                    break;

                case 2:
                    p1s[2]     = w1;
                    p2s[2]     = w2;
                    points[2]  = w;
                    pointCount = ProcessThree(out x1, out x2, ref p1s, ref p2s, ref points);
                    break;
                }

                // If we have three points, then the origin is in the corresponding triangle.
                if (pointCount == 3)
                {
                    //GJKIterations = iter;
                    return(0.0f);
                }

                float maxSqr = -Settings.FLT_MAX;
                for (int i = 0; i < pointCount; ++i)
                {
                    maxSqr = CommonMath.Max(maxSqr, Vector2.Dot(points[i], points[i]));
                }

#if TARGET_FLOAT32_IS_FIXED
                if (pointCount == 3 || vSqr <= 5.0 * Common.Settings.FLT_EPSILON * maxSqr)
#else
                if (vSqr <= 100.0f * Settings.FLT_EPSILON * maxSqr)
#endif
                {
                    //GJKIterations = iter;
                    v    = x2 - x1;
                    vSqr = Vector2.Dot(v, v);

                    return(CommonMath.Sqrt(vSqr));
                }
            }

            //GJKIterations = maxIterations;
            return(CommonMath.Sqrt(vSqr));
        }