zoukankan      html  css  js  c++  java
  • [Ogre][地形]OgreTerrain的实现原理分析

    转自:http://www.xuebuyuan.com/1482609.html

    一.世界地图

    将整个世界切分成多个Tile,每个Tile大小相同,用二维坐标形式索引起来,如图:

    中心点(0,0)位置的Tile为世界地图的中心点,例如坐标可以定位为(0,0,0),由于Tile大小相等,世界坐标与Tile就可以进行转换,可以根据玩家所在的坐标快速的定位Tile。例如,当tile长度为12000时,玩家坐标为(13000,13000) 那么可以知道玩家在索引为(1,1)的Tile上。

    二.Tile实现

    从顶点组织和材质两个主要方面做说明

    顶点组织

    Tile可以设置用多少个顶点来表达真实世界的多大单位,如用513*513个顶点来渲染出游戏世界的12000*12000面积的地表。

    由于要支持LOD,既根据相机到地表的距离,提交渲染的三角形要相应的减少。我们采用顶点数目不变,通过提交不同的索引来达到减少三角形的目的。

    现在的问题是,如果规划这些索引来满足这个需求。用四叉树进行分割是比较好的方式。

    由于是基于Ogre实现,就可以把顶点交由Rendable对象管理,这样材质的处理和到相机的距离判断都很方便。四叉树从根节点开始每一个节点都是一个Readable对象。树的根结点用最粗糙的索引,越向下越精细。这样当玩家站在这个大Tile上时,通过相机去查看有哪些节点可以被玩家看到,然后再根据距离和节点的高度(delta值)计算lod来决定是当前节点被渲染还是它的子节点应该被渲染。被渲染的节点被加入到渲染队列,渲染时回调Rendable对象的getRenderOption函数来要求提供顶点和索引,这时节点可以在这里提供自己的索引和顶点。

    注意顶点的组织有一些特殊。以下以2049*2049个顶点来表示一块Tile为例做说明

    LOD 0: 2049 vertices, 32 x 65 vertex tiles (tree depth 5)vdata 0-15 [129x16]

    LOD 1: 1025 vertices, 32 x 33 vertex tiles (tree depth 5)vdata 0-15 [129x16]

    LOD 2: 513 vertices, 16 x 33 vertex tiles (tree depth 4)vdata 0-15 [129x16]

    LOD 3: 257 vertices, 8 x 33 vertex tiles (tree depth 3)vdata 16-17 [129x2]

    LOD 4: 129 vertices, 4 x 33 vertex tiles (tree depth 2)vdata 16-17 [129x2]

    LOD 5: 65 vertices, 2 x 33 vertex tiles (tree depth 1)vdata 16-17 [129x2]

    LOD 6: 33 vertices, 1 x 33 vertex tiles (tree depth 0) vdata 18 [33]

    LOD 0 为最清晰的级别定点数最多,根结点(tree depth 0)为做粗糙的级别,顶点数最少

    树的级别还有LOD的计算公式见Terrain::determineLodLevels()函数。

    LOD0 行的信息表明这个LOD级别有2049*2049个顶点,节点数有32*32个,每个节点有65*65个顶点。

    LOD1行的信息表明这个LOD级别是与LOD0位于同一个树深度上,只不过是以不同的索引来确定顶点数

    LOD2行的信息表明这个LOD级别位于深度为4的树节点上,节点数为16*16,每个节点的顶点数为33*33

    以上3个LOD级别可以共用一套顶点,位于深度为4的树节点上,每个节点上顶点数为129*129

    LOD3行的信息表明这个LOD级别位于深度为3的树节点上,节点数为8*8,每个节点上的顶点数为33*33

    LOD4行的信息表明这个LOD级别位于深度为2的树节点上,节点数为4*4,每个节点上的顶点数为33*33

    LOD5行的信息表明这个LOD级别位于深度为1的树节点上,节点数为2*2,每个节点上的顶点数为33*33

    以上三个LOD级别共用一套顶点,挂在树的深度为1的节点上

    LOD6行的信息表明这个LOD级别位于树的根结点上,节点数为1,节点上顶点数为33*33

    解读一下以上绿色部分让人疑惑的内容

    l 为什么出现的各种数据都是2N+1?

    很简单,因为整个地表都是根据四叉树分割的规则的格子,例如5*5个顶点才可以表示4*4个格子

    l 为什么实际节点块的大小是129?

    因为索引数据是用的16位整数,最大寻址能到129*129,下一个257*257超出了范围

    l 为什么叶子节点有2个LOD级别?

    计算公式(Math::Log2(mMaxBatchSize- 1.0f) -Math::Log2(mMinBatchSize
    - 1.0f) + 1.0f); 上例中的最大批次为65,最小批次为33。所以计算出叶子节点上的lod级别为2,最大级别65是最精细的lod,33是次级,这样做是为了配合地表高度(delta)和相机距离来计算出更多样的lod层级。

    l 怎么知道哪些LOD层级/树深度可以共用一套顶点?

    顶点块都是129*129的,如上例所示16*16那一深度的129*129个顶点可够它自己和下一个深度的32*32的节点使用。2*2那一个树深度的129*129个顶点可供4*4和8*8的节点使用。具体的计算公式见Terrain::distributeVertexData()

    l 为什么总的顶点数要多于2049*2049?

    2049^2 = 4198401 vertices

    最后使用的顶点数:(16 * 129)^2 + (2 * 129)^2 + 33^2 = 4327749 vertices

    因为不是简单的平面切分顶点,而是用四叉树做分割,根据总的顶点数和最大批次最小批次等参数来决定数的深度以及顶点如何共用,所以要有2049只是作为一个基数来参考,最后用的129*129的块数才决定最终的顶点数。

    具体的计算方法见Terrain::distributeVertexData()

     

    http://blog.csdn.net/xuantao/article/details/7304073

    http://blog.csdn.net/pizi0475/article/details/6321094

    http://blog.csdn.net/swq0553/article/details/5888954

     

  • 相关阅读:
    [剑指Offer] 59.按之字形顺序打印二叉树
    [剑指Offer] 58.对称的二叉树
    [剑指Offer] 57.二叉树的下一个结点
    [剑指Offer] 56.删除链表中重复的结点
    [剑指Offer] 55.链表中环的入口结点
    [计算机网络] C++模拟telnet登陆SMTP服务发送邮件过程
    [计算机网络-应用层] 因特网中的电子邮件
    [计算机网络-应用层] DNS:因特网的目录服务
    [剑指Offer] 54.字符流中的第一个不重复的字符
    [剑指Offer] 53.表示数值的字符串
  • 原文地址:https://www.cnblogs.com/lyggqm/p/5498216.html
Copyright © 2011-2022 走看看