⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wmlintrtri2tri2.cpp

📁 3D Game Engine Design Source Code非常棒
💻 CPP
📖 第 1 页 / 共 2 页
字号:
        else  // d1 < d0 < d2
        {
            m_eMap = M11;
            m_aiIndex[0] = 1;
            m_aiIndex[1] = 0;
            m_aiIndex[2] = 2;
            m_fMin = fD1;
            m_fMax = fD2;
        }
    }
}
//----------------------------------------------------------------------------
template <class Real>
bool _Configuration<Real>::NoIntersect (const _Configuration& rkCfg0,
    const _Configuration& rkCfg1, Real fTMax, Real fSpeed, int& riSide,
    _Configuration& rkTCfg0, _Configuration& rkTCfg1, Real& rfTFirst,
    Real& rfTLast)
{
    Real fInvSpeed, fT;

    if ( rkCfg1.m_fMax < rkCfg0.m_fMin )
    {
        // V1-interval initially on left of V0-interval
        if ( fSpeed <= (Real)0.0 )
            return true;  // intervals moving apart

        // update first time
        fInvSpeed = ((Real)1.0)/fSpeed;
        fT = (rkCfg0.m_fMin - rkCfg1.m_fMax)*fInvSpeed;
        if ( fT > rfTFirst )
        {
            rfTFirst = fT;
            riSide = -1;
            rkTCfg0 = rkCfg0;
            rkTCfg1 = rkCfg1;
        }

        // test for exceedance of time interval
        if ( rfTFirst > fTMax )
            return true;

        // update last time
        fT = (rkCfg0.m_fMax - rkCfg1.m_fMin)*fInvSpeed;
        if ( fT < rfTLast )
            rfTLast = fT;

        // test for separation
        if ( rfTFirst > rfTLast )
            return true;
    }
    else if ( rkCfg0.m_fMax < rkCfg1.m_fMin )
    {
        // V1-interval initially on right of V0-interval
        if ( fSpeed >= (Real)0.0 )
            return true;  // intervals moving apart

        // update first time
        fInvSpeed = ((Real)1.0)/fSpeed;
        fT = (rkCfg0.m_fMax - rkCfg1.m_fMin)*fInvSpeed;
        if ( fT > rfTFirst )
        {
            rfTFirst = fT;
            riSide = 1;
            rkTCfg0 = rkCfg0;
            rkTCfg1 = rkCfg1;
        }

        // test for exceedance of time interval
        if ( rfTFirst > fTMax )
            return true;

        // update last time
        fT = (rkCfg0.m_fMin - rkCfg1.m_fMax)*fInvSpeed;
        if ( fT < rfTLast )
            rfTLast = fT;

        // test for separation
        if ( rfTFirst > rfTLast )
            return true;
    }
    else
    {
        // V0-interval and V1-interval initially overlap
        if ( fSpeed > (Real)0.0 )
        {
            // update last time
            fInvSpeed = ((Real)1.0)/fSpeed;
            fT = (rkCfg0.m_fMax - rkCfg1.m_fMin)*fInvSpeed;
            if ( fT < rfTLast )
                rfTLast = fT;

            // test for separation
            if ( rfTFirst > rfTLast )
                return true;
        }
        else if ( fSpeed < (Real)0.0 )
        {
            // update last time
            fInvSpeed = ((Real)1.0)/fSpeed;
            fT = (rkCfg0.m_fMin - rkCfg1.m_fMax)*fInvSpeed;
            if ( fT < rfTLast )
                rfTLast = fT;

            // test for separation
            if ( rfTFirst > rfTLast )
                return true;
        }
    }

    return false;
}
//----------------------------------------------------------------------------
template <class Real>
void _Configuration<Real>::GetIntersection (const _Configuration& rkCfg0,
    const _Configuration& rkCfg1, int iSide, const Vector2<Real> akV0[3],
    const Vector2<Real> akV1[3], int& riQuantity, Vector2<Real> akVertex[6])
{
    Vector2<Real> kEdge, kDiff;
    const Vector2<Real>* pkOrigin;
    Real fInvEdE, fMin, fMax, afInterval[2];
    int i;

    if ( iSide == 1 )  // V1-interval contacts V0-interval on right
    {
        if ( rkCfg0.m_eMap == M21 || rkCfg0.m_eMap == M11 )
        {
            riQuantity = 1;
            akVertex[0] = akV0[rkCfg0.m_aiIndex[2]];
        }
        else if ( rkCfg1.m_eMap == M12 || rkCfg1.m_eMap == M11 )
        {
            riQuantity = 1;
            akVertex[0] = akV1[rkCfg1.m_aiIndex[0]];
        }
        else  // rkCfg0.m_eMap == M12 && rkCfg1.m_eMap == M21 (edge overlap)
        {
            pkOrigin = &akV0[rkCfg0.m_aiIndex[1]];
            kEdge = akV0[rkCfg0.m_aiIndex[2]] - *pkOrigin;
            fInvEdE = ((Real)1.0)/kEdge.Dot(kEdge);
            kDiff = akV1[rkCfg1.m_aiIndex[1]] - *pkOrigin;
            fMin = kEdge.Dot(kDiff)*fInvEdE;
            kDiff = akV1[rkCfg1.m_aiIndex[0]] - *pkOrigin;
            fMax = kEdge.Dot(kDiff)*fInvEdE;
            assert( fMin <= fMax );
            riQuantity = FindIntersection((Real)0.0,(Real)1.0,fMin,fMax,
                afInterval[0],afInterval[1]);
            assert( riQuantity > 0 );
            for (i = 0; i < riQuantity; i++)
                akVertex[i] = *pkOrigin + afInterval[i]*kEdge;
        }
    }
    else if ( iSide == -1 )  // V1-interval contacts V0-interval on left
    {
        if ( rkCfg1.m_eMap == M21 || rkCfg1.m_eMap == M11 )
        {
            riQuantity = 1;
            akVertex[0] = akV1[rkCfg1.m_aiIndex[2]];
        }
        else if ( rkCfg0.m_eMap == M12 || rkCfg0.m_eMap == M11 )
        {
            riQuantity = 1;
            akVertex[0] = akV0[rkCfg0.m_aiIndex[0]];
        }
        else  // rkCfg1.m_eMap == M12 && rkCfg0.m_eMap == M21 (edge overlap)
        {
            pkOrigin = &akV1[rkCfg1.m_aiIndex[1]];
            kEdge = akV1[rkCfg1.m_aiIndex[2]] - *pkOrigin;
            fInvEdE = 1.0f/kEdge.Dot(kEdge);
            kDiff = akV0[rkCfg0.m_aiIndex[1]] - *pkOrigin;
            fMin = kEdge.Dot(kDiff)*fInvEdE;
            kDiff = akV0[rkCfg0.m_aiIndex[0]] - *pkOrigin;
            fMax = kEdge.Dot(kDiff)*fInvEdE;
            assert( fMin <= fMax );
            riQuantity = FindIntersection((Real)0.0,(Real)1.0,fMin,fMax,
                afInterval[0],afInterval[1]);
            assert( riQuantity > 0 );
            for (i = 0; i < riQuantity; i++)
                akVertex[i] = *pkOrigin + afInterval[i]*kEdge;
        }
    }
    else  // triangles were initially intersecting
    {
        Triangle2<Real> kTri0, kTri1;
        kTri0.Origin() = akV0[0];
        kTri0.Edge0() = akV0[1] - akV0[0];
        kTri0.Edge1() = akV0[2] - akV0[0];
        kTri1.Origin() = akV1[0];
        kTri1.Edge0() = akV1[1] - akV1[0];
        kTri1.Edge1() = akV1[2] - akV1[0];
        FindIntersection(kTri0,kTri1,riQuantity,akVertex);
    }
}
//----------------------------------------------------------------------------
template <class Real>
bool Wml::TestIntersection (Real fTMax, const Triangle2<Real>& rkTri0,
    const Vector2<Real>& rkW0, const Triangle2<Real>& rkTri1,
    const Vector2<Real>& rkW1, Real& rfTFirst, Real& rfTLast)
{
    Vector2<Real> akV0[3] =
    {
        rkTri0.Origin(),
        rkTri0.Origin() + rkTri0.Edge0(),
        rkTri0.Origin() + rkTri0.Edge1()
    };

    Vector2<Real> akV1[3] =
    {
        rkTri1.Origin(),
        rkTri1.Origin() + rkTri1.Edge0(),
        rkTri1.Origin() + rkTri1.Edge1()
    };

    // process as if V0-triangle is stationary and V1-triangle is moving
    Vector2<Real> kW = rkW1 - rkW0;
    int iSide = 0;  // 0 = NONE, -1 = LEFT, +1 = RIGHT
    rfTFirst = (Real)0.0f;
    rfTLast = Math<Real>::MAX_REAL;

    _Configuration<Real> kCfg0, kCfg1, kTCfg0, kTCfg1;
    int iI0, iI1, iI2;
    Vector2<Real> kD;
    Real fSpeed;

    // process edges of V0-triangle
    for (iI0 = 1, iI1 = 2, iI2 = 0; iI2 < 3; iI0 = iI1, iI1 = iI2, iI2++)
    {
        // test axis V0[i1] + t*perp(V0[i2]-V0[i1]), perp(x,y) = (y,-x)
        kD.X() = akV0[iI2].Y() - akV0[iI1].Y();
        kD.Y() = akV0[iI1].X() - akV0[iI2].X();
        fSpeed = kD.Dot(kW);

        kCfg0.ComputeTwo(akV0,kD,iI0,iI1,iI2);
        kCfg1.ComputeThree(akV1,kD,akV0[iI1]);

        if ( _Configuration<Real>::NoIntersect(kCfg0,kCfg1,fTMax,fSpeed,iSide,
             kTCfg0,kTCfg1,rfTFirst,rfTLast) )
        {
            return false;
        }
    }

    // process edges of V1-triangle
    for (iI0 = 1, iI1 = 2, iI2 = 0; iI2 < 3; iI0 = iI1, iI1 = iI2, iI2++)
    {
        // test axis V1[i1] + t*perp(V1[i2]-V1[i1]), perp(x,y) = (y,-x)
        kD.X() = akV1[iI2].Y() - akV1[iI1].Y();
        kD.Y() = akV1[iI1].X() - akV1[iI2].X();
        fSpeed = kD.Dot(kW);

        kCfg1.ComputeTwo(akV1,kD,iI0,iI1,iI2);
        kCfg0.ComputeThree(akV0,kD,akV1[iI1]);

        if ( _Configuration<Real>::NoIntersect(kCfg0,kCfg1,fTMax,fSpeed,iSide,
             kTCfg0,kTCfg1,rfTFirst,rfTLast) )
        {
            return false;
        }
    }

    return true;
}
//----------------------------------------------------------------------------
template <class Real>
bool Wml::FindIntersection (Real fTMax, const Triangle2<Real>& rkTri0,
    const Vector2<Real>& rkW0, const Triangle2<Real>& rkTri1,
    const Vector2<Real>& rkW1, Real& rfTFirst, Real& rfTLast,
    int& riQuantity, Vector2<Real> akVertex[6])
{
    Vector2<Real> akV0[3] =
    {
        rkTri0.Origin(),
        rkTri0.Origin() + rkTri0.Edge0(),
        rkTri0.Origin() + rkTri0.Edge1()
    };

    Vector2<Real> akV1[3] =
    {
        rkTri1.Origin(),
        rkTri1.Origin() + rkTri1.Edge0(),
        rkTri1.Origin() + rkTri1.Edge1()
    };

    // process as if V0-triangle is stationary and V1-triangle is moving
    Vector2<Real> kW = rkW1 - rkW0;
    int iSide = 0;  // 0 = NONE, -1 = LEFT, +1 = RIGHT
    rfTFirst = (Real)0.0f;
    rfTLast = Math<Real>::MAX_REAL;

    _Configuration<Real> kCfg0, kCfg1, kTCfg0, kTCfg1;
    int iI0, iI1, iI2;
    Vector2<Real> kD;
    Real fSpeed;

    // process edges of V0-triangle
    for (iI0 = 1, iI1 = 2, iI2 = 0; iI2 < 3; iI0 = iI1, iI1 = iI2, iI2++)
    {
        // test axis V0[i1] + t*perp(V0[i2]-V0[i1]), perp(x,y) = (y,-x)
        kD.X() = akV0[iI2].Y() - akV0[iI1].Y();
        kD.Y() = akV0[iI1].X() - akV0[iI2].X();
        fSpeed = kD.Dot(kW);

        kCfg0.ComputeTwo(akV0,kD,iI0,iI1,iI2);
        kCfg1.ComputeThree(akV1,kD,akV0[iI1]);

        if ( _Configuration<Real>::NoIntersect(kCfg0,kCfg1,fTMax,fSpeed,iSide,
             kTCfg0,kTCfg1,rfTFirst,rfTLast) )
        {
            return false;
        }
    }

    // process edges of V1-triangle
    for (iI0 = 1, iI1 = 2, iI2 = 0; iI2 < 3; iI0 = iI1, iI1 = iI2, iI2++)
    {
        // test axis V1[i1] + t*perp(V1[i2]-V1[i1]), perp(x,y) = (y,-x)
        kD.X() = akV1[iI2].Y() - akV1[iI1].Y();
        kD.Y() = akV1[iI1].X() - akV1[iI2].X();
        fSpeed = kD.Dot(kW);

        kCfg1.ComputeTwo(akV1,kD,iI0,iI1,iI2);
        kCfg0.ComputeThree(akV0,kD,akV1[iI1]);

        if ( _Configuration<Real>::NoIntersect(kCfg0,kCfg1,fTMax,fSpeed,iSide,
             kTCfg0,kTCfg1,rfTFirst,rfTLast) )
        {
            return false;
        }
    }

    // move triangles to first contact
    Vector2<Real> akMoveV0[3], akMoveV1[3];
    for (int i = 0; i < 3; i++)
    {
        akMoveV0[i] = akV0[i] + rfTFirst*rkW0;
        akMoveV1[i] = akV1[i] + rfTFirst*rkW1;
    };

    _Configuration<Real>::GetIntersection(kTCfg0,kTCfg1,iSide,akMoveV0,
        akMoveV1,riQuantity,akVertex);

    return riQuantity > 0;
}
//----------------------------------------------------------------------------

//----------------------------------------------------------------------------
// explicit instantiation
//----------------------------------------------------------------------------
namespace Wml
{
template WML_ITEM bool TestIntersection<float> (
    const Triangle2<float>&, const Triangle2<float>&);
template WML_ITEM bool FindIntersection<float> (
    const Triangle2<float>&, const Triangle2<float>&, int&,
    Vector2<float>[6]);
template WML_ITEM bool TestIntersection<float> (float,
    const Triangle2<float>&, const Vector2<float>&,
    const Triangle2<float>&, const Vector2<float>&, float&, float&);
template WML_ITEM bool FindIntersection<float> (float,
    const Triangle2<float>&, const Vector2<float>&,
    const Triangle2<float>&, const Vector2<float>&, float&, float&, int&,
    Vector2<float>[6]);

template WML_ITEM bool TestIntersection<double> (
    const Triangle2<double>&, const Triangle2<double>&);
template WML_ITEM bool FindIntersection<double> (
    const Triangle2<double>&, const Triangle2<double>&, int&,
    Vector2<double>[6]);
template WML_ITEM bool TestIntersection<double> (double,
    const Triangle2<double>&, const Vector2<double>&,
    const Triangle2<double>&, const Vector2<double>&, double&, double&);
template WML_ITEM bool FindIntersection<double> (double,
    const Triangle2<double>&, const Vector2<double>&,
    const Triangle2<double>&, const Vector2<double>&, double&, double&, int&,
    Vector2<double>[6]);
}
//----------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -