Hello
We have implemented a custom 3D Tileset 1.1 generator that uses implicit tiling to define the various octree nodes. The generated tilesets work as expected with the Cesium Viewer, provided no textures are applied.
For example, here is a mesh tiled with 3 subtree levels and debugShowBoundingVolume: true
enabled in the Cesium Sandcastle viewer. The tileset is defined using "refine": "ADD"
so more detail appears as the model is zoomed in:
You can see that the implicit tiling node boundaries work as expected, and the nodes correctly appear/disappear as the camera is zoomed in/out.
However, here is the exact same model and view projection, but this time now with
baseColorTexture
defined on the mesh material. There are no other differences between the scenes/models:
Notice how now only the first subtree level nodes are rendered? This makes the model look broken, as the tiles in the more-detailed levels are missing…
Why is there a difference between how the implicit tiles are resolved when there is a texture present, versus when there is not? Is there a way to make the textured version behave the same as the non-textured version?
This tileset by default has a root geometricError
of ~10.5 (calculated as 10% of the diagonal length of the root bounding box), however I tried adjusting this to various values (1, 100, 1000, 10000 etc), and it makes no difference to how the textured tileset is rendered. However as expected, changing geometricError
does affect how the non-textured tileset is rendered (e.g. a geometricError
of 1 gives a similar broken mesh to the textured tileset).
Any idea how I can fix this such that the textured tileset has the same implicit tiling as the non-textured tileset? I don’t understand why there is a difference.
Thanks
From the description so far, this indeed sounds like a bug (and a surprising one, for what it’s worth - I cannot imagine how the texture should affect the tile selection algorithm at all).
One wild guess - and a somewhat shallow one, admittedly - could be that it just has a problem with the texture itself. For example, when the texture data is “invalid” in some way, then it would fail to load these tiles, and they would simply not appear. But that should at least cause some error messages in the console.
Is it possible to share such a tileset (one that is as small and as simple as possible) to reproduce the issue? (I could try to create a tileset that matches your description, but … that could be a bit of effort, and when it does not show the behavior that you described, we’d be back at square one).
Yes I"m happy to share the sample tilesets with you. Do you have a private upload capability I can use to send it to you? This is client data that I’m not sure can be shared publicly.
FWIW, you can see the texture working correctly in the second screenshot above - it is the jagged-line looking geometry that crosses the boundaries between tiles. These are the triangles that do not fit entirely in the lower-level subtree nodes (hard to see against the background terrain).
Iff that data is not too large (i.e. only a few MB), then maybe you can send the data sets via mail to marco
@cesium
.com
and I’d at least try it out. Maybe it’s possible to identify the reason and write it up as an issue. Depending on what the reason is, fixing it might be more complicated, but … I’m at least curious why textures should change the behavior in such a way…
Thanks Marco. I have sent you an email with a link to download the sample tilesets.
Please let me know if you need help with it or if you have any questions.
Based on a short investigation of the tileset, I have identified that the reason for the behavior is Shared identical external textures from GLB files are not accounted for in resource statistics · Issue #11897 · CesiumGS/cesium · GitHub
I won’t share any details of the data set (beyond what can be derived from describing the issue), but when trying to load the textured version, CesiumJS prints the following message in the console:
The tiles needed to meet maximumScreenSpaceError would use more memory than allocated for this tileset.
The tileset will be rendered with a larger screen space error (see memoryAdjustedScreenSpaceError).
Consider using larger values for cacheBytes and maximumCacheOverflowBytes.
An attempt of a quick summary of what is happening there:
- CesiumJS tries to load several glTF assets (tile contents) with a certain level of detail
- All these glTF files refer to the same texture file
- CesiumJS is loading this texture file only once (!)
- but due to the issue #11897, CesiumJS thinks that this texture is loaded once for each tile, which would exceed the available memory
- It therefore reduces the level of detail that is displayed… up to a point where basically “nothing” is displayed any more…
As a workaround, for this specific case, and until the issue #11897 is fixed: One can set the maximumCacheOverflowBytes
of the tileset to a ridiculously large value, to basically “disable” the mechanism that does the memory-based LOD adjustment. For example, the default value is 1.5GB, and one can set it to 1.5 terabytes by creating the tileset like this:
const tileset = await Cesium.Cesium3DTileset.fromUrl(
...
{
// XXX Disable memory usage check for glTFs
// that refer to the same external texture.
// This is a HACK and should be removed as soon as
// https://github.com/CesiumGS/cesium/issues/11897
// is fixed!!!
maximumCacheOverflowBytes: (1536 * 1024 * 1024) * 1024
}
This is only a workaround. It does not have a negative impact in terms of performance or memory consumption, but for other tilesets, using this workaround may cause “Out-Of-Memory”-errors that are usually prevented by the default maximumCacheOverflowBytes
value.
Thanks Marco. That explanation makes sense. Indeed, I can confirm that overriding maximumCacheOverflowBytes
as you suggest fixes the tiling issue in this case, although this will likely cause other issues when viewing tilesets that genuinely have a large number of textures…
Is there any way we can bump Issue #11897 up the priority list at all?
Being able to share textures across tiles is quite an important capability, especially in the browser environment where there are very limited resources.
For example, this particular tileset with a single 11MB texture has a total size of 63MB, however if the texture is instead embedded into each tile then the total tileset size blows out to 470MB!
There is no “explicit” way to increase the priority of this issue. You may have seen that I did do a first analysis pass when it was opened, but it is not yet completely clear how this will be resolved. I also think that the capability to share textures and other resuources between tiles it is important, and that ‘workaround’ is really quirky, but there are currently a few things with relatively high priority in the queue, so I’m not sure when exactly this one can be addressed. (I can try to allocate some time, but cannot make promises. In any case, updates will be posted in the issue, and usually in related forum threads as well)