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

📄 mgcterrainblock.cpp

📁 《3D游戏引擎设计》的源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
            fRMax += ( fDxMax >= fDxMin ? fDxMax : fDxMin );
        }
        else
        {
            fRMin += fDxMax;
            fRMax += fDxMin;
        }

        if ( rkModelEye.y < m_kMin.y )
        {
            fRMin += fDyMin;
            fRMax += fDyMax;
        }
        else if ( rkModelEye.y <= m_kMax.y )
        {
            fRMax += ( fDyMax >= fDyMin ? fDyMax : fDyMin );
        }
        else
        {
            fRMin += fDyMax;
            fRMax += fDyMin;
        }

        // compute fmin
        MgcReal fDenom = fRMin + fHMax;
        MgcReal fFMin =
            (fDenom > 0.0 ? fRMin/(fDenom*fDenom) : MgcMath::INFINITY);
        fDenom = fRMax + fHMax;
        fTmp = (fDenom > 0.0 ? fRMax/(fDenom*fDenom) : MgcMath::INFINITY);
        if ( fTmp < fFMin )
            fFMin = fTmp;
        
        // compute fmax
        MgcReal fFMax;
        if ( fRMin >= fHMin )
        {
            fDenom = fRMin + fHMin;
            fFMax =
                (fDenom > 0.0 ? fRMin/(fDenom*fDenom) : MgcMath::INFINITY);
        }
        else if ( fRMax <= fHMin )
        {
            fDenom = fRMax + fHMin;
            fFMax =
                (fDenom > 0.0 ? fRMax/(fDenom*fDenom) : MgcMath::INFINITY);
        }
        else
        {
            fFMax = (fHMin > 0.0 ? 0.25/fHMin : MgcMath::INFINITY);
        }
        
        m_fDeltaL = fTolerance/fFMax;
        m_fDeltaH = (fFMin > 0.0 ? fTolerance/fFMin : MgcMath::INFINITY);
    }
    else  // fTolerance == 0.0
    {
        m_fDeltaL = 0.0;
        m_fDeltaH = MgcMath::INFINITY;
    }
}
//---------------------------------------------------------------------------
void MgcTerrainBlock::ComputeInterval (const MgcVector3& rkModelEye,
    const MgcVector3& rkModelDir, MgcReal fTolerance, MgcVector2& rkLoc,
    MgcReal fSpacing)
{
    // close terrain assumption

    if ( fTolerance > 0.0 )
    {
        // compute fmin and fmax

        // temporary quantities
        MgcReal fLmEx = rkLoc.x - rkModelEye.x;
        MgcReal fLmEy = rkLoc.y - rkModelEye.y;
        MgcReal fTmp = fSpacing*MgcReal(m_ucStride);
        MgcReal fXSum = fLmEx + fTmp;
        MgcReal fYSum = fLmEy + fTmp;
        MgcReal fXDif = fLmEx - fTmp;
        MgcReal fYDif = fLmEy - fTmp;

        // find corners of block closest to and farthest from eye
        MgcReal fFMin = MgcMath::Abs(rkModelDir.x*fXDif + rkModelDir.y*fYDif);
        MgcReal fFMax = fFMin;

        fTmp = MgcMath::Abs(rkModelDir.x*fXSum + rkModelDir.y*fYDif);
        if ( fTmp >= fFMin )
            fFMin = fTmp;
        else 
            fFMax = fTmp;

        fTmp = MgcMath::Abs(rkModelDir.x*fXSum + rkModelDir.y*fYSum);
        if ( fTmp >= fFMin )
            fFMin = fTmp;
        else 
            fFMax = fTmp;

        fTmp = MgcMath::Abs(rkModelDir.x*fXDif + rkModelDir.y*fYSum);
        if ( fTmp >= fFMin )
            fFMin = fTmp;
        else
            fFMax = fTmp;

        m_fDeltaL = fTolerance*fFMax;
        m_fDeltaH = fTolerance*fFMin;
    }
    else  // fTolerance == 0.0
    {
        m_fDeltaL = 0.0;
        m_fDeltaH = MgcMath::INFINITY;
    }
}
//---------------------------------------------------------------------------
bool MgcTerrainBlock::TestIntersect (const MgcBox3& rkBox,
    const MgcFrustum& rkFrustum)
{
    // for convenience
    const MgcVector3* akA = rkBox.Axes();
    const MgcReal* afE = rkBox.Extents();

    MgcVector3 kDiff = rkBox.Center() - rkFrustum.Origin();

    MgcReal afA[3], afB[3], afC[3], afD[3];
    MgcReal afNA[3], afNB[3], afNC[3], afND[3];
    MgcReal afNApLC[3], afNAmLC[3], afNBpUC[3], afNBmUC[3];
    MgcReal afLC[3], afLD[3], afUC[3], afUD[3], afLBpUA[3], afLBmUA[3];
    MgcReal fDdD, fR, fP, fMin, fMax, fMTwoLF, fMTwoUF, fLB, fUA, fTmp;
    int i, j;

    // M = D
    afD[2] = kDiff.Dot(rkFrustum.DVector());
    for (i = 0; i < 3; i++)
        afC[i] = akA[i].Dot(rkFrustum.DVector());
    fR = afE[0]*MgcMath::Abs(afC[0]) +
         afE[1]*MgcMath::Abs(afC[1]) +
         afE[2]*MgcMath::Abs(afC[2]);
    if ( afD[2] + fR < rkFrustum.DMin() || afD[2] - fR > rkFrustum.DMax() )
        return false;

    // M = n*L - l*D
    for (i = 0; i < 3; i++)
    {
        afA[i] = akA[i].Dot(rkFrustum.LVector());
        afLC[i] = rkFrustum.LBound()*afC[i];
        afNA[i] = rkFrustum.DMin()*afA[i];
        afNAmLC[i] = afNA[i] - afLC[i];
    }
    afD[0] = kDiff.Dot(rkFrustum.LVector());
    fR = afE[0]*MgcMath::Abs(afNAmLC[0]) +
         afE[1]*MgcMath::Abs(afNAmLC[1]) +
         afE[2]*MgcMath::Abs(afNAmLC[2]);
    afND[0] = rkFrustum.DMin()*afD[0];
    afLD[2] = rkFrustum.LBound()*afD[2];
    fDdD = afND[0] - afLD[2];
    fMTwoLF = rkFrustum.GetMTwoLF();
    if ( fDdD + fR < fMTwoLF || fDdD > fR )
        return false;

    // M = -n*L - l*D
    for (i = 0; i < 3; i++)
        afNApLC[i] = afNA[i] + afLC[i];
    fR = afE[0]*MgcMath::Abs(afNApLC[0]) +
         afE[1]*MgcMath::Abs(afNApLC[1]) +
         afE[2]*MgcMath::Abs(afNApLC[2]);
    fDdD = -(afND[0] + afLD[2]);
    if ( fDdD + fR < fMTwoLF || fDdD > fR )
        return false;

    // M = n*U - u*D
    for (i = 0; i < 3; i++)
    {
        afB[i] = akA[i].Dot(rkFrustum.UVector());
        afUC[i] = rkFrustum.UBound()*afC[i];
        afNB[i] = rkFrustum.DMin()*afB[i];
        afNBmUC[i] = afNB[i] - afUC[i];
    }
    afD[1] = kDiff.Dot(rkFrustum.UVector());
    fR = afE[0]*MgcMath::Abs(afNBmUC[0]) +
         afE[1]*MgcMath::Abs(afNBmUC[1]) +
         afE[2]*MgcMath::Abs(afNBmUC[2]);
    afND[1] = rkFrustum.DMin()*afD[1];
    afUD[2] = rkFrustum.UBound()*afD[2];
    fDdD = afND[1] - afUD[2];
    fMTwoUF = rkFrustum.GetMTwoUF();
    if ( fDdD + fR < fMTwoUF || fDdD > fR )
        return false;

    // M = -n*U - u*D
    for (i = 0; i < 3; i++)
        afNBpUC[i] = afNB[i] + afUC[i];
    fR = afE[0]*MgcMath::Abs(afNBpUC[0]) +
         afE[1]*MgcMath::Abs(afNBpUC[1]) +
         afE[2]*MgcMath::Abs(afNBpUC[2]);
    fDdD = -(afND[1] + afUD[2]);
    if ( fDdD + fR < fMTwoUF || fDdD > fR )
        return false;

    // M = A[i]
    for (i = 0; i < 3; i++)
    {
        fP = rkFrustum.LBound()*MgcMath::Abs(afA[i]) +
             rkFrustum.UBound()*MgcMath::Abs(afB[i]);
        afNC[i] = rkFrustum.DMin()*afC[i];
        fMin = afNC[i] - fP;
        if ( fMin < 0.0 )
            fMin *= rkFrustum.GetDRatio();
        fMax = afNC[i] + fP;
        if ( fMax > 0.0 )
            fMax *= rkFrustum.GetDRatio();
        fDdD = afA[i]*afD[0] + afB[i]*afD[1] + afC[i]*afD[2];
        if ( fDdD + afE[i] < fMin || fDdD - afE[i] > fMax )
            return false;
    }

    // M = Cross(L,A[i])
    for (i = 0; i < 3; i++)
    {
        fP = rkFrustum.UBound()*MgcMath::Abs(afC[i]);
        fMin = afNB[i] - fP;
        if ( fMin < 0.0 )
            fMin *= rkFrustum.GetDRatio();
        fMax = afNB[i] + fP;
        if ( fMax > 0.0 )
            fMax *= rkFrustum.GetDRatio();
        fDdD = -afC[i]*afD[1] + afB[i]*afD[2];
        fR = afE[0]*MgcMath::Abs(afB[i]*afC[0]-afB[0]*afC[i]) +
             afE[1]*MgcMath::Abs(afB[i]*afC[1]-afB[1]*afC[i]) +
             afE[2]*MgcMath::Abs(afB[i]*afC[2]-afB[2]*afC[i]);
        if ( fDdD + fR < fMin || fDdD - fR > fMax )
            return false;
    }

    // M = Cross(U,A[i])
    for (i = 0; i < 3; i++)
    {
        fP = rkFrustum.LBound()*MgcMath::Abs(afC[i]);
        fMin = -afNA[i] - fP;
        if ( fMin < 0.0 )
            fMin *= rkFrustum.GetDRatio();
        fMax = -afNA[i] + fP;
        if ( fMax > 0.0 )
            fMax *= rkFrustum.GetDRatio();
        fDdD = afC[i]*afD[0] - afA[i]*afD[2];
        fR = afE[0]*MgcMath::Abs(afA[i]*afC[0]-afA[0]*afC[i]) +
             afE[1]*MgcMath::Abs(afA[i]*afC[1]-afA[1]*afC[i]) +
             afE[2]*MgcMath::Abs(afA[i]*afC[2]-afA[2]*afC[i]);
        if ( fDdD + fR < fMin || fDdD - fR > fMax )
            return false;
    }

    // M = Cross(n*D+l*L+u*U,A[i])
    for (i = 0; i < 3; i++)
    {
        fLB = rkFrustum.LBound()*afB[i];
        fUA = rkFrustum.UBound()*afA[i];
        afLBpUA[i] = fLB + fUA;
        afLBmUA[i] = fLB - fUA;
    }
    for (i = 0; i < 3; i++)
    {
        fP = rkFrustum.LBound()*MgcMath::Abs(afNBmUC[i]) +
             rkFrustum.UBound()*MgcMath::Abs(afNAmLC[i]);
        fTmp = rkFrustum.DMin()*afLBmUA[i];
        fMin = fTmp - fP;
        if ( fMin < 0.0 )
            fMin *= rkFrustum.GetDRatio();
        fMax = fTmp + fP;
        if ( fMax > 0.0 )
            fMax *= rkFrustum.GetDRatio();
        fDdD = -afD[0]*afNBmUC[i] + afD[1]*afNAmLC[i] + afD[2]*afLBmUA[i];
        fR = 0.0;
        for (j = 0; j < 3; j++)
        {
            fR += afE[j]*MgcMath::Abs(-afA[j]*afNBmUC[i]+ afB[j]*afNAmLC[i]
                + afC[j]*afLBmUA[i]);
        }
        if ( fDdD + fR < fMin || fDdD - fR > fMax )
            return false;
    }

    // M = Cross(n*D+l*L-u*U,A[i])
    for (i = 0; i < 3; i++)
    {
        fP = rkFrustum.LBound()*MgcMath::Abs(afNBpUC[i]) +
             rkFrustum.UBound()*MgcMath::Abs(afNAmLC[i]);
        fTmp = rkFrustum.DMin()*afLBpUA[i];
        fMin = fTmp - fP;
        if ( fMin < 0.0 )
            fMin *= rkFrustum.GetDRatio();
        fMax = fTmp + fP;
        if ( fMax > 0.0 )
            fMax *= rkFrustum.GetDRatio();
        fDdD = -afD[0]*afNBpUC[i] + afD[1]*afNAmLC[i] + afD[2]*afLBpUA[i];
        fR = 0.0;
        for (j = 0; j < 3; j++)
        {
            fR += afE[j]*MgcMath::Abs(-afA[j]*afNBpUC[i]+ afB[j]*afNAmLC[i]
                + afC[j]*afLBpUA[i]);
        }
        if ( fDdD + fR < fMin || fDdD - fR > fMax )
            return false;
    }

    // M = Cross(n*D-l*L+u*U,A[i])
    for (i = 0; i < 3; i++)
    {
        fP = rkFrustum.LBound()*MgcMath::Abs(afNBmUC[i]) +
             rkFrustum.UBound()*MgcMath::Abs(afNApLC[i]);
        fTmp = -rkFrustum.DMin()*afLBpUA[i];
        fMin = fTmp - fP;

⌨️ 快捷键说明

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