Changing ImageryProvider randomly obscures existing billboards and labels

712 views
Skip to first unread message

rencia...@gmail.com

unread,
Apr 2, 2014, 11:55:13 AM4/2/14
to cesiu...@googlegroups.com, ren...@suritec.co.za
Hi, When I change the Map provider, the existing billboards and labels are then randomly semi-obscured as if rendering the new tiles interferes with who is on top. Sometimes it only happens when one zooms in or out of the globe....
Do I need to put in the CompositePrimitive raiseToTop code - then please show me how - do I raise the entire BillboardCollection? Sandcastle code follows.
Many thanks!
Regards
Rencia


require(['Cesium'], function(Cesium) {
"use strict";

var widget = new Cesium.CesiumWidget('cesiumContainer', {
imageryProvider : new Cesium.ArcGisMapServerImageryProvider({
url : 'http://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer'
})
});

var layers = widget.centralBody.imageryLayers;


var ellipsoid = widget.centralBody.ellipsoid;
var scene = widget.scene;
var primitives = scene.primitives;


var image = new Image();
image.onload = function() {
var billboards = new Cesium.BillboardCollection();
var textureAtlas = scene.context.createTextureAtlas({
image : image
});
billboards.textureAtlas = textureAtlas;

billboards.add({
position : ellipsoid.cartographicToCartesian(Cesium.Cartographic.fromDegrees(-75.59777, 40.03883)),
imageIndex : 0
});
scene.primitives.add(billboards);
};
image.src = '../images/Cesium_Logo_overlay.png';

function changeMap(layers){
var provider = new Cesium.TileMapServiceImageryProvider({
url :'../../../Source/Assets/Textures/' + 'NaturalEarthII'
});
try{
layers.removeAll();
}catch( e){
}
layers.addImageryProvider(provider);
widget.centralBody.depthTestAgainstTerrain = true;
}

Sandcastle.addToolbarButton('changeMap', function() {
changeMap(layers);
});

Sandcastle.finishedLoading();
});

Kevin Ring

unread,
Apr 7, 2014, 4:09:44 PM4/7/14
to cesiu...@googlegroups.com
Hi,

Changing the base imagery layer causes Cesium to re-refine the terrain surface (or the ellipsoid surface if you're not using terrain) from the low-resolution root.  The end result is that the surface may appear to move up or down relative to other objects placed near the surface until the imagery down to the level you're looking at has been fully loaded.  If you're seeing a change in obscuration after the new layer is done loading, though, then you may be seeing a different problem.

Kevin



--
You received this message because you are subscribed to the Google Groups "cesium-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cesium-dev+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--

Rencia Cloete

unread,
Apr 14, 2014, 6:30:55 AM4/14/14
to cesiu...@googlegroups.com
Thanks Kevin, will do more testing & see if the problem persists after some passage of time....



--
You received this message because you are subscribed to a topic in the Google Groups "cesium-dev" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/cesium-dev/fHVc4gVI6vI/unsubscribe.
To unsubscribe from this group and all its topics, send an email to cesium-dev+...@googlegroups.com.

rencia...@gmail.com

unread,
Apr 22, 2014, 3:57:28 AM4/22/14
to cesiu...@googlegroups.com, rencia...@gmail.com
On Monday, 14 April 2014 12:30:55 UTC+2, Rencia Cloete wrote:
> Thanks Kevin, will do more testing & see if the problem persists after some passage of time....
>
>
>


>
> Hi Kevin, nope, obscuration persists. When move the graphic around, the billboards and labels surface and semi-obscure randomly .... even 10 minutes later.
Any ideas?
Thanks
Regards
Rencia
>

rencia...@gmail.com

unread,
Apr 22, 2014, 4:35:40 AM4/22/14
to cesiu...@googlegroups.com, rencia...@gmail.com

rencia...@gmail.com

unread,
May 6, 2014, 5:11:44 AM5/6/14
to cesiu...@googlegroups.com, rencia...@gmail.com
On Tuesday, 22 April 2014 09:57:28 UTC+2, rencia...@gmail.com wrote:

Hi, have just upgraded to b28, sorted some other issues but this one is a bit worse. I see that in b29 coming is "Improved terrain and imagery rendering performance when very close to the surface" - might that solve my problem?

See sandcastle code below. Obscuration now happening right from the start, not only after change base imagery layer. My real billboards are much smaller than this image so I lose them entirely.... Commenting out the depthTestAgainstTerrain on line 31 solves it for the billboards but then the ellipsoid and ellipsoidOutlineGeometry doesn't work properly when under the surface. See my other post
https://groups.google.com/forum/embed/?place=forum%2Fcesium-dev&showsearch=true&hideforumtitle=true&parenturl=http%3A%2F%2Fcesiumjs.org%2Fforum.html&theme=default#!topic/cesium-dev/ZCzBQsDALD0

Many thanks.
Rencia

rencia...@gmail.com

unread,
May 6, 2014, 5:12:40 AM5/6/14
to cesiu...@googlegroups.com, rencia...@gmail.com

Oops, here is my code:


require(['Cesium'], function(Cesium) {
"use strict";

var handler;
var label;
var billboard;

function addBillboard(scene, ellipsoid) { //, image) {


var image = new Image();

image.src = '../images/Cesium_Logo_overlay.png';

var billboards = new Cesium.BillboardCollection();

var textureAtlas = scene.createTextureAtlas({


image : image
});
billboards.textureAtlas = textureAtlas;

billboard = billboards.add({


position : ellipsoid.cartographicToCartesian(Cesium.Cartographic.fromDegrees(-75.59777, 40.03883)),
imageIndex : 0
});

billboard.isBillBoard = true;
scene.primitives.add(billboards);
}


var widget = new Cesium.CesiumWidget('cesiumContainer');

var scene = widget.scene;
var ellipsoid = scene.globe.ellipsoid;

scene.globe.depthTestAgainstTerrain = true; //so that shapes UNDER the surface are not visible

addBillboard(scene, ellipsoid);

Sandcastle.finishedLoading();
});

Kevin Ring

unread,
May 13, 2014, 3:01:22 PM5/13/14
to cesiu...@googlegroups.com
Hi,

Since you're not specifying a height in the call to Cesium.Cartographic.fromDegrees, Cesium uses a height of 0.0 meters, relative to the WGS84 ellipsoid.  In most cases, that's underneath the terrain surface.

You can use the sampleTerrain function to compute the height of terrain at a given list of longitude/latitudes.

It's also a good idea to set the billboard's verticalOrigin property to Cesium.VerticalOrigin.Bottom.  Otherwise, half of the billboard will still be below terrain.

Kevin


--
You received this message because you are subscribed to the Google Groups "cesium-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cesium-dev+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

rencia...@gmail.com

unread,
May 21, 2014, 10:08:08 AM5/21/14
to cesiu...@googlegroups.com, ren...@suritec.co.za
Only seeing this now ... Thanks Kevin! Will give those a bash.
Regards
Rencia

Rencia Cloete

unread,
May 21, 2014, 10:24:22 AM5/21/14
to cesiu...@googlegroups.com
Kevin, any chance you could advise me on my other issue. Have excluded 2D for the moment because of it but REALLY want it back!
See

Many thanks!
Regards
Rencia



--
You received this message because you are subscribed to a topic in the Google Groups "cesium-dev" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/cesium-dev/fHVc4gVI6vI/unsubscribe.
To unsubscribe from this group and all its topics, send an email to cesium-dev+...@googlegroups.com.

Rencia Cloete

unread,
May 22, 2014, 9:36:54 AM5/22/14
to cesiu...@googlegroups.com, ren...@suritec.co.za
Hi Kevin, have switched on the notification in google mail now, so it notifies me when emails arrive!!
I tried the terrainprovider you suggested - not much success - then I switched off my depthTestAgainstTerrain and voila!! Works.
However I also need that depthTest on account of the ellipsoids .... 
Below is my sandcastle code, draws billboard, polygon & ellipsoid - if you comment / uncomment the depthTestAgainstTerrain on line 12, you will see what I mean. Zoom in & out when it it is on and you see how the polygon & billboard disappear/appear. 
We need the ellipsoid to be cut off at the earth/sea surface. If we use it to surround for eg. an object rising from the surface, it gradually reveals more until when the object is higher than the diameter, you will see the whole ellipse.

How can I chop off the portion of the ellipsoid below the surface? Or should I be using an entirely different object altogether? Remember that the ellipsoid also needs to move position with the object...  (For the movement - Dan gave me the solution to seperate out the modelmatrix - which causes the 2D to fail, but 3D moves easily)

Summary of issues desperate for help:
1. Visibility of billboards, polylineCollections, labels and polygons VERSUS hiding ellipsoid portion below surface
2. Moving ellipsoid but still keeping 2D integrity .... 

Please help. Thanks!
Regards
Rencia

Code:


require(['Cesium'], function(Cesium) {
    "use strict";
    
        var widget = new Cesium.CesiumWidget('cesiumContainer', {
        imageryProvider : new Cesium.OpenStreetMapImageryProvider({
        })
    });

    var scene = widget.scene;
    //scene.globe.depthTestAgainstTerrain = true;
    
    var primitives = scene.primitives;
    var ellipsoid = scene.globe.ellipsoid;
    
    var terrainProvider = new Cesium.CesiumTerrainProvider({
        url : '//cesiumjs.org/smallterrain'
    });
    
    var billboard;
 
    function addBillboard(scene, ellipsoid, terrainProvider) { //, image) {
            var image = new Image();
            image.src = '../images/Cesium_Logo_overlay.png';
        var positions = ellipsoid.cartographicArrayToCartesianArray([
            Cesium.Cartographic.fromDegrees(18.06, -32.65)
         ]);
        var promise = Cesium.sampleTerrain(terrainProvider, 11, positions);
        Cesium.when(promise, function(updatedPositions) {

            var billboards = new Cesium.BillboardCollection();
            var textureAtlas = scene.createTextureAtlas({

                image : image
            });
            billboards.textureAtlas = textureAtlas;
            billboard = billboards.add({

                position : positions[0],
                imageIndex : 0,
                verticalOrigin : Cesium.VerticalOrigin.BOTTOM
            });
            billboard.isBillBoard = true;
            scene.primitives.add(billboards);
        });
    }
    
    function drawPoly(terrainProvider, primitives) {
    
        // Red polygon
        var positions = ellipsoid.cartographicArrayToCartesianArray([
            Cesium.Cartographic.fromDegrees(17.96, -32.65),
            Cesium.Cartographic.fromDegrees(18.06, -32.75),
            Cesium.Cartographic.fromDegrees(18.37, -32.67),
            Cesium.Cartographic.fromDegrees(17.97, -32.56)
        ]);
        
        var promise = Cesium.sampleTerrain(terrainProvider, 11, positions);
        Cesium.when(promise, function(updatedPositions) {
            var redPolygonInstance = new Cesium.GeometryInstance({
                geometry : Cesium.PolygonGeometry.fromPositions({
                    positions : positions,
                    vertexFormat : Cesium.PerInstanceColorAppearance.VERTEX_FORMAT
                }),
                attributes: {
                    color: Cesium.ColorGeometryInstanceAttribute.fromColor(new Cesium.Color(1.0, 0.0, 0.0, 0.2))
                }
            });
        
         
        
            // Add polygon instances to primitives
            primitives.add(new Cesium.Primitive({
                geometryInstances : redPolygonInstance,
                appearance : new Cesium.PerInstanceColorAppearance({
                    closed : true,
                    translucent : true
                })
            }));
         });
    }
    
    function drawDome(scene, ellipsoid, terrainProvider) {
         // Create ellipsoid are position with model matrix
        var height = -2500.0;
        var positions = ellipsoid.cartographicArrayToCartesianArray([
            Cesium.Cartographic.fromDegrees(18.06, -32.60)
         ]);
        var radii = new Cesium.Cartesian3(5000.0, 5000.0, 5000.0);
        var promise = Cesium.sampleTerrain(terrainProvider, 11, positions);
        Cesium.when(promise, function(updatedPositions) {
        
            var ellipsoidmodelMatrix = Cesium.Matrix4.multiplyByTranslation(
                Cesium.Transforms.eastNorthUpToFixedFrame(positions[0]),
                new Cesium.Cartesian3(0.0, 0.0, height)
            );
            var ellipsoidGeometry = new Cesium.EllipsoidGeometry({
                vertexFormat : Cesium.VertexFormat.VERTEX_FORMAT,
                radii : radii
            });
            var ellipsoidInstance = new Cesium.GeometryInstance({
                geometry : ellipsoidGeometry,
                //modelMatrix : ellipsoidmodelMatrix,
                id : 'dome',
                attributes : {
                    color : Cesium.ColorGeometryInstanceAttribute.fromColor(new Cesium.Color(0.0, 0.0, 1.0, 0.4))
                }
            });
            
            // Add ellipsoid instance to primitives
            var domePrimitive = new Cesium.Primitive({
                geometryInstances : ellipsoidInstance,
                id : 'dome',
                appearance : new Cesium.PerInstanceColorAppearance({
                    translucent : true//,
                    //closed : true
                })
            });
            domePrimitive.modelMatrix = ellipsoidmodelMatrix;
            scene.primitives.add(domePrimitive);
        });
    }
    
    Sandcastle.addToolbarButton('Draw polygon', function() {
        //cleanup();
        drawPoly(terrainProvider, primitives);
    });
    
    Sandcastle.addToolbarButton('Draw billboard', function() {
        //cleanup();
        addBillboard(scene, ellipsoid, terrainProvider);
    });
       
    Sandcastle.addToolbarButton('Draw dome', function() {
        //cleanup();
        drawDome(scene, ellipsoid, terrainProvider);
    });

    
    var destination = Cesium.Cartographic.fromDegrees(18.06, -32.70, 25000.0);

    var flight = Cesium.CameraFlightPath.createAnimationCartographic(scene, {
            destination : destination
        });
    scene.animations.add(flight);

    Sandcastle.finishedLoading();
});
 


Kevin Ring

unread,
May 23, 2014, 5:04:16 PM5/23/14
to cesiu...@googlegroups.com
Hi,

I would try leaving depthTestAgainstTerrain on, and then put your billboard a bit above the terrain surface.  Adding one meter should do the trick.

Kevin


--
You received this message because you are subscribed to the Google Groups "cesium-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cesium-dev+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Rencia Cloete

unread,
May 23, 2014, 6:23:00 PM5/23/14
to cesiu...@googlegroups.com
Hi Kevin, nope I tried that, went as high as 10m, still the obscuration persists. Thats when I started posting to you guys...
Its turning out a bit tricky to keep using the terrainprovider, the polygon keeps changing so have to store the points, going back and forth between java & javascript.... isn't there some way I can chop that ellipsoid for the dome in half? 
Sorry to be a nuisance!
Thanks
Rencia


--
You received this message because you are subscribed to a topic in the Google Groups "cesium-dev" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/cesium-dev/fHVc4gVI6vI/unsubscribe.
To unsubscribe from this group and all its topics, send an email to cesium-dev+...@googlegroups.com.

Rencia Cloete

unread,
May 23, 2014, 6:36:54 PM5/23/14
to cesiu...@googlegroups.com
Hi Kevin, What about a depthTest Setting attached to a specific object only not the whole globe? How difficult would that be to implement?
Thinking out loud...
R

Rencia Cloete

unread,
May 24, 2014, 6:04:32 PM5/24/14
to cesiu...@googlegroups.com
Hiya, Been thinking all day about that depthTest. When its set to true, the graphics render more slowly, objects flicker - eg.  polylineCollections  come and go as you zoom in & out.
I implemented the code to use the sampleTerrain Setting that you suggested for the obscuration - using a brief sampling of the objects I am using, - running in the sandcastle - a fantastic tool by the way! 
Thats the code I posted above. Could not get it to work the way you suggested, but maybe I am doing it incorrectly? I so appreciate that you must be busy people - and doing this opensource on the side; but would muchly appreciate you having a look at that code .... 

But if  depthTestAgainstTerrain = false; presto, MUCH more dynamic response from the graphics! And no obscuration!
SO - it seems to make sense that if one places a filter like that on the rendering of every object - they would take longer, having to be re-interpreted with every zoom of the mouse! and after thousands of objects - which we still need to simulate, the response might decay more. 

The obscuration of the objects is the more pressing problem though because that could affect the human interpretation of the information, certainly the ease of its use.
SO, I am imagining adding a depthTest to only a certain specific instance of an object say THIS ellipsoid+ellipsoidOutline. 

I will do a search on the cesium.js to see if I can find a reference to your actual code that does exactly that - but seperating it from its context to extract only that kernel is a daunting task and will take much time. I would very much appreciate it if you could isolate the code FOR me that actually evaluates & sets occlusion on a specific object.  Do you think what I suggest is possible? Is it as easily done as I imagine?
If I had the actual code fragment it would make it so much easier to incorporate into my code that constructs or moves the graphic representation of the object.

Even more excellent if you added it as say an attribute.... but i need it real soon, like midweek next week if possible. So perhaps quicker if for mow I just added it to the code that constructs & moves the object....
What do you think?
Thanks.
Rencia

Rencia Cloete

unread,
Jun 2, 2014, 9:47:43 AM6/2/14
to cesiu...@googlegroups.com
Hi Kevin, any further info on the depthtest versus sampleTerrain? Thanks. 

Kevin Ring

unread,
Jun 2, 2014, 11:03:32 AM6/2/14
to cesiu...@googlegroups.com
Hi Rencia,

That's suspicious that turning off the depth test improves performance.  Perhaps surprisingly, turning off the depth test results in Cesium doing more work, not less.  Specifically, after it renders terrain, it issues an additional command to clear the depth buffer before rendering the rest of the graphics.  This is also the reason that we can't control depth testing per primitive: once the depth buffer is cleared, it is not available for use by any primitives.  It's possible to leave the depth buffer intact but disable depth testing for individual primitives, but then primitives on the back side of the globe are visible, too (and possibly other rendering artifacts).

The obscuration at different zoom levels is probably caused by the changing level of detail of the terrain surface.  You may be able to solve or at least reduce this by moving the object higher (even higher than 10 m) above the terrain surface.  But mostly this is a tough problem, and it's one that we'll solve eventually but not extremely soon.  In the meantime, one way to deal with surface-conforming geometry is to rasterize it.  Import your vector data into something like Geoserver and then serve it to Cesium as a WMS imagery layer.

Kevin

Rencia Cloete

unread,
Jun 3, 2014, 1:34:17 PM6/3/14
to cesiu...@googlegroups.com
Thanks Kevin. Will play around a bit more then.
Regards
Rencia
Reply all
Reply to author
Forward
0 new messages