最新-基于四叉树的LOD地形设计

  上次说过要在这里把最新的地形设计写出来,不过一直没时间写,也想画些UML图,但没工具画,呵呵,只能通过手写了。希望大家看得明白吧。
        基本设计思想:
        主要有以下几个类,
        CTerrainBlock,地形一个block,每个对象拥有自己的顶点缓冲和相对应的LOD值。
        HeightMap类,读入高度图,并根据策略创建一定数量的CTerrainBlock。例如1024x1024的地形,我把每个block大小设置为64x64,那么这个HeightMap有16 x 16个block。
        CQuadTree类,四叉树类,根据block的大小划分四叉树。

        基本流程:当场景渲染时,在场景UpdateScene的时候,首先Update了Camera数据,然后从新计算Frustum,然后调用m_quadTree.GetRenderObject(list& renderList)函数,以递归形式把quadTree中的在可视区内的渲染对象加到渲染队列,加入队列前并计算出CTerrainBlock的LOD值。到渲染时,首先根据地形的LOD值与相邻四个作判断,然后修补裂缝,具体做法是动态改变IB的值,有些LOD算法是一开始就根据不同的LOD和四边的情况生成N个公共的IB,到渲染时可根据当前情况选择合适的IB以解决裂缝问题。这样可省去计算IB的时间,不过IB的数量会增多,就是以内存换时间。我现在的做法是以时间换内存。
        下面是UpdateScene的代码:
void  CTerrainSceneManager::UpdateScene()
ExpandedBlockStart.gifContractedBlock.gif
{
    
//在这里应该把所有object更新一次,然后更新渲染队列
    CAMERAINST->Update();

    FRUSTUM
->CalculateFrustum();

    m_listRender.clear();
    m_quadTree.GetRenderableObject(m_listRender);

    
//下面的代码也可以在每个Object的Render时调用Update,这里我还没体会到底放在哪里好。当时考虑到shader的调用,所以放到Render里,把这里注释了。
    
//for (list<CTerrainBlock*>::iterator it = m_listRender.begin(); it != m_listRender.end(); it++)
    
//{
    
//    (*it)->Update();
    
//}
}

下面是CTerrainBlock的部分代码
  1 void  CTerrainBlock::Update()
  2 ExpandedBlockStart.gifContractedBlock.gif {
  3    
  4    FixCrack(TERRAINSCENE->GetTerrain());  //候补裂缝
  5    m_dwTotalIndex = ComputeIndics();      //计算索引并填充IB
  6    //UpdateShader();
  7    UpdateEffect();                        //更新Shader
  8}

  9
 10 void  CTerrainBlock::FixCrack(CHeightMap *  pTerrain)
 11 ExpandedBlockStart.gifContractedBlock.gif {
 12    m_nLeftIndexCount = 0;
 13    m_nRightIndexCount = 0;
 14    m_nBottomIndexCount = 0;
 15    m_nTopIndexCount = 0;
 16
 17    //上方
 18    CTerrainBlock* pBlock = pTerrain->GetBlock(m_nNeighbor[0]);
 19
 20    if (pBlock)
 21ExpandedSubBlockStart.gifContractedSubBlock.gif    {
 22        FixCrackEdge(pBlock->GetLODLevel(), BLOCK_TOP);
 23    }

 24
 25    //右方
 26    pBlock = pTerrain->GetBlock(m_nNeighbor[1]);
 27
 28    if (pBlock)
 29ExpandedSubBlockStart.gifContractedSubBlock.gif    {
 30        FixCrackEdge(pBlock->GetLODLevel(), BLOCK_RIGHT);
 31    }

 32
 33    //下方
 34    pBlock = pTerrain->GetBlock(m_nNeighbor[2]);
 35
 36    if (pBlock)
 37ExpandedSubBlockStart.gifContractedSubBlock.gif    {
 38        FixCrackEdge(pBlock->GetLODLevel(), BLOCK_BOTTOM);
 39    }

 40
 41    //左方
 42    pBlock = pTerrain->GetBlock(m_nNeighbor[3]);
 43
 44    if (pBlock)
 45ExpandedSubBlockStart.gifContractedSubBlock.gif    {
 46        FixCrackEdge(pBlock->GetLODLevel(), BLOCK_LEFT);
 47    }

 48}

 49
 50 void  CTerrainBlock::FixCrackEdge( int  nNeighborLevel, BLOCKEDGE edge)
 51 ExpandedBlockStart.gifContractedBlock.gif {
 52    if (m_nLODLevel == 3 || nNeighborLevel == m_nLODLevel)
 53ExpandedSubBlockStart.gifContractedSubBlock.gif    {
 54        return;
 55    }

 56    if ((nNeighborLevel - m_nLODLevel) == 1)
 57ExpandedSubBlockStart.gifContractedSubBlock.gif    {
 58        switch(edge)
 59ExpandedSubBlockStart.gifContractedSubBlock.gif        {
 60        case BLOCK_TOP:
 61            //m_vtTopEdge.clear();
 62            m_nTopIndexCount = 1;
 63
 64            break;
 65        case BLOCK_RIGHT:
 66            m_nRightIndexCount = 1;
 67
 68            break;
 69        case BLOCK_BOTTOM:
 70            m_nBottomIndexCount = 1;
 71
 72            break;
 73        case BLOCK_LEFT:
 74            m_nLeftIndexCount = 1;
 75
 76            break;
 77        }

 78    }

 79    else if ((nNeighborLevel - m_nLODLevel) == 2)
 80ExpandedSubBlockStart.gifContractedSubBlock.gif    {
 81        switch(edge)
 82ExpandedSubBlockStart.gifContractedSubBlock.gif        {
 83        case BLOCK_TOP:
 84            m_nTopIndexCount = 3;
 85
 86            break;
 87        case BLOCK_RIGHT:
 88            m_nRightIndexCount = 3;
 89
 90            break;
 91        case BLOCK_BOTTOM:
 92            m_nBottomIndexCount = 3;
 93
 94            break;
 95        case BLOCK_LEFT:
 96            m_nLeftIndexCount = 3;
 97
 98            break;
 99        }

100    }

101}

