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

📄 wmlterrainblock.cpp

📁 3D Game Engine Design Source Code非常棒
💻 CPP
📖 第 1 页 / 共 2 页
字号:
            fDenom = fRMax + fHMin;
            fFMax = (fDenom > 0.0f ? fRMax/(fDenom*fDenom) : Mathf::MAX_REAL);
        }
        else
        {
            fFMax = (fHMin > 0.0f ? 0.25f/fHMin : Mathf::MAX_REAL);
        }
        
        m_fDeltaL = fTolerance/fFMax;
        m_fDeltaH = (fFMin > 0.0f ? fTolerance/fFMin : Mathf::MAX_REAL);
    }
    else  // fTolerance == 0
    {
        m_fDeltaL = 0.0f;
        m_fDeltaH = Mathf::MAX_REAL;
    }
}
//----------------------------------------------------------------------------
void TerrainBlock::ComputeInterval (const Vector3f& rkModelEye,
    const Vector3f& rkModelDir, float fTolerance, Vector2f& rkLoc,
    float fSpacing)
{
    // close terrain assumption

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

        // temporary quantities
        float fLmEx = rkLoc.X() - rkModelEye.X();
        float fLmEy = rkLoc.Y() - rkModelEye.Y();
        float fTmp = fSpacing*float(m_ucStride);
        float fXSum = fLmEx + fTmp;
        float fYSum = fLmEy + fTmp;
        float fXDif = fLmEx - fTmp;
        float fYDif = fLmEy - fTmp;

        // find corners of block closest to and farthest from eye
        float fFMin = fabsf(rkModelDir.X()*fXDif + rkModelDir.Y()*fYDif);
        float fFMax = fFMin;

        fTmp = fabsf(rkModelDir.X()*fXSum + rkModelDir.Y()*fYDif);
        if ( fTmp >= fFMin )
            fFMin = fTmp;
        else 
            fFMax = fTmp;

        fTmp = fabsf(rkModelDir.X()*fXSum + rkModelDir.Y()*fYSum);
        if ( fTmp >= fFMin )
            fFMin = fTmp;
        else 
            fFMax = fTmp;

        fTmp = fabsf(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
    {
        m_fDeltaL = 0.0f;
        m_fDeltaH = Mathf::MAX_REAL;
    }
}
//----------------------------------------------------------------------------
void TerrainBlock::TestIntersectFrustum (const TerrainPage* pkPage,
    const Camera* pkCamera)
{
    SetVisibilityTested(true);

    // axis-aligned bounding box of page in terrain model space
    Vector3f kMCenter = 0.5f*(m_kMin + m_kMax);
    Vector3f kMExtent = 0.5f*(m_kMax - m_kMin);

    // transform to world space (parent's coordinate system)
    Box3f kWBox;
    kWBox.Center() = pkPage->Scale()*(pkPage->Rotate()*kMCenter) +
        pkPage->Translate();
    int i;
    for (i = 0; i < 3; i++)
    {
        kWBox.Axis(i) = pkPage->Rotate().GetColumn(i);
        kWBox.Extent(i) = pkPage->Scale()*kMExtent[i];
    }

    // inverse transform from world space to camera space
    Box3f kCBox;
    Vector3f kDiff = kWBox.Center() - pkCamera->GetLocation();
    kCBox.Center() = Vector3f(kDiff.Dot(pkCamera->GetLeft()),
        kDiff.Dot(pkCamera->GetUp()),kDiff.Dot(pkCamera->GetDirection()));
    for (i = 0; i < 3; i++)
    {
        kCBox.Axis(i) = Vector3f(
            pkCamera->GetLeft().Dot(kWBox.Axis(i)),
            pkCamera->GetUp().Dot(kWBox.Axis(i)),
            pkCamera->GetDirection().Dot(kWBox.Axis(i)));
        kCBox.Extent(i) = kWBox.Extent(i);
    }

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

    SetVisible(TestIntersection(kCBox,kFrustum));
}
//----------------------------------------------------------------------------
void TerrainBlock::SimplifyVertices (TerrainPage* pkPage,
    const Vector3f& rkModelEye, const Vector3f& rkModelDir, float fTolerance,
    bool bCloseAssumption)
{
    unsigned short usSize = pkPage->m_usSize;
    unsigned short usOrigin = m_ucX + usSize*m_ucY;
    TerrainVertex* pkVOrigin = pkPage->m_akTVertex + usOrigin;
    TerrainVertex* pkTVertex;
    unsigned short usOffset;
    Vector3f kDiff;
    float 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 TerrainBlock::Disable (TerrainPage* pkPage)
{
    TerrainVertex* 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 + -