diff --git a/Source/Scene/Scene.js b/Source/Scene/Scene.js
index ad3ee9943f55..f862a479b648 100644
--- a/Source/Scene/Scene.js
+++ b/Source/Scene/Scene.js
@@ -3529,16 +3529,7 @@ define([
return result;
};
- function isExcluded(object, objectsToExclude) {
- if (!defined(objectsToExclude) || objectsToExclude.length === 0) {
- return false;
- }
- return (objectsToExclude.indexOf(object) > -1) ||
- (objectsToExclude.indexOf(object.primitive) > -1) ||
- (objectsToExclude.indexOf(object.id) > -1);
- }
-
- function drillPick(limit, pickCallback, objectsToExclude) {
+ function drillPick(limit, pickCallback) {
// 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.
@@ -3556,6 +3547,7 @@ define([
while (defined(pickedResult)) {
var object = pickedResult.object;
var position = pickedResult.position;
+ var exclude = pickedResult.exclude;
if (defined(position) && !defined(object)) {
result.push(pickedResult);
@@ -3566,7 +3558,7 @@ define([
break;
}
- if (!isExcluded(object, objectsToExclude)) {
+ if (!exclude) {
result.push(pickedResult);
if (0 >= --limit) {
break;
@@ -3645,7 +3637,9 @@ define([
var object = that.pick(windowPosition, width, height);
if (defined(object)) {
return {
- object : object
+ object : object,
+ position : undefined,
+ exclude : false
};
}
};
@@ -3744,7 +3738,16 @@ define([
});
}
- function getRayIntersection(scene, ray, async) {
+ function isExcluded(object, objectsToExclude) {
+ if (!defined(object) || !defined(objectsToExclude) || objectsToExclude.length === 0) {
+ return false;
+ }
+ return (objectsToExclude.indexOf(object) > -1) ||
+ (objectsToExclude.indexOf(object.primitive) > -1) ||
+ (objectsToExclude.indexOf(object.id) > -1);
+ }
+
+ function getRayIntersection(scene, ray, objectsToExclude, async, requirePosition) {
var context = scene._context;
var uniformState = context.uniformState;
var frameState = scene._frameState;
@@ -3798,12 +3801,13 @@ define([
if (defined(object) || defined(position)) {
return {
object : object,
- position : position
+ position : position,
+ exclude : (!defined(position) && requirePosition) || isExcluded(object, objectsToExclude)
};
}
}
- function getRayIntersections(scene, ray, limit, objectsToExclude, async) {
+ function getRayIntersections(scene, ray, limit, objectsToExclude, async, requirePosition) {
//>>includeStart('debug', pragmas.debug);
Check.defined('ray', ray);
if (scene._mode !== SceneMode.SCENE3D) {
@@ -3811,20 +3815,20 @@ define([
}
//>>includeEnd('debug');
var pickCallback = function() {
- return getRayIntersection(scene, ray, async);
+ return getRayIntersection(scene, ray, objectsToExclude, async, requirePosition);
};
- return drillPick(limit, pickCallback, objectsToExclude);
+ return drillPick(limit, pickCallback);
}
- function pickFromRay(scene, ray, objectsToExclude, async) {
- var results = getRayIntersections(scene, ray, 1, objectsToExclude, async);
+ function pickFromRay(scene, ray, objectsToExclude, async, requirePosition) {
+ var results = getRayIntersections(scene, ray, 1, objectsToExclude, async, requirePosition);
if (results.length > 0) {
return results[0];
}
}
- function drillPickFromRay(scene, ray, limit, objectsToExclude, async) {
- return getRayIntersections(scene, ray, limit, objectsToExclude, async);
+ function drillPickFromRay(scene, ray, limit, objectsToExclude, async, requirePosition) {
+ return getRayIntersections(scene, ray, limit, objectsToExclude, async, requirePosition);
}
/**
@@ -3832,6 +3836,10 @@ define([
* or undefined
if there were no intersections. The intersected object has a primitive
* property that contains the intersected primitive. Other properties may be set depending on the type of primitive
* and may be used to further identify the picked object. The ray must be given in world coordinates.
+ *
+ * This function only picks globe tiles and 3D Tiles that are rendered in the current view. Picks all other + * primitives regardless of their visibility. + *
* * @private * @@ -3842,7 +3850,7 @@ define([ * @exception {DeveloperError} Ray intersections are only supported in 3D mode. */ Scene.prototype.pickFromRay = function(ray, objectsToExclude) { - return pickFromRay(this, ray, objectsToExclude, false); + return pickFromRay(this, ray, objectsToExclude, false, false); }; /** @@ -3851,6 +3859,10 @@ define([ * properties may also be set depending on the type of primitive and may be used to further identify the picked object. * The primitives in the list are ordered by first intersection to last intersection. The ray must be given in * world coordinates. + *+ * This function only picks globe tiles and 3D Tiles that are rendered in the current view. Picks all other + * primitives regardless of their visibility. + *
* * @private * @@ -3862,7 +3874,7 @@ define([ * @exception {DeveloperError} Ray intersections are only supported in 3D mode. */ Scene.prototype.drillPickFromRay = function(ray, limit, objectsToExclude) { - return drillPickFromRay(this, ray, limit, objectsToExclude, false); + return drillPickFromRay(this, ray, limit, objectsToExclude, false, false); }; /** @@ -3882,7 +3894,7 @@ define([ ray = Ray.clone(ray); objectsToExclude = objectsToExclude.slice(); return launchAsyncLoader(this, ray, objectsToExclude, function() { - return pickFromRay(that, ray, objectsToExclude, true); + return pickFromRay(that, ray, objectsToExclude, true, false); }); }; @@ -3904,7 +3916,7 @@ define([ ray = Ray.clone(ray); objectsToExclude = objectsToExclude.slice(); return launchAsyncLoader(this, ray, objectsToExclude, function() { - return drillPickFromRay(that, ray, limit, objectsToExclude, true); + return drillPickFromRay(that, ray, limit, objectsToExclude, true, false); }); }; @@ -3945,7 +3957,7 @@ define([ function sampleHeightMostDetailed(scene, position, objectsToExclude) { var ray = getRayForSampleHeight(scene, position); return launchAsyncLoader(scene, ray, objectsToExclude, function() { - var pickResult = pickFromRay(scene, ray, objectsToExclude, true); + var pickResult = pickFromRay(scene, ray, objectsToExclude, true, true); if (defined(pickResult)) { return getHeightFromCartesian(scene, pickResult.position); } @@ -3955,7 +3967,7 @@ define([ function clampToHeightMostDetailed(scene, cartesian, objectsToExclude) { var ray = getRayForClampToHeight(scene, cartesian); return launchAsyncLoader(scene, ray, objectsToExclude, function() { - var pickResult = pickFromRay(scene, ray, objectsToExclude, true); + var pickResult = pickFromRay(scene, ray, objectsToExclude, true, true); if (defined(pickResult)) { return pickResult.position; } @@ -3989,7 +4001,7 @@ define([ } //>>includeEnd('debug'); var ray = getRayForSampleHeight(this, position); - var pickResult = pickFromRay(this, ray, objectsToExclude, false); + var pickResult = pickFromRay(this, ray, objectsToExclude, false, true); if (defined(pickResult)) { return getHeightFromCartesian(this, pickResult.position); } @@ -4024,7 +4036,7 @@ define([ } //>>includeEnd('debug'); var ray = getRayForClampToHeight(this, cartesian); - var pickResult = pickFromRay(this, ray, objectsToExclude, false); + var pickResult = pickFromRay(this, ray, objectsToExclude, false, true); if (defined(pickResult)) { return Cartesian3.clone(pickResult.position, result); } @@ -4034,9 +4046,9 @@ define([ * Initiates an asynchronous {@link Scene#sampleHeight} request using the maximum level of detail for 3D Tilesets * regardless of visibility. * - * @param {Cartographic|Cartographic[]} positions The cartographic position(s) to sample height from. + * @param {Cartographic[]} positions The cartographic positions to sample height from. * @param {Object[]} [objectsToExclude] A list of primitives, entities, or features to not sample height from. - * @returns {Promise.undefined
if there was no scene geometry to sample height from.
+ * @returns {Promise.undefined
if there was no scene geometry to sample height from.
*
* @see Scene#sampleHeight
*
@@ -4051,24 +4063,21 @@ define([
}
//>>includeEnd('debug');
objectsToExclude = defined(objectsToExclude) ? objectsToExclude.slice() : objectsToExclude;
- positions = isArray(positions) ? positions : [positions];
var length = positions.length;
var promises = new Array(length);
for (var i = 0; i < length; ++i) {
promises[i] = sampleHeightMostDetailed(this, positions[i], objectsToExclude);
}
- return when.all(promises).then(function(heights) {
- return (length === 1) ? heights[0] : heights;
- });
+ return when.all(promises);
};
/**
* Initiates an asynchronous {@link Scene#clampToHeight} request using the maximum level of detail for 3D Tilesets
* regardless of visibility.
*
- * @param {Cartesian3} cartesians The cartesian positions.
+ * @param {Cartesian3[]} cartesians The cartesian positions.
* @param {Object[]} [objectsToExclude] A list of primitives, entities, or features to not clamp to.
- * @returns {Promise.undefined
if there was no scene geometry to clamp to.
+ * @returns {Promise.undefined
if there was no scene geometry to clamp to.
*
* @see Scene#clampToHeight
*
@@ -4083,15 +4092,12 @@ define([
}
//>>includeEnd('debug');
objectsToExclude = defined(objectsToExclude) ? objectsToExclude.slice() : objectsToExclude;
- cartesians = isArray(cartesians) ? cartesians : [cartesians];
var length = cartesians.length;
var promises = new Array(length);
for (var i = 0; i < length; ++i) {
promises[i] = clampToHeightMostDetailed(this, cartesians[i], objectsToExclude);
}
- return when.all(promises).then(function(cartesians) {
- return (length === 1) ? cartesians[0] : cartesians;
- });
+ return when.all(promises);
};
/**
diff --git a/Specs/Scene/PickSpec.js b/Specs/Scene/PickSpec.js
index 26812206a792..05669fd72fb2 100644
--- a/Specs/Scene/PickSpec.js
+++ b/Specs/Scene/PickSpec.js
@@ -17,6 +17,7 @@ defineSuite([
'Scene/Cesium3DTileStyle',
'Scene/EllipsoidSurfaceAppearance',
'Scene/Globe',
+ 'Scene/PointPrimitiveCollection',
'Scene/Primitive',
'Scene/Scene',
'Scene/SceneMode',
@@ -43,6 +44,7 @@ defineSuite([
Cesium3DTileStyle,
EllipsoidSurfaceAppearance,
Globe,
+ PointPrimitiveCollection,
Primitive,
Scene,
SceneMode,
@@ -541,6 +543,19 @@ defineSuite([
}, primitiveRay);
});
+ it('picks primitive that doesn\'t write depth', function() {
+ var collection = scene.primitives.add(new PointPrimitiveCollection());
+ var point = collection.add({
+ position : Cartographic.fromRadians(0.0, 0.0, 100.0),
+ disableDepthTestDistance : Number.POSITIVE_INFINITY
+ });
+
+ expect(scene).toPickFromRayAndCall(function(result) {
+ expect(result.object.primitive).toBe(point);
+ expect(result.position).toBeUndefined();
+ }, primitiveRay);
+ });
+
it('throws if ray is undefined', function() {
expect(function() {
scene.pickFromRay(undefined);
@@ -889,6 +904,35 @@ defineSuite([
}, cartographic, [rectangle2, rectangle3]);
});
+ it('excludes primitive that doesn\'t write depth', function() {
+ if (!scene.sampleHeightSupported) {
+ return;
+ }
+
+ var rectangle = createSmallRectangle(0.0);
+
+ var height = 100.0;
+ var cartographic = new Cartographic(0.0, 0.0, height);
+ var collection = scene.primitives.add(new PointPrimitiveCollection());
+ var point = collection.add({
+ position : Cartographic.toCartesian(cartographic)
+ });
+
+ expect(scene).toSampleHeightAndCall(function(height) {
+ expect(height).toEqualEpsilon(height, CesiumMath.EPSILON3);
+ }, cartographic);
+
+ point.disableDepthTestDistance = Number.POSITIVE_INFINITY;
+ expect(scene).toSampleHeightAndCall(function(height) {
+ expect(height).toEqualEpsilon(0.0, CesiumMath.EPSILON3);
+ }, cartographic);
+
+ rectangle.show = false;
+ expect(scene).toSampleHeightAndCall(function(height) {
+ expect(height).toBeUndefined();
+ }, cartographic);
+ });
+
it('throws if position is undefined', function() {
if (!scene.sampleHeightSupported) {
return;
@@ -1027,6 +1071,34 @@ defineSuite([
}, cartesian, [rectangle2, rectangle3]);
});
+ it('excludes primitive that doesn\'t write depth', function() {
+ if (!scene.clampToHeightSupported) {
+ return;
+ }
+
+ var rectangle = createSmallRectangle(0.0);
+
+ var cartesian = Cartesian3.fromRadians(0.0, 0.0, 100.0);
+ var collection = scene.primitives.add(new PointPrimitiveCollection());
+ var point = collection.add({
+ position : cartesian
+ });
+
+ expect(scene).toClampToHeightAndCall(function(clampedCartesian) {
+ expect(clampedCartesian).toEqualEpsilon(cartesian, CesiumMath.EPSILON3);
+ }, cartesian);
+
+ point.disableDepthTestDistance = Number.POSITIVE_INFINITY;
+ expect(scene).toClampToHeightAndCall(function(clampedCartesian) {
+ expect(clampedCartesian).toEqualEpsilon(cartesian, CesiumMath.EPSILON3);
+ }, cartesian);
+
+ rectangle.show = false;
+ expect(scene).toClampToHeightAndCall(function(clampedCartesian) {
+ expect(clampedCartesian).toBeUndefined();
+ }, cartesian);
+ });
+
it('throws if cartesian is undefined', function() {
if (!scene.clampToHeightSupported) {
return;