コード例 #1
0
        private static bool XenoDetection(
            XenoScan <T> a,
            XenoScan <T> b,
            int maxIterations,
            out Vector <T> point,
            out Vector <T> normal,
            out T penetration)
        {
            point       = null;
            normal      = null;
            penetration = default(T);

            Vector <T> minkowskiDifference = b.Position - a.Position;

            normal = -minkowskiDifference;

            if (NearlyZero(minkowskiDifference.MagnitudeSquared))
            {
                minkowskiDifference = new Vector <T>(
                    Compute.Divide(Constant <T> .One, Compute.Convert <int, T>(100000)),
                    Constant <T> .Zero,
                    Constant <T> .Zero);
            }

            Vector <T> a_xenoScan1 = Quaternion <T> .Rotate(a.Orientation, a.XenoScan(Quaternion <T> .Rotate(a.Orientation, minkowskiDifference)));

            Vector <T> b_xenoScan1 = Quaternion <T> .Rotate(b.Orientation, b.XenoScan(Quaternion <T> .Rotate(b.Orientation, normal)));

            Vector <T> xenoScans1_subtract = b_xenoScan1 - a_xenoScan1;

            if (Compute.LessThanOrEqual(Vector <T> .DotProduct(xenoScans1_subtract, normal), Constant <T> .Zero))
            {
                return(false);
            }

            Vector <T> crossOfXenoAndMD = Vector <T> .CrossProduct(xenoScans1_subtract, minkowskiDifference);

            if (NearlyZero(crossOfXenoAndMD.MagnitudeSquared))
            {
                crossOfXenoAndMD = (xenoScans1_subtract - minkowskiDifference).Normalize();
                point            = (a_xenoScan1 + b_xenoScan1) * Compute.Divide(Constant <T> .One, Constant <T> .Two);
                penetration      = Vector <T> .DotProduct(xenoScans1_subtract, crossOfXenoAndMD);

                return(true);
            }

            Vector <T> a_xenoScan2 = Quaternion <T> .Rotate(a.Orientation, a.XenoScan(Quaternion <T> .Rotate(a.Orientation, -crossOfXenoAndMD)));

            Vector <T> b_xenoScan2 = Quaternion <T> .Rotate(b.Orientation, b.XenoScan(Quaternion <T> .Rotate(b.Orientation, normal)));

            Vector <T> xenoScans2_subtract = b_xenoScan2 - a_xenoScan2;

            if (Compute.LessThanOrEqual(Vector <T> .DotProduct(xenoScans2_subtract, normal), Constant <T> .Zero))
            {
                return(false);
            }

            Vector <T> crossOfXenoScans = Vector <T> .CrossProduct(xenoScans1_subtract - minkowskiDifference, xenoScans2_subtract - minkowskiDifference);

            T distance = Vector <T> .DotProduct(crossOfXenoAndMD, minkowskiDifference);

            if (Compute.LessThan(distance, Constant <T> .Zero))
            {
                Vector <T> temp;

                temp = xenoScans1_subtract;
                xenoScans1_subtract = xenoScans2_subtract;
                xenoScans2_subtract = temp;

                temp        = a_xenoScan1;
                a_xenoScan1 = a_xenoScan2;
                a_xenoScan2 = temp;

                temp        = b_xenoScan1;
                b_xenoScan1 = b_xenoScan2;
                b_xenoScan2 = temp;

                normal = -normal;
            }

            int  phase2 = 0;
            int  phase1 = 0;
            bool hit    = false;

            while (true)
            {
                if (phase1 > maxIterations)
                {
                    return(false);
                }

                phase1++;

                Vector <T> neg_normal = -normal;

                Vector <T> a_xenoScan3 = Quaternion <T> .Rotate(a.Orientation, a.XenoScan(Quaternion <T> .Rotate(a.Orientation, neg_normal)));

                Vector <T> b_xenoScan3 = Quaternion <T> .Rotate(b.Orientation, b.XenoScan(Quaternion <T> .Rotate(b.Orientation, normal)));

                Vector <T> xenoScans3_subtract = b_xenoScan3 - a_xenoScan3;

                if (Compute.LessThan(Vector <T> .DotProduct(xenoScans3_subtract, normal), Constant <T> .Zero))
                {
                    return(false);
                }

                if (Compute.LessThan(Vector <T> .DotProduct(Vector <T> .CrossProduct(xenoScans1_subtract, xenoScans3_subtract), minkowskiDifference), Constant <T> .Zero))
                {
                    xenoScans2_subtract = xenoScans3_subtract;
                    a_xenoScan2         = a_xenoScan3;
                    b_xenoScan2         = b_xenoScan3;
                    normal = Vector <T> .CrossProduct(xenoScans1_subtract - minkowskiDifference, xenoScans3_subtract - minkowskiDifference);

                    continue;
                }

                if (Compute.LessThan(Vector <T> .DotProduct(Vector <T> .CrossProduct(xenoScans3_subtract, xenoScans2_subtract), minkowskiDifference), Constant <T> .Zero))
                {
                    xenoScans1_subtract = xenoScans3_subtract;
                    a_xenoScan1         = a_xenoScan3;
                    b_xenoScan1         = b_xenoScan3;
                    normal = Vector <T> .CrossProduct(xenoScans3_subtract - minkowskiDifference, xenoScans2_subtract - minkowskiDifference);

                    continue;
                }

                while (true)
                {
                    phase2++;

                    normal = Vector <T> .CrossProduct(xenoScans2_subtract - xenoScans1_subtract, xenoScans3_subtract - xenoScans1_subtract);

                    // Ommited because appears to be an error
                    //if (NearlyZero(normal.Magnitude()))
                    //    return true;

                    normal = normal.Normalize();

                    if (!hit && Compute.GreaterThanOrEqual(Vector <T> .DotProduct(normal, xenoScans1_subtract), Constant <T> .Zero))
                    {
                        hit = true;
                    }

                    neg_normal = -normal;

                    Vector <T> a_xenoScan4 = Quaternion <T> .Rotate(a.Orientation, a.XenoScan(Quaternion <T> .Rotate(a.Orientation, neg_normal)));

                    Vector <T> b_xenoScan4 = Quaternion <T> .Rotate(b.Orientation, b.XenoScan(Quaternion <T> .Rotate(b.Orientation, normal)));

                    Vector <T> xenoScans4_subtract = b_xenoScan4 - a_xenoScan4;

                    T delta = Vector <T> .DotProduct(xenoScans4_subtract - xenoScans3_subtract, normal);

                    penetration = Vector <T> .DotProduct(xenoScans4_subtract, normal);

                    // If the boundary is thin enough or the origin is outside the support plane for the newly discovered vertex, then we can terminate
                    if (Compute.LessThanOrEqual(delta, CollideEpsilon) || Compute.LessThanOrEqual(penetration, Constant <T> .Zero) || phase2 > maxIterations)
                    {
                        if (hit)
                        {
                            T b0 = Vector <T> .DotProduct(Vector <T> .CrossProduct(xenoScans1_subtract, xenoScans2_subtract), xenoScans3_subtract);

                            T b1 = Vector <T> .DotProduct(Vector <T> .CrossProduct(xenoScans3_subtract, xenoScans2_subtract), minkowskiDifference);

                            T b2 = Vector <T> .DotProduct(Vector <T> .CrossProduct(minkowskiDifference, xenoScans1_subtract), xenoScans3_subtract);

                            T b3 = Vector <T> .DotProduct(Vector <T> .CrossProduct(xenoScans2_subtract, xenoScans1_subtract), minkowskiDifference);

                            T sum = Compute.Add(b0, b1, b2, b3);

                            if (Compute.LessThanOrEqual(sum, Constant <T> .Zero))
                            {
                                b0 = Constant <T> .Zero;
                                b1 = Vector <T> .DotProduct(Vector <T> .CrossProduct(xenoScans2_subtract, xenoScans3_subtract), normal);

                                b2 = Vector <T> .DotProduct(Vector <T> .CrossProduct(xenoScans3_subtract, xenoScans1_subtract), normal);

                                b3 = Vector <T> .DotProduct(Vector <T> .CrossProduct(xenoScans1_subtract, xenoScans2_subtract), normal);

                                sum = Compute.Add(b0, b1, b2, b3);
                            }

                            T inv = Compute.Divide(Constant <T> .One, sum);

                            point =
                                (a.Position * b0 +
                                 a_xenoScan1 * b1 +
                                 a_xenoScan2 * b2 +
                                 a_xenoScan3 * b3 +

                                 b.Position * b0 +
                                 b_xenoScan1 * b1 +
                                 b_xenoScan2 * b2 +
                                 b_xenoScan3 * b3)
                                * inv;
                        }

                        return(hit);
                    }

                    Vector <T> xeno4CrossMD = Vector <T> .CrossProduct(xenoScans4_subtract, minkowskiDifference);

                    T dot = Vector <T> .DotProduct(xeno4CrossMD, xenoScans1_subtract);

                    if (Compute.GreaterThanOrEqual(dot, Constant <T> .Zero))
                    {
                        dot = Vector <T> .DotProduct(xeno4CrossMD, xenoScans2_subtract);

                        if (Compute.GreaterThanOrEqual(dot, Constant <T> .Zero))
                        {
                            xenoScans1_subtract = xenoScans4_subtract;
                            a_xenoScan1         = a_xenoScan4;
                            b_xenoScan1         = b_xenoScan4;
                        }
                        else
                        {
                            xenoScans3_subtract = xenoScans4_subtract;
                            a_xenoScan3         = a_xenoScan4;
                            b_xenoScan3         = b_xenoScan4;
                        }
                    }
                    else
                    {
                        dot = Vector <T> .DotProduct(xeno4CrossMD, xenoScans3_subtract);

                        if (Compute.GreaterThanOrEqual(dot, Constant <T> .Zero))
                        {
                            xenoScans2_subtract = xenoScans4_subtract;
                            a_xenoScan2         = a_xenoScan4;
                            b_xenoScan2         = b_xenoScan4;
                        }
                        else
                        {
                            xenoScans1_subtract = xenoScans4_subtract;
                            a_xenoScan1         = a_xenoScan4;
                            b_xenoScan1         = b_xenoScan4;
                        }
                    }
                }
            }
        }