- IndexedDB cache: Once 3D data is downloaded and processed we cache it in IndexedDB so we can reload it quicker.
- Streaming: We optimized parallel streaming of i3s nodes and data so scene layers load faster and in priority order.
- Progressive loading: Integrated mesh scene layers now download an intermediate level of detail (LOD) first then refine to more detailed LOD.
There are already many cache levels for scene layers: Data is cached in CDNs and on the client where the web browser automatically caches all requests. However, the geometry data for scene layers is usually in a geographic coordinate system and we need to convert it to an earth centered coordinate system for global scenes. Also, for optimal rendering performance we want to convert the data to a GPU friendly format with interleaved positions, texture coordinates, colors, etc.
Ideally, we would keep all geometry data on the GPU and render only the visible parts. However, GPU memory is very limited and we have to remove invisible nodes. To avoid repeating these transformations when displaying parts of a scene layer that we have looked at before, we store the geometry data in a format we can directly upload to the GPU in an additional cache level. This cache uses the IndexedDB API to store temporary data, so we refer to it as the IndexedDB cache. The following diagram illustrates the cache hierarchy on the client:
The diagram ends where we send out a request to the server. If you are interested further in what happens next, take a look at Paul’s excellent blog on caching in ArcGIS Online.
To create an optimal user experience it is very important to load the right data at the right time. Data that is in the center of the screen or right in front of the viewer should be loaded before data at the border of the screen or in the background. However, network latency makes it hard to use the full bandwidth of the connection and still maintain a strict ordering of requests. The following diagram shows that serial ordering of requests wastes some bandwidth due to the latency of requests (illustrated in green). On the other hand, parallel requests use the full available bandwidth, but don’t preserve the order of requests:
The optimal number of parallel requests depends roughly on three parameters: network latency, network bandwidth, and size of the requested data. In i3s services there are two main resources:
- Index Nodes: The spatial index, which tells us where the data of the service is located. This consists of many small requests.
- Geometry Data: The data we want to display on the screen. These are generally few but very large requests.
For those two different types of resources, different strategies are needed. For the small index nodes it is very important to request many nodes in parallel to hide network latency and optimally use the bandwidth. On the other hand, for the large geometry data the bandwidth of your connection is easily saturated, but requesting many in parallel makes loading individual nodes slower.
In this release, we individually tuned the parameters for these two kinds of requests to make optimal use of your bandwidth while still keeping the order in which we draw data close to the optimal order. As a result of these improvements, you can see that the loading order is very close to the optimal order (front-to-back) in the following video:
Sometimes displaying a less detailed version of your data quickly is better than waiting for the details to load, even though in the end slightly more data is being downloaded. Our level of detail system is based on the screen resolution, so we can simulate a lower resolution and first download all the nodes we would display in this case. This gives us a quick overview of the layer, and we can then start to refine the display with more detailed data.
The loading order between those two levels of detail is another interesting topic. In general, we want to download the low detail geometries first, however, we want to start refining data in the center of the display while still downloading low detailed background nodes. To do this we add a penalty dependent on the scale of the current view to our node ordering priority, which is based on the distance to a point of interest.
We tested this with various scene layers and concluded that this is a big improvement for integrated mesh scene layers, as can be seen in the following video:
In the top right corner of this video, you can see that even if we don’t have the current view in cache already, the progressive loading downloads an overview of the scene’s content very quickly. While the total loading time is slightly longer than the non-progressive loading on the left side, the difference can only be noticed in the background and overall the progressive loading feels much faster.
I hope you like the performance of 3D scene layers in Scene Viewer. I’m looking forward to many web scenes and apps being created that really showcase your data. There are still many opportunities where we can do better and this is an exciting topic that we will keep working on. Stay tuned for the next release to see even more improvements in this area.
Screenshots and videos: