Adding 50,000 Billboards to a BillboardCollection seems to make Cesium hang while rendering

Hi,

I am adding roughly 50,000 billboards to a billboard collection then loading this onto the map. For small test data sets it loads instantly, but once I start increasing the number, Cesium seems to "hang" for over a minute while they are rendered to the map. Is that expected or should the 50,000 billboards appear instantly?

I've read lots of posts on the trade offs between using entities and primitives and it seems for this use case, I need the performance of the primitives to load many billboards at once over the additional entity functionality.

I also tried using the entity clustering functionality that was recently reduced but the speed of zooming around the map didn't seem anywhere near as fast as if I had them all loaded and displayed as billboard primitives.

The relevant code is along the lines of:

//create collection
var billboards = new Cesium.BillboardCollection();

//loop through all my data and create billboards for each
var pinBuilder = new Cesium.PinBuilder();
var pin = pinBuilder.fromText(text, color, 64).toDataURL();
var billboard = {
  position: Cesium.Cartesian3.fromDegrees(parseFloat(value.longitude), parseFloat(value.latitude)),
  image: pin,
  verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
  id: addedObjects
};

billboards.add(billboard);
//end loop

//add collection to the scene
viewer.scene.primitives.add(billboards);

Hello,

For visualizing that many points, I would recommend using a point instead of a billboard. They optimized to have the best performance. You can read more about it in this blog post: http://cesiumjs.org/2016/03/02/Performance-Tips-for-Points/

Sorry, but I don’t have any tips for improving the performance of the billboards.

Best,

Hannah

Thanks Hannah, I will give it a go and get back to you.

PointPrimitives can’t be clustered can they?

50,000 billboards should work fine depending on the specifics. In your pseudocode, it looks like you are generating a unique pin for every billboard. I suspect most of the lag you are seeing is generating the pins and then adding them to the texture atlas. If you use the same billboard for everything they show up instantly. Here’s a complete Sandcastle example showing this:

var viewer = new Cesium.Viewer(‘cesiumContainer’);

Sandcastle.addToolbarButton(“Go”, function(){

//create collection

var billboards = new Cesium.BillboardCollection();

//loop through all my data and create billboards for each

var pinBuilder = new Cesium.PinBuilder();

var pin = pinBuilder.fromColor(Cesium.Color.RED, 32).toDataURL();

for(var i = 0; i< 50000; i++){

var billboard = {

position: new Cesium.Cartesian3.fromDegrees(-Math.random()*180, Math.random()*180),

image: pin,

verticalOrigin: Cesium.VerticalOrigin.BOTTOM,

id: i

};

billboards.add(billboard);

}

//end loop

//add collection to the scene

viewer.scene.primitives.add(billboards);

});

If you truly have 50,000 unique billboards, you may run into issues with texture memory more than anything else, but it all depends on the specifics. If you can provide more information, I can make some suggestions.

Thanks heaps Matt, that did the trick! I didn’t have 50,000 unique billboards, more like a dozen which I now reuse.

OK, so final question (for now), do you think clustering of 50,000 entities will be efficient or should I stick to the primitives?

Clustering should work fine, but let us know if you run into issues. The Entity API is pretty efficient with it’s billboard usage, so I don’t think you would get any improvement by trying to do clustering yourself at the primitive level.

OK, great, I’ll give it a try and report back. Thanks heaps for answering these questions. I’ve been working with Cesium every day for the last few years and reading this forum but I wish I had started posting here more often, it would have saved a lot of time :slight_smile:

Thanks for your advice. I ended up going with a BillboardCollection which loaded very fast. I had some trouble trying to have labels displayed for every Billboard but in the end I made a separate function that checked the current zoom level and if it was zoomed in close enough, it would find what Billboards are within the current viewed bounding box, and then add labels to the map for that section.

This seems to work a lot better than adding a label collection from the start, even if they were hidden and even if the translucent by distance was used for that collection.

Can you show me your code example?