102
103 void  CTerrainBlock::ComputeNeighbor()
104 ExpandedBlockStart.gifContractedBlock.gif {
105    m_nNeighbor[0= m_nTopLeftX + (m_nTopLeftY - m_wGridsPerRow) * m_dwTerrainSize;   //上方
106    m_nNeighbor[1= m_nTopLeftX + m_wGridsPerRow + m_nTopLeftY * m_dwTerrainSize;     //右方                                                           //右方
107    m_nNeighbor[2= m_nTopLeftX + (m_nTopLeftY + m_wGridsPerRow) * m_dwTerrainSize;   //下方                                                             //下方
108    m_nNeighbor[3= m_nTopLeftX - m_wGridsPerRow + m_nTopLeftY * m_dwTerrainSize;     //左方                                                      //左方
109}

110
111 DWORD CTerrainBlock::ComputeIndics()
112 ExpandedBlockStart.gifContractedBlock.gif {
113    WORD* pIndices = NULL;
114
115    m_pIndexBuffer->Lock(00, (void**)&pIndices, NULL);
116
117    DWORD dwIndex = 0;
118    
119    DWORD dwTopLeft = 0;//m_data.dwTopLeft;     //声明,topleft是要在block里的topleft,而不是在整个地形的topleft
120    DWORD dwTopRight = m_wBlockSize - 1;
121    DWORD dwBottomRight = m_dwNumBlockVertices - 1;
122    DWORD dwBottomLeft = dwBottomRight - (m_wBlockSize - 1);
123    if (m_nLODLevel == 3)   //最大层
124ExpandedSubBlockStart.gifContractedSubBlock.gif    {
125        for (DWORD nRow = 0; nRow < m_nRealCell; nRow++)    //
126ExpandedSubBlockStart.gifContractedSubBlock.gif        {
127            for (DWORD nCol = 0; nCol < m_nRealCell; nCol++)  
128ExpandedSubBlockStart.gifContractedSubBlock.gif            {
129                *(pIndices + dwIndex++= dwTopLeft + nCol * m_wIndexStride + nRow * m_wIndexStride * m_wBlockSize;
130                *(pIndices + dwIndex++= dwTopLeft + (nCol + 1* m_wIndexStride + nRow * m_wIndexStride * m_wBlockSize;
131                *(pIndices + dwIndex++= dwTopLeft + (nCol + 1* m_wIndexStride + (nRow + 1* m_wIndexStride * m_wBlockSize;
132
133                *(pIndices + dwIndex++= dwTopLeft + nCol * m_wIndexStride + nRow * m_wIndexStride * m_wBlockSize;
134                *(pIndices + dwIndex++= dwTopLeft + (nCol + 1* m_wIndexStride + (nRow + 1* m_wIndexStride * m_wBlockSize;
135                *(pIndices + dwIndex++= dwTopLeft + nCol * m_wIndexStride + (nRow + 1* m_wIndexStride * m_wBlockSize;
136            }

137        }

138
139    }

140
141    if (m_nLODLevel <= 2)        //第二、第三层
142ExpandedSubBlockStart.gifContractedSubBlock.gif    {
143        //处理上边
144        if (m_nTopIndexCount == 1)
145ExpandedSubBlockStart.gifContractedSubBlock.gif        {
146            for (DWORD nCol = 0; nCol < m_nRealCell; nCol += 2)
147ExpandedSubBlockStart.gifContractedSubBlock.gif            {
148                DWORD dwBottom = dwTopLeft + (nCol + 1* m_wIndexStride + m_wIndexStride * m_wBlockSize;//m_wIndexStride + m_wIndexStride * m_wBlockSize + nCol * m_wIndexStride * 2;
149
150                if (nCol == 0)    //处理右边的三角形
151ExpandedSubBlockStart.gifContractedSubBlock.gif                {
152
153                    *(pIndices + dwIndex++= dwBottom;
154                    *(pIndices + dwIndex++= dwBottom + m_wIndexStride - m_wIndexStride * m_wBlockSize;
155                    *(pIndices + dwIndex++= dwBottom + m_wIndexStride;
156                }

157                else if (nCol == m_nRealCell - 2)
158ExpandedSubBlockStart.gifContractedSubBlock.gif                {
159                    //左下边三角形
160                    *(pIndices + dwIndex++= dwBottom;                          
161                    *(pIndices + dwIndex++= dwBottom - m_wIndexStride;
162                    *(pIndices + dwIndex++= dwBottom - m_wIndexStride - m_wIndexStride * m_wBlockSize;
163                }

164                else
165ExpandedSubBlockStart.gifContractedSubBlock.gif                {
166                    //左下边三角形
167                    *(pIndices + dwIndex++= dwBottom;                          
168                    *(pIndices + dwIndex++= dwBottom - m_wIndexStride;
169                    *(pIndices + dwIndex++= dwBottom - m_wIndexStride - m_wIndexStride * m_wBlockSize;
170
171                    //右下边三角形
172                    *(pIndices + dwIndex++= dwBottom;                          
173                    *(pIndices + dwIndex++= dwBottom + m_wIndexStride - m_wIndexStride * m_wBlockSize;
174                    *(pIndices + dwIndex++= dwBottom + m_wIndexStride;
175                }

176
177                //处理上边的三角形
178                *(pIndices + dwIndex++= dwBottom;                          
179                *(pIndices + dwIndex++= dwBottom - m_wIndexStride - m_wIndexStride * m_wBlockSize;
180                *(pIndices + dwIndex++= dwBottom + m_wIndexStride - m_wIndexStride * m_wBlockSize;
181
182            }

183        }

184        else if (m_nTopIndexCount == 3)
185ExpandedSubBlockStart.gifContractedSubBlock.gif        {
186            for (DWORD nCol = 0; nCol < m_nRealCell; nCol += 4)
187ExpandedSubBlockStart.gifContractedSubBlock.gif            {
188                DWORD dwBottom = dwTopLeft + (nCol + 2* m_wIndexStride + m_wIndexStride * m_wBlockSize;
189
190                if (nCol == 0)    //处理右边的三角形
191ExpandedSubBlockStart.gifContractedSubBlock.gif                {
192                    *(pIndices + dwIndex++= dwBottom + m_wIndexStride;
193                    *(pIndices + dwIndex++= dwBottom + m_wIndexStride * 2 - m_wIndexStride * m_wBlockSize;
194                    *(pIndices + dwIndex++= dwBottom + m_wIndexStride * 2;
195                }

196                else if (nCol == m_nRealCell - 4)
197ExpandedSubBlockStart.gifContractedSubBlock.gif                {
198                    //左下边三角形
199                    *(pIndices + dwIndex++= dwBottom - m_wIndexStride;                          
200                    *(pIndices + dwIndex++= dwBottom - 2 * m_wIndexStride;
201                    *(pIndices + dwIndex++= dwBottom - 2 * m_wIndexStride - m_wIndexStride * m_wBlockSize;
202                }

203                else
204ExpandedSubBlockStart.gifContractedSubBlock.gif                {
205                    //左下边三角形
206                    *(pIndices + dwIndex++= dwBottom - m_wIndexStride;                          
207                    *(pIndices + dwIndex++= dwBottom - 2 * m_wIndexStride;
208                    *(pIndices + dwIndex++= dwBottom - 2 * m_wIndexStride - m_wIndexStride * m_wBlockSize;
209
210                    //右下边三角形
211                    *(pIndices + dwIndex++= dwBottom + m_wIndexStride;                          
212                    *(pIndices + dwIndex++= dwBottom + m_wIndexStride * 2 - m_wIndexStride * m_wBlockSize;
213                    *(pIndices + dwIndex++= dwBottom + m_wIndexStride * 2;
214                }

215
216                //处理上边的3个三角形
217                *(pIndices + dwIndex++= dwBottom;                          
218                *(pIndices + dwIndex++= dwBottom - m_wIndexStride;
219                *(pIndices + dwIndex++= dwBottom - 2 * m_wIndexStride - m_wIndexStride * m_wBlockSize;
220
221                *(pIndices + dwIndex++= dwBottom;                          
222                *(pIndices + dwIndex++= dwBottom - 2 * m_wIndexStride - m_wIndexStride * m_wBlockSize;
223                *(pIndices + dwIndex++= dwBottom + 2 * m_wIndexStride - m_wIndexStride * m_wBlockSize;
224
225                *(pIndices + dwIndex++= dwBottom;                          
226                *(pIndices + dwIndex++= dwBottom + 2 * m_wIndexStride - m_wIndexStride * m_wBlockSize;
227                *(pIndices + dwIndex++= dwBottom + m_wIndexStride;
228
229            }

230        }

231        else if (m_nTopIndexCount == 0)    //不需要修补
232ExpandedSubBlockStart.gifContractedSubBlock.gif        {
233            for (DWORD i = 0; i < m_nRealCell; i++)
234ExpandedSubBlockStart.gifContractedSubBlock.gif            {
235                if (i == 0)
236ExpandedSubBlockStart.gifContractedSubBlock.gif                {
237                    *(pIndices + dwIndex++= dwTopLeft + m_wIndexStride + m_wIndexStride * m_wBlockSize;
238                    *(pIndices + dwIndex++= dwTopLeft;
239                    *(pIndices + dwIndex++= dwTopLeft + m_wIndexStride;
240
241                }

242                else if (i == m_nRealCell - 1)
243ExpandedSubBlockStart.gifContractedSubBlock.gif                {
244                    *(pIndices + dwIndex++= dwTopLeft + i * m_wIndexStride + m_wIndexStride * m_wBlockSize;
245                    *(pIndices + dwIndex++= dwTopLeft + i * m_wIndexStride;
246                    *(pIndices + dwIndex++= dwTopRight;
247                }

248                else
249ExpandedSubBlockStart.gifContractedSubBlock.gif                {
250                    *(pIndices + dwIndex++= dwTopLeft + (i + 1* m_wIndexStride + m_wIndexStride * m_wBlockSize;
251                    *(pIndices + dwIndex++= dwTopLeft + i * m_wIndexStride + m_wIndexStride * m_wBlockSize;
252                    *(pIndices + dwIndex++= dwTopLeft + i * m_wIndexStride;
253
254                    *(pIndices + dwIndex++= dwTopLeft + i * m_wIndexStride;
255                    *(pIndices + dwIndex++= dwTopLeft + (i + 1* m_wIndexStride;
256                    *(pIndices + dwIndex++= dwTopLeft + (i + 1* m_wIndexStride + m_wIndexStride * m_wBlockSize;
257                }

258            }

259        }

260    
261    
262}


这样LOD的地形大概完成,下面是DEBUG版本贴图:
1025 x1025 的地形:


WireFrame截图:


129x129截图:


因为129X129的顶点数较少,所以开了水面反射与折射帧数还是比较高。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值