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

📄 mgcterrainpage.cpp

📁 《3D游戏引擎设计》的源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
                                break;
                        }
                    }
                    else // distant assumption
                    {
                        for (i = 0; i < 4; i++, pkChild++)
                        {
                            pkChild->ComputeInterval(rkModelEye,
                                m_fWorldTolerance);
                            if (pkChild->GetDeltaMax() > pkChild->GetDeltaL())
                                break;
                        }
                    }

                    // subdivide only if children all agree it should happen
                    if ( i < 4 )
                    {
                        // add child blocks (parent already removed)
                        for (i = 0; i < 4; i++, usChild++)
                        {
                            // add child block
                            AddToQueue(usChild);
                            assert( !m_akBlock[usChild].GetProcessed() );
                            m_usNumUnprocessed++;
                        }
                        continue;
                    }
                }
            }

            // tag block as processed
            pkBlock->SetProcessed(true);
        }

        // put processed block at rear of queue
        AddToQueue(usBlock);
    }
}
//---------------------------------------------------------------------------
void MgcTerrainPage::SimplifyVertices (const MgcVector3& rkModelEye,
    const MgcVector3& rkModelDir, bool bCloseAssumption)
{
    unsigned int usQueue, usBlock;

    if ( m_usFront < m_usRear )
    {
        for (usQueue = m_usFront; usQueue < m_usRear; usQueue++)
        {
            usBlock = m_ausQueue[usQueue];
            if ( m_akBlock[usBlock].GetVisible() )
            {
                m_akBlock[usBlock].SimplifyVertices(this,rkModelEye,
                    rkModelDir,m_fWorldTolerance,bCloseAssumption);
            }
        }
    }
    else
    {
        for (usQueue = m_usFront; usQueue < m_usQueueQuantity; usQueue++)
        {
            usBlock = m_ausQueue[usQueue];
            if ( m_akBlock[usBlock].GetVisible() )
            {
                m_akBlock[usBlock].SimplifyVertices(this,rkModelEye,
                    rkModelDir,m_fWorldTolerance,bCloseAssumption);
            }
        }
        for (usQueue = 0; usQueue < m_usRear; usQueue++)
        {
            usBlock = m_ausQueue[usQueue];
            if ( m_akBlock[usBlock].GetVisible() )
            {
                m_akBlock[usBlock].SimplifyVertices(this,rkModelEye,
                    rkModelDir,m_fWorldTolerance,bCloseAssumption);
            }
        }
    }
}
//---------------------------------------------------------------------------
void MgcTerrainPage::Simplify (MgcRenderer* pkRenderer,
    const MgcVector3& rkModelEye, const MgcVector3& rkModelDir, 
    bool bCloseAssumption)
{
    if ( m_fWorldTolerance == -1.0f )
        SetPixelTolerance(pkRenderer,m_fPixelTolerance);

    SimplifyBlocks(pkRenderer->GetCamera(),rkModelEye,rkModelDir,
        bCloseAssumption);
    SimplifyVertices(rkModelEye,rkModelDir,bCloseAssumption);

    m_bNeedsTessellation = true;
}
//---------------------------------------------------------------------------
void MgcTerrainPage::Render (MgcTerrainBlock& rkBlock)
{
    unsigned short usOrigin = rkBlock.GetX() + m_usSize*rkBlock.GetY();
    unsigned short usTwoStride = 2*rkBlock.GetStride();
    unsigned short usTwoStrideTimesSize = usTwoStride*m_usSize;
    unsigned short usIndex[5] =
    {
        usOrigin,
        usOrigin + usTwoStride,
        usOrigin + rkBlock.GetStride()*(m_usSize + 1),
        usOrigin + usTwoStrideTimesSize,
        usOrigin + usTwoStrideTimesSize + usTwoStride
    };

    if ( rkBlock.GetEven() )
    {
        RenderTriangle(usIndex[0],usIndex[3],usIndex[1]);
        RenderTriangle(usIndex[4],usIndex[1],usIndex[3]);
    }
    else
    {
        RenderTriangle(usIndex[1],usIndex[0],usIndex[4]);
        RenderTriangle(usIndex[3],usIndex[4],usIndex[0]);
    }

}
//---------------------------------------------------------------------------
void MgcTerrainPage::RenderTriangle (unsigned short usT, unsigned short usL,
    unsigned short usR)
{
    // determine if triangle is leaf or interior
    bool bInterior;
    if ( usR > usT )
    {
        if ( usL > usT )
            bInterior = (usR - usT > 1);
        else
            bInterior = (usT - usL > 1);
    }
    else
    {
        if ( usL > usT )
            bInterior = (usL - usT > 1);
        else
            bInterior = (usT - usR > 1);
    }

    if ( bInterior )
    {
        // Triangle is part of internal block and can be subdivided.  M is
        // the midpoint of edge <L,R>.
        unsigned short usM = ((usL + usR) >> 1);
        if ( m_akTVertex[usM].GetEnabled() )
        {
            RenderTriangle(usM,usT,usL);
            RenderTriangle(usM,usR,usT);
            return;
        }
    }

    // pack the vertex data
    unsigned char ucX, ucY;
    if ( m_ausLookup[usT] == (unsigned short)(~0) )
    {
        ucX = usT % m_usSize;
        ucY = usT / m_usSize;

        m_akVertex[m_uiVertexQuantity].x = GetX(ucX);
        m_akVertex[m_uiVertexQuantity].y = GetY(ucY);
        m_akVertex[m_uiVertexQuantity].z = GetHeight(usT);
        m_akTexture[m_uiVertexQuantity].x = GetTexture(ucX);
        m_akTexture[m_uiVertexQuantity].y = GetTexture(ucY);
        m_ausLookup[usT] = m_uiVertexQuantity++;
    }

    if ( m_ausLookup[usR] == (unsigned short)(~0) )
    {
        ucX = usR % m_usSize;
        ucY = usR / m_usSize;
        
        m_akVertex[m_uiVertexQuantity].x = GetX(ucX);
        m_akVertex[m_uiVertexQuantity].y = GetY(ucY);
        m_akVertex[m_uiVertexQuantity].z = GetHeight(usR);
        m_akTexture[m_uiVertexQuantity].x = GetTexture(ucX);
        m_akTexture[m_uiVertexQuantity].y = GetTexture(ucY);
        m_ausLookup[usR] = m_uiVertexQuantity++;
    }

    if ( m_ausLookup[usL] == (unsigned short)(~0) )
    {
        ucX = usL % m_usSize;
        ucY = usL / m_usSize;

        m_akVertex[m_uiVertexQuantity].x = GetX(ucX);
        m_akVertex[m_uiVertexQuantity].y = GetY(ucY);
        m_akVertex[m_uiVertexQuantity].z = GetHeight(usL);
        m_akTexture[m_uiVertexQuantity].x = GetTexture(ucX);
        m_akTexture[m_uiVertexQuantity].y = GetTexture(ucY);
        m_ausLookup[usL] = m_uiVertexQuantity++;
    }

    // add triangle to connectivity array
    m_auiConnect[m_uiConnectLength++] = m_ausLookup[usT];
    m_auiConnect[m_uiConnectLength++] = m_ausLookup[usR];
    m_auiConnect[m_uiConnectLength++] = m_ausLookup[usL];
    m_uiTriangleQuantity++;
}
//---------------------------------------------------------------------------
void MgcTerrainPage::RenderBlocks ()
{
    // reset dynamic quantities
    memset(m_ausLookup,0xFF,m_usSize*m_usSize*sizeof(unsigned short));
    m_uiVertexQuantity = 0;
    m_uiTriangleQuantity = 0;
    m_uiConnectLength = 0;

    unsigned short usQueue;
    if ( m_usFront < m_usRear )
    {
        for (usQueue = m_usFront; usQueue < m_usRear; usQueue++)
        {
            MgcTerrainBlock& rkBlock = m_akBlock[m_ausQueue[usQueue]];
            if ( rkBlock.GetVisible() )
                Render(rkBlock);
        }
    }
    else
    {
        for (usQueue = m_usFront; usQueue < m_usQueueQuantity; usQueue++)
        {
            MgcTerrainBlock& rkBlock = m_akBlock[m_ausQueue[usQueue]];
            if ( rkBlock.GetVisible() )
                Render(rkBlock);
        }
        for (usQueue = 0; usQueue < m_usRear; usQueue++)
        {
            MgcTerrainBlock& rkBlock = m_akBlock[m_ausQueue[usQueue]];
            if ( rkBlock.GetVisible() )
                Render(rkBlock);
        }
    }
}
//---------------------------------------------------------------------------
void MgcTerrainPage::StitchLR (MgcTerrainPage* pkRight)
{
    // 'this' is left page, 'pkRight' is right page
    assert( pkRight->m_usSize == m_usSize );

    unsigned short usR = m_usSize;
    for (unsigned short usY = 1; usY < m_usSizeM1; usY++, usR += m_usSize)
    {
        unsigned short usL = m_usSizeM1 + usR;
        MgcTerrainVertex* pkLVertex = &m_akTVertex[usL];
        MgcTerrainVertex* pkRVertex = &pkRight->m_akTVertex[usR];
        pkRVertex->SetDependent(0,pkLVertex);
        pkLVertex->SetDependent(1,pkRVertex);
    }
}
//---------------------------------------------------------------------------
void MgcTerrainPage::StitchTB (MgcTerrainPage* pkBottom)
{
    // 'this' is top page, 'pkBottom' is bottom page
    assert( pkBottom->m_usSize == m_usSize );

    unsigned short usOffset = m_usSize*m_usSizeM1;
    for (unsigned short usB = 1; usB < m_usSizeM1; usB++)
    {
        unsigned short usT = usB + usOffset;
        MgcTerrainVertex* pkTVertex = &m_akTVertex[usT];
        MgcTerrainVertex* pkBVertex = &pkBottom->m_akTVertex[usB];
        pkBVertex->SetDependent(1,pkTVertex);
        pkTVertex->SetDependent(0,pkBVertex);
    }
}
//---------------------------------------------------------------------------
void MgcTerrainPage::UnstitchLR (MgcTerrainPage* pkRight)
{
    // 'this' is left page, 'pkRight' is right page
    assert( pkRight->m_usSize == m_usSize );

    unsigned short usR = m_usSize;  // y = 1
    for (unsigned short usY = 1; usY < m_usSizeM1; usY++, usR += m_usSize)
    {
        unsigned short usL = m_usSizeM1 + usR;
        MgcTerrainVertex* pkLVertex = &m_akTVertex[usL];
        MgcTerrainVertex* pkRVertex = &pkRight->m_akTVertex[usR];
        pkRVertex->SetDependent(0,0);
        pkLVertex->SetDependent(1,0);
    }
}
//---------------------------------------------------------------------------
void MgcTerrainPage::UnstitchTB (MgcTerrainPage* pkBottom)
{
    // 'this' is top page, 'pBottom' is bottom page
    assert( pkBottom->m_usSize == m_usSize );

    unsigned short usOffset = m_usSize*m_usSizeM1;
    for (unsigned short usB = 1; usB < m_usSizeM1; usB++)
    {
        unsigned short usT = usB + usOffset;
        MgcTerrainVertex* pkTVertex = &m_akTVertex[usT];
        MgcTerrainVertex* pkBVertex = &pkBottom->m_akTVertex[usB];
        pkBVertex->SetDependent(1,0);
        pkTVertex->SetDependent(0,0);
    }
}
//---------------------------------------------------------------------------
void MgcTerrainPage::Draw (MgcRenderer& rkRenderer)
{
    if ( m_bNeedsTessellation )
    {
        m_bNeedsTessellation = false;
        RenderBlocks();
    }

    MgcTriMesh::Draw(rkRenderer);
}
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
// streaming
//---------------------------------------------------------------------------
MgcObject* MgcTerrainPage::Factory (MgcStream& rkStream)
{
    MgcTerrainPage* pkObject = new MgcTerrainPage;
    MgcStream::Link* pkLink = new MgcStream::Link(pkObject);
    pkObject->Load(rkStream,pkLink);
    return pkObject;
}
//---------------------------------------------------------------------------
void MgcTerrainPage::Load (MgcStream& rkStream, MgcStream::Link* pkLink)
{
    MgcTriMesh::Load(rkStream,pkLink);
}
//---------------------------------------------------------------------------
void MgcTerrainPage::Link (MgcStream& rkStream, MgcStream::Link* pkLink)
{
    MgcTriMesh::Link(rkStream,pkLink);
}
//---------------------------------------------------------------------------
bool MgcTerrainPage::Register (MgcStream& rkStream)
{
    return MgcTriMesh::Register(rkStream);
}
//---------------------------------------------------------------------------
void MgcTerrainPage::Save (MgcStream& rkStream)
{
    MgcTriMesh::Save(rkStream);
}
//---------------------------------------------------------------------------

⌨️ 快捷键说明

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