Hello,
I am facing a severe frustum culling/disappearing issue with a custom 3D Tileset and would really appreciate some insight into how Cesium’s HLOD evaluates culling.
The Setup: I am building a pipeline using a custom Node.js script to generate instanced houses. Currently, I have grouped my instances into several .i3dm files. I am wrapping them in a static tileset.json.
The Problem: When I load the tileset into CesiumJS and orbit/pan the camera, entire tiles (chunks of houses) suddenly disappear.
-
I turned on tileset.debugShowBoundingVolume = true.
-
The bizarre part: The white bounding box (region) of the tile is clearly still visible and inside the camera frustum, but the models inside it are culled anyway!
My tileset.json structure:
{
"asset": {
"version": "1.0"
},
"geometricError": 2000,
"root": {
"boundingVolume": {
"sphere": [
-1617432.0230176821,
5750458.410555924,
2227819.831162883,
1383.6894803552796
]
},
"geometricError": 1000,
"refine": "ADD",
"children": [
{
"boundingVolume": {
"region": [
1.8450022654088003,
0.3591809758919692,
1.8450197187013202,
0.3591984291844891,
-32.28153994824592,
47.71846005175408
]
},
"geometricError": 0,
"content": {
"uri": "NhaChucNang.i3dm"
}
},
// ... other children with similar strict regions
]
}
}
-
Does Cesium strictly respect the tileset.json bounding volume, or does it still read the internal binary FeatureTable bounding sphere of the I3DM file and cull based on that?
-
Why would a Tile be culled if its boundingVolume debug box is still fully visible on the screen?
I have shared a code showing the issue.
Any guidance or hints on what I might be doing wrong would be a lifesaver. Thank you!
The good news is: You’re not doing something wrong.
The bad news is: You’re not doing something wrong.
This is a known issue, and tracked in Wrong bounding volume computations for model · Issue #12108 · CesiumGS/cesium · GitHub . So there is nothing that you could do to resolve this on your side (except for opening a pull request…). I already tried to address this several times, but … … let’s say “it’s complicated”.
There are ways of (post) processing the data in a way so that the issue is “less severe”. Specifically: You can drag-and-drop your glTF file into https://gltf.report/ , then select the <> (Script) panel at the left, paste this…
import { clearNodeParent, clearNodeTransform, flatten, prune } from '@gltf-transform/functions';
const root = document.getRoot();
for (const node of root.listNodes()) {
if (node.getMesh()) {
clearNodeParent(node);
clearNodeTransform(node);
}
}
await document.transform(
flatten(),
prune(),
);
then hit "Run >", and then press “Export” (in the lower right) to obtain a GLB file. When creating the I3DM for that new GLB file, the effect will not be as severe as it is now.
But … that issue has caused so much trouble in the meantime that I’ll (once more) take some time during the weekend and see whether I can at least find a way to improve the situation here.
I created a draft PR for addressing this at Try to fix bounding volumes one more time by javagl · Pull Request #13437 · CesiumGS/cesium · GitHub
Note that the current state there involves some ~“debug visualization” that shows up as a bunch of red lines everywhere!
But the main point is that on this state, the buildings should no longer disappear:
Thank you for the update! It seems the culling issue is indeed resolved in the build you provided.
I see that debugShowBoundingVolume is intentionally left enabled for this first pass. However, it’s hitting 1 FPS on my device, which makes it nearly impossible to verify the fix effectively or check for visual regressions.
Now that we’ve confirmed the culling issue is likely resolved, could you provide a ‘clean’ build with debug volumes disabled? This would allow me to test the actual performance and smoothness of the tileset transition
.
Yeah, I have updated the PR to no longer include the debug bounding spheres (they seemed to cause trouble in CI anyhow).
The link with your sandcastle is the same as in the previous post, maybe you want to have another look.