如何在Web上直接浏览大规模OSGB格式倾斜模型(三):实现Pa
欢迎关注公号【三维网格3D】,第一时间获取最新文章
在上一篇《如何在Web上直接浏览大规模OSGB格式倾斜模型(二):转换OSGB》中,我们已经实现单个osgb格式模型的转换和显示,本篇我们来实现PagedLOD,加载大规模的模型。
在开始之前,先来感受一下我们商业版的性能优势:
解析性能对比:开源版vs商业版
两个字:快,稳!
欢迎咨询,后台回复【商务合作】,获取联系方式!
正文开始了,代码量比较大,3.1.1节之后内容,推荐在电脑上阅读。
1、认识PagedLOD
简单说,PagedLOD可以从Paged和LOD两方面来认识。
首先认识LOD,这是一种技术,英文全称是Levels of Detail,意为多细节层次,《地理信息系统名词》第二版,也称为细节层次模型,并给出定义:通过建立原始精细模型的多个近似简化模型,表示原始模型不同程度的细节。三维渲染引擎,根据视点与模型的距离,加载不同简化程度(细节层次)的模型,达到提升渲染效率和浏览体验等目的。
1.2、Paged
然后认识Paged,这可以理解“分页的”,强调LOD的组织方式,即各个层次的模型的存储和检索,模型文件之间的链接关系。
1.3、PagedLOD
本质上,PagedLOD是一颗调度树,可以是四叉树,也可以是八叉树。
如基于数字高程的地形图层则可以用四叉树,将一定空间范围的包围盒,按一分为四的方式,逐级细分,这个过程中,可以理解为细分的包围盒高度上始终不变。
而我们研究的倾斜摄影模型数据集,本质上是一个八叉树集合,但并不是严格的八叉树,生成过程大概可以这样理解:
(1)先将包含数据集内所有点的包围盒,等分为x*y个小包围盒,得到x*y颗八叉树的根节点,这里的x和y就是我们后面要用的行列号,对每一个根节点进行(2)至(7)步操作;
(2)用根节点包围盒去裁剪原始模型,得到根节点原始模型;
(3)对根节点原始模型,进行简化,得到根节点模型;
(4)将根节点细分(节点包围盒一分为四或者一分为八)得到子节点,或者仅对原始模型进行简化(节点包围盒不变),这一级的模型比根节点更清晰;
(5)对第(4)步中生成的子节点进行第(6)至(7)步操作,直到模型的细节(清晰度)与原始模型一致。
(6)用子节点包围盒去裁剪根节点原始模型,简化,得到子节点模型;
(7)将子节点细分,或者仅简化节点模型,得到孙节点;
2、OSGB倾斜模型文件结构
在开始实现之前,我们结合解析结果来加深对PagedLOD的认识和理解。一个倾斜模型osgb文件,可能有两种情况:
(1)只包含一个LOD节点,解析结果根节点类型就是PagedLOD,这种情况对应根节点或者第1.3节(4)、(7)步中节点包围盒不变的情况;
(2)包含多个LOD节点,对应第1.3节(4)、(7)节点细分的情况。
2.1、单个PagedLOD
2.2、多个PagedLOD
2.3、LOD参数
Center和Radius节点包围球,Center为中心,Radius为半径,可用于视锥裁剪过滤,计算决定是否加载下一细节层次的参数range。
FileNames文件名,第二个为下一层次模型文件名。
RangeList第一个为当前层次可见的范围,即当range大于范围最大值时,加载下一个细节层次的模型。
RangeMode指示range参数计算模式。
0表示range和RangeList中的值是视点到节点中心的距离;
1表示range和RangeList中的值是包围球投影后占屏幕的像素(只是一个估算值)。
3、实现PagedLOD
关键步骤:
(1)从根节点开始,遍历调度树;
(2)检查是否有下一层次,如有则继续,否则显示当前层次模型并结束遍历;
(3)计算range, 包围球投影,估算占据屏幕像素数;包围球中心到视点的距离;
(4)如果range大于RangeList[0].max,检查下一层次是否已经加载;
(5)如果未加载,则开始请求下一层次模型文件,并显示当前层次模型,结束遍历;
(6)如果已经加载,则从下一层次开始遍历,重复(2)至(6);
渲染流程:
1.遍历子节点:按其状态分别加入可渲染队列、待加载队列、待转换队列;
2.处理可渲染节点:将节点内容包含的3d对象加入渲染队列;
3.对待加载列表和待转换列表进行排序;
4.处理待转换节点:转换osgb;
5.处理待加载节点:加载、解析osgb;
6.内存管理:当估算的内存占用超过阈值时,卸载过期瓦片。
实现效果(three.js版):
3.1、接口定义
LOD类封装基本的计算功能,包括包围球投影,距离,视锥裁剪等。
PagedLOD类封装当前层次的模型创建、显示等功能,并根据RangeList和FileNames创建下一层次节点(类型为PagedLODSet)。
PagedLODSet类封装osgb文件读取、解析、创建当前层次的节点(类型为PagedLOD),渲染,射线查询,创建并导出索引等功能。
PagedLODQueue类封装排队功能,包含入队,出队,排序等。
PagedLODContent类负责转换osgb,创建并提供节点模型3D对象。
3.1.1、PagedLODSet类
构造函数参数解释:
url数据集路径,可以是:
metadata.xml路径
索引文件index.json路径
metadata.xml或者index.json所在文件夹路径,优先尝试加载index.json,不存在则自动加载metadata.xml
osgb模型文件,单个模型LOD
lodScaleLOD缩放倍数,同一视野下,倍数越大,显示的瓦片分辨率越低,同时渲染的瓦片越少
maxMemeory当估算的内存占用(单位为byte)超过该值时,卸载过期瓦片。默认为 1024 * 1024 * 500
maxRequest最大并发请求数量,如果当前请求数量超过该值,则当前帧不发出新的请求。默认为 4
maxParsing最大转换任务数量,如果当前未完成转换的任务数量大于等于该值,则当前帧不启动新的转换任务.默认为 1
domains负载均衡数据服务节点列表。url中节点模板标记为{t},即url形如:http://{t}.ds.mesh-3d.com
pendingSortFunc自定义排队函数,用于对待请求和待转换瓦片队列的排序。对排队结果的应用:越靠前越早被处理(请求、解析数据或转换osgb)
onInitProgress初始化进度回调函数,仅数据集没有创建索引文件index.json时有用,因为此情况下需要按给定的行列号范围,逐个尝试猜测的根节点文件是否存在,耗时比较长
grid入口文件为 metadata.xml 时,需指定行列号范围(minX/Y,maxX/Y),数据目录相对路径等信息
minX最小列号,默认为 0
maxX最大列号,默认为 8
minY最小行号,默认为 0
maxY最大行号,默认为 8
dataDir数据目录相对路径,相对于metadata.xml或者index.json所在文件夹,默认为'/Data'
tilePattern瓦片文件名(不包含后缀)模板,默认为'Tile_{x}_{y}'
ext瓦片文件后缀,默认为'osgb'
proxy代理,可选
debugVolumetrue则创建并显示调试线框(瓦片包围盒)
debugVolumeOnlytrue则仅显示调试线框
3.1.2、LOD类
3.1.3、PagedLOD类
3.1.4、PagedLODContent类
下面贴出关键代码,都是从可运行的源码中直接复制过来的,可以说比较详尽了,希望对你动手实现有帮助。
3.2、包围球投影
3.3、LOD计算range
3.4、PagedLOD初始化
3.4、PagedLOD遍历
3.5、PagedLODSet初始化
3.6、PagedLODSet遍历
3.7、PagedLODSet渲染程序入口
欢迎关注公号【三维网格3D】,第一时间获取最新文章