I’m struggling to digest the docs and create a valid tileset with implicit tiling, and I feel like maybe I’m misunderstanding something obvious and getting some fundamentals wrong. Hopefully someone can help me out.
I have a large piece of terrain that I progressively split into a quadtree of 5 levels and I end up with 1, 2x2, 4x4, 8x8, and 16x16 chunks as a result. Each level has a different level of detail and the goal is a non-sparse quadtree.
Now, what’s the correct tileset.json structure here? Is there still a need for subtrees? It seems like I wouldn’t gain anything from using subtrees but I don’t think I have an option not to use them.
From quickly skimming over the JSON, I don’t see anything that is obviously wrong. You might want to apply the 3D Tiles Validator to your tileset, to see whether it reports any issues.
Is there still a need for subtrees?
Subtrees are inherent in the Implicit Tiling approach. So you at least need one subtree. If the question was whether you need additional subtrees, then the answer is “No” - for 5 levels, you should be fine with having that in a single subtree.
(The concept of multiple subtrees is only relevant for deep implicit hierarchies. There is some discussion at 3DTILES_implicit_tiling: How to make subtree division easier to do correctly? · Issue #576 · CesiumGS/3d-tiles · GitHub , but that might not immediately be relevant now)
Unfortunately Ion doesn’t give me an error, but it also doesn’t display any of the geometry.
Are you uploading that directly to ion? I think that ion will not perform any sanity checks here. So when that data is invalid, then … it is still served as it is. However, CesiumJS will often report some error. When you open that data set (e.g. using the “Open complete code example” link), and then press “F12” to see the developer console, do you see any error messages there?
Thanks @Marco13 for your suggestions. Unfortunately I get no errors in CesiumJS when loading that tile, just some google analytics being blocked error.
The validator threw some errors related to the buffers being empty in the subtree json file (please note I changed the template for the subtree file and it’s now on purpose at subtrees/0/0/0.json):
{
"date": "2025-02-27T00:12:50.389Z",
"numErrors": 1,
"numWarnings": 0,
"numInfos": 0,
"issues": [
{
"type": "ARRAY_LENGTH_MISMATCH",
"path": "subtrees/0/0/0.json/buffers",
"message": "Array 'buffers' must have a length of at least 1, but the actual length is 0",
"severity": "ERROR"
}
]
}
I made a dummy buffer and a buffer view pointing to a 1 byte binary file, which seems to have got rid of the error. Now I get a bunch of errors for my glb files, which I guess I should fix next in case they are causing issues with the rendering. But, I was hoping it was something else since the glb files work fine in various DCC apps, there’s just some issues with tangents and whatnot.
Just to confirm that the message about the subtree/buffers is not caused by an issue in the validator that was fixed a while ago: Which version of the validator are you using? When you run npx 3d-tiles-validator -version
then it should be at least version 0.5.1 (with 0.6.0 being the latest version right now).
Now I get a bunch of errors for my glb files, which I guess I should fix next in case they are causing issues with the rendering.
Yes! Invalid GLB files can cause all sorts of rendering errors.
You can also validate single GLB files by dragging-and-dropping them into the glTF Validator at glTF Validator . The 3D Tiles validator is using the glTF-Validator internally, so it will report the same errors - but when you just want to validate a single GLB, then the drag-and-drop tool may be easier.
If you’re stuck, and the data can be shared (and it’s not too large), then you can also attach the data as a ZIP here, maybe I can allocate some time to have a look.
I can see the online validator throwing some errors for some of the glbs, I’ll try to correct these. It’s not all files and the errors are things like, the vertex color isn’t normalized in a 0-1 range, and that kind of stuff, so I was hoping that would be the reason nothing at all renders, but I should fix those regardless.
I’m afraid the data is somewhat sensitive. Any chance it’s possible to send to you through private support?
I fixed all the glb warnings and errors. Both the 3d tiles validator and the online gltf validator report no more errors, but still nothing renders in cesium.
One thing that may still be a reason why nothing is displayed is that the bounding regions do not match the actual bounds of the geometry (this is not (yet) checked by the validator). But until now, that’s just a first guess. If the overall size of the data is not excessively large, then you can send it to marco at cesium.com (I cannot promise that I’d ~“get it working”, but I’d have a look and see whether I can find out what’s wrong…)
The tileset has been provided internally, and it turns out that my guess was right in this case: The bounding volume of the tileset did not contain the actual geometry data from the GLB files.
The geometry data in the tiles has been “centered at the origin”, i.e. with a bounding box like (-1,-1,-1)-(1,1,1). But the tileset JSON defined a bounding region, which is always in latitude/longitude/height (EPSG:4979), and essentially describes bounds on the surface of the globe - therefore, it cannot contain the geometry data that is located at the origin.
The solution was to insert a proper transform matrix in the root tile of the tileset JSON. The transform that had to be inserted was the one that could be computed with Cesium.Transforms.eastNorthUpToFixedFrame from the bottom center point of the bounding region.
As described in the specification, this transform will affect the geometry, but it will not affect the bounding region - meaning that it will move the geometry that is contained in the tiles into the bounding region that is defined in the tileset JSON, so that the geometry is displayed at the right position in CesiumJS and other viewers.
As noted above: This is something that should be checked by the validator. And in fact, there already is an issue about that: Validate that geometry is fully contained in bounding volumes · Issue #233 · CesiumGS/3d-tiles-validator · GitHub . There are still aspects that make this a bit difficult. For example, for things like I3DM or GLB that contains EXT_mesh_gpu_instancing, or even just morphing or animations, it can be tricky to compute the actual bounds. And in any case, it could be really costly in terms of performance. But it could still be worthwhile to add a baseline implementation (for simple B3DM/PNTS/GLB) that could be disabled by default, and enabled with some --performBoundingVolumeValidation flag.