Display a large number of GLB models

I have a scene where I need to display a FAIRLY large (~250) of simple 3D models.

The GLB file contain a simple blender cube, with a simple rotation animation (it’s ~5kb large).

Here is a screenshot : Imgur: The magic of the Internet
And another one : Imgur: The magic of the Internet

As you can see, the number or the size or complexity of the objects displayed is fairly low and yet the CPU usage is very high. If I try to display 1000~ cubes, which seems reasonable, the CPU doesn’t quit the 100%. 2000 it crashes.

So I guess I am not using the good method ?

Here is the code repsonsible to display the cubes :

function addBox(viewer, longitude, latitude, modelUri) {
    const modelHeight = 50;
    const heightAboveTerrain = 50;
    const minimumVisibleDistance = 0;
    const maximumVisibleDistance = 10000;

    const terrainProvider = viewer.terrainProvider;
    const positions = [Cesium.Cartographic.fromDegrees(longitude, latitude)];

    return Cesium.sampleTerrainMostDetailed(terrainProvider, positions)
        .then((updatedPositions) => {
            const terrainHeight = updatedPositions[0].height;
            const positionHeight = terrainHeight + heightAboveTerrain;
            const position = Cesium.Cartesian3.fromDegrees(longitude, latitude, positionHeight);

            const hpr = new Cesium.HeadingPitchRoll(0, 0, 0);
            const orientation = Cesium.Transforms.headingPitchRollQuaternion(position, hpr);

            const scale = modelHeight / 50; // Assuming the original model is 50m tall

            const entity = viewer.entities.add({
                name: 'GLB Model',
                position: position,
                orientation: orientation,
                model: {
                    uri: modelUri,
                    scale: scale,
                    heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND,
                    distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
                        minimumVisibleDistance, 
                        maximumVisibleDistance
                    )
                }
            });

            return entity;
        });
}

I loop through 250 pairs of coordinates, and I display my 100 cubes like that :

    questBoxes.forEach(questBox => {

        addBox(viewer, questBox.lng, questBox.lat,  './models/cube.glb');
    })
}

I am not even trying to display a BIG number of BIG models. Just 200 cubes, and the CPU is already through the roof.

Any idea ? How other people do ? It seems like a common usecase.

I recommend avoiding the use of Glb models for this task. Instead, you should consider using Geometry along with instancing techniques. This approach is more efficient, especially when dealing with a large number of similar objects. Instancing allows you to draw many objects using a single draw call, which can significantly improve performance.

Hi @adcomere,
At first glance, I don’t see a major problem, as long as the .forEach loop only runs once at startup. Can you share your code as a Sandcastle example?

Have you considered using a BillboardCollection instead of individual GLB models?

The following is a Sandcastle that loads and displays the “Plane” model 100 times:

There obviously are some race conditions in sampleTerrainMostDetailed, because they are not always ending up in such a nice grid. But in terms of performance, this should not be a problem:

Cesium Many GLBs

It’s running at 60FPS, with low CPU load.

When you are talking about the CPU load, then I assume that this refers to the time while these models are created. And yes, the CPU will be busy there - mainly because of sampleTerrainMostDetailed, which is a very costly operation.

(Maybe you could improve the performance (or reduce the delay while loading) by not passing in each position individually, but instead, creating an array containing all the desired model positions, calling sampleTerrainMostDetailed only once (passing in this array), and then creating the models based on the resulting updatedPositions. But this is only a guess, and the details depend on factors that may require further investigations)

1 Like