Cesium在2016年3月份左右推出3D Tiles数据规范,在glTF基础上提供了LOD能力,定位就是Web环境下海量三维模型数据。虽然目前3D Tiles还是Beta阶段,有不少硬伤,但3D Tiles数据规范于2016年9月30日开始了OGC标准化进程,积极成分还是很大。

之前的glTF时分享了个人对二进制格式的一些想法和谨慎的态度。3D Tiles简单说就是具备LOD能力的glTF。有了数据首先是提供API可以渲染,保证用起来,下一步就要了解该数据规范的具体特点,比如倾斜,矢量,点云,OSM等支持情况,项目实施和风险评估等。最后,作为一个数据规范,从数据生产到深层次应用,需要时间沉淀出完善丰富的解决方案。

本文主要集中在渲染调度层面。看完本文可能会觉得思路很简单。在实际应用中有很多细节,比如浏览时各种操作的差异,并发量,内存和显存管理,异步传输和Workers线程等等各种调优。思路简单,但要把这些小细节打磨好就不容易了。本文只讲诗和远方,鞋里的沙子自己来处理吧。

先看看如何加载3D Tiles数据,如上所示,Cesium提供了Cesium3DTileset类来管理,主要负责Tile的调度。在Cesium中,3DTiles就相当于一个Primitive的位置。

3D Tile表述

当我们创建一个Cesium3DTileset后,每一个Tile对应一个Cesium3DTile。如上根节点是root,content是根节点对应的文件名,这里是parent.b3dm,四个子节点,子节点对应的文件名分别为ll.b3dm……。

如上,在获取JSON对象后,首先创建rootTile根节点,然后在while循环中,以广度优先的方式遍历这个树,每个节点都有一个parentTile属性绑定父节点(根节点除外),同时有一个children数组,保存该节点对应的所有子节点。

这样,在初始化阶段,Cesium3DTileset中就保存了该3DTiles树上的所有节点及关联,当然此时只是属性信息,并没有加载数据内容,所以内存上还是可以接受。这就相当于我们读书,都会先看这本书的目录,了解一个大概。但个人认为,第一,没必要,实际上只需要找到根节点,下面按需顺藤摸瓜就可以(JSON在搜索节点上很麻烦);第二,如果数据量很大的情况下,初次加载全部节点是一个性能瓶颈。这是3D Tiles目前设计上的不足。

Cesium3DTile中通过一个简单的Cesium3DTileContentFactory工厂模式,目前主要提供四种类型。根据当前数据的具体类型(Type)来创建对应的内容(Content),本篇不涉及这块。初始化结束后,和之前glTF或primitive一样,基于状态的驱动流程:

如上是调度管理的逻辑,四个函数的作用大概如下:

  • processTiles

    • 处理Tile对应的DrawCommand状态,判断一些半透明等渲染顺序

  • selectTiles

    • 请求具体的b3dm数据,不同Type根据对应的类来完成数据的下载,根据LOD策略决定哪些Tile进入渲染队列。

  • updateTiles

    • 当前帧状态下遍历这棵树,调用该Tile对应的Model::update,完成数据的解析最终构造出DrawCommand

  • unloadTiles

    • 判断当前Tiles数目是否超过上限,卸载多余的Tile

在selectTiles函数中,首先是下载Tile对应的数据内容(b3dm后缀),通过contentUnloaded标识来判断,如果根节点的数据还没有下载,则request,然后返回。

一个简单的request,里面的信息量其实也不小,调用对应Cesium3DTile和Content对应的request来下载数据,这这里Cesium专门封装了一个RequestScheduler类来管理并发,我们最后在介绍这个。这里注意,当该数据下载完成后,则添加到两个队列:processQueue和removeQueue。

在Key2中,就是一个LOD策略的实现,上图给出了追加的逻辑注释。Cesium目前支持两种方式Add追加和Replace替换两种方式。Add方式较为简单,是Tiles求并的思路,而Replace是覆盖的思路,较为复杂,因为要控制父子节点直接的可见不可见,从代码来看,Cesium在这一块处理的比较简单,应该会出现闪烁的效果,不知道是否有人可以证实这个推测是否正确?

UpdateTiles看上去就比较简单了,指定具体的Content..update,这个过程就是之前Pimitive和Model对应的update。

对于可以卸载的Tile,则满足条件后调用unloadContent,但个人觉得这块设计的还是有些疑虑。首先,设计的很不错,从Content到BatchTable,到Model,以及Texture都提供了destory方法,但纹理还是应该提供纹理管理器的概念,解决重用纹理的释放。

让我学到的一点就是RequestScheduler类,大概思路是规定每次并发的最大请求数,每一帧收集下载请求但并不发送该请求,在下一帧对请求队列排序(相机远近),然后再发送。实现的很巧妙,方便管理。毕竟在海量数据下,有这样一个Manager来控制是很有必要的。

问题比较大的地方是删除上(因为没有大数据测试,仅从代码逻辑猜测)。第一,update和select两个都是异步或者workers线程机制,在数据量比较大的情况下会有内存泄漏。第二,Replace队列无脑删除,并不是根据当前的范围和LOD,这个在设计上是一个很大的缺陷,只考虑了可见不可见,但没有优化删除策略。

总体来说,作为一个开源项目,3D Tiles迈出了很坚实的一步,数据规范设计的很优雅,基于glTF也降低了学习成本。同时Cesium提供了渲染3D Tiles的接口,稍显不足的就是还没有成熟的,免费的数据生成工具,可以从osg转为3d tiles,这是目前最大的瓶颈。简单说,Cesium目前提供了基本技术和规范,但并没有提供完整的解决方案,同时还缺少基于3D Tiles的丰富的扩展和应用。当然,我们不能对一个开源项目要求苛刻,而且我相信,也希望Cesium后续后慢慢完善,前面把路走踏实了,慢一点都可以接受,路遥知马力,踏踏实实做事情方能立本,本立而道生,在这个物欲横流的世界,这么简单的道理,其实并不简单。

Cesium原理篇:3D Tiles(1)渲染调度的更多相关文章

  1. Cesium原理篇:5最长的一帧之影像

    如果把地球比做一个人,地形就相当于这个人的骨骼,而影像就相当于这个人的外表了.之前的几个系列,我们全面的介绍了Cesium的地形内容,详见: Cesium原理篇:1最长的一帧之渲染调度 Cesium原 ...

  2. Cesium原理篇:3最长的一帧之地形(2:高度图)

           这一篇,接着上一篇,内容集中在高度图方式构建地球网格的细节方面.        此时,Globe对每一个切片(GlobeSurfaceTile)创建对应的TileTerrain类,用来维 ...

  3. Cesium原理篇:7最长的一帧之Entity(下)

    上一篇,我们介绍了当我们添加一个Entity时,通过Graphics封装其对应参数,通过EntityCollection.Add方法,将EntityCollection的Entity传递到DataSo ...

  4. Cesium入门10 - 3D Tiles

    Cesium入门10 - 3D Tiles Cesium中文网:http://cesiumcn.org/ | 国内快速访问:http://cesium.coinidea.com/ 我们团队有时把Ces ...

  5. Cesium原理篇:3D Tiles(1)渲染调度【转】

    Cesium在2016年3月份左右推出3D Tiles数据规范,在glTF基础上提供了LOD能力,定位就是Web环境下海量三维模型数据.虽然目前3D Tiles还是Beta阶段,有不少硬伤,但3D T ...

  6. Cesium原理篇:3D Tiles(2)数据结构

    上一节介绍3D Tiles渲染调度的时候,我们提到目前Cesium支持的Cesium3DTileContent目前支持如下类型: Batched3DModel3DTileContent Instanc ...

  7. Cesium原理篇:3D Tiles(3)个人总结

    个人结论:目前,在演示层面,3D Tiles问题不大,但项目应用上就不够成熟了,所以问问自己,你是想吃瓜呢还是想吃螃蟹? 好的方面 数据规范 我非常喜欢glTF的整体设计,概括有四点:第一,数据块(B ...

  8. Cesium原理篇:6 Renderer模块(1: Buffer)

    刚刚结束完地球切片的渲染调度后,打算介绍一下目前大家都很关注的3D Tiles方面的内容,但发现要讲3D Tiles,或者充分理解它,需要对DataSource,Primitive要有基础,而这要求对 ...

  9. Cesium原理篇:6 Render模块(6: Instance实例化)

    最近研究Cesium的实例化,尽管该技术需要在WebGL2.0,也就是OpenGL ES3.0才支持.调试源码的时候眼前一亮,发现VAO和glDrawBuffers都不是WebGL1.0的标准函数,都 ...

随机推荐

  1. 纯css三角形

    三角形原理: 盒子c内容width为0,height为0,盒子给一定宽度的border,分别为四边的border设置不同的颜色,则可以得到不同样式的三角形举个简单的栗子:CSS代码 .box1{ wi ...

  2. 模块划分--MVVM指南(课程学习)

    实现流水化开发,需要使用“模块划分”的程序开发方式.如此,团队里的每个人负责某项\某几项特定的技术领域,在特定的技术领域更加专业.这样,每个人的效率更高.在专业的技能更熟练,更深入,也会提高队员的成就 ...

  3. Win7 x64 Eclipse无法识别手机 / adb interface有黄色感叹号,无法识别

    今天公司停电,因此把安卓项目带回宿舍做.宿舍的笔记本,装的是Win7 x64,手机连上电脑后,windows可以识别,但Eclipse的DDMS中却无法识别,什么都没有: 然后打开设备管理器查看,发现 ...

  4. 前端MVVM框架:Knockout.JS(一)

    前言 在我们平时开发 Web 应用程序的时候,如果项目不算特别大的话,一般都是拿 jQuery 再配合一些前端 UI 框架就在项目上面应用了.如果页面逻辑稍微复杂的话,那个在写前端 JavaScrip ...

  5. 搜索框(SearchView)的功能与用法

    SearchView是搜索框组件,它可以让用户在文本框内输入汉字,并允许通过监听器监控用户输入,当用户用户输入完成后提交搜索按钮时,也通过监听器执行实际的搜索. 使用SearchView时可以使用如下 ...

  6. Lazy.js : 让 JavaScript 变懒

    Lazy.js : 让 JavaScript 变懒 http://segmentfault.com/a/1190000000358463

  7. JavaScript 模拟装饰者模式

    /** * 抽象coffee父类,其实可以不用的 */ function Coffee () {} Coffee.prototype.cost = function() { throw '实现这个方法 ...

  8. spring mvc 注解入门示例

    web.xml <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi=" ...

  9. 爱你不容易 —— Stream详解

    作为前端,我们常常会和 Stream 有着频繁的接触.比如使用 gulp 对项目进行构建的时候,我们会使用 gulp.src 接口将匹配到的文件转为 stream(流)的形式,再通过 .pipe() ...

  10. [转载] HTTP协议详解

    转自:http://blog.csdn.net/gueter/archive/2007/03/08/1524447.aspx Author :Jeffrey 引言 HTTP是一个属于应用层的面向对象的 ...