Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Per-feature post-processing #6476

Merged
merged 50 commits into from
Jun 4, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
601841c
Per-feature post-processing WIP.
bagnell Feb 5, 2018
0875b17
Per-feature post-process WIP.
bagnell Feb 5, 2018
43d2b45
Per-feature post-process [skip ci].
bagnell Feb 5, 2018
6a159eb
Merge branch 'post-processing-1.0' into per-feature-post-process
bagnell Mar 27, 2018
c6781a3
Remove render state override.
bagnell Mar 27, 2018
1766464
Add ability to have multiple silhouette colors.
bagnell Mar 28, 2018
77826df
Add black and white selected feature option.
bagnell Mar 28, 2018
d36507e
Fix silhouette artifact. Add mouse over black and white example.
bagnell Mar 29, 2018
8c4d392
Fix single silhouetted example. Add Sandcastle example.
bagnell Mar 29, 2018
82bf70b
Only render pick id when post process has selected features.
bagnell Mar 30, 2018
8408c7f
Use derived pick commands for billboards.
bagnell Mar 30, 2018
bca8eda
Update picking for 3D Tiles.
bagnell Apr 5, 2018
1599d31
If command is not pickable, write depth.
bagnell Apr 10, 2018
e5ca775
Remove more picking code in favor of derived commands. Add dev Sandca…
bagnell Apr 11, 2018
5616502
Disable blending for pick render state.
bagnell Apr 11, 2018
6879b96
Use derived pick commands for vector tile polylines.
bagnell Apr 12, 2018
cb38405
Use derived commands for primitives (not classification).
bagnell Apr 12, 2018
d1dd710
Merge branch 'post-processing-1.0' into per-feature-post-process
bagnell Apr 19, 2018
4daa234
Fixes after merge.
bagnell Apr 19, 2018
98f280b
Update ModelInstanceCollection WIP. Update picking test sandcastle ex…
bagnell Apr 19, 2018
8f2d660
Add fix and example for model instancing.
bagnell Apr 20, 2018
eb66871
Fix point cloud picking and add example.
bagnell Apr 20, 2018
fc19067
Add vector tile picking examples.
bagnell Apr 20, 2018
cefe1d8
Add private pick id getter to primitives.
bagnell Apr 20, 2018
8c6e4c4
Merge branch 'post-processing-1.0' into per-feature-post-process
bagnell May 3, 2018
c912b25
Fix after merge.
bagnell May 3, 2018
a87ee51
Fix renamed constant after merge.
bagnell May 3, 2018
15d796e
Fix some tests.
bagnell May 3, 2018
63e3f5b
Fix picking b3dms without a batch id and fix more tests. [ci skip]
bagnell May 4, 2018
2cf7fab
Merge branch 'post-processing-1.0' into per-feature-post-process
bagnell May 4, 2018
effb7c5
Fix instanced picking and vector tile points tests.
bagnell May 8, 2018
05e83d2
Fix more tests. Remove pick id declaration and use the original fragm…
bagnell May 8, 2018
6b54601
Fix vector tile picking tests.
bagnell May 8, 2018
f5ebf96
Fix remaining tests.
bagnell May 9, 2018
3a04a35
Add per-feature tests.
bagnell May 9, 2018
9ef51fa
Fix eslint error.
bagnell May 9, 2018
4771073
Update CHANGEs.md and doc.
bagnell May 9, 2018
15d7f7e
Fix WebGL stub test failures.
bagnell May 9, 2018
675e6d4
Create batch table pick texture on pick or per-feature post-process.
bagnell May 9, 2018
b5c71e2
Typos
lilleyse May 10, 2018
0f5f189
Updates from review.
bagnell May 10, 2018
cdb00a4
Add fallback to feature color for 3D Tiles picking example.
bagnell May 10, 2018
8959e7c
Fix silhouettes with alpha and add console warning when silhouettes a…
bagnell May 11, 2018
96d3916
Fix crash when switching between stages in the per-feature post-proce…
bagnell May 11, 2018
f6ccb68
Fix crashes and remove unneeded code.
bagnell May 11, 2018
d88c2ee
Merge branch 'master' into per-feature-post-process
bagnell May 15, 2018
d01201d
Fix after merge.
bagnell May 15, 2018
664f72f
Update CHANGES.md.
bagnell May 15, 2018
d38bbbf
Merge branch 'master' into per-feature-post-process
bagnell May 15, 2018
428abde
Merge branch 'master' into per-feature-post-process
bagnell Jun 4, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
253 changes: 167 additions & 86 deletions Apps/Sandcastle/gallery/3D Tiles Feature Picking.html
Original file line number Diff line number Diff line change
Expand Up @@ -65,96 +65,177 @@
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 yellow on hover.
viewer.screenSpaceEventHandler.setInputAction(function onMouseMove(movement) {
// If a feature was previously highlighted, undo the highlight
if (Cesium.defined(highlighted.feature)) {
highlighted.feature.color = highlighted.originalColor;
highlighted.feature = undefined;
}

// Pick a new feature
var pickedFeature = viewer.scene.pick(movement.endPosition);
if (!Cesium.defined(pickedFeature)) {
nameOverlay.style.display = 'none';
return;
}

// A feature was picked, so show it's overlay content
nameOverlay.style.display = 'block';
nameOverlay.style.bottom = viewer.canvas.clientHeight - movement.endPosition.y + 'px';
nameOverlay.style.left = movement.endPosition.x + 'px';
var name = pickedFeature.getProperty('name');
if (!Cesium.defined(name)) {
name = pickedFeature.getProperty('id');
}
nameOverlay.textContent = name;

// Highlight the feature if it's not already selected.
if (pickedFeature !== selected.feature) {
highlighted.feature = pickedFeature;
Cesium.Color.clone(pickedFeature.color, highlighted.originalColor);
pickedFeature.color = Cesium.Color.YELLOW;
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

// Color a feature on selection and show metadata in the InfoBox.
// Get default left click handler for when a feature is not picked on left click
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;

// 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>' +
'<tr><th>Longitude</th><td>' + pickedFeature.getProperty('longitude') + '</td></tr>' +
'<tr><th>Latitude</th><td>' + pickedFeature.getProperty('latitude') + '</td></tr>' +
'<tr><th>Height</th><td>' + pickedFeature.getProperty('height') + '</td></tr>' +
'<tr><th>Terrain Height (Ellipsoid)</th><td>' + pickedFeature.getProperty('TerrainHeight') + '</td></tr>' +
'</tbody></table>';
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);

// If silhouettes are supported, silhouette features in blue on mouse over and silhouette green on mouse click.
// If silhouettes are not supported, change the feature color to yellow on mouse over and green on mouse click.

var silhouetteBlue = Cesium.PostProcessStageLibrary.createEdgeDetectionStage();
if (silhouetteBlue.isSupported(viewer.scene)) {
// Silhouettes are supported
silhouetteBlue.uniforms.color = Cesium.Color.BLUE;
silhouetteBlue.uniforms.length = 0.01;
silhouetteBlue.selectedFeatures = [];

var silhouetteGreen = Cesium.PostProcessStageLibrary.createEdgeDetectionStage();
silhouetteGreen.uniforms.color = Cesium.Color.LIME;
silhouetteGreen.uniforms.length = 0.01;
silhouetteGreen.selectedFeatures = [];

viewer.scene.postProcessStages.add(Cesium.PostProcessStageLibrary.createSilhouetteStage([silhouetteBlue, silhouetteGreen]));

// Silhouette a feature blue on hover.
viewer.screenSpaceEventHandler.setInputAction(function onMouseMove(movement) {
// If a feature was previously highlighted, undo the highlight
silhouetteBlue.selectedFeatures = [];

// Pick a new feature
var pickedFeature = viewer.scene.pick(movement.endPosition);
if (!Cesium.defined(pickedFeature)) {
nameOverlay.style.display = 'none';
return;
}

// A feature was picked, so show it's overlay content
nameOverlay.style.display = 'block';
nameOverlay.style.bottom = viewer.canvas.clientHeight - movement.endPosition.y + 'px';
nameOverlay.style.left = movement.endPosition.x + 'px';
var name = pickedFeature.getProperty('name');
if (!Cesium.defined(name)) {
name = pickedFeature.getProperty('id');
}
nameOverlay.textContent = name;

// Highlight the feature if it's not already selected.
if (pickedFeature !== selected.feature) {
silhouetteBlue.selectedFeatures = [pickedFeature];
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

// Silhouette a feature on selection and show metadata in the InfoBox.
viewer.screenSpaceEventHandler.setInputAction(function onLeftClick(movement) {
// If a feature was previously selected, undo the highlight
silhouetteGreen.selectedFeatures = [];

// 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 (silhouetteGreen.selectedFeatures[0] === pickedFeature) {
return;
}

// Save the selected feature's original color
var highlightedFeature = silhouetteBlue.selectedFeatures[0];
if (pickedFeature === highlightedFeature) {
silhouetteBlue.selectedFeatures = [];
}

// Highlight newly selected feature
silhouetteGreen.selectedFeatures = [pickedFeature];

// 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);
} else {
// Silhouettes are not supported. Instead, change the feature color.

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

// Color a feature yellow on hover.
viewer.screenSpaceEventHandler.setInputAction(function onMouseMove(movement) {
// If a feature was previously highlighted, undo the highlight
if (Cesium.defined(highlighted.feature)) {
highlighted.feature.color = highlighted.originalColor;
highlighted.feature = undefined;
}
// Pick a new feature
var pickedFeature = viewer.scene.pick(movement.endPosition);
if (!Cesium.defined(pickedFeature)) {
nameOverlay.style.display = 'none';
return;
}
// A feature was picked, so show it's overlay content
nameOverlay.style.display = 'block';
nameOverlay.style.bottom = viewer.canvas.clientHeight - movement.endPosition.y + 'px';
nameOverlay.style.left = movement.endPosition.x + 'px';
var name = pickedFeature.getProperty('name');
if (!Cesium.defined(name)) {
name = pickedFeature.getProperty('id');
}
nameOverlay.textContent = name;
// Highlight the feature if it's not already selected.
if (pickedFeature !== selected.feature) {
highlighted.feature = pickedFeature;
Cesium.Color.clone(pickedFeature.color, highlighted.originalColor);
pickedFeature.color = Cesium.Color.YELLOW;
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

// Color a feature on selection and show metadata in the InfoBox.
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;
// 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>' +
'<tr><th>Longitude</th><td>' + pickedFeature.getProperty('longitude') + '</td></tr>' +
'<tr><th>Latitude</th><td>' + pickedFeature.getProperty('latitude') + '</td></tr>' +
'<tr><th>Height</th><td>' + pickedFeature.getProperty('height') + '</td></tr>' +
'<tr><th>Terrain Height (Ellipsoid)</th><td>' + pickedFeature.getProperty('TerrainHeight') + '</td></tr>' +
'</tbody></table>';
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
}

//Sandcastle_End
Sandcastle.finishedLoading();
}
Expand Down
101 changes: 101 additions & 0 deletions Apps/Sandcastle/gallery/Per-Feature Post Processing.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
<meta name="description" content="Post processing effects.">
<meta name="cesium-sandcastle-labels" content="Showcases, Post Processing">
<title>Cesium Demo</title>
<script type="text/javascript" src="../Sandcastle-header.js"></script>
<script type="text/javascript" src="../../../ThirdParty/requirejs-2.1.20/require.js"></script>
<script type="text/javascript">
require.config({
baseUrl : '../../../Source',
waitSeconds : 60
});
</script>
</head>
<body class="sandcastle-loading" data-sandcastle-bucket="bucket-requirejs.html">
<style>
@import url(../templates/bucket.css);
</style>
<div id="cesiumContainer" class="fullSize"></div>
<div id="loadingOverlay"><h1>Loading...</h1></div>
<div id="toolbar"></div>
<script id="cesium_sandcastle_script">
function startup(Cesium) {
'use strict';
//Sandcastle_Begin
var viewer = new Cesium.Viewer('cesiumContainer', {
shouldAnimate : true
});

var position = Cesium.Cartesian3.fromDegrees(-123.0744619, 44.0503706);
var url = '../../SampleData/models/CesiumMan/Cesium_Man.glb';
viewer.trackedEntity = viewer.entities.add({
name : url,
position : position,
model : {
uri : url
}
});

var collection = viewer.scene.postProcessStages;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

collection?

Be precise.

What should be the canonical name used throughout? stages, right?

var silhouette = collection.add(Cesium.PostProcessStageLibrary.createSilhouetteStage());
silhouette.uniforms.color = Cesium.Color.LIME;
var blackAndWhite = collection.add(Cesium.PostProcessStageLibrary.createBlackAndWhiteStage());
blackAndWhite.uniforms.gradations = 5.0;

if (!silhouette.isSupported(viewer.scene)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't it odd that a user needs to create an instance to check isSupported? Is there clean and obvious way to avoid this with static isSupported somewhere appropriate like GroundPrimitive.isSupported?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How else would it work? There isn't a class for each of the stages. If there was, we could do something like Silhouette.isSupported.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe:

if (!Cesium.PostProcessStageLibrary.isSilhouetteSupported(viewer.scene)) {

Slightly more coupled, but cleaner for the end user.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bagnell do you plan on adding this in #6680?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, db5cb75

console.log('This browser does not support the silhouette post process.');
}

var handler;
function addMouseOver(stage) {
handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
handler.setInputAction(function(movement) {
var pickedObject = viewer.scene.pick(movement.endPosition);
if (Cesium.defined(pickedObject)) {
stage.selectedFeatures = [pickedObject.primitive];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we sure selectedFeatures is the right term? What all can this be? A primitive, entity, 3D tileset feature?

Maybe just selected or something like appliesTo?

} else {
stage.selectedFeatures = [];
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
}

function removeMouseOver(stage) {
handler = handler && handler.destroy();
stage.selectedFeatures = [];
}

Sandcastle.addToolbarMenu([{
text : 'Mouse-over Black and White',
onselect : function() {
blackAndWhite.enabled = true;
silhouette.enabled = false;

removeMouseOver(silhouette);
addMouseOver(blackAndWhite);
}
}, {
text : 'Mouse-over Silhouette',
onselect : function() {
blackAndWhite.enabled = false;
silhouette.enabled = true;

removeMouseOver(blackAndWhite);
addMouseOver(silhouette);
}
}]);
//Sandcastle_End
Sandcastle.finishedLoading();
}
if (typeof Cesium !== "undefined") {
startup(Cesium);
} else if (typeof require === "function") {
require(["Cesium"], startup);
}
</script>
</body>
</html>
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading