瓦片(Tiles)
iTwin.js 显示系统负责在 web 浏览器的限制下,可视化来自各种来源的大量数据。它主要通过使用瓦片来实现这一点,瓦片是一种将大型模型的几何体划分为子体积层次结构的机制,每个子体积表示模型几何体在特定细节级别的一部分。结果是一个 TileTree,可以高效地查询只渲染与用户当前查看的空间体积相对应的模型部分所需的瓦片,其详细程度适合于当前的视锥和视口分辨率。
显示系统可以聚合来自各种来源的不同类型的瓦片,包括:
- iModels,采用 iTwin.js 后端生产的瓦片;
- 标准 3DTiles 格式,如 Bentley ContextCapture 生成的实景和点云;
- OrbitGT 格式的点云;
- 来自各种来源的地图图像,包括 Bing 和 MapBox;
- Cersium 三维全球地形网格;
- OpenStreetMap 提供的全球建筑白模;
- 应用程序通过 TileGraphicsProviders 提供的任何格式的 3d tiles;
Cesium 的 《3DTiles 参考》 提供了一般概念的良好概述,以及标准 3d tiles 格式的一些特定细节。
iTwin.js 后端生产的瓦片(Tiles)为 iModel 瓦片格式,这在许多方面与其他格式不同。
1. 场景创建
空间视图可以按照其 ModelSelector 的指定聚合任意数量的空间模型(Model)。每个模型都与一个 TileTree 关联,该 TileTree 为该模型提供图形。下面的动画 GIF 演示了如何将办公楼的空间视图由四个独立的模型组成:一个提供管网,另一个提供结构元素,第三个是建筑组件,最后是景观。
视图(View)还可以包含与真实模型、地图、地形或自定义提供者关联的 TileTree。组装场景需要遍历每个 TileTree,选择最适合显示的瓦片(Tiles),可能需要排队请求以加载更合适的瓦片,最后将瓦片渲染到屏幕上。
此过程主要由 TileTreeReference.addToScene 实现。虽然 TileTreeReference 的不同实现的细节有所不同,但它通常看起来像以下内容,从根(Root)文件开始:
If the tile intersects the viewed volume and any clip volumes applied to the view or model:
If the tile is of appropriate level of detail for the current view:
If the tile's graphics are loaded:
Select the tile for display.
Otherwise:
Select the tile for loading.
If the graphics of the tile's direct descendants are loaded:
Select the descendant tiles for display.
Otherwise, if the graphics of the tile's direct ancestor are loaded:
Select the parent tile for display.
Otherwise:
Repeat the process for each of the tile's direct descendants.
选定要显示的所有瓦片的图形将添加到场景图中。然后,渲染器将图形解构为有序的渲染命令序列,并将其组织为多个渲染过程。例如,在一个过程中绘制不透明几何体,在后续过程中绘制透明几何体。最后,将这些命令提交到 GPU,并将新图像快速显示到屏幕上。
2. 瓦片加载
瓦片通常在没有图形的情况下出现-仅当(如果)在场景创建期间选择瓦片进行显示时,才会加载其图形。TileAdmin 维护一个瓦片内容请求队列。在任何给定时间,最多可以有 N 个内容请求处于“飞行中”;其余的驻留在优先级队列上。精确的最大值取决于应用程序配置;对于 web 应用程序,默认值为 10,以考虑 HTTP/1.1 的限制;对于桌面和移动应用程序,它基于客户端设备的硬件并发性。取消时,将从队列中删除挂起的请求,例如,如果视锥发生更改,以至于不再需要在任何视口中显示瓦片的图形。
3. 资源管理
瓦片图形消耗图形内存,瓦片本身消耗 JavaScript 堆内存。在一段可配置的停用期后,通常会丢弃瓦片及其 WebGL 资源和所有后代。同样,整个 TileTree 在(通常更长)的停用期后也会被丢弃。
每个瓦片跟踪记录其从 WebGL 请求的内存总量。TileAdmin.gpuMemoryLimit 可以配置为对所消耗的图形内存量的限制;如果瓦片占用的内存总量超过此限制,则丢弃最近使用最少的瓦片的图形,直到满足该限制为止。瓦片本身不会被丢弃,当前选择在任何视口中显示的任何瓦片的图形也不存在丢弃。此限制需要根据不同场景进行平衡:过低的限制可能会导致对相同瓦片内容的重复请求过多;而过高的限制可能会超过客户端的可用图形内存,通常会导致上下文丢失。