inline bool XM_CALLCONV Intersects()

in Inc/DirectXCollision.inl [4445:4724]


        inline bool XM_CALLCONV Intersects(FXMVECTOR A0, FXMVECTOR A1, FXMVECTOR A2, GXMVECTOR B0, HXMVECTOR B1, HXMVECTOR B2) noexcept
    {
        static const XMVECTORU32 SelectY = { { { XM_SELECT_0, XM_SELECT_1, XM_SELECT_0, XM_SELECT_0 } } };
        static const XMVECTORU32 SelectZ = { { { XM_SELECT_0, XM_SELECT_0, XM_SELECT_1, XM_SELECT_0 } } };
        static const XMVECTORU32 Select0111 = { { { XM_SELECT_0, XM_SELECT_1, XM_SELECT_1, XM_SELECT_1 } } };
        static const XMVECTORU32 Select1011 = { { { XM_SELECT_1, XM_SELECT_0, XM_SELECT_1, XM_SELECT_1 } } };
        static const XMVECTORU32 Select1101 = { { { XM_SELECT_1, XM_SELECT_1, XM_SELECT_0, XM_SELECT_1 } } };

        XMVECTOR Zero = XMVectorZero();

        // Compute the normal of triangle A.
        XMVECTOR N1 = XMVector3Cross(XMVectorSubtract(A1, A0), XMVectorSubtract(A2, A0));

        // Assert that the triangle is not degenerate.
        assert(!XMVector3Equal(N1, Zero));

        // Test points of B against the plane of A.
        XMVECTOR BDist = XMVector3Dot(N1, XMVectorSubtract(B0, A0));
        BDist = XMVectorSelect(BDist, XMVector3Dot(N1, XMVectorSubtract(B1, A0)), SelectY);
        BDist = XMVectorSelect(BDist, XMVector3Dot(N1, XMVectorSubtract(B2, A0)), SelectZ);

        // Ensure robustness with co-planar triangles by zeroing small distances.
        uint32_t BDistIsZeroCR;
        XMVECTOR BDistIsZero = XMVectorGreaterR(&BDistIsZeroCR, g_RayEpsilon, XMVectorAbs(BDist));
        BDist = XMVectorSelect(BDist, Zero, BDistIsZero);

        uint32_t BDistIsLessCR;
        XMVECTOR BDistIsLess = XMVectorGreaterR(&BDistIsLessCR, Zero, BDist);

        uint32_t BDistIsGreaterCR;
        XMVECTOR BDistIsGreater = XMVectorGreaterR(&BDistIsGreaterCR, BDist, Zero);

        // If all the points are on the same side we don't intersect.
        if (XMComparisonAllTrue(BDistIsLessCR) || XMComparisonAllTrue(BDistIsGreaterCR))
            return false;

        // Compute the normal of triangle B.
        XMVECTOR N2 = XMVector3Cross(XMVectorSubtract(B1, B0), XMVectorSubtract(B2, B0));

        // Assert that the triangle is not degenerate.
        assert(!XMVector3Equal(N2, Zero));

        // Test points of A against the plane of B.
        XMVECTOR ADist = XMVector3Dot(N2, XMVectorSubtract(A0, B0));
        ADist = XMVectorSelect(ADist, XMVector3Dot(N2, XMVectorSubtract(A1, B0)), SelectY);
        ADist = XMVectorSelect(ADist, XMVector3Dot(N2, XMVectorSubtract(A2, B0)), SelectZ);

        // Ensure robustness with co-planar triangles by zeroing small distances.
        uint32_t ADistIsZeroCR;
        XMVECTOR ADistIsZero = XMVectorGreaterR(&ADistIsZeroCR, g_RayEpsilon, XMVectorAbs(BDist));
        ADist = XMVectorSelect(ADist, Zero, ADistIsZero);

        uint32_t ADistIsLessCR;
        XMVECTOR ADistIsLess = XMVectorGreaterR(&ADistIsLessCR, Zero, ADist);

        uint32_t ADistIsGreaterCR;
        XMVECTOR ADistIsGreater = XMVectorGreaterR(&ADistIsGreaterCR, ADist, Zero);

        // If all the points are on the same side we don't intersect.
        if (XMComparisonAllTrue(ADistIsLessCR) || XMComparisonAllTrue(ADistIsGreaterCR))
            return false;

        // Special case for co-planar triangles.
        if (XMComparisonAllTrue(ADistIsZeroCR) || XMComparisonAllTrue(BDistIsZeroCR))
        {
            XMVECTOR Axis, Dist, MinDist;

            // Compute an axis perpindicular to the edge (points out).
            Axis = XMVector3Cross(N1, XMVectorSubtract(A1, A0));
            Dist = XMVector3Dot(Axis, A0);

            // Test points of B against the axis.
            MinDist = XMVector3Dot(B0, Axis);
            MinDist = XMVectorMin(MinDist, XMVector3Dot(B1, Axis));
            MinDist = XMVectorMin(MinDist, XMVector3Dot(B2, Axis));
            if (XMVector4GreaterOrEqual(MinDist, Dist))
                return false;

            // Edge (A1, A2)
            Axis = XMVector3Cross(N1, XMVectorSubtract(A2, A1));
            Dist = XMVector3Dot(Axis, A1);

            MinDist = XMVector3Dot(B0, Axis);
            MinDist = XMVectorMin(MinDist, XMVector3Dot(B1, Axis));
            MinDist = XMVectorMin(MinDist, XMVector3Dot(B2, Axis));
            if (XMVector4GreaterOrEqual(MinDist, Dist))
                return false;

            // Edge (A2, A0)
            Axis = XMVector3Cross(N1, XMVectorSubtract(A0, A2));
            Dist = XMVector3Dot(Axis, A2);

            MinDist = XMVector3Dot(B0, Axis);
            MinDist = XMVectorMin(MinDist, XMVector3Dot(B1, Axis));
            MinDist = XMVectorMin(MinDist, XMVector3Dot(B2, Axis));
            if (XMVector4GreaterOrEqual(MinDist, Dist))
                return false;

            // Edge (B0, B1)
            Axis = XMVector3Cross(N2, XMVectorSubtract(B1, B0));
            Dist = XMVector3Dot(Axis, B0);

            MinDist = XMVector3Dot(A0, Axis);
            MinDist = XMVectorMin(MinDist, XMVector3Dot(A1, Axis));
            MinDist = XMVectorMin(MinDist, XMVector3Dot(A2, Axis));
            if (XMVector4GreaterOrEqual(MinDist, Dist))
                return false;

            // Edge (B1, B2)
            Axis = XMVector3Cross(N2, XMVectorSubtract(B2, B1));
            Dist = XMVector3Dot(Axis, B1);

            MinDist = XMVector3Dot(A0, Axis);
            MinDist = XMVectorMin(MinDist, XMVector3Dot(A1, Axis));
            MinDist = XMVectorMin(MinDist, XMVector3Dot(A2, Axis));
            if (XMVector4GreaterOrEqual(MinDist, Dist))
                return false;

            // Edge (B2,B0)
            Axis = XMVector3Cross(N2, XMVectorSubtract(B0, B2));
            Dist = XMVector3Dot(Axis, B2);

            MinDist = XMVector3Dot(A0, Axis);
            MinDist = XMVectorMin(MinDist, XMVector3Dot(A1, Axis));
            MinDist = XMVectorMin(MinDist, XMVector3Dot(A2, Axis));
            if (XMVector4GreaterOrEqual(MinDist, Dist))
                return false;

            return true;
        }

        //
        // Find the single vertex of A and B (ie the vertex on the opposite side
        // of the plane from the other two) and reorder the edges so we can compute
        // the signed edge/edge distances.
        //
        // if ( (V0 >= 0 && V1 <  0 && V2 <  0) ||
        //      (V0 >  0 && V1 <= 0 && V2 <= 0) ||
        //      (V0 <= 0 && V1 >  0 && V2 >  0) ||
        //      (V0 <  0 && V1 >= 0 && V2 >= 0) ) then V0 is singular;
        //
        // If our singular vertex is not on the positive side of the plane we reverse
        // the triangle winding so that the overlap comparisons will compare the
        // correct edges with the correct signs.
        //
        XMVECTOR ADistIsLessEqual = XMVectorOrInt(ADistIsLess, ADistIsZero);
        XMVECTOR ADistIsGreaterEqual = XMVectorOrInt(ADistIsGreater, ADistIsZero);

        XMVECTOR AA0, AA1, AA2;
        bool bPositiveA;

        if (DirectX::Internal::XMVector3AllTrue(XMVectorSelect(ADistIsGreaterEqual, ADistIsLess, Select0111)) ||
            DirectX::Internal::XMVector3AllTrue(XMVectorSelect(ADistIsGreater, ADistIsLessEqual, Select0111)))
        {
            // A0 is singular, crossing from positive to negative.
            AA0 = A0; AA1 = A1; AA2 = A2;
            bPositiveA = true;
        }
        else if (DirectX::Internal::XMVector3AllTrue(XMVectorSelect(ADistIsLessEqual, ADistIsGreater, Select0111)) ||
            DirectX::Internal::XMVector3AllTrue(XMVectorSelect(ADistIsLess, ADistIsGreaterEqual, Select0111)))
        {
            // A0 is singular, crossing from negative to positive.
            AA0 = A0; AA1 = A2; AA2 = A1;
            bPositiveA = false;
        }
        else if (DirectX::Internal::XMVector3AllTrue(XMVectorSelect(ADistIsGreaterEqual, ADistIsLess, Select1011)) ||
            DirectX::Internal::XMVector3AllTrue(XMVectorSelect(ADistIsGreater, ADistIsLessEqual, Select1011)))
        {
            // A1 is singular, crossing from positive to negative.
            AA0 = A1; AA1 = A2; AA2 = A0;
            bPositiveA = true;
        }
        else if (DirectX::Internal::XMVector3AllTrue(XMVectorSelect(ADistIsLessEqual, ADistIsGreater, Select1011)) ||
            DirectX::Internal::XMVector3AllTrue(XMVectorSelect(ADistIsLess, ADistIsGreaterEqual, Select1011)))
        {
            // A1 is singular, crossing from negative to positive.
            AA0 = A1; AA1 = A0; AA2 = A2;
            bPositiveA = false;
        }
        else if (DirectX::Internal::XMVector3AllTrue(XMVectorSelect(ADistIsGreaterEqual, ADistIsLess, Select1101)) ||
            DirectX::Internal::XMVector3AllTrue(XMVectorSelect(ADistIsGreater, ADistIsLessEqual, Select1101)))
        {
            // A2 is singular, crossing from positive to negative.
            AA0 = A2; AA1 = A0; AA2 = A1;
            bPositiveA = true;
        }
        else if (DirectX::Internal::XMVector3AllTrue(XMVectorSelect(ADistIsLessEqual, ADistIsGreater, Select1101)) ||
            DirectX::Internal::XMVector3AllTrue(XMVectorSelect(ADistIsLess, ADistIsGreaterEqual, Select1101)))
        {
            // A2 is singular, crossing from negative to positive.
            AA0 = A2; AA1 = A1; AA2 = A0;
            bPositiveA = false;
        }
        else
        {
            assert(false);
            return false;
        }

        XMVECTOR BDistIsLessEqual = XMVectorOrInt(BDistIsLess, BDistIsZero);
        XMVECTOR BDistIsGreaterEqual = XMVectorOrInt(BDistIsGreater, BDistIsZero);

        XMVECTOR BB0, BB1, BB2;
        bool bPositiveB;

        if (DirectX::Internal::XMVector3AllTrue(XMVectorSelect(BDistIsGreaterEqual, BDistIsLess, Select0111)) ||
            DirectX::Internal::XMVector3AllTrue(XMVectorSelect(BDistIsGreater, BDistIsLessEqual, Select0111)))
        {
            // B0 is singular, crossing from positive to negative.
            BB0 = B0; BB1 = B1; BB2 = B2;
            bPositiveB = true;
        }
        else if (DirectX::Internal::XMVector3AllTrue(XMVectorSelect(BDistIsLessEqual, BDistIsGreater, Select0111)) ||
            DirectX::Internal::XMVector3AllTrue(XMVectorSelect(BDistIsLess, BDistIsGreaterEqual, Select0111)))
        {
            // B0 is singular, crossing from negative to positive.
            BB0 = B0; BB1 = B2; BB2 = B1;
            bPositiveB = false;
        }
        else if (DirectX::Internal::XMVector3AllTrue(XMVectorSelect(BDistIsGreaterEqual, BDistIsLess, Select1011)) ||
            DirectX::Internal::XMVector3AllTrue(XMVectorSelect(BDistIsGreater, BDistIsLessEqual, Select1011)))
        {
            // B1 is singular, crossing from positive to negative.
            BB0 = B1; BB1 = B2; BB2 = B0;
            bPositiveB = true;
        }
        else if (DirectX::Internal::XMVector3AllTrue(XMVectorSelect(BDistIsLessEqual, BDistIsGreater, Select1011)) ||
            DirectX::Internal::XMVector3AllTrue(XMVectorSelect(BDistIsLess, BDistIsGreaterEqual, Select1011)))
        {
            // B1 is singular, crossing from negative to positive.
            BB0 = B1; BB1 = B0; BB2 = B2;
            bPositiveB = false;
        }
        else if (DirectX::Internal::XMVector3AllTrue(XMVectorSelect(BDistIsGreaterEqual, BDistIsLess, Select1101)) ||
            DirectX::Internal::XMVector3AllTrue(XMVectorSelect(BDistIsGreater, BDistIsLessEqual, Select1101)))
        {
            // B2 is singular, crossing from positive to negative.
            BB0 = B2; BB1 = B0; BB2 = B1;
            bPositiveB = true;
        }
        else if (DirectX::Internal::XMVector3AllTrue(XMVectorSelect(BDistIsLessEqual, BDistIsGreater, Select1101)) ||
            DirectX::Internal::XMVector3AllTrue(XMVectorSelect(BDistIsLess, BDistIsGreaterEqual, Select1101)))
        {
            // B2 is singular, crossing from negative to positive.
            BB0 = B2; BB1 = B1; BB2 = B0;
            bPositiveB = false;
        }
        else
        {
            assert(false);
            return false;
        }

        XMVECTOR Delta0, Delta1;

        // Reverse the direction of the test depending on whether the singular vertices are
        // the same sign or different signs.
        if (bPositiveA ^ bPositiveB)
        {
            Delta0 = XMVectorSubtract(BB0, AA0);
            Delta1 = XMVectorSubtract(AA0, BB0);
        }
        else
        {
            Delta0 = XMVectorSubtract(AA0, BB0);
            Delta1 = XMVectorSubtract(BB0, AA0);
        }

        // Check if the triangles overlap on the line of intersection between the
        // planes of the two triangles by finding the signed line distances.
        XMVECTOR Dist0 = XMVector3Dot(Delta0, XMVector3Cross(XMVectorSubtract(BB2, BB0), XMVectorSubtract(AA2, AA0)));
        if (XMVector4Greater(Dist0, Zero))
            return false;

        XMVECTOR Dist1 = XMVector3Dot(Delta1, XMVector3Cross(XMVectorSubtract(BB1, BB0), XMVectorSubtract(AA1, AA0)));
        if (XMVector4Greater(Dist1, Zero))
            return false;

        return true;
    }