inline bool XM_CALLCONV BoundingBox::Intersects()

in Inc/DirectXCollision.inl [1540:1701]


inline bool XM_CALLCONV BoundingBox::Intersects(FXMVECTOR V0, FXMVECTOR V1, FXMVECTOR V2) const noexcept
{
    XMVECTOR Zero = XMVectorZero();

    // Load the box.
    XMVECTOR vCenter = XMLoadFloat3(&Center);
    XMVECTOR vExtents = XMLoadFloat3(&Extents);

    XMVECTOR BoxMin = XMVectorSubtract(vCenter, vExtents);
    XMVECTOR BoxMax = XMVectorAdd(vCenter, vExtents);

    // Test the axes of the box (in effect test the AAB against the minimal AAB
    // around the triangle).
    XMVECTOR TriMin = XMVectorMin(XMVectorMin(V0, V1), V2);
    XMVECTOR TriMax = XMVectorMax(XMVectorMax(V0, V1), V2);

    // for each i in (x, y, z) if a_min(i) > b_max(i) or b_min(i) > a_max(i) then disjoint
    XMVECTOR Disjoint = XMVectorOrInt(XMVectorGreater(TriMin, BoxMax), XMVectorGreater(BoxMin, TriMax));
    if (DirectX::Internal::XMVector3AnyTrue(Disjoint))
        return false;

    // Test the plane of the triangle.
    XMVECTOR Normal = XMVector3Cross(XMVectorSubtract(V1, V0), XMVectorSubtract(V2, V0));
    XMVECTOR Dist = XMVector3Dot(Normal, V0);

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

    // for each i in (x, y, z) if n(i) >= 0 then v_min(i)=b_min(i), v_max(i)=b_max(i)
    // else v_min(i)=b_max(i), v_max(i)=b_min(i)
    XMVECTOR NormalSelect = XMVectorGreater(Normal, Zero);
    XMVECTOR V_Min = XMVectorSelect(BoxMax, BoxMin, NormalSelect);
    XMVECTOR V_Max = XMVectorSelect(BoxMin, BoxMax, NormalSelect);

    // if n dot v_min + d > 0 || n dot v_max + d < 0 then disjoint
    XMVECTOR MinDist = XMVector3Dot(V_Min, Normal);
    XMVECTOR MaxDist = XMVector3Dot(V_Max, Normal);

    XMVECTOR NoIntersection = XMVectorGreater(MinDist, Dist);
    NoIntersection = XMVectorOrInt(NoIntersection, XMVectorLess(MaxDist, Dist));

    // Move the box center to zero to simplify the following tests.
    XMVECTOR TV0 = XMVectorSubtract(V0, vCenter);
    XMVECTOR TV1 = XMVectorSubtract(V1, vCenter);
    XMVECTOR TV2 = XMVectorSubtract(V2, vCenter);

    // Test the edge/edge axes (3*3).
    XMVECTOR e0 = XMVectorSubtract(TV1, TV0);
    XMVECTOR e1 = XMVectorSubtract(TV2, TV1);
    XMVECTOR e2 = XMVectorSubtract(TV0, TV2);

    // Make w zero.
    e0 = XMVectorInsert<0, 0, 0, 0, 1>(e0, Zero);
    e1 = XMVectorInsert<0, 0, 0, 0, 1>(e1, Zero);
    e2 = XMVectorInsert<0, 0, 0, 0, 1>(e2, Zero);

    XMVECTOR Axis;
    XMVECTOR p0, p1, p2;
    XMVECTOR Min, Max;
    XMVECTOR Radius;

    // Axis == (1,0,0) x e0 = (0, -e0.z, e0.y)
    Axis = XMVectorPermute<XM_PERMUTE_0W, XM_PERMUTE_1Z, XM_PERMUTE_0Y, XM_PERMUTE_0X>(e0, XMVectorNegate(e0));
    p0 = XMVector3Dot(TV0, Axis);
    // p1 = XMVector3Dot( V1, Axis ); // p1 = p0;
    p2 = XMVector3Dot(TV2, Axis);
    Min = XMVectorMin(p0, p2);
    Max = XMVectorMax(p0, p2);
    Radius = XMVector3Dot(vExtents, XMVectorAbs(Axis));
    NoIntersection = XMVectorOrInt(NoIntersection, XMVectorGreater(Min, Radius));
    NoIntersection = XMVectorOrInt(NoIntersection, XMVectorLess(Max, XMVectorNegate(Radius)));

    // Axis == (1,0,0) x e1 = (0, -e1.z, e1.y)
    Axis = XMVectorPermute<XM_PERMUTE_0W, XM_PERMUTE_1Z, XM_PERMUTE_0Y, XM_PERMUTE_0X>(e1, XMVectorNegate(e1));
    p0 = XMVector3Dot(TV0, Axis);
    p1 = XMVector3Dot(TV1, Axis);
    // p2 = XMVector3Dot( V2, Axis ); // p2 = p1;
    Min = XMVectorMin(p0, p1);
    Max = XMVectorMax(p0, p1);
    Radius = XMVector3Dot(vExtents, XMVectorAbs(Axis));
    NoIntersection = XMVectorOrInt(NoIntersection, XMVectorGreater(Min, Radius));
    NoIntersection = XMVectorOrInt(NoIntersection, XMVectorLess(Max, XMVectorNegate(Radius)));

    // Axis == (1,0,0) x e2 = (0, -e2.z, e2.y)
    Axis = XMVectorPermute<XM_PERMUTE_0W, XM_PERMUTE_1Z, XM_PERMUTE_0Y, XM_PERMUTE_0X>(e2, XMVectorNegate(e2));
    p0 = XMVector3Dot(TV0, Axis);
    p1 = XMVector3Dot(TV1, Axis);
    // p2 = XMVector3Dot( V2, Axis ); // p2 = p0;
    Min = XMVectorMin(p0, p1);
    Max = XMVectorMax(p0, p1);
    Radius = XMVector3Dot(vExtents, XMVectorAbs(Axis));
    NoIntersection = XMVectorOrInt(NoIntersection, XMVectorGreater(Min, Radius));
    NoIntersection = XMVectorOrInt(NoIntersection, XMVectorLess(Max, XMVectorNegate(Radius)));

    // Axis == (0,1,0) x e0 = (e0.z, 0, -e0.x)
    Axis = XMVectorPermute<XM_PERMUTE_0Z, XM_PERMUTE_0W, XM_PERMUTE_1X, XM_PERMUTE_0Y>(e0, XMVectorNegate(e0));
    p0 = XMVector3Dot(TV0, Axis);
    // p1 = XMVector3Dot( V1, Axis ); // p1 = p0;
    p2 = XMVector3Dot(TV2, Axis);
    Min = XMVectorMin(p0, p2);
    Max = XMVectorMax(p0, p2);
    Radius = XMVector3Dot(vExtents, XMVectorAbs(Axis));
    NoIntersection = XMVectorOrInt(NoIntersection, XMVectorGreater(Min, Radius));
    NoIntersection = XMVectorOrInt(NoIntersection, XMVectorLess(Max, XMVectorNegate(Radius)));

    // Axis == (0,1,0) x e1 = (e1.z, 0, -e1.x)
    Axis = XMVectorPermute<XM_PERMUTE_0Z, XM_PERMUTE_0W, XM_PERMUTE_1X, XM_PERMUTE_0Y>(e1, XMVectorNegate(e1));
    p0 = XMVector3Dot(TV0, Axis);
    p1 = XMVector3Dot(TV1, Axis);
    // p2 = XMVector3Dot( V2, Axis ); // p2 = p1;
    Min = XMVectorMin(p0, p1);
    Max = XMVectorMax(p0, p1);
    Radius = XMVector3Dot(vExtents, XMVectorAbs(Axis));
    NoIntersection = XMVectorOrInt(NoIntersection, XMVectorGreater(Min, Radius));
    NoIntersection = XMVectorOrInt(NoIntersection, XMVectorLess(Max, XMVectorNegate(Radius)));

    // Axis == (0,0,1) x e2 = (e2.z, 0, -e2.x)
    Axis = XMVectorPermute<XM_PERMUTE_0Z, XM_PERMUTE_0W, XM_PERMUTE_1X, XM_PERMUTE_0Y>(e2, XMVectorNegate(e2));
    p0 = XMVector3Dot(TV0, Axis);
    p1 = XMVector3Dot(TV1, Axis);
    // p2 = XMVector3Dot( V2, Axis ); // p2 = p0;
    Min = XMVectorMin(p0, p1);
    Max = XMVectorMax(p0, p1);
    Radius = XMVector3Dot(vExtents, XMVectorAbs(Axis));
    NoIntersection = XMVectorOrInt(NoIntersection, XMVectorGreater(Min, Radius));
    NoIntersection = XMVectorOrInt(NoIntersection, XMVectorLess(Max, XMVectorNegate(Radius)));

    // Axis == (0,0,1) x e0 = (-e0.y, e0.x, 0)
    Axis = XMVectorPermute<XM_PERMUTE_1Y, XM_PERMUTE_0X, XM_PERMUTE_0W, XM_PERMUTE_0Z>(e0, XMVectorNegate(e0));
    p0 = XMVector3Dot(TV0, Axis);
    // p1 = XMVector3Dot( V1, Axis ); // p1 = p0;
    p2 = XMVector3Dot(TV2, Axis);
    Min = XMVectorMin(p0, p2);
    Max = XMVectorMax(p0, p2);
    Radius = XMVector3Dot(vExtents, XMVectorAbs(Axis));
    NoIntersection = XMVectorOrInt(NoIntersection, XMVectorGreater(Min, Radius));
    NoIntersection = XMVectorOrInt(NoIntersection, XMVectorLess(Max, XMVectorNegate(Radius)));

    // Axis == (0,0,1) x e1 = (-e1.y, e1.x, 0)
    Axis = XMVectorPermute<XM_PERMUTE_1Y, XM_PERMUTE_0X, XM_PERMUTE_0W, XM_PERMUTE_0Z>(e1, XMVectorNegate(e1));
    p0 = XMVector3Dot(TV0, Axis);
    p1 = XMVector3Dot(TV1, Axis);
    // p2 = XMVector3Dot( V2, Axis ); // p2 = p1;
    Min = XMVectorMin(p0, p1);
    Max = XMVectorMax(p0, p1);
    Radius = XMVector3Dot(vExtents, XMVectorAbs(Axis));
    NoIntersection = XMVectorOrInt(NoIntersection, XMVectorGreater(Min, Radius));
    NoIntersection = XMVectorOrInt(NoIntersection, XMVectorLess(Max, XMVectorNegate(Radius)));

    // Axis == (0,0,1) x e2 = (-e2.y, e2.x, 0)
    Axis = XMVectorPermute<XM_PERMUTE_1Y, XM_PERMUTE_0X, XM_PERMUTE_0W, XM_PERMUTE_0Z>(e2, XMVectorNegate(e2));
    p0 = XMVector3Dot(TV0, Axis);
    p1 = XMVector3Dot(TV1, Axis);
    // p2 = XMVector3Dot( V2, Axis ); // p2 = p0;
    Min = XMVectorMin(p0, p1);
    Max = XMVectorMax(p0, p1);
    Radius = XMVector3Dot(vExtents, XMVectorAbs(Axis));
    NoIntersection = XMVectorOrInt(NoIntersection, XMVectorGreater(Min, Radius));
    NoIntersection = XMVectorOrInt(NoIntersection, XMVectorLess(Max, XMVectorNegate(Radius)));

    return XMVector4NotEqualInt(NoIntersection, XMVectorTrueInt());
}