TilesRenderer: "ADD" seems to always load all child tiles
Question
Hi
I'd like to write a plugin with a calculateTileViewError function which returns inView: false if the tile is farther away than a certain distance from the camera. As far as I can see in the current implementation [1], a plugin can only override inView to true, but not to false if the tile volume was above found to intersect the frustum.
Is it possible with the current plugin mechanism to implement hiding of far away tiles?
[1] https://github.com/NASA-AMMOS/3DTilesRendererJS/blob/master/src/three/renderer/TilesRenderer.js#L973
Supplemental Data
No response
Library Version
0.4.11
Three.js Version
0.170.0
Hi @manisandro! This sounds similar to what @xawill and @jsulli were interested in (see #1116 and #1062), though I'm not sure if there's been any more work done in that direction. It's otherwise not supported at the moment.
What's your usecase in this specific instance, though? If you're just trying to modify the far plane for the camera used for traversal it would be much easier to just create a "dummy" camera that mirrors the positoni and settings of the real camera but with a different far plane.
Thanks for your reply! My use case is the following: I have a with a 3D tiles model of a city. Especially in first-person-view mode, the performance is heavily affected by the fact that the frustum cone is horizontal an hence all tiles in the view direction will be loaded. Performance is even more affected when rotating the first-person camera, as it will mean that many new tiles from the camera point to the horizon will change their visibility. I've experimented, overwriting the calculateTileViewError function prototype, by clamping the visibility depending on the camera distance, and it brings a noticeable performance improvement. What I'd also like to experiment is setting that distance very close while rotating the camera, and then gradually increasing the distance while the scene is idle, as to gradually load the buildings from near to far.
the performance is heavily affected by the fact that the frustum cone is horizontal an hence all tiles in the view direction will be loaded.
Generally this shouldn't be an issue if the tile set data is structured well assuming the performance bottleneck is the number of tiles loaded and rendered in a frame. If you can share the tile set I can take a quick look at the structure.
What I'd also like to experiment is setting that distance very close while rotating the camera, and then gradually increasing the distance while the scene is idle, as to gradually load the buildings from near to far.
Again this shouldn't be necessary if the data source is well formed but if you'd still like to try it I recommend passing a dummy camera with your modified camera settings into the TilesRenderer instead of using the main camera.
The tileset is at [1], to see it in action see [2] (note that initial loading might be very slow if you are in a region for which the CDN has not yet cached the data, but once loaded, subsequent performance should be good). Thanks!
- [1] https://data.sourcepole.com/3dtiles/stadt-zuerich/tileset.json
- [2] https://qwc2.sourcepole.ch/?c=2652685%2C1189401&s=1000000&l=Buildings&bl=ch.swisstopo.pixelkarte-farbe&t=zh_1&v=3d&bl3d=ch.swisstopo.swissimage&v3d=2683202.9%2C1241426.1%2C6512.8%2C2683810.1%2C1246400.6%2C0.0%2C0.0
Thank you for the link to the tile set. It looks like this tile set is fairly flat and using the "ADD" refinement at the root of the hierarchy, which is correct. This project hasn't been tested with many "ADD" refinement tile sets, though, since there haven't been that many available to test with and it looks like there may need to be some changes to this project to support ADD correctly.
It may be a few weeks before I can look into this but in the mean time I recommend using a "dummy" camera and setting the far plane to a shorter value.
Ok thanks! Do you have some pointers re. setting the dummy camera which I can look at?
// create a dummy camera with the adjust near plane
const dummyCamera = camera.clone();
dummyCamera.near = 1000;
dummyCamera.updateProjectionMatrix();
tiles.setCamera( dummyCamera );
// ...
// update the dummy camera position to match the render camera before updating tiles
dummyCamera.position.copy( camera.position );
dummyCamera.rotation.copy( camera.rotation );
dummyCamera.updateMatrixWorld();
tiles.update();
Thanks a lot!
Maybe an obvious point, but have you tried significantly raising the errorTarget @manisandro? Your initial post mirrors the confusion I had when messing with plugins to alter tile loading behavior - but it seems like your complaint (tiles refine too aggressively) could be addressed without any of that.
Yes I tried, but as far as I could read from the code the error target only applies to subdivisions of a root tile, not whether the root tile itself is displayed or not - that is only decided based on whether the tile volume is in the frustum or not.
@manisandro I've taken a look at this projects behavior vs cesium and confirmed that Cesium is handling "ADD" refinement children differently and loading fewer of them (unless "loadSiblings" is set to "true") and displaying fewer of them. Regarding your performance issues - can you confirm whether your concern is the number of tiles downloaded or the number of tiles rendered?
I've looked through the refinement section in the spec again and through the traversal logic in this project and as far as I can tell it's doing the correct thing by the word of the spec. However, looking into Cesium's approach a bit further - it looks as though Cesium is using the parent's to evaluate visibility of the children of "ADD" refinement tiles - the logic for which doesn't seem to be clear from the comments. I'll have to submit and issue at Cesium to clarify.
I'm looking to reduce the number of tiles rendered (which I suppose will initially also affect the number of tiles downloaded). I.e. ideally I'd like to implement a slider with which I can control how far away tiles are rendered, to allow reducing the rendering load on low-end machines.
I'm looking to reduce the number of tiles rendered (which I suppose will initially also affect the number of tiles downloaded)
In this case it would really be more relevant to improve structure of the data set. Simply providing a flat list of nodes under a single parent is side stepping what makes 3d tiles efficient to render. It would be better to provide bounded subtrees under the parent node (eg something like a quad tree) so that the tiles traversal algorithm can more effectively choose what to render. Then the "error target" can be raised in order to accommodate less powerful machines, as is intended, rather than hacking around with render distances. Is there a reason this tile set hierarchy can't be split up?
I've also opened an issue at the cesium forum to discuss Cesium's current handling of "ADD" tiles and it seems there's at least some initial agreement that this behavior is not strictly inline with the 3d tiles specification so for now I'd like to see how this conversation plays out.
This is important to address, but as a fallback (since we don't necessarily know how users will produce their tiles) I've also implemented setting a closer far plane when rendering the 3D tiles (and for the matter, also other threejs objects), which is working well. From my point of view, this can be closed. Thanks for the suggestions!
I opened PR #1261 with my proposal. Not sure if this fits your needs @manisandro however.
Thank you for the link to the tile set. It looks like this tile set is fairly flat and using the "ADD" refinement at the root of the hierarchy, which is correct. This project hasn't been tested with many "ADD" refinement tile sets, though, since there haven't been that many available to test with and it looks like there may need to be some changes to this project to support ADD correctly.
@gkjohnson Here is another tileset of 3D buildings you can try. It covers whole Switzerland (small country, but still).