Scene pre/postRender Event

The application is using Cesium v1.19 and I have a question about Scene.preRender and Scene.postRender usages. All data is streamed via CZML and we have a multiple CzmlDataSource instances in the Viewer. CZML packets are streamed every second, with each update containing multiple CZML packets.

This is our scenario… When the browser receives a CZML update, we would like to apply a routine that traverses the CZML and apply some client-side business logic. For example – Lookup all point entities and adjust their respective label position to a different location than what was sent by the service. Essentially, my goal is to adjust data coming from the service and prior to render, then display them on a per-client/browser basis.

Lets assume the code below.

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

// process initial czml packet with 100 different points around the global

viewer.scene.preRender.addEventListener(function(s,t) {

console.log('PreRender: ’ + t

  • ', ground: ’ + s.groundPrimitives.length

  • ', primitives: ’ + s.primitives .length);

});

``

My questions are:

  1. When the event is raised from the code above, does the passed-in Scene object contains entities prior to the incoming CZML update? Or, does it contain all entities from the update (but not rendered)?

  2. If the same routine is hooked up to Scene.postRender and I traverse the entities and change its color (for example), would that color change be immediately applied, or in the next render cycle?

  3. Are there any performance gotchas that I need to consider when changing incoming CZML packets prior to rendering them?

Thank you.

Hello,

If you’re making changes to the entities created by the CZML data source, I would handle it in the .then returned by CzmlDataSource.load. That way you don’t have to poll every frame the way the scene.preRender event does.

You can see an example for how to do this here: http://cesiumjs.org/Cesium/Apps/Sandcastle/index.html?src=GeoJSON%20and%20TopoJSON.html&label=DataSources

This example is with GeoJson, but the CzmlDataSource works the same way.

Best,

Hannah

Thank you for the response.

I initial thought was that the Scene only exposes visible entities (i.e. when the user zooms into a smaller region); therefore, intercepting the preRender would limit the amount of processing. Is that incorrect?

scene.primitives could potentially contain primitives that are visible and hidden depending on which entity types you are using. I don’t recommend trying to access these primitives as it might have weird side effects since the primitives are being created by the datasource.

-Hannah

Roger that.

From a quick look at the code, it looks like the child entity should still render if the parent is missing. It looks like it will create a parent if one doesn’t exist.

-Hannah

When processing the promise returned when loading the CzmlDataSource, the incoming data sets the show property of the point to false; however, in the promise, it is true. Below is a snippet of the example.

var czmlDocument = [{

“id” : “document”,

“name” : “CZML Point”,

“version” : “1.0”

}];

var czml = [

{

“id” : “point 1”,

“name”: “point”,

“position” : {

“cartographicDegrees” : [-111.0, 40.0, 0]

},

“point”: {

“color”: {

“rgba”: [255, 255, 255, 255]

},

“outlineColor”: {

“rgba”: [255, 0, 0, 255]

},

“outlineWidth” : 4,

“pixelSize”: 20,

“show”:false

}

}];

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

var dataSource = new Cesium.CzmlDataSource(‘test’);

viewer.dataSources.add(dataSource);

dataSource.load(czmlDocument);

dataSource.process(czml).then(function(ds) {

var isVisible = function(entity) {

return entity.show === true;

};

var visible = ds.entities.values.filter(function(e,index) {

console.log(’(’ + e.id + ‘) show:’ + e.show);

return isVisible(e);

});

console.log('Visible: ’ + visible.length);

});

``

Thank you.

Thinh Ho

The show value is on point, so you need to use entity.point.show === true instead of entity.show === true.

-Hannah

Thank you for spotting that!

Entity positions are injected as ECEF coordinates in the position.cartesian attribute in the CZML. I would like to Cesium.SceneTransforms.wgs84ToWindowCoordinates(scene, position, result) and having some problems with the conversion as the transformation method takes degrees. Essentially, my goal is to figure out the screen positions of entities within the promise.

Is there a conversion for this in Cesium?

From the Scene object, it seems that I can get the Primitives and use Billboard.computeScreenSpacePosition and Label.computeScreenSpacePosition. Is there a conversion from Primitive to Entity?

Thank you.

The SceneTransforms.wgs84ToWindowCoordinates function should work. You can get the position from the entities via entity.position.getValue(viewer.clock.currentTime). You shouldn’t need to do any conversion.
If that doesn’t work, could you paste a code example with what you’re trying to do? That way I can see whether or not it’s a bug.

Best,

Hannah