实现基于四叉树的LOD地形时,我遇到的主要问题是如何修补地形裂缝。

本段我将描述使用LOD地形的优势,我实现LOD地形的思路,实现LOD地形核心模块的详细过程,以及修补地形裂缝的思路。

首先,LOD地形与一般地形不同:一般的地形是这样实现的:整个地形是一个三角形网格,一个513*513的地形包括513*513个顶点,512*512*2个三角形;在开始渲染地形之前,写入地形的顶点缓冲(vertexbuffer)和索引缓冲(indices buffer),顶点缓冲和索引缓冲都是数组;顶点缓冲存储的是地形的顶点,每个顶点的属性包括其自身的坐标;索引缓冲存储的是每一帧渲染的顶点的索引,在顶点缓冲中,每个顶点都有自己的索引,索引缓冲的元素便是存储于顶点缓冲中的元素的索引;每一帧渲染(Render或Draw)地形的时候,只根据索引缓冲便可渲染出地形,比如,一个3*3的地形,顶点缓冲中一共有9个元素,即9个顶点,若索引缓冲中存储的元素是{0,1,3},则渲染的是顶点缓冲中第0、1、3个顶点,渲染出的形状是部分地形:一个三角形,类似的,若索引缓冲中存储的元素是{0,1,3,1,3,4},则渲染出的形状是部分地形:由两个三角形拼接而成的正方形,若索引缓冲中存储的元素是{{0,1,3,}{1,3,4,}{1,2,4,}{2,4,5,}{3,4,6,}{4,6,7,}{4,5,7,}{5,7,8}},则渲染出的是完整的地形。LOD地形是这样实现的:整个地形也是一个三角形网格,与一般地形不同的是,LOD地形当中,距离摄像头(摄像头相当于我们的眼睛)较近的地方,地形的三角网格较多,距离摄像头较远的地形,地形的三角网格较少,这样在距离摄像头较近的地方,我们看到的地形就更细致更真实,在距离摄像头较远的地方,渲染出来的地形比较粗糙,但是我们看到的效果和用一般地形渲染远处地形呈现的效果一样,所以,LOD地形每一帧渲染的顶点个数小于一般地形每一帧渲染的顶点个数,其渲染速度比一般地形的渲染速度高。之所以选择LOD地形,是因为用一般地形的渲染方式渲染大型的地形会导致程序的运行效率比较低,而用LOD地形的渲染方式则会在渲染同样大小的地形时提高程序的运行效率。比如,只渲染512*512的一般地形时,程序的帧速率(FPS)是100帧/秒,而只渲染1024*1024的一般地形时,程序的帧速率降到20帧/秒。3D游戏不仅包括地形,而且包括其他场景,其他场景的渲染效率有时候较低,比如粒子系统、多层纹理映射等都会使程序的渲染效率降低。包括地形在内的整个场景的帧速率至少要达到30帧/秒,才能保证游戏的流畅度。所以,如果使用大型的地形,必须保证地形的帧速率达到90帧/秒以上,这样才能提高整个游戏场景的渲染效率。

其次,我在实现LOD地形时,选择的地形数据结构是四叉树(QuadTree),在开始渲染地形之前,首先写入整个地形的顶点缓冲、索引缓冲,在每一帧开始渲染地形之前,根据摄像头当前的坐标更新索引缓冲,然后根据索引缓冲渲染出地形,接下来我将详细介绍如何在每一帧更新索引缓冲。首先介绍四叉树,地形的四叉树结构QuadTreeData的核心属性:int类型的中心顶点的索引m_nCenter,int类型的左上、右上、左下、右下顶点的索引m_nCorner[4],QuadTreeData*类型的左上、右上、左下、右下四个孩子节点m_pChild[4],bool类型的真实叶子变量m_bRealLeaf,bool类型的虚拟叶子变量m_bVirtualLeaf。整个地形是一个四叉树,以下举例说明如何建造地形:一个5*5的地形,头节点的m_nCenter是12,m_nCorner[4]依次是0、4、20、24,m_pChild[0]的m_nCenter是6,m_nCorner[4]依次是0、2、10、12,m_pChild[1]、m_pChild[2]、m_pChild[3]的属性值可以此类推。以下是我定义的四叉树结构体:

typedef struct QuadTreeData  

float maxHeight;
float minHeight; vector<int> mCrackU;
vector<int> mCrackR;
vector<int> mCrackB;
vector<int> mCrackL; int m_nCenter; /// 四叉数保存的第一个值,某网格中心点的索引
int m_nCorner[]; /// 四叉树保存的第二个值 bool m_bVisible;
bool m_bVirtualLeaf; ///虚拟的叶子
bool m_bRealLeaf; ///真实的叶子,真实的叶子没有中心 int mLevel;
int mSelfCorner;
bool m_bHandled; vector<byte> mCode;
vector<byte> mCodeU;
vector<byte> mCodeB;
vector<byte> mCodeL;
vector<byte> mCodeR; double mGUID; QuadTreeData* m_pChild[];
QuadTreeData* m_pFather;
QuadTreeData* m_pAncester; QuadTreeData;

我们可以设定整个四叉树的最多层级,比如9,头结点的层级是0。若某个四叉树节点的m_nCorner[1]和m_nCorner[0]相差为1,或者该四叉树节点位于整个四叉树的第9层,则该四叉树节点为真实叶子,其m_bRealLeaf值为true,四个孩子节点的值均为空NULL,至此,整个地形的四叉树建造完成。更新索引缓冲时,首先更新虚拟叶子节点:遍历四叉树的每个节点,并评价每个节点:若该节点为真实节点,则该节点不可再分,将virtualLeaf设置为true;若该节点为虚拟节点,若该节点不满足评价公式(不可再细分),则将该节点的virtualLeaf设置为true。否则将virtualLeaf设置为false(评价公式:g=d/e×r×C1×C2 ,当g<1 ,则该节点可再分,virtualLeaf设置为false。其中,d表示节点和摄像机的距离;e表示节点边长;r=e/diff ,其中diff表示该节点四个角最大高度与最小高度的差值;C1 、C2 代表分辨率。);其次修补地形裂缝,大致思路是:四叉树的每个节点都有自己的huffman编码,通过huffman编码可以遍历到自己的位置,如下图所示:

每个节点同等级的上、下、左、右兄弟节点的huffman编码可以根据自己处于父节点的位置(左上、右上、左下、右下)推导出来。在第一步更新了四叉树的虚拟叶子节点之后,遍历所有的虚拟叶子节,通过每个叶子节点的左上、右上、左下、右下兄弟节点的huffman编码找到每个叶子节点的兄弟节点,若兄弟节点的virtualLeaf值为false,则在兄弟节点与该节点共享的边上存在裂缝,进行修补:找出兄弟节点在该边因细分所添加的三角形网的顶点,将这些点的索引依次压入该节点该条边用于修补裂缝的点的链表。至此,修补裂缝结束;最后创建新的索引缓冲:遍历所有虚拟叶子节点,若该节点四个边的用于修补裂缝的点的列表均为空,则将该节点的索引压入索引缓冲,否则,将该节点存在裂缝的边的用于修补裂缝的点的链表作为构建地形的三角形网的顶点,压入该节点的索引。至此,索引缓冲更新完毕。

效果图如下:

原文链接:

Unity教程之-基于四叉树UQuadtree在Unity中实现场景资源的动态管理

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

基于四叉树(QuadTree)的LOD地形实现

面向GPU的多LOD因子的大规模场景可视化策略

[转]基于四叉树(QuadTree)的LOD地形实现的更多相关文章

  1. 回想四叉树LOD地形(上)

           唉.~事实上这是在差点儿相同一年前实现的东西,但当时没作好记录.放了那么久了,假设不做点总结的话,好像有点对不起自己,于是·········还是做点什么吧.        我脑洞比較小, ...

  2. [译]2D空间中使用四叉树Quadtree进行碰撞检测优化

    操作系统:Windows8.1 显卡:Nivida GTX965M 开发工具:Unity2017.2.0f3 原文出处 : Quick Tip: Use Quadtrees to Detect Lik ...

  3. C++: 基于四叉树数据结构的自适应网格(初探)

    C++: 基于四叉树数据结构的自适应网格 二叉树是一种典型的非线性存储数据结构,查找效率可以达到\(O(log_2N)\),同样,这类树状结构存在许多种变体,详细参考邓俊辉老师的<数据结构C++ ...

  4. Elasticsearch 在地理信息空间索引的探索和演进

    vivo 互联网服务器团队- Shuai Guangying 本文梳理了Elasticsearch对于数值索引实现方案的升级和优化思考,从2015年至今数值索引的方案经历了多个版本的迭代,实现思路从最 ...

  5. Ogre代码学习之1——Ogre中地形lod的基础:deltaHeight的计算

    Ogre的地形系统中的重要概念:高度差,英文HeightDeltas,表示某个完整细节中的顶点,在某个它被隐去的lod中被插值之后的高度和原始高度(即高度图中的高度)之差. DeltaHeight = ...

  6. 转:Ogre TerrainGroup地形赏析

    1.1  参考 http://www.ogre3d.org/tikiwiki/tiki-index.php?page=Ogre+Terrain+System http://www.ogre3d.org ...

  7. WebGL简易教程(九):综合实例:地形的绘制

    目录 1. 概述 2. 实例 2.1. TerrainViewer.html 2.2. TerrainViewer.js 3. 结果 4. 参考 1. 概述 在上一篇教程<WebGL简易教程(八 ...

  8. Ogre 1.8 terrain 和 paging 组件

    以下转自:http://hi.baidu.com/xocoder/item/e8d87cf53d87612b753c4cfd OGRE地形生成 OGRE可以通过两个接口来生成地形,分别是void Te ...

  9. 游戏引擎架构 (Jason Gregory 著)

    第一部分 基础 第1章 导论 (已看) 第2章 专业工具 (已看) 第3章 游戏软件工程基础 (已看) 第4章 游戏所需的三维数学 (已看) 第二部分 低阶引擎系统 第5章 游戏支持系统 (已看) 第 ...

随机推荐

  1. Maven学习——安装与修改Maven的本地仓库路径

    一.Maven的下载安装配置 1.1.下载 官网 http://maven.apache.org/download.cgi 1.2.安装配置 apache-maven-3.3.3-bin.zip 解压 ...

  2. oc 字符串

    #import <Foundation/Foundation.h> int main(int argc, const char * argv[]) { @autoreleasepool { ...

  3. C语言复习

  4. 网络开始---多线程---NSThread-02-线程状态(了解)(三)

    #import "HMViewController.h" @interface HMViewController () @property (nonatomic, strong) ...

  5. MySql下载安装(Mac平台) 终端启动 XMAPP启动

    1,下载 2,点击MySQL Community Server之后,然后看到需要注册登录的节目,我们就点击最下面just start my download直接下载.懒的注册或者登陆: 3.下载后,& ...

  6. 由一个activity跳转到另一个activity

    定义一个按钮,当点击的时候跳转到另一个activity的界面 1.新建第二个activity 2.在第二个Java源码处继承第一个activity,导入 3.在source中复写Oncreat方法 4 ...

  7. unity学习网站汇总

    由于最近要学习unity3d 开发,把自己找来的资料汇总下 unity3D官方学习资源:https://www.assetstore.unity3d.com/ unity3D API查询网站:http ...

  8. LeetCode 2 Add Two Numbers(链表操作)

    题目来源:https://leetcode.com/problems/add-two-numbers/ You are given two linked lists representing two ...

  9. CentOS 6.4安装配置LNMP服务器(Nginx+PHP+MySQL)

    准备篇 1.配置防火墙,开启80端口.3306端口 vi /etc/sysconfig/iptables-A INPUT -m state --state NEW -m tcp -p tcp --dp ...

  10. ehcache整合spring注解方式

    一.简介 在hibernate中就是用到了ehcache 充当缓存.spring对ehcache也提供了支持,使用也比较简单,只需在spring的配置文件中将ehcache的ehcache.xml文件 ...