3dtiles协议具备了超大规模的数据加载调度的能力。本人分析了cesium的源码,结合自己的理解总结了一下加载调度的实现。

3dtiles的数据结构

3dtiles是金字塔状的层次结构,最上层是不太精细的数据,越到下层模型数据越精细,渲染成本越高。一般根据视口离tile的远近来加载不同的层级。

上面的层级关系可以用父子关系描述:

roottile:parent:null  ,children:tile1,tile2

tile1:parent:rootile , children:tile3,tile4

tile2:parent:rootile, children:tile5,tile6

tile3:parent:tile1,    children:null

tile4:parent:tile1,    children:null

tile5:parent:tile2,    childrend:null

3dtiles的状态

每个tile用两种不同主线的状态来描述,一种用来描述tile的数据是否已经通过http加载到内容,一种是当前tile是否需要渲染出来。整个渲染流程都是围绕着这两种状态进行业务逻辑的编写。

数据加载状态,我们通过下面几种状态来覆盖全部:只有当LoadState为ContentLoaded的时候,tile才能够被渲染出来。

LoadState
{Destroying = -3,Failed = -2,FailedTemporarily = -1,Unloaded = 0,ContentLoading = 1,ContentLoaded = 2,Done = 3};

渲染状态,描述当前tile是否可以渲染出来,我们通过下面几种状态来描述:

None = 0,
Rendered = 1,
Refined = 2
Unrefined = 3

备注:渲染状态不会管当前tile是否内容已经加载,他只是描述当前tile在当前视口范围是否需要渲染。

状态解释:

None:表示tile刚刚创建

Rendered:表示当前正在被渲染的tile

Regined:表示当前的tile没有被渲染,但是其child有被渲染

Unrefined:表示当前tile没有被渲染,其child也没有被渲染,其parent有被渲染

这里解释下英文:Regined表示精细的,即其有更精细的模型被渲染,我们用来表示当前tile的child有被渲染。UnRegined表示非精细的,即其不精细的模型被渲染,我们用来表示当前tile的parent被渲染出来。

上面4种状态,可以描述任何一个tile当前的状态情况。

3dtiles的调度

整个3dtiles的调度,其实就是不停的去计算当前视口哪些tile可以被渲染的过程。我简化了部分不重要的逻辑,切换到重点,画了下面的流程图:

每次都是从roottile开始计算,调用_visitTile函数,该函数在渲染调度方面,主要干了3个事情,是否是叶子节点、达到sse,达不到sse。

如果是叶子节点就直接将当前tile的状态设置为Rendered,并将其tile丢进渲染的队列。

如果有子节点,就判断sse的值,sse我这里不做过多解释,有点复杂。这个参数用来判断是渲染当前tile,还是子节点的tile。

如果sse的值需要我们渲染当前tile,我们就需要所有的子child里面正在被渲染的tile的状态设置为Unrefined状态,并push到不再渲染的tile队列里面。这里是通过一个嵌套循环来实现。不过我们不需要遍历所有的子child,我们只需要遍历当前tile的状态为Regined的,Regined的状态说明可以看上一节的描述。

如果sse的值需要我们渲染子child,我们会遍历所有的子child,然后即上面的函数vistiVisibleChildrenNearToFar,这个函数内部又会重新调用_visitTile。

通过上面的逻辑,我们可以清楚的得到两个队列:renderlist和norenderlist。

renderlist表示当前需要渲染的tile队列

norenderlist表示原先是渲染状态,现在不需要在状态的队列。

得到这两个队列之后,我们就可以调用渲染的函数进行数据的渲染。不过这里需要渲染的队列tile,有可能有的数据内容还没有请求到。我们需要在渲染的时候进行过滤。

3dtiles的内存回收

我们不可能把所有的tile的数据都存储在内存里面,机器的内存是有限制的,我们也不能这么做。所以我们要把在没有在渲染状态的数据回收掉。cesium的做法是设置一个内存大小阀值来实现的。当超过这个阀值才会进行内存回收的逻辑。我这里想通过超时时间来实现。我们维护一个双向链表的回收队列。为什么是双向链表呢?这是为了可以非常快的删除任意一个节点。

我们开启一个定时器,定期的去计算哪些tile已经超过一个固定值没有被渲染了。那么我们将其从回收队列里面剔除,并将数据内容释放掉。

我们的tile在状态由Rendered变成非Rendered状态时候,我们会将当前tile丢入回收队列。

我们的tile状态变成Rendered的时候,我们又会从回收队列里面删除这个tile。

我们通过延迟回收,来实现当相机快速移动的时候,不会频繁的进行数据请求。又保证了最终内存的能够控制在一定范围之内。

3dtiles的数据请求

前面将的状态都是在说渲染状态,我们的数据何时被请求呢?这里由于比较简单,我就放在最后说了。当我们的tile的状态变成Rendered的时候,会触发数据请求命令。如果数据已经加载到内存,就不会再请求,如果数据状态为非ContentLoaded状态,我们会重新发起数据请求。

整个3dtile的最核心的调度流程大概就这些。

3dtiles加载调度原理分析相关推荐

  1. python类加载机制_PHP面向对象自动加载机制原理与用法分析

    本文实例讲述了PHP面向对象自动加载机制原理与用法.分享给大家供大家参考,具体如下: 在学习PHP的面向对象的时候,会知道很多"语法糖",也就是魔术方法.有一个加自动加载的魔术方法 ...

  2. 嵌入式操作系统多任务调度原理分析与RUST参考实现

    操作系统多任务调度原理分析与RUST参考实现 作为一名在软件领域工程师,在职业生涯的尽头能有幸接触到一部分硬件产品是我莫大的荣幸.秉承我一贯刨根问底,不搞清楚问题本质不罢休的作风和态度,结合基本的计算 ...

  3. 模块加载过程代码分析1

    一.概述 模块是作为ELF对象文件存放在文件系统中的,并通过执行insmod程序链接到内核中.对于每个模块,系统都要分配一个包含以下数据结构的内存区. 一个module对象,表示模块名的一个以null ...

  4. 【Android 逆向】整体加固脱壳 ( DexClassLoader 加载 dex 流程分析 | RawDexFile.cpp 分析 | dvmRawDexFileOpen函数读取 DEX 文件 )

    文章目录 前言 一.RawDexFile.cpp 中 dvmRawDexFileOpen() 方法分析 前言 上一篇博客 [Android 逆向]整体加固脱壳 ( DexClassLoader 加载 ...

  5. 【Android 逆向】整体加固脱壳 ( DexClassLoader 加载 dex 流程分析 | 查找 DexFile 对应的C代码 | dalvik_system_DexFile.cpp 分析 )

    文章目录 前言 一.查找 DexFile 对应的 C++ 代码 1.根据 Native 文件命名惯例查找 C++ 代码 2.根据方法名查找 二.dalvik_system_DexFile.cpp 源码 ...

  6. 【Android 逆向】整体加固脱壳 ( DexClassLoader 加载 dex 流程分析 | DexFile loadDexFile 函数 | 构造函数 | openDexFile 函数 )

    文章目录 前言 一.DexFile.loadDexFile 函数分析 二.DexFile 构造函数分析 三.DexFile.openDexFile 函数分析 前言 上一篇博客 [Android 逆向] ...

  7. 【Android 逆向】整体加固脱壳 ( DexClassLoader 加载 dex 流程分析 | DexPathList 中根据 File 加载 DexFile | loadDexFile 分析 )

    文章目录 前言 一.根据 File 加载 DexFile 二.DexPathList.loadDexFile 函数分析 前言 上一篇博客 [Android 逆向]整体加固脱壳 ( DexClassLo ...

  8. 【Android 逆向】整体加固脱壳 ( DexClassLoader 加载 dex 流程分析 | DexPathList 构造函数分析 | makeDexElements 函数分析 )

    文章目录 前言 一.DexPathList 构造函数分析 二.DexPathList.makeDexElements 函数分析 三.Element 类分析 前言 上一篇博客 [Android 逆向]整 ...

  9. 网页性能优化02-懒加载工作原理

    懒加载工作原理 1.1-懒加载介绍(以图片懒加载为例) 1.为什么要有懒加载技术 (1)img标签特点:不管图片隐藏还是显示 有src属性都会去加载 例如电商类网站,一个页面有几百张图片.有时候假设用 ...

最新文章

  1. numpy 数组 保留小数点后两位小数
  2. php cannot find libz,brew安装php70出现configure: error: Cannot find libz 错误解决方法
  3. jmeter压测过程中内存溢出
  4. 文件和目录(二)--unix环境高级编程读书笔记
  5. 三、java IO--使用字节流写入文件
  6. 计算机基础中的函数,《计算机基础》中EXCEL函数的简单使用综述
  7. ipad一直卡在白苹果_近万字多图带你玩转iPad——iPad指南
  8. 监督学习、无监督学习、强化学习概念
  9. Python学习(八):返回值变量的作用域参数的传递浅拷贝和深拷贝类对象和方法
  10. 【ZBH选讲·树变环】
  11. 5G通信名词释义详解【5G通信技术基础篇---istrangeboy精品博文】
  12. 年老时最后悔但为时已晚的几件事
  13. 许一世情 陪你 浪尽天涯
  14. 字符串java_字符串的常用方法(内建函数)
  15. js 竖向(横向)列表无缝衔接滚动
  16. 如果格局决定了人生,那么到底什么决定了格局?
  17. java虚拟机能自动处理 异常_对于非运行时异常,程序中一般可不做处理,由java虚拟机自动...
  18. vxi11协议服务器的实现,通过VXI-11协议控制LXI仪器
  19. 计算机中的M.2, PCIe
  20. python进行KNN算法分析实战(鸢尾花数据集)

热门文章

  1. cvc-complex-type.2.3: Element 'beans' cannot have character [children]
  2. 《转》SAP RM07扩展
  3. 全局流控介绍和实现思路
  4. RISC-V架构指令集开源
  5. Raspberry Pi 构建一个飞机观察器
  6. 一系列JavaScript的基础工具
  7. STM32F429HAL库ADCDMA学习笔记
  8. matlab2016a的光伏阵列,DAMPPT 光伏电池阵列输出功率受光照强度和温度变化的影响,因此最大 点跟踪( )技 matlab 272万源代码下载- www.pudn.com...
  9. 会php会javascript,javascript – 只会php和js但不会java,能做手机应用开发吗?
  10. python json库函数_Python JSON