Minimize 3dtiles (b3dm) tile formation

I am working with 3d tiles (b3dm) and I’m facing this issue because I’m a GIS data of Newyork buidlings and I’m custom adding faces say at every 3m height on buildings whose heights are almost 200m or 400m+. I’m also using the concept of tileset.json SSE to handle thousands of .b3dm tiles. Now my problem is that making those thousands of b3dm tiles (12,000+ b3dm) takes almost 1hour even with 4 processors. Now I wanna make it fast to say atleast 10 to 20min is there a way I can achieve this ? I have also applied the concept of voxel rendering here to store same values (RAN/RF data) in the vertices and later applying custom shader to apply coloing on buildings for my digital twin AIQ-3D.
Can anybody help me this.

There is not so much information in that question. When you mention 12000 B3DM files, then that’s not necessarily an issue: If each of them contains a single triangle, that’s fine. If each of them contains 100MB of textures and geometry, that could be a challenge.

(How the voxels are playing into this is not clear. In general, I’d hesitate to put voxels into B3DM files, and would not even expect that to work. Voxels are usually contained in GLB, and it’s not clear whether the voxel rendering can handle that additional wrapping into B3DM…)

How are you creating these B3DM files right now, and what do they contain, exactly?

Hey Marco thank you for replying,
I am kinda new in this GIS data and how it’s plot using cesiumJS, so I asked my AI to help me explain the logic I hope you understand the logic by AI below:

Each building is turned into a colored 3D shell, then many of those shells are packed into one .b3dm file. The coverage color is stored on the corners of the triangles. The shader fills in the pixels between those corners.

One building

The footprint is a flat polygon. Its height comes from the GeoJSON. For a normal New York house that is a 4-sided box about 8 m tall, the finished tile piece is about 212 vertices and 244 triangles. A plain box would be 8 vertices. Almost all of the extra points are the thin outline, not the walls.

Vertices on the shell. The polygon is stacked at several heights: the ground, every RSRP layer that falls inside the building (1.7 m, then every 3 m up to 120 m), and the roof at the building’s own height. An 8 m house gets five levels: 0, 1.7, 3, 6, and the roof. A tower uses all 41 layers, then one last ring at its real roof. Points that land on the same corner are welded into one vertex.

Triangles on the shell. Each footprint edge between two heights becomes a quad, which is two triangles. The floor is one cap. The roof is one cap. There are no walls inside the building. If any edge is longer than 20 m, that face is split so extra vertices sit in the middle of the wall or roof. Short houses are not split. A large roof is.

The outline. A separate mesh of square tubes, 5 cm thick, runs up every corner between those same heights, plus once around the ground and once around the roof. Each tube section is 8 triangles. On a small house this outline is roughly 190 of the 212 vertices. Those tubes are what you see as the dark building edge.

How RSRP gets onto the building

Every vertex is converted back to longitude, latitude, and height. The sample is nudged a few metres toward the center of the footprint, so a wall reads the signal inside the building rather than the street. That point is looked up in the voxel grid and blended between the nearest horizontal cells and the height layers above and below it.

The result is stored as a color on that vertex:

  • Red is the signal, scaled from the weakest RSRP in the project to the strongest.
  • Green is a label. 0 means a real wall or roof with signal. 255 means no signal. 2 or 128 means this vertex belongs to an outline tube.
  • Alpha is fully opaque.

Outline vertices are not used as the heatmap. The shader paints them dark gray.

What the shader does

A triangle only has colors at its three corners. When the GPU draws the triangle, it blends those three colors across every pixel. The shader reads that blended red value and turns it back into dBm, then into the legend color. That is why coverage changes smoothly up a wall and across a roof, following the vertices that were planted on the height rings and on the 20 m grid.

How that becomes a .b3dm

Buildings are grouped by a quadtree. A group closes when it has about 100 buildings, or when the tree is 8 levels deep. Each building’s shell and outline are concatenated into one mesh. Every vertex is tagged with that building’s batch number, and a small table stores the building id, type, height, and base height. The mesh is written as a GLB and wrapped in a .b3dm. The leaf’s screen-error is set to 0, so once Cesium decides that part of the city is close enough, it loads that whole file.

For this New York set that is about 547,000 buildings → 12,601 tiles → 6.8 GB. A typical tile holds 11–40 buildings, about 10,000 vertices and 12,500 triangles. The heaviest tile reached 430,000 vertices because tall, large footprints kept every height ring and every 20 m split inside one leaf.

I understand the number of traingle is very huge so is there a way I can reduce this without affecting how the buildings look with the current approach ?

I have a .bil/.hdr file of height say 3m, 6m, 9m (which contains rsrp value (RAN/RF data), and so on. I slice the buildings(add vertices) at these heights and also add some extra vertices so that the more rsrp can be embed into the buildings and later using a customShader I apply coloring.

I hope you understand and can suggest some solution.

The main point of the first post seemed to be

Now my problem is that making those thousands of b3dm tiles (12,000+ b3dm) takes almost 1hour even with 4 processors. Now I wanna make it fast to say atleast 10 to 20min is there a way I can achieve this ?

The second post did elaborate how the buildings are constructed. There are some details that are likely not relevant, and others that are still a bit vague. My understanding is that the buildings eventually look roughly like this:

I just created this to get a better idea, here it is as a GLB file:

CesiumForum47536.zip (48.3 KB)

These “outlines” do indeed add a considerable complexity. This example has 750KB. Omitting the “outlines” reduces that to 110 KB. And it would likely be possible to reduce this even further. From the description, it sounds like it is still using somewhat fine-grained geometry and vertex colors. Solutions with more coarse-grained geometry could exist. This could probably use textures for the desired coloring, but these textures could be tiny (maybe even as small as 8x8 pixels, if they only capture some gradient).
All this could be “desirable”, because if a renderer has to display all this geometry at once, it will be a challenge. Specifically: In order to have a true “Level Of Detail”, some more thought will have to go into that. What could a “lower level of detail” be? The first shot could be to omit the outlines, or use simpler geometry for the outlines, or emulate the outlines with glTF/extensions/2.0/Vendor/CESIUM_primitive_outline/README.md at main · KhronosGroup/glTF · GitHub .

But when the main problem is that creating this data is slow, then the first analysis pass would be to check where exactly this time is spent. I didn’t run dedicated “tests/benchmarks” with the code snipped that I used for creating that GLB. But do you have a clearer idea about what is actually the most costly thing in your creation process? Things like

Every vertex is converted back to longitude, latitude, and height …

or looking up that ‘RSRP’ value and assigning colors based on that sound like they could be expensive. (An easy first pass could be to “uncomment” the step that assigns the colors, to see what the pure geometry generation takes. If this takes 4 minutes instead of 4 hours, then you know that no optimization of the geometry itself bring noticable savings…)

Your understanding was pretty much correct, I removed the extra outlines and time and size of b3dm tiles did reduces.

I checked that I was doing over complexity while making these 3d buildings. I removed those things entierly.
I saw quite a few probelms on going deeper into my codebase and removed each of them. I also understand a bit more about python’s multiprocessing like chunksize and maxtaskperchild which overall improve my time consumption drastically.
thank you for your help.