Performance question with Sandcastle

I’m trying to port a hack I made to display storm data a WebGL globe (http://www.chromeexperiments.com/detail/storm-tracks-webgl/) into Cesium.

I’ve been using Sandcastle and finding it very slow to render a small portion of the data. Before I carry on and make it look pretty, I wanted to improve the performance. Likely I’ve done something silly so another pair of eyes would be much appreciated. For example, I thought I could create a circle for each type of storm track up front and clone it as required but I wasn’t able to figure out how to do that.

Code I pasted into the “Circles & Ellipses” example within Sandcastle here:

require([

'Cesium', 

'Widgets/Dojo/CesiumViewerWidget', 

'http://callum.com/sandbox/webglex/storm_tracks_webgl/js/storms.js'

], function(

Cesium, CesiumViewerWidget)

{

"use strict";

function plotStorms(widget) {

    var start_date_time = new Date(2012, 1, 1);

    var end_date_time = new Date(2012, 12, 31);

    var scene = widget.scene;

    var ellipsoid = widget.ellipsoid;

    var primitives = scene.getPrimitives();

    for (var i = 0; i < storms.length; ++i) {

        var storm_date_time = new Date(storms[i][1][2]).getTime();

        if (storm_date_time >= start_date_time && storm_date_time <= end_date_time) {

            var storm_name = storms[i][0].toString();

            for (var j = 1; j < storms[i].length; ++j) {

                var lat = storms[i][j][0];

                var lng = storms[i][j][1];

                var wind_kts = storms[i][j][3];



                var plot_size = 1;

                var plot_col = '#ffff00';

                

                if (wind_kts <= 34)

                {

                    plot_col = '#5ebaff';

                    plot_size = 1;

                }

                else 

                if (wind_kts >= 35 && wind_kts <= 63)

                { 

                    plot_col = '#00faf4';

                    plot_size = 2;

                }

                else 

                if (wind_kts >= 64 && wind_kts <= 82) 

                { 

                    plot_col = '#ffffcc';

                    plot_size = 3;

                }

                else 

                if (wind_kts >= 83 && wind_kts <= 95) 

                { 

                    plot_col = '#ffe775';

                    plot_size = 4;

                }

                else

                if (wind_kts >= 96 && wind_kts <= 112) 

                { 

                    plot_col = '#ffc140';

                    plot_size = 5;

                }

                else

                if (wind_kts >= 113 && wind_kts <= 136) 

                { 

                    plot_col = '#ff8f20';

                    plot_size = 6;

                }

                else 

                if (wind_kts >= 137) 

                { 

                    plot_col = '#ff6060';

                    plot_size = 7;

                }

                var circle = new Cesium.Polygon();

                circle.setPositions(

                    Cesium.Shapes.computeCircleBoundary(

                        ellipsoid,

                        ellipsoid.cartographicToCartesian(Cesium.Cartographic.fromDegrees(lng, lat)),

                        10000.0 + plot_size * 10000.0));

                circle.material = Cesium.Material.fromType(scene.getContext(), 'Color');

                circle.material.uniforms.color = Cesium.Color.fromCssColorString(plot_col);

                primitives.add(circle);

            }

        }

    }

}

var widget = new CesiumViewerWidget({});



widget.placeAt('cesiumContainer');

widget.startup();

plotStorms(widget);

Sandcastle.finishedLoading();

});

Many thanks in advance.

Cal.

Hi Callum,

Great to see the Storm Tracker making its way to Cesium! I had a chat with some of the other guys, and it turns out that “Cesium.Polygon” has not yet got the optimization treatment that Billboards and Labels have received. In particular, each circle you create is being added as a separate primitive, so adding 1800 circles is causing 1800 drawElements calls and that crushes your performance.

Take a look at the “Billboards” demo in Sandcastle, and note that a single “BillboardCollection” primitive is created, and the billboards are added to that. All of the billboards are then grouped into a single vertex array for a single draw call, so you can have tens of thousands of them or more.

It’s on our TODO list to make a PolygonCollection, but it won’t be real soon (terrain & models are higher priority). In the meantime, try switching your demo to create Billboards instead of polygons. The downside is your dots will be sized in screen-space instead of world-space, but, the demo should run full speed.

A more interesting thing to try might be to convert the storm.js data to CZML. Each storm could be expressed as a single polygon or billboard that changes location, color, and size over time. There could be polylines left behind to show where past storms had been, and you could watch the history of storms unfold in fast-forward on the globe. Could be quite interesting.

–Ed.

Thanks Ed - loads of interesting things to try there. Like you said, a CZML approach sounds the most interesting. I’ll see what I can come up with over the weekend - love the temporal element you suggested.

Really impressed with Cesium - most of all, it’s fun to hack on - just like things should be :slight_smile: