CesiumGS/3d-tiles

Availability as you need it rather than explicitly listed for all tiles

jerstlouis opened this issue · 9 comments

(in the context of implicit tiling)
In OGC API - Tiles, we have this recommendation to return an HTTP response header that indicates whether a requested tile is "empty" or "full". (See recommendation 3).

In either case, a client would know not to look for tiles at any deeper level when comes the time for refining to a greater detail.

This avoids the need to explicitly provide tiles availability for the tileset, and allows for a single tileset for the entire world without the need for any tileset metadata proportional to the extent / detail of that data. All that is needed in terms of TileSet metadata is the particular tiling scheme in use, and its limits (i.e. extent) within that scheme, if any (see also #587 avoiding the need for transforms).

Another interesting idea that we should consider. Some initial thoughts...

In either case, a client would know not to look for tiles at any deeper level when comes the time for refining to a greater detail.

Does this too strongly assume that refinement is top-down? There may be other traversal strategies or analytics that benefit from availability being present in memory and fast random access.

This does add a tiny bit of complexity to the server. If I'm understanding correctly tiles wouldn't be able to be served statically?

Note that subtrees can store various types of tile metadata (including tighter min/max) in addition to availability so there is still some benefit in partitioning the implicit tileset into subtrees.

Does this too strongly assume that refinement is top-down? There may be other traversal strategies or analytics that benefit from availability being present in memory and fast random access.

True, but the overhead of going top-down is roughly 33% and in a 3D viewer scenario is really beneficial as you will always want to have the next lower level cached in memory as you move away and want to reduce resolution. A separate query / availability of this information could still be provided, but a full availability for a detailed worldwide dataset is not practical with a single / simple tileset. For a dynamic server, you could always request availability for a particular area / level of details as a separate operation to handle those non-visualization use cases where that could be useful.

This does add a tiny bit of complexity to the server. If I'm understanding correctly tiles wouldn't be able to be served statically?

This would require the ability to respond with a specific HTTP header, which probably could be configured with e.g. a simple Apache server somehow, but maybe not on an S3 bucket? The same information could also be embedded in the parent tile's payload somehow.

Note that subtrees can store various types of tile metadata (including tighter min/max) in addition to availability so there is still some benefit in partitioning the implicit tileset into subtrees.

I think the key piece of information we are currently missing in our implementation for 2D TileMatrixSets is min / max height information, since the spatial extent can be inferred from the limits of the tiles in terms of min and max rows/columns. I think that would also be an interesting candidate for information to embed in the parent tile's payload for each child tile. See also somewhat related suggestion in #582 (comment) to handle nearby tiles with content spilling into neighboring tiles (allowing to do a simple visibility testing purely based on the tile's extent -- irrespective of content, before refining based on the glTF node hierarchy bounding boxes).

I have a strong opinion (from our own efforts implementing 3D Tiles support in our client) about tiles pointing to tilesets greatly over-complicating things. It also does not fit the "single tileset" / single URI template of OGC API - Tiles / simple random access to ANY tile in the whole tileset.

Sorry to be late joining this conversation but I am doing my first steps in the 3D tiles ecosystem, trying to generate a global tileset of GLTF content.

My initial (and very naïve) expectation was that 3D tiles could work in a similar way than imagery or terrain providers do in Cesium. Tiles would be loaded as required by some visibility rules (SSE, distance, refinement, etc.) and refined as long as available and/or bound to a min/max level.

The concept of availability (and the subtree structure in general) is, at first, difficult to understand and eventually, makes implementation complicated.

I can understand the necessity for more complex traversal methods, storing granular metadata, etc... but in my case, I am just looking for simplicity of tileset generation.

I would be quite happy with a more rustic way of handling the tileset, specifying a minimum/maximum zoom level, and trusting the client to stop loading/refining when nothing is served back to it (http headers)

Yet again, I am just starting with 3D tiles and have a naïve understanding of the mechanics involved so I may just completely have missed the point.

To further prove my point, and as I am fiddling and try to work around the current model (sorry), I made a tileset with just one 0_0_0.subtree spanning all 14 levels of my tiles tree, and with the following content:

{"tileAvailability":{"constant":1},"contentAvailability":[{"constant":1}],"childSubtreeAvailability":{"constant":0}}

I thought this would force the tiles to be fetched ad-hock, just as described in my previous comment.

Cesium then goes into a loop and crashes the browser with an out-of-memory exception.

I know I am being silly here but this shows that the complexity of this model may lead some other silly developers into despair and/or trouble. .

This also makes me wonder about what Cesium is doing with the subtree structure: is it being pushed into memory for later processing? If yes, this sort of defeat the purpose of "streamed" tiles

Just to keep updating the idea developed in this thread, I would like to share my recent attempt at using 3dtiles.

I generated a global dataset of 3D buildings (similar to Cesium's OSM buildings) but found the concept of tiles availability and subtree definitions too dauting. Because of this complexity, I ended up not using 3Dtiles in the end and made a very crude GLFT tiles loader. This loads tiles at 3 different zoom levels based on distance from camera. If a tiles does not exist, the server returns 404 and... that's it. While not very elegant, my "super_fast_and_optimized_NGINX_static_server" does not mind returning many 404s.

While this does the job, it is missing all the smart LOD features you get when using 3D tiles (ScreenSpace error, culling, etc.) which my application would very much benefit from.

Hence the idea of having a simplified 3DTiles mode that would not rely on subtree definition for tiles availability but just stop loading sub-tiles when the server returns 404.

Does this make sense? Would such a hybrid mode be possible?

Would such a hybrid mode be possible?

@xtassin The OATiles-hint response header in OGC API - Tiles (recommendation 4) allows to make the distinction between nothing here at this particular generalization level vs. don't bother requesting this at any deeper level. Note that you can return any kind of content with OGC API - Tiles, including batched 3D models as binary glTF (see also 2DTMS Annex J on additional dimensions).

@jerstlouis, I fail to see the distinction in the OGC API. Anyways, "don't bother requesting this at any deeper level" implies that you (your server) somewhat already know about sub-tiles availability. My tileset is even more dumb than that and the server just returns tiles when they exist or 404 when they dont. I expect the client to stop the tiles refinement when 404 is returned. The whole process only relies on a static dataset, a properly configured HTTP server and a client that knows when to stop. This saves on complexity when generating the tileset, limits the number of files stored on the server and the number of HTTP requests sent.

@xtassin The distinction is e.g., a tile for a large area which only contains smaller buildings that are not relevant or visible from afar, but as you get closer to the tile, those small buildings become visible. In this case, the large tile would have had no glTF payload, but not the OATiles-hint: empty response header, so the client would still refine it when it gets closer.

A dumb server may not support this, which is why this is only a recommendation. However, if a client is expected to stop refining when 404 is returned (not the case with OGC API - Tiles, unless OATiles-hint: empty or full is included in the response), then you would need a 200 empty payload tile to ensure that the client does refine this large tile with nothing to see.

@jerstlouis thanks, this is very clear and indeed, a flaw in my (too) dumb mechanism. However, I do not see a real problem with a 200 response with empty payload to indicate further refinement, and stopping at a 404 down the tree. This would still allows to implement a simple static server and rely on actual file availability instead of meta data. (would that be an advantage though?)