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

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

作者: 三维网格 | 来源:发表于2021-11-08 11:35 被阅读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】,第一时间获取最新文章

    相关文章

      网友评论

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

          本文链接:https://www.haomeiwen.com/subject/slduzltx.html