Skip to content

Commit

Permalink
Merge remote-tracking branch 'agi/master' into issue1076
Browse files Browse the repository at this point in the history
  • Loading branch information
abwood committed Oct 4, 2013
2 parents 348f501 + cbae2eb commit 4d8de5d
Show file tree
Hide file tree
Showing 5 changed files with 337 additions and 36 deletions.
136 changes: 106 additions & 30 deletions Apps/Sandcastle/gallery/Picking.html
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,52 @@
};
image.src = '../images/Cesium_Logo_overlay.png';
}

function addOverlappingPolygons(scene, ellipsoid) {
var primitives = scene.getPrimitives();

// Add primitives from bottom to top.
var redPolygon = primitives.add(new Cesium.Polygon({
positions : ellipsoid.cartographicArrayToCartesianArray([
Cesium.Cartographic.fromDegrees(-70.0, 30.0),
Cesium.Cartographic.fromDegrees(-60.0, 30.0),
Cesium.Cartographic.fromDegrees(-60.0, 40.0),
Cesium.Cartographic.fromDegrees(-70.0, 40.0)
])
}));
redPolygon.material.uniforms.color = new Cesium.Color(1.0, 0.0, 0.0, 0.5);

var bluePolygon = primitives.add(new Cesium.Polygon({
positions : ellipsoid.cartographicArrayToCartesianArray([
Cesium.Cartographic.fromDegrees(-75.0, 34.0),
Cesium.Cartographic.fromDegrees(-63.0, 34.0),
Cesium.Cartographic.fromDegrees(-63.0, 40.0),
Cesium.Cartographic.fromDegrees(-75.0, 40.0)
])
}));
bluePolygon.material.uniforms.color = new Cesium.Color(0.0, 0.0, 1.0, 0.5);

var greenPolygon = primitives.add(new Cesium.Polygon({
positions : ellipsoid.cartographicArrayToCartesianArray([
Cesium.Cartographic.fromDegrees(-67.0, 36.0),
Cesium.Cartographic.fromDegrees(-55.0, 36.0),
Cesium.Cartographic.fromDegrees(-55.0, 30.0),
Cesium.Cartographic.fromDegrees(-67.0, 30.0)
])
}));
greenPolygon.material.uniforms.color = new Cesium.Color(0.0, 1.0, 0.0, 0.5);

// Give polygons identifiers for easy lookup later
redPolygon.id = 0;
bluePolygon.id = 1;
greenPolygon.id = 2;

// simple flags used for multi-picking
redPolygon.picked = false;
bluePolygon.picked = false;
greenPolygon.picked = false;
}

function cleanup() {
widget.scene.getPrimitives().removeAll();
handler = handler && handler.destroy();
Expand Down Expand Up @@ -208,6 +253,8 @@

function layerCompositePrimitive(scene, ellipsoid) {
Sandcastle.declare(layerCompositePrimitive); // For highlighting in Sandcastle.
addOverlappingPolygons(scene, ellipsoid);

var primitives = scene.getPrimitives();
// Move the primitive that the mouse is over to the top.
handler = new Cesium.ScreenSpaceEventHandler(scene.getCanvas());
Expand All @@ -217,37 +264,56 @@
primitives.raiseToTop(p.primitive);
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
}

var originalColor= {};
function multiPickPrimitives(scene, ellipsoid) {
Sandcastle.declare(multiPickPrimitives); // For highlighting in Sandcastle.
addOverlappingPolygons(scene, ellipsoid);

var primitives = scene.getPrimitives();
// Move the primitive that the mouse is over to the top.
handler = new Cesium.ScreenSpaceEventHandler(scene.getCanvas());
handler.setInputAction(function(movement) {
// clear picked flags
var numberOfPrimitves = primitives.getLength();
for (var i = 0; i < numberOfPrimitves; ++i) {
var p = primitives.get(i);
p.processedPick = false;
}

// get an array of all primitives at the mouse position
var pickedObjects = scene.drillPick(movement.endPosition);
if(Cesium.defined(pickedObjects)) {
for( i=0; i<pickedObjects.length; ++i) {
var polygon = pickedObjects[i].primitive;

if(polygon.picked === false) {
originalColor[polygon.id] = polygon.material.uniforms.color;
polygon.material.uniforms.color = {
red : 1.0,
green : 1.0,
blue : 0.0,
alpha : 0.5
};
polygon.picked = true;
}

polygon.processedPick = true;
}
}

// return unpicked primitives to their original color
for (i = 0; i < numberOfPrimitves; ++i) {
var primitive = primitives.get(i);

if(primitive.processedPick === false && Cesium.defined(originalColor[primitive.id])) {
primitive.material.uniforms.color = originalColor[primitive.id];
primitive.picked = false;
}
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

// Add primitives from bottom to top.
var redPolygon = primitives.add(new Cesium.Polygon({
positions : ellipsoid.cartographicArrayToCartesianArray([
Cesium.Cartographic.fromDegrees(-70.0, 30.0),
Cesium.Cartographic.fromDegrees(-60.0, 30.0),
Cesium.Cartographic.fromDegrees(-60.0, 40.0),
Cesium.Cartographic.fromDegrees(-70.0, 40.0)
])
}));
redPolygon.material.uniforms.color = new Cesium.Color(1.0, 0.0, 0.0, 0.5);

var bluePolygon = primitives.add(new Cesium.Polygon({
positions : ellipsoid.cartographicArrayToCartesianArray([
Cesium.Cartographic.fromDegrees(-75.0, 34.0),
Cesium.Cartographic.fromDegrees(-63.0, 34.0),
Cesium.Cartographic.fromDegrees(-63.0, 40.0),
Cesium.Cartographic.fromDegrees(-75.0, 40.0)
])
}));
bluePolygon.material.uniforms.color = new Cesium.Color(0.0, 0.0, 1.0, 0.5);

var greenPolygon = primitives.add(new Cesium.Polygon({
positions : ellipsoid.cartographicArrayToCartesianArray([
Cesium.Cartographic.fromDegrees(-67.0, 36.0),
Cesium.Cartographic.fromDegrees(-55.0, 36.0),
Cesium.Cartographic.fromDegrees(-55.0, 30.0),
Cesium.Cartographic.fromDegrees(-67.0, 30.0)
])
}));
greenPolygon.material.uniforms.color = new Cesium.Color(0.0, 1.0, 0.0, 0.5);
}

function drawExtent(scene, ellipsoid) {
Expand Down Expand Up @@ -439,6 +505,16 @@
};
button.textContent = 'Layer Primitives';
toolbar.appendChild(button);

button = document.createElement('button');
button.className = 'cesium-button';
button.onclick = function() {
cleanup();
multiPickPrimitives(scene, ellipsoid);
Sandcastle.highlight(multiPickPrimitives);
};
button.textContent = 'Drill-Down Picking';
toolbar.appendChild(button);

button = document.createElement('button');
button.className = 'cesium-button';
Expand Down
4 changes: 2 additions & 2 deletions Apps/Sandcastle/gallery/Polyline.html
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
geometry : new Cesium.PolylineGeometry({
positions : positions,
width : 10.0,
vertexFormat : Cesium.PolylineMaterialAppearance.VERTEX_FORMAT,
vertexFormat : Cesium.PolylineColorAppearance.VERTEX_FORMAT,
colors : colors
})
}),
Expand All @@ -84,7 +84,7 @@
geometry : new Cesium.PolylineGeometry({
positions : positions,
width : 10.0,
vertexFormat : Cesium.PolylineMaterialAppearance.VERTEX_FORMAT,
vertexFormat : Cesium.PolylineColorAppearance.VERTEX_FORMAT,
colors : colors,
colorsPerVertex : true
})
Expand Down
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ Beta Releases
if (defined(p) && defined(p.id)) {
// Use properties and functions in p.id
}
* Added `Scene.drillPick` to return list of objects each containing 1 primitive at a screen space position.

### b21 - 2013-10-01

Expand Down
92 changes: 88 additions & 4 deletions Source/Scene/Scene.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ define([
'../Core/defaultValue',
'../Core/defined',
'../Core/destroyObject',
'../Core/DeveloperError',
'../Core/GeographicProjection',
'../Core/Ellipsoid',
'../Core/Occluder',
Expand All @@ -20,6 +21,7 @@ define([
'../Core/GeometryInstance',
'../Core/GeometryPipeline',
'../Core/ColorGeometryInstanceAttribute',
'../Core/ShowGeometryInstanceAttribute',
'../Renderer/Context',
'../Renderer/ClearCommand',
'../Renderer/PassState',
Expand All @@ -44,6 +46,7 @@ define([
defaultValue,
defined,
destroyObject,
DeveloperError,
GeographicProjection,
Ellipsoid,
Occluder,
Expand All @@ -59,6 +62,7 @@ define([
GeometryInstance,
GeometryPipeline,
ColorGeometryInstanceAttribute,
ShowGeometryInstanceAttribute,
Context,
ClearCommand,
PassState,
Expand Down Expand Up @@ -789,7 +793,6 @@ define([
frameState.creditDisplay.beginFrame();

var context = this._context;

us.update(context, frameState);

this._commandList.length = 0;
Expand Down Expand Up @@ -886,12 +889,26 @@ define([
var scratchColorZero = new Color(0.0, 0.0, 0.0, 0.0);

/**
* DOC_TBA
* Returns an object with a `primitive` property that contains the first (top) primitive in the scene
* at a particular window coordinate or undefined if nothing is at the location. Other properties may
* potentially be set depending on the type of primitive.
*
* @memberof Scene
*
* @param {Cartesian2} windowPosition Window coordinates to perform picking on.
*
* @returns {Object} Object containing the picked primitive.
*
* @exception {DeveloperError} windowPosition is undefined.
*
*/
Scene.prototype.pick = function(windowPosition) {
if(!defined(windowPosition)) {
throw new DeveloperError('windowPosition is undefined.');
}

var context = this._context;
var primitives = this._primitives;
var us = this.getUniformState();
var frameState = this._frameState;

var drawingBufferPosition = SceneTransforms.transformWindowToDrawingBuffer(context, windowPosition);
Expand All @@ -904,10 +921,12 @@ define([
updateFrameState(this, frameState.frameNumber, frameState.time);
frameState.cullingVolume = getPickCullingVolume(this, drawingBufferPosition, rectangleWidth, rectangleHeight);
frameState.passes.pick = true;

us.update(context, frameState);

var commandLists = this._commandList;
commandLists.length = 0;
primitives.update(context, frameState, commandLists);
this._primitives.update(context, frameState, commandLists);
createPotentiallyVisibleSet(this, 'pickList');

scratchRectangle.x = drawingBufferPosition.x - ((rectangleWidth - 1.0) * 0.5);
Expand All @@ -918,6 +937,71 @@ define([
context.endFrame();
return object;
};

/**
* Returns a list of objects, each containing a `primitive` property, for all primitives at
* a particular window coordinate position. Other properties may also be set depending on the
* type of primitive. The primitives in the list are ordered by their visual order in the
* scene (front to back).
*
* @memberof Scene
*
* @param {Cartesian2} windowPosition Window coordinates to perform picking on.
*
* @returns {Array} Array of objects, each containing 1 picked primitives.
*
* @exception {DeveloperError} windowPosition is undefined.
*
* @example
* var pickedObjects = Scene.drillPick(new Cartesian2(100.0, 200.0));
*/
Scene.prototype.drillPick = function(windowPosition) {
// PERFORMANCE_IDEA: This function calls each primitive's update for each pass. Instead
// we could update the primitive once, and then just execute their commands for each pass,
// and cull commands for picked primitives. e.g., base on the command's owner.
if (!defined(windowPosition)) {
throw new DeveloperError('windowPosition is undefined.');
}

var pickedObjects = [];

var pickedResult = this.pick(windowPosition);
while (defined(pickedResult) && defined(pickedResult.primitive)) {
var primitive = pickedResult.primitive;
pickedObjects.push(pickedResult);

// hide the picked primitive and call picking again to get the next primitive
if (defined(primitive.show)) {
primitive.show = false;
} else if (typeof primitive.setShow === 'function') {
primitive.setShow(false);
} else if (typeof primitive.getGeometryInstanceAttributes === 'function') {
var attributes = primitive.getGeometryInstanceAttributes(pickedResult.id);
if (defined(attributes) && defined(attributes.show)) {
attributes.show = ShowGeometryInstanceAttribute.toValue(false);
}
}

pickedResult = this.pick(windowPosition);
}

// unhide the picked primitives
for (var i = 0; i < pickedObjects.length; ++i) {
var p = pickedObjects[i].primitive;
if (defined(p.show)) {
p.show = true;
} else if (typeof p.setShow === 'function') {
p.setShow(true);
} else if (typeof p.getGeometryInstanceAttributes === 'function') {
var attr = p.getGeometryInstanceAttributes(pickedObjects[i].id);
if (defined(attr) && defined(attr.show)) {
attr.show = ShowGeometryInstanceAttribute.toValue(true);
}
}
}

return pickedObjects;
};

/**
* DOC_TBA
Expand Down
Loading

0 comments on commit 4d8de5d

Please sign in to comment.