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

📄 mgcterrainblock.cpp

📁 《3D游戏引擎设计》的源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
        if ( fMin < 0.0 )
            fMin *= rkFrustum.GetDRatio();
        fMax = fTmp + fP;
        if ( fMax > 0.0 )
            fMax *= rkFrustum.GetDRatio();
        fDdD = -afD[0]*afNBmUC[i] + afD[1]*afNApLC[i] - afD[2]*afLBpUA[i];
        fR = 0.0;
        for (j = 0; j < 3; j++)
        {
            fR += afE[j]*MgcMath::Abs(-afA[j]*afNBmUC[i]+ afB[j]*afNApLC[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(afNBpUC[i]) +
             rkFrustum.UBound()*MgcMath::Abs(afNApLC[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]*afNBpUC[i] + afD[1]*afNApLC[i] - afD[2]*afLBmUA[i];
        fR = 0.0;
        for (j = 0; j < 3; j++)
        {
            fR += afE[j]*MgcMath::Abs(-afA[j]*afNBpUC[i]+ afB[j]*afNApLC[i]
                - afC[j]*afLBmUA[i]);
        }
        if ( fDdD + fR < fMin || fDdD - fR > fMax )
            return false;
    }

    return true;
}
//---------------------------------------------------------------------------
void MgcTerrainBlock::TestIntersectFrustum (const MgcTerrainPage* pPage,
    const MgcCamera* pkCamera)
{
    SetVisibilityTested(true);

    // centered-form bounding box of page in terrain model space
    MgcBox3 kBox;
    kBox.Center() = 0.5*(m_kMin + m_kMax);
    kBox.Extent(0) = 0.5*(m_kMax.x - m_kMin.x);
    kBox.Extent(1) = 0.5*(m_kMax.y - m_kMin.y);
    kBox.Extent(2) = 0.5*(m_kMax.z - m_kMin.z);
    kBox.Axis(0) = MgcVector3::UNIT_X;
    kBox.Axis(1) = MgcVector3::UNIT_Y;
    kBox.Axis(2) = MgcVector3::UNIT_Z;

    // inverse transform to camera space
    MgcVector3 kDiff = kBox.Center() - pkCamera->GetLocation();
    kBox.Center() = MgcVector3(kDiff.Dot(pkCamera->GetLeft()),
        kDiff.Dot(pkCamera->GetUp()),kDiff.Dot(pkCamera->GetDirection()));
    kBox.Axis(0) = MgcVector3(pkCamera->GetLeft().x,pkCamera->GetUp().x,
        pkCamera->GetDirection().x);
    kBox.Axis(1) = MgcVector3(pkCamera->GetLeft().y,pkCamera->GetUp().y,
        pkCamera->GetDirection().y);
    kBox.Axis(2) = MgcVector3(pkCamera->GetLeft().z,pkCamera->GetUp().z,
        pkCamera->GetDirection().z);

    // default frustum matches camera coordinate frame
    MgcFrustum kFrustum;
    kFrustum.LBound() = pkCamera->GetFrustumRight();
    kFrustum.UBound() = pkCamera->GetFrustumTop();
    kFrustum.DMin() = pkCamera->GetFrustumNear();
    kFrustum.DMax() = pkCamera->GetFrustumFar();
    kFrustum.Update();

    SetVisible(TestIntersect(kBox,kFrustum));
    //SetVisible(true);
}
//---------------------------------------------------------------------------
void MgcTerrainBlock::SimplifyVertices (MgcTerrainPage* pkPage,
    const MgcVector3& rkModelEye, const MgcVector3& rkModelDir,
    MgcReal fTolerance, bool bCloseAssumption)
{
    unsigned short usSize = pkPage->m_usSize;
    unsigned short usOrigin = m_ucX + usSize*m_ucY;
    MgcTerrainVertex* pkVOrigin = pkPage->m_akTVertex + usOrigin;
    MgcTerrainVertex* pkTVertex;
    unsigned short usOffset;
    MgcVector3 kDiff;
    MgcReal fRSqr, fLenSqr, fDistDir;

    // simplify at (stride,0)
    if ( m_fDeltaL <= m_fDelta[0] )
    {
        pkTVertex = pkVOrigin + m_ucStride;
        if ( m_fDelta[0] <= m_fDeltaH )
        {
            // test vertex delta against tolerance
            if ( !pkTVertex->GetEnabled() )
            {
                kDiff.x = rkModelEye.x - pkPage->GetX(m_ucX+m_ucStride);
                kDiff.y = rkModelEye.y - pkPage->GetY(m_ucY);
                if ( bCloseAssumption ) 
                {
                    fDistDir = rkModelDir.x*kDiff.x + rkModelDir.y*kDiff.y;
                    if ( m_fDelta[0] > fTolerance*fDistDir*fDistDir )
                        pkTVertex->Enable();
                }
                else // distant assumption
                {
                    kDiff.z = rkModelEye.z -
                        pkPage->GetHeight(usOrigin+m_ucStride);
                    fRSqr = kDiff.x*kDiff.x + kDiff.y*kDiff.y;
                    fLenSqr = fRSqr + kDiff.z*kDiff.z;
                    if ( m_fDelta[0]*fRSqr > fTolerance*fLenSqr*fLenSqr )
                        pkTVertex->Enable();
                }
            }
        }
        else
        {
            if ( !pkTVertex->GetEnabled() )
                pkTVertex->Enable();
        }
    }

    // simplify at (2*stride,stride)
    if ( m_fDeltaL <= m_fDelta[1] )
    {
        usOffset = (usSize+2)*m_ucStride;
        pkTVertex = pkVOrigin + usOffset;
        if ( m_fDelta[1] <= m_fDeltaH )
        {
            // test vertex delta against tolerance
            if ( !pkTVertex->GetEnabled() )
            {
                kDiff.x = rkModelEye.x - pkPage->GetX(m_ucX+2*m_ucStride);
                kDiff.y = rkModelEye.y - pkPage->GetY(m_ucY+m_ucStride);
                if ( bCloseAssumption ) 
                {
                    fDistDir = rkModelDir.x*kDiff.x + rkModelDir.y*kDiff.y;
                    if ( m_fDelta[1] > fTolerance*fDistDir*fDistDir )
                        pkTVertex->Enable();
                }
                else // distant assumption
                {
                    kDiff.z = rkModelEye.z -
                        pkPage->GetHeight(usOrigin+usOffset);
                    fRSqr = kDiff.x*kDiff.x + kDiff.y*kDiff.y;
                    fLenSqr = fRSqr + kDiff.z*kDiff.z;
                    if ( m_fDelta[1]*fRSqr > fTolerance*fLenSqr*fLenSqr )
                        pkTVertex->Enable();
                }
            }
        }
        else
        {
            if ( !pkTVertex->GetEnabled() )
            {
                pkTVertex->Enable();
            }
        }
    }

    // simplify at (stride,2*stride)
    if ( m_fDeltaL <= m_fDelta[2] )
    {
        usOffset = (2*usSize+1)*m_ucStride;
        pkTVertex = pkVOrigin + usOffset;
        if ( m_fDelta[2] <= m_fDeltaH )
        {
            // test vertex delta against tolerance
            if ( !pkTVertex->GetEnabled() )
            {
                kDiff.x = rkModelEye.x - pkPage->GetX(m_ucX+m_ucStride);
                kDiff.y = rkModelEye.y - pkPage->GetY(m_ucY+2*m_ucStride);
                if ( bCloseAssumption ) 
                {
                    fDistDir = rkModelDir.x*kDiff.x + rkModelDir.y*kDiff.y;
                    if ( m_fDelta[2] > fTolerance*fDistDir*fDistDir )
                        pkTVertex->Enable();
                }
                else // distant assumption
                {
                    kDiff.z = rkModelEye.z -
                        pkPage->GetHeight(usOrigin+usOffset);
                    fRSqr = kDiff.x*kDiff.x + kDiff.y*kDiff.y;
                    fLenSqr = fRSqr + kDiff.z*kDiff.z;
                    if ( m_fDelta[2]*fRSqr > fTolerance*fLenSqr*fLenSqr )
                        pkTVertex->Enable();
                }
            }
        }
        else
        {
            if ( !pkTVertex->GetEnabled() )
                pkTVertex->Enable();
        }
    }

    // simplify at (0,stride)
    if ( m_fDeltaL <= m_fDelta[3] )
    {
        usOffset = usSize*m_ucStride;
        pkTVertex = pkVOrigin + usOffset;
        if ( m_fDelta[3] <= m_fDeltaH )
        {
            // test vertex delta against tolerance
            if ( !pkTVertex->GetEnabled() )
            {
                kDiff.x = rkModelEye.x - pkPage->GetX(m_ucX);
                kDiff.y = rkModelEye.y - pkPage->GetY(m_ucY+m_ucStride);
                if ( bCloseAssumption ) 
                {
                    fDistDir = rkModelDir.x*kDiff.x + rkModelDir.y*kDiff.y;
                    if ( m_fDelta[3] > fTolerance*fDistDir*fDistDir )
                        pkTVertex->Enable();
                }
                else // distant terrain assumption
                {
                    kDiff.z = rkModelEye.z -
                        pkPage->GetHeight(usOrigin+usOffset);
                    fRSqr = kDiff.x*kDiff.x + kDiff.y*kDiff.y;
                    fLenSqr = fRSqr + kDiff.z*kDiff.z;
                    if ( m_fDelta[3]*fRSqr > fTolerance*fLenSqr*fLenSqr )
                        pkTVertex->Enable();
                }
            }
        }
        else
        {
            if ( !pkTVertex->GetEnabled() )
                pkTVertex->Enable();
        }
    }

    // simplify at (stride,stride)
    if ( m_fDeltaL <= m_fDelta[4] )
    {
        usOffset = (usSize+1)*m_ucStride;
        pkTVertex = pkVOrigin + usOffset;
        if ( m_fDelta[4] <= m_fDeltaH )
        {
            // test vertex delta against tolerance
            if ( !pkTVertex->GetEnabled() )
            {
                kDiff.x = rkModelEye.x - pkPage->GetX(m_ucX+m_ucStride);
                kDiff.y = rkModelEye.y - pkPage->GetY(m_ucY+m_ucStride);
                if ( bCloseAssumption ) 
                {
                    fDistDir = rkModelDir.x*kDiff.x + rkModelDir.y*kDiff.y;
                    if ( m_fDelta[4] > fTolerance*fDistDir*fDistDir )
                        pkTVertex->Enable();
                }
                else // distant terrain assumption
                {
                    kDiff.z = rkModelEye.z -
                        pkPage->GetHeight(usOrigin+usOffset);
                    fRSqr = kDiff.x*kDiff.x + kDiff.y*kDiff.y;
                    fLenSqr = fRSqr + kDiff.z*kDiff.z;
                    if ( m_fDelta[4]*fRSqr > fTolerance*fLenSqr*fLenSqr )
                        pkTVertex->Enable();
                }
            }
        }
        else
        {
            if ( !pkTVertex->GetEnabled() )
                pkTVertex->Enable();
        }
    }

    // enable the corner vertices
    if ( GetEven() )
    {
        pkTVertex = pkVOrigin + 2*m_ucStride;
        if ( !pkTVertex->GetEnabled() )
            pkTVertex->Enable();

        pkTVertex = pkVOrigin + 2*usSize*m_ucStride;
        if ( !pkTVertex->GetEnabled() )
            pkTVertex->Enable();
    }
    else
    {
        pkTVertex = pkVOrigin;
        if ( !pkTVertex->GetEnabled() )
            pkTVertex->Enable();

        pkTVertex = pkVOrigin + 2*(usSize+1)*m_ucStride;
        if ( !pkTVertex->GetEnabled() )
            pkTVertex->Enable();
    }
}
//---------------------------------------------------------------------------
void MgcTerrainBlock::Disable (MgcTerrainPage* pkPage)
{
    MgcTerrainVertex* akTVertex[9];
    GetVertex9(pkPage->m_usSize,pkPage->m_akTVertex,akTVertex);
    for (int i = 0; i < 9; i++)
    {
        if ( akTVertex[i]->GetEnabled() )
            akTVertex[i]->Disable();
    }
}
//---------------------------------------------------------------------------

⌨️ 快捷键说明

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