实现基于四叉树的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]的属性值可以此类推。以下是我定义的四叉树结构体:

  1. typedef struct QuadTreeData
  2.  
  3. float maxHeight;
  4. float minHeight;
  5.  
  6. vector<int> mCrackU;
  7. vector<int> mCrackR;
  8. vector<int> mCrackB;
  9. vector<int> mCrackL;
  10.  
  11. int m_nCenter; /// 四叉数保存的第一个值,某网格中心点的索引
  12. int m_nCorner[]; /// 四叉树保存的第二个值
  13.  
  14. bool m_bVisible;
  15. bool m_bVirtualLeaf; ///虚拟的叶子
  16. bool m_bRealLeaf; ///真实的叶子,真实的叶子没有中心
  17.  
  18. int mLevel;
  19. int mSelfCorner;
  20. bool m_bHandled;
  21.  
  22. vector<byte> mCode;
  23. vector<byte> mCodeU;
  24. vector<byte> mCodeB;
  25. vector<byte> mCodeL;
  26. vector<byte> mCodeR;
  27.  
  28. double mGUID;
  29.  
  30. QuadTreeData* m_pChild[];
  31. QuadTreeData* m_pFather;
  32. QuadTreeData* m_pAncester;
  33.  
  34. 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. 分形几何算法和实现(C语言)

    初识分形 1.分形的含义: 英文单词Fractal,它是由美籍法国数学家曼德勃罗(Benoit Mandelbrot)创造出来的.其含义是不规则的.破碎的.分数的.曼德勃罗是想用此词来描述自然界中传统 ...

  2. Struts2(十一)OGNL标签三与Struts2标签

    一.UI标签 二.简单例子 <h1>添加信息</h1> <!--通过指定theme的属性改变主题 --> <s:form action="" ...

  3. 颠覆式前端UI开发框架:React

    转自:http://www.infoq.com/cn/articles/subversion-front-end-ui-development-framework-react/ 基于HTML的前端界面 ...

  4. 《SQL Server企业级平台管理实践》读书笔记——SQL Server中收缩数据库不好用的原因

    数据库管理员有时候需要控制文件的大小,可能选择收缩文件,或者把某些数据文件情况以便从数据库里删除. 这时候我们就要使用到DBCC SHRINKFILE命令,此命令的脚本为: DBCC SHRINKFI ...

  5. Gulp使用入门操作十一步压缩JS

    前提需要安装nodejs 一. 全局安装Gulp npm install -g gulp 二.新建一个 gulpfile.js 文件 chapter2└── gulpfile.js 三.在 gulpf ...

  6. 在Ubuntu Server下搭建LAMP环境学习记录

    更新于2015/6/16日,因图片地址失效,请在此地址查看:http://note.youdao.com/share/?id=1c249ae6dc6150cbf692adec67b23a33& ...

  7. 基础总结篇之一:Activity生命周期

    子曰:溫故而知新,可以為師矣.<論語> 学习技术也一样,对于技术文档或者经典的技术书籍来说,指望看一遍就完全掌握,那基本不大可能,所以我们需要经常回过头再仔细研读几遍,以领悟到作者的思想精 ...

  8. [工具] 分布式系统下批量创建用户及分发公钥打通ssh通道的脚本

    在分布式系统下偶尔会有这样的需求,要增加一个服务时,需要在集群的所有节点上创建同一个用户,然后打通ssh通道,再分发软件包.配置.执行命令.启动服务... 这个问题的根源是如何集中配置和管理系统,专业 ...

  9. A + B Problem II

    之前总是在查阅别人的文档,看着其他人的博客,自己心里总有一份冲动,想记录一下自己学习的经历.学习算法有一段时间了,于是想从算法开始自己的博客生涯O(∩_∩)O~~ 今天在网上看了一道大数相加(高精度) ...

  10. Web性能优化之动态合并JS/CSS文件并缓存客户端

    来源:微信公众号CodeL 在Web开发过程中,会产生很多的js/css文件,传统的引用外部文件的方式会产生多次的http请求,从而加重服务器负担且网页加载缓慢,如何在一次请求中将多个文件一次加载出来 ...