Search code examples
javascriptcesiumjs

How do I clip an entity or geometry against underside of terrain


I am using the Cesium.Globe clipping planes to extract a square geographic section. But one problem is that terrain back-faces are not rendered which makes it look weird when the user selects a shallow viewing angle.

Shallow View

I thought one way to hide this was to render the "soil" as a box or wall under the terrain, but I would need the top of the box or wall to confirm to the terrain geometry (red line). I figure I can achieve this by using a WallGeometry around the culled terrain instead of a box, and set the height of each section based on the result of a sampleTerrain call.

But I was wondering if Cesium doesn't provide an easier and cleaner way to do this. (Like perhaps some Boolean union function or something)

Cut out box

Cesium Sandcastle link

var viewer = new Cesium.Viewer('cesiumContainer', {
        skyAtmosphere: false,
        shouldAnimate : true,
        terrainProvider: Cesium.createWorldTerrain()
    });
var globe = viewer.scene.globe;

var position = Cesium.Cartographic.toCartesian(new Cesium.Cartographic.fromDegrees(-113.2665534, 36.0939345, 100));
var distance = 3000.0;

globe.clippingPlanes = new Cesium.ClippingPlaneCollection({
    modelMatrix : Cesium.Transforms.eastNorthUpToFixedFrame(position),
    planes : [
        new Cesium.ClippingPlane(new Cesium.Cartesian3( 1.0,  0.0, 0.0), distance),
        new Cesium.ClippingPlane(new Cesium.Cartesian3(-1.0,  0.0, 0.0), distance),
        new Cesium.ClippingPlane(new Cesium.Cartesian3( 0.0,  1.0, 0.0), distance),
        new Cesium.ClippingPlane(new Cesium.Cartesian3( 0.0, -1.0, 0.0), distance)
    ],
    unionClippingRegions : true,
            edgeWidth:3,
    edgeColor: Cesium.Color.RED,
    enabled : true
});
var rockBox = viewer.entities.add({
    name : 'RockBox',
    position: Cesium.Cartesian3.fromDegrees(-113.2665534, 36.0939345, 900),
    box : {
        dimensions : new Cesium.Cartesian3(distance*2, distance*2,800.0),
        material : Cesium.Color.GRAY.withAlpha(0.4),
        outline : true,
        outlineColor : Cesium.Color.GRAY
    }
});
var waterTable = viewer.entities.add({
    name : 'WaterTable',
    position: Cesium.Cartesian3.fromDegrees(-113.2665534, 36.0939345, 440),
    box : {
        dimensions : new Cesium.Cartesian3(distance*2, distance*2, 160.0),
        material : Cesium.Color.BLUE.withAlpha(0.9),
        outline : true,
        outlineColor : Cesium.Color.BLUE
    }
});

viewer.zoomTo(viewer.entities);

Solution

  • At updated CesiumGS version (currently 1.72), we show back faces of terrain via public API like this:

    viewer.scene.globe.backFaceCulling = false;