转自: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

[Ogre][地形]OgreTerrain的实现原理分析的更多相关文章

  1. [Ogre][地形]OgreTerrain分析以及使用

    Ogre 1.7.2中的地形教程 ○读者可以对照着Ogre1.7.2中的terrain.h源码进行阅读加深理解,蓝色部分均为源码 ○去除了一些具体场景比如添加mesh,设置setAmbientLigh ...

  2. Handler系列之原理分析

    上一节我们讲解了Handler的基本使用方法,也是平时大家用到的最多的使用方式.那么本节让我们来学习一下Handler的工作原理吧!!! 我们知道Android中我们只能在ui线程(主线程)更新ui信 ...

  3. Java NIO使用及原理分析(1-4)(转)

    转载的原文章也找不到!从以下博客中找到http://blog.csdn.net/wuxianglong/article/details/6604817 转载自:李会军•宁静致远 最近由于工作关系要做一 ...

  4. 原子类java.util.concurrent.atomic.*原理分析

    原子类java.util.concurrent.atomic.*原理分析 在并发编程下,原子操作类的应用可以说是无处不在的.为解决线程安全的读写提供了很大的便利. 原子类保证原子的两个关键的点就是:可 ...

  5. Android中Input型输入设备驱动原理分析(一)

    转自:http://blog.csdn.net/eilianlau/article/details/6969361 话说Android中Event输入设备驱动原理分析还不如说Linux输入子系统呢,反 ...

  6. 转载:AbstractQueuedSynchronizer的介绍和原理分析

    简介 提供了一个基于FIFO队列,可以用于构建锁或者其他相关同步装置的基础框架.该同步器(以下简称同步器)利用了一个int来表示状态,期望它能够成为实现大部分同步需求的基础.使用的方法是继承,子类通过 ...

  7. Camel运行原理分析

    Camel运行原理分析 以一个简单的例子说明一下camel的运行原理,例子本身很简单,目的就是将一个目录下的文件搬运到另一个文件夹,处理器只是将文件(限于文本文件)的内容打印到控制台,首先代码如下: ...

  8. NOR Flash擦写和原理分析

    NOR Flash擦写和原理分析 1. NOR FLASH 的简单介绍 NOR FLASH 是很常见的一种存储芯片,数据掉电不会丢失.NOR FLASH支持Execute On Chip,即程序可以直 ...

  9. 使用AsyncTask异步更新UI界面及原理分析

    概述: AsyncTask是在Android SDK 1.5之后推出的一个方便编写后台线程与UI线程交互的辅助类.AsyncTask的内部实现是一个线程池,所有提交的异步任务都会在这个线程池中的工作线 ...

随机推荐

  1. VisualStudio如何以源码文本方式打开rc文件

    视图 >> 解决方案资源管理器 >> 右击XXX.rc >> 打开方式 >> 源代码(文本)编辑器

  2. PAT 解题报告 1049. Counting Ones (30)

    1049. Counting Ones (30) The task is simple: given any positive integer N, you are supposed to count ...

  3. 通过xib加载textfield的时候 发生 this class is not key value coding-compliant for the key textField. 情况怎么解决

    连线的时候不要选files’owner 要选xib自己的class

  4. JAVA-语法-运算符

    1.赋值运算符  =  (优先级较低) 2.算数运算符  +  —  *  /  % 3.字符串连接运算   +  (把其他类型转成字符串并和字符串类型进行连接) 4.扩展赋值运算符   +=   — ...

  5. (转)@SuppressWarnings的使用、作用、用法

    在java编译过程中会出现很多警告,有很多是安全的,但是每次编译有很多警告影响我们对error的过滤和修改,我们可以在代码中加上 @SuppressWarnings(“XXXX”) 来解决 例如:@S ...

  6. (转)json+flexgrid+jbox组合运用页面刷新<jsp>

    插件效果 1.JSP页面 1 <%@ page language="java" contentType="text/html; charset=UTF-8" ...

  7. maven的中传递依赖,maven的依赖管理(转)

    在maven的pom文件中 <dependencies> <dependency> <groupId>junit</groupId> <artif ...

  8. bean中集合属性的配置

    在实际的开发中,有的bean中会有集合属性,如下: package com.sevenhu.domain; import java.util.List; /** * Created by hu on ...

  9. c++ 中this底层

    成员变量设置在一个结构体中, 操作成员变量的成员函数,其实质上就是拥有一个隐藏的 成员变量结构体的地址指针,俗称this指针.

  10. 。。。验证码,发送不同的GET请求。。。

    今天讲课的时候,突然发现了一个新的知识点,但是作为老师的我也不会,呵呵.然而我在VIP群里问了,发现人家都会,说的是非常的精炼,是的,他们确实厉害! function changeNum(){     ...