Search code examples
javascriptcesiumjs

Entity not Visually Updating when its Position Changes


The title says it all, I can't get an entity to move around the globe visually, even though its position is moving. This code will reproduce the problem in Sandcastle:

var viewer = new Cesium.Viewer('cesiumContainer');

var e = viewer.entities.add({
    name : 'Sphere',
    position: Cesium.Cartesian3.fromDegrees(-100, 30.0, 300000.0),
    ellipsoid : {
        radii : new Cesium.Cartesian3(200000.0, 200000.0, 200000.0)
    }
});

viewer.scene.postRender.addEventListener(function(scene, time) {
    var pos = e.position._value;

    var cart = Cesium.Ellipsoid.WGS84.cartesianToCartographic(pos);

    pos = Cesium.Cartesian3.fromRadians(cart.longitude + (1 * Math.PI / 180), cart.latitude, cart.height);

    e.position = pos;
});

If you select the sphere in the demo, you'll see that the green selection indicator will be moving around the globe, but the sphere will be stuck in one place. I imagine there's some simple function call I'm missing, but I've been googling for the last few hours and I can't find a solution.

I've already looked at the Picking demo on Sandcastle, but nothing there seems to be relevant. The functionality I'm looking for is just to have a shape looping through the same set of coordinates indefinitely, so I can't use a SampledPositionProperty, as far as I've seen anyway.


Solution

  • I suspect the cause of this is a little tricky: In Cesium, the ellipsoid geometry is build asynchronously by a Web Worker. By asking for a change in position with every postRender event, you're basically thrashing the worker, it can't get one request finished before the next one starts. So we end up never seeing the position update at all. If you relax the speed a bit, you'll notice the position does update.

    For example, here's your code again with postRender replaced by setInterval of 400ms. This is more like a clock ticking than a smooth animation, but it shows the position being updated:

    var viewer = new Cesium.Viewer('cesiumContainer');
    
    var e = viewer.entities.add({
        name : 'Sphere',
        position: Cesium.Cartesian3.fromDegrees(-100, 30.0, 300000.0),
        ellipsoid : {
            radii : new Cesium.Cartesian3(200000.0, 200000.0, 200000.0)
        }
    });
    
    window.setInterval(function() {
        var pos = e.position._value;
    
        var cart = Cesium.Ellipsoid.WGS84.cartesianToCartographic(pos);
    
        pos = Cesium.Cartesian3.fromRadians(cart.longitude + (1 * Math.PI / 180), cart.latitude, cart.height);
    
        e.position = pos;
    }, 400);
    

    Currently there's no way to know from the Entity API when the worker is done updating the geometry. You may have to move this example out of Entity API and use the Primitive API instead.