如何在Web上直接浏览大规模OSGB格式倾斜模型(三):实现Pa

2021-11-08  本文已影响0人  三维网格

欢迎关注公号【三维网格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】,第一时间获取最新文章

上一篇下一篇

猜你喜欢

热点阅读