3TZ files are flickering and vanishing when view is moving

In my project where I am using mars3d wrapper with cesium js, when I upload 3TZ tileset file with Terrain (DTM) file I can see terrain is loaded correctly but tileset is sometimes flickering and vanishing out on zoom in and zoom out or changing the camera angle.
But I have tried two different asset having different sizes of 3TZ:

  1. Large Asset- Tried two assets of having sizes 450MB and 960MB they both are having the same flickering and vanishing problem.

  2. Small Asset- Asset of size 45 MB is working perfectly fine.

Note- No code changes and generation of 3TZ is through the same workflow pipeline, and I am generating 3TZ using ODM.

I tried to load the 3TZ tileset on a plain cesium code in different test file and it also has a same problem.

Attaching both the videos for reference-
Plain Cesium Viewer

Custom Code using Mars3D wrapper

“Things that are flickering” is some sort of a baseline issue where it’s hard to zoom into what exactly causes it in one specific case.

In this case, I’m a bit surprised by the 3TZ part. CesiumJS does not really know what 3TZ is. It is sending out requests and receiving responses. Is it right to assume that you’re somehow serving the contents of that 3TZ file, and the behavior of CesiumJS is independent of whether it is from 3TZ or not?

You mentioned that it works for a “small asset”, but flickers for a “large asset”. Could you have a look at the Developer Console (at the bottom after pressing F12 in the browser), and have a look at whether this prints any error/warning messages?
(It wouldn’t surprise me if there was a message about the maximum memory consumption being exceeded and the maximum screen space error being adjusted)

In any case, I’ll likely move this thread into the CesiumJS section later.

Thanks for the response.
I was reading this cesium discussion, here someone is having issue in rendering the large 3TZ file and in discussion it was shared that it might be due to large MESH or .b3dm file and suggested size to load it fast was under 500KB and when I inspected my .b3dm files then it was more than 4500KB (~4.5MB) so then I optimised the 3TZ file and reduced the file size and when b3dm file was in range of 1000KB to 1500KB then it was perfectly fine.

Conclusion: Reducing and Optimising the 3TZ and .b3dm files inside the tileset fixed this problem.

Note: Need to compromise with the quality.

I see. So there likely isn’t anything specific for 3TZ in this case. To put it that way: You could unpack the 3TZ into a directory (it’s just a ZIP file after all), and then serve the resulting B3DM files directly, and would still observe the same behavior. And I assume that, under the hood, this behavior is related to the message/warning that would then (still) be printed, indicating that there is ~“just too much data loaded at once”. Reducing the size of the B3DM files is one option to address this. Playing with the maximumScreenSpaceError is another. There are many others, but the details depend on the exact structure of the data.

Can you let me know what are the other possible ways to fix this issue without reducing the B3DM files as this is degrading the quality.
If you have any suggestions please let me know

The first (important) diagnosis, in order to make sure that the reason for the “flickering” is what I suspect it to be, would be this:

Could you have a look at the Developer Console (at the bottom after pressing F12 in the browser), and have a look at whether this prints any error/warning messages?
(It wouldn’t surprise me if there was a message about the maximum memory consumption being exceeded and the maximum screen space error being adjusted)

If there is no such message, then the reason for the flickering must be something else (and I couldn’t pinpoint “THE” reason in this case, but only make guesses). Some of this could be easier if the data could be shared, so that others could reproduce the issue, but this may not be possible when the data is very large or confidential.

I checked the developer console and there were no issues at all, so I am attaching 3TZ data which I have used.
I have generated 3D model using two different tools:

  1. Using ODM: Output

  2. Using Agisoft Metashape Pro: Output

Agisoft’s 3TZ is more stable even though ODM’s output is also having similar size of around 500MB.

Note - I have generated the 3D model using the Publicly available drone images by ESRI.

The “ESRI-Campus-By-Agisoft” one: This seems to work well for me. It seems to contain a somewhat clean LOD hierarchy. The largest tile content has only 264KB. While moving around with debugShowBoundingVolume enabled, it looks like it is cleanly and sensibly refining.


The “ESRI-Campus-By-ODM” one: Well… :face_with_diagonal_mouth: . For me, when loading it, it immediately prints the message that I suspected:

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.

And I’m a bit surprised when you say that this does not appear for you.


Details: (Skip to the section “The workaround” below if you’re not interested in the details…)

The reason for that console message is pretty simple: The tile content is HUGE.

(There are many other things to be said. Each LOD contains the same number of tiles. Apparently that tool just generates 16 tiles with a fixed structure, and the LOD levels only consist of different levels of detail for these exact tiles. That looks a bit unusual, but can be OK. It contains several cases of "children": [], which is invalid. It also has cases like "content": null,, which is valid but a bit odd. However, these are details for now…)

Note that the tile contents being “HUGE” does not mean too much. I don’t say whether this is “good” or “bad”. There is not even a theoretical concept of “good” or “bad” when it comes to tilesets and their structure. But in this case, it is simply the reason for the issues that you’re observing.

The tile content for the highest LOD level involves B3DM files that have a whopping 50MB. I extracted the GLB from one of these, and dropped it into gltf.report :

The tile occupies roughly 359MB of VRAM. Approximately 358MB of that are occupied by that 8192x8192 texture! (Just as a comparison: The largest GLB from the other data set uses several 256x256 textures, but occupies less than 3MB of VRAM).

Skipping some differentiation between “RAM” and “VRAM” here (that distinction is not made cleanly in CesiumJS anyhow): When it tries to load this LOD, it will try to load 16 * 360MB, which will exceed some of the internal memory limits.

It would be possible to resolve that in different ways. One could apply some post-processing to this tileset, and reduce the texture size, or use KTX for the textures. (I’m a freelancer, by the way…)


The workaround

As the console message suggests, you can create the tileset using a different value for the cacheBytes, like this:

const tileset = await Cesium.Cesium3DTileset.fromUrl(
  "http://localhost:8003/ESRI-Campus-By-ODM/tileset.json", {
  cacheBytes: 536870912 * 16 // This is 16 times the default (!)
});
viewer.scene.primitives.add(tileset);

This should prevent the flickering :crossed_fingers: but of course, at the price of a very high memory consumption.

Thank you so much @Marco13 for the detailed explanation and now it seems to be pretty clear that reducing the b3dm files were the working solution for me.
For your information, I first generated the OBJ and 3d_tiles using the ODM and then wrapped into 3TZ tileset format using 3d-tiles-tools by ODM only, so it was the default behaviour of LODs which I haven’t touched, do you have any idea how I can achieve the same level of clean hierarchy like the file ESRI-by-Agisoft as it is generated by Agisoft Metashape Pro and its a proprietary tool, so I need a different workaround as reducing the b3dm sizes are directly affecting the quality a lot so this is the reason I am looking something similar to Metashape Tileset Generation flow.

(As mentioned above: Whether or not the data is wrapped into a 3TZ file is unrelated to this issue. 3TZ is “only” a packaging/convenience format)

Beyond that:

I cannot give any recommendations about tools for converting OBJ to 3D Tiles - except fo the obvious one, https://ion.cesium.com/ . You can upload your OBJ there, and then also download the resulting tileset if you want to. I’d suggest to give it a try, at least.

If the goal is to “improve” an existing tileset that was created with another tool (like the “ESRI-Campus-By-ODM” one in this case), then such an improvement would fall into one of two “categories”:

1. The improvement could essentially “re-tile” the data to create a completely new tileset. This is hardly doable. Very roughly: Depending on the exact structure of the input tileset, this could be prohibitively expensive (in terms of the compuation), and more importantly, it may result in a very poor visual quality.

2. The improvement could try to improve the tileset while keeping the structure of the original tileset.json. This is relatively easy. But any improvement there is limited by the existing structure. As I said, the structure of the “ESRI-Campus-By-ODM” tileset JSON is a bit unusual, in that it looks like this

         root 
         /|\ \ ...
        / | \ \ ...
LOD0   O  O  O   ... 16 children
       |  |  |
LOD1   O  O  O 
       |  |  |
LOD2   O  O  O 

There are 3 LOD levels, but not a real “hierarchy”. Each child is just a “chain” with the different LOD levels. (Again: This is not “good” or “bad” per se. It is what it is…)

Given the limited options (i.e. the fact that it’s hardly possible to re-structure the tileset JSON), what can be done:

It would be relatively easy to process each tile content - i.e. each B3DM file - and perform optimizations on this B3DM file. This would read each B3DM, extract the GLB, “optimize” the GLB (see below), pack the GLB into a B3DM, and write out that resulting B3DM.

“Optimize” here could, for example, mean to simplify the geometry, or apply Draco- or meshopt compression to glTF. Similarly, optimizations like “reducing the texture size” could be doable with a few lines of code. Applying KTX compression would also be easy.

There are many engineering considerations to be taken into account here. On top of the limitation of having to keep the JSON structure, there is the obvious trade-off between “size reduction” and “quality”.

And (this may be important): I don’t know this “ODM” tool. Maybe there already are some configuration parameters in this tool that would result in smaller leaf tiles? Maybe have a look at some of the docs and settings of this tool…


An aside: The 3D Tiles Tools offer the core of that functionality for such an optimization. This would be similar to what is shown in the TileContentProcessingDemo. This shows how to apply Draco- or meshopt compression, and could easily be tweaked to perform (arbitrary) other optimizations (with the engineering question being: “Which ones, exactly?”). But note that this snippet is only a demo - this is not an official tool, and not operating on a public, stable API!

Thank you so much for such a detailed explanation, it is indeed really very helpful.