Cesium: Model pick shaders do not use clipping planes

Created on 3 Feb 2018  路  5Comments  路  Source: CesiumGS/cesium

The clipping planes code is added to the model render fragment shader but not the pick fragment shader. In the below example, rotate the camera to be level with the clipping plane and pick where one of the towers would be if it wasn't clipped. It will still be highlighted.

// Add a clipping plane, a plane geometry to show the representation of the
// plane, and control the magnitude of the plane distance with the mouse.
// Clipping planes are not currently supported in Internet Explorer.

var viewer = new Cesium.Viewer('cesiumContainer', {
    infoBox: false,
    selectionIndicator: false
});
var scene = viewer.scene;

var clipObjects = ['BIM', 'Point Cloud', 'Instanced', 'Model'];
var viewModel = {
    debugBoundingVolumesEnabled : false,
    edgeStylingEnabled : true,
    exampleTypes : clipObjects,
    currentExampleType : clipObjects[0]
};

var targetY = 0.0;
var planeEntities = [];
var selectedPlane;

// Select plane when mouse down
var downHandler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
downHandler.setInputAction(function(movement) {
    var pickedObject = scene.pick(movement.position);
    if (Cesium.defined(pickedObject) &&
            Cesium.defined(pickedObject.id) &&
            Cesium.defined(pickedObject.id.plane)) {
        selectedPlane = pickedObject.id.plane;
        selectedPlane.material = Cesium.Color.WHITE.withAlpha(0.05);
        selectedPlane.outlineColor = Cesium.Color.WHITE;
        scene.screenSpaceCameraController.enableInputs = false;
    }
}, Cesium.ScreenSpaceEventType.LEFT_DOWN);

// Release plane on mouse up
var upHandler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
upHandler.setInputAction(function() {
    if (Cesium.defined(selectedPlane)) {
        selectedPlane.material = Cesium.Color.WHITE.withAlpha(0.1);
        selectedPlane.outlineColor = Cesium.Color.WHITE;
        selectedPlane = undefined;
    }

    scene.screenSpaceCameraController.enableInputs = true;
}, Cesium.ScreenSpaceEventType.LEFT_UP);

// Update plane on mouse move
var moveHandler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
moveHandler.setInputAction(function(movement) {
    if (Cesium.defined(selectedPlane)) {
        var deltaY = movement.startPosition.y - movement.endPosition.y;
        targetY += deltaY;
    }
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

var scratchPlane = new Cesium.Plane(Cesium.Cartesian3.UNIT_X, 0.0);
function createPlaneUpdateFunction(plane, transform) {
    return function () {
        plane.distance = targetY;
        return Cesium.Plane.transform(plane, transform, scratchPlane);
    };
}

var tileset;
function loadTileset(url) {
    var clippingPlanes = [
        new Cesium.Plane(new Cesium.Cartesian3(0.0, 0.0, -1.0), -100.0)
    ];

    tileset = viewer.scene.primitives.add(new Cesium.Cesium3DTileset({
        url : url,
        clippingPlanes : new Cesium.ClippingPlaneCollection({
            planes : clippingPlanes,
            edgeWidth : viewModel.edgeStylingEnabled ? 1.0 : 0.0
        })
    }));

    tileset.debugShowBoundingVolume = viewModel.debugBoundingVolumesEnabled;
    return tileset.readyPromise.then(function() {
        var boundingSphere = tileset.boundingSphere;
        var radius = boundingSphere.radius;

        viewer.zoomTo(tileset, new Cesium.HeadingPitchRange(0.5, -0.2, radius * 4.0));

        for (var i = 0; i < clippingPlanes.length; ++i) {
            var plane = clippingPlanes[i];
            var planeEntity = viewer.entities.add({
                position : boundingSphere.center,
                plane : {
                    dimensions : new Cesium.Cartesian2(radius * 2.5, radius * 2.5),
                    material : Cesium.Color.WHITE.withAlpha(0.1),
                    plane : new Cesium.CallbackProperty(createPlaneUpdateFunction(plane, tileset.modelMatrix), false),
                    outline : true,
                    outlineColor : Cesium.Color.WHITE
                }
            });

            planeEntities.push(planeEntity);
        }
    }).otherwise(function(error) {
        console.log(error);
    });
}

var modelEntityClippingPlanes;
function loadModel(url) {
    var clippingPlanes = [
        new Cesium.Plane(new Cesium.Cartesian3(0.0, 0.0, -1.0), -100.0)
    ];

    modelEntityClippingPlanes = new Cesium.ClippingPlaneCollection({
        planes : clippingPlanes,
        edgeWidth : viewModel.edgeStylingEnabled ? 1.0 : 0.0
    });

    function updateClippingPlanes() {
        return modelEntityClippingPlanes;
    }

    var position = Cesium.Cartesian3.fromDegrees(-123.0744619, 44.0503706, 100.0);
    var heading = Cesium.Math.toRadians(135.0);
    var pitch = 0.0;
    var roll = 0.0;
    var hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll);
    var orientation = Cesium.Transforms.headingPitchRollQuaternion(position, hpr);
    var entity = viewer.entities.add({
        name : url,
        position : position,
        orientation : orientation,
        model : {
            uri : url,
            scale : 8,
            minimumPixelSize : 100.0,
            clippingPlanes : new Cesium.CallbackProperty(updateClippingPlanes, false)
        }
    });

    viewer.trackedEntity = entity;

    for (var i = 0; i < clippingPlanes.length; ++i) {
        var plane = clippingPlanes[i];
        var planeEntity = viewer.entities.add({
            position : position,
            plane : {
                dimensions : new Cesium.Cartesian2(300.0, 300.0),
                material : Cesium.Color.WHITE.withAlpha(0.1),
                plane : new Cesium.CallbackProperty(createPlaneUpdateFunction(plane, Cesium.Matrix4.IDENTITY), false),
                outline : true,
                outlineColor : Cesium.Color.WHITE
            }
        });

        planeEntities.push(planeEntity);
    }
}

// Power Plant design model provided by Bentley Systems
var bimUrl = Cesium.CesiumIon.createResource(1459, { accessToken: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIzNjUyM2I5Yy01YmRhLTQ0MjktOGI0Zi02MDdmYzBjMmY0MjYiLCJpZCI6NDQsImFzc2V0cyI6WzE0NTldLCJpYXQiOjE0OTkyNjQ3ODF9.SW_rwY-ic0TwQBeiweXNqFyywoxnnUBtcVjeCmDGef4' });
var pointCloudUrl = Cesium.CesiumIon.createResource(1460, { accessToken: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIyMzk2YzJiOS1jZGFmLTRlZmYtYmQ4MS00NTA3NjEwMzViZTkiLCJpZCI6NDQsImFzc2V0cyI6WzE0NjBdLCJpYXQiOjE0OTkyNjQ3NTV9.oWjvN52CRQ-dk3xtvD4e8ZnOHZhoWSpJLlw115mbQJM' });
var instancedUrl = '../../../Specs/Data/Cesium3DTiles/Instanced/InstancedOrientation/';
var modelUrl = '../../SampleData/models/CesiumAir/Cesium_Air.glb';

bimUrl.then(function(resource) {
    return loadTileset(resource);
});

// Track and create the bindings for the view model
var toolbar = document.getElementById('toolbar');
Cesium.knockout.track(viewModel);
Cesium.knockout.applyBindings(viewModel, toolbar);

Cesium.knockout.getObservable(viewModel, 'currentExampleType').subscribe(function(newValue) {
    reset();

    if (newValue === clipObjects[0]) {
        bimUrl.then(function(resource) {
            return loadTileset(resource);
        });
    } else if (newValue === clipObjects[1]) {
        pointCloudUrl.then(function(resource) {
            return loadTileset(resource);
        }).then(function() {
            tileset.clippingPlanes.modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(tileset.boundingSphere.center);
        });
    } else if (newValue === clipObjects[2]) {
        loadTileset(instancedUrl).then(function() {
            tileset.clippingPlanes.modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(tileset.boundingSphere.center);
        });
    } else {
        loadModel(modelUrl);
    }
});

Cesium.knockout.getObservable(viewModel, 'debugBoundingVolumesEnabled').subscribe(function(value) {
    if (Cesium.defined(tileset)) {
        tileset.debugShowBoundingVolume = value;
    }
});

Cesium.knockout.getObservable(viewModel, 'edgeStylingEnabled').subscribe(function(value) {
    var edgeWidth = value ? 1.0 : 0.0;

    if (Cesium.defined(tileset)) {
        tileset.clippingPlanes.edgeWidth = edgeWidth;
    }

    if (Cesium.defined(modelEntityClippingPlanes)) {
        modelEntityClippingPlanes.edgeWidth = edgeWidth;
    }
});

function reset() {
    viewer.entities.removeAll();
    viewer.scene.primitives.removeAll();
    planeEntities = [];
    targetY = 0.0;
}

// Information about the currently selected feature
    var selected = {
        feature: undefined,
        originalColor: new Cesium.Color()
    };

// Information about the currently highlighted feature
    var highlighted = {
        feature: undefined,
        originalColor: new Cesium.Color()
    };

// An entity object which will hold info about the currently selected feature for infobox display
    var selectedEntity = new Cesium.Entity();

// Color a feature on selection and show metadata in the InfoBox.
    var clickHandler = viewer.screenSpaceEventHandler.getInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
    viewer.screenSpaceEventHandler.setInputAction(function onLeftClick(movement) {
        // If a feature was previously selected, undo the highlight
        if (Cesium.defined(selected.feature)) {
            selected.feature.color = selected.originalColor;
            selected.feature = undefined;
        }

        // Pick a new feature
        var pickedFeature = viewer.scene.pick(movement.position);
        if (!Cesium.defined(pickedFeature)) {
            clickHandler(movement);
            return;
        }

        // Select the feature if it's not already selected
        if (selected.feature === pickedFeature) {
            return;
        }
        selected.feature = pickedFeature;

        // Save the selected feature's original color
        if (pickedFeature === highlighted.feature) {
            Cesium.Color.clone(highlighted.originalColor, selected.originalColor);
            highlighted.feature = undefined;
        } else {
            Cesium.Color.clone(pickedFeature.color, selected.originalColor);
        }

        // Highlight newly selected feature
        pickedFeature.color = Cesium.Color.LIME;

        if (!Cesium.defined(pickedFeature.getProperty)) {
            return;
        }

        // Set feature infobox description
        var featureName = pickedFeature.getProperty('name');
        selectedEntity.name = featureName;
        selectedEntity.description = 'Loading <div class="cesium-infoBox-loading"></div>';
        viewer.selectedEntity = selectedEntity;
        selectedEntity.description = '<table class="cesium-infoBox-defaultTable"><tbody>' +
                                     '<tr><th>BIN</th><td>' + pickedFeature.getProperty('BIN') + '</td></tr>' +
                                     '<tr><th>DOITT ID</th><td>' + pickedFeature.getProperty('DOITT_ID') + '</td></tr>' +
                                     '<tr><th>SOURCE ID</th><td>' + pickedFeature.getProperty('SOURCE_ID') + '</td></tr>' +
                                     '</tbody></table>';
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);


category - gltf priority - high type - bug

All 5 comments

Good catch @bagnell, I am surprised we let this through.

@likangning93 do you want to do this as part of your infinite clipping plane/box?

Verified that this seems to work fine with pointclouds at least.

Very nice, thanks!!!

Removing priority next release, this will come in with #6201

Was this page helpful?
0 / 5 - 0 ratings

Related issues

lilleyse picture lilleyse  路  4Comments

jony89 picture jony89  路  4Comments

rahwang picture rahwang  路  3Comments

hanbollar picture hanbollar  路  4Comments

OmarShehata picture OmarShehata  路  4Comments