diff --git a/.idea/cesium.iml b/.idea/cesium.iml
index 5ecdb1a3e790..075b2a75ef2b 100644
--- a/.idea/cesium.iml
+++ b/.idea/cesium.iml
@@ -9,4 +9,4 @@
-
\ No newline at end of file
+
diff --git a/.idea/jsLibraryMappings.xml b/.idea/jsLibraryMappings.xml
index d45df048bf58..4bb85da06f3a 100644
--- a/.idea/jsLibraryMappings.xml
+++ b/.idea/jsLibraryMappings.xml
@@ -4,4 +4,4 @@
-
\ No newline at end of file
+
diff --git a/.idea/runConfigurations/Run_tests.xml b/.idea/runConfigurations/Run_tests.xml
index 4a52554ce6db..fb0f97e40d3d 100644
--- a/.idea/runConfigurations/Run_tests.xml
+++ b/.idea/runConfigurations/Run_tests.xml
@@ -7,4 +7,4 @@
-
\ No newline at end of file
+
diff --git a/CHANGES.md b/CHANGES.md
index b93d70feaacf..8f6d9fa25aad 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -7,6 +7,7 @@ Change Log
* Fixed issue with displaying `MapboxImageryProvider` default token error message [#5191](https://github.com/AnalyticalGraphicsInc/cesium/pull/5191)
* Added a `depthFailMaterial` property to line entities, which is the material used to render the line when it fails the depth test. [#5160](https://github.com/AnalyticalGraphicsInc/cesium/pull/5160)
* Upgrade FXAA to version 3.11. [#5200](https://github.com/AnalyticalGraphicsInc/cesium/pull/5200)
+* `Scene.pickPosition` now caches results per frame to increase performance [#5117](https://github.com/AnalyticalGraphicsInc/cesium/issues/5117)
* Fix billboards not initially clustering. [#5208](https://github.com/AnalyticalGraphicsInc/cesium/pull/5208)
### 1.32 - 2017-04-03
diff --git a/Source/Scene/Scene.js b/Source/Scene/Scene.js
index 33b8cfec3b26..d0bcf630c963 100644
--- a/Source/Scene/Scene.js
+++ b/Source/Scene/Scene.js
@@ -321,6 +321,9 @@ define([
this._cameraStartFired = false;
this._cameraMovedTime = undefined;
+ this._pickPositionCache = {};
+ this._pickPositionCacheDirty = false;
+
this._minimumDisableDepthTestDistance = 0.0;
/**
@@ -2548,6 +2551,8 @@ define([
var scratchEyeTranslation = new Cartesian3();
function render(scene, time) {
+ scene._pickPositionCacheDirty = true;
+
if (!defined(time)) {
time = JulianDate.now();
}
@@ -2979,6 +2984,15 @@ define([
}
//>>includeEnd('debug');
+ var cacheKey = windowPosition.toString();
+
+ if (this._pickPositionCacheDirty){
+ this._pickPositionCache = {};
+ this._pickPositionCacheDirty = false;
+ } else if (this._pickPositionCache.hasOwnProperty(cacheKey)){
+ return Cartesian3.clone(this._pickPositionCache[cacheKey], result);
+ }
+
var context = this._context;
var uniformState = context.uniformState;
@@ -3040,10 +3054,12 @@ define([
uniformState.update(this.frameState);
}
+ this._pickPositionCache[cacheKey] = Cartesian3.clone(result);
return result;
}
}
+ this._pickPositionCache[cacheKey] = undefined;
return undefined;
};
@@ -3078,6 +3094,7 @@ define([
var cart = projection.unproject(result, scratchPickPositionCartographic);
ellipsoid.cartographicToCartesian(cart, result);
}
+
return result;
};
diff --git a/Specs/Scene/SceneSpec.js b/Specs/Scene/SceneSpec.js
index eed4a60940bf..74c8141709db 100644
--- a/Specs/Scene/SceneSpec.js
+++ b/Specs/Scene/SceneSpec.js
@@ -33,6 +33,7 @@ defineSuite([
'Scene/Scene',
'Scene/ScreenSpaceCameraController',
'Scene/TweenCollection',
+ 'Scene/SceneTransforms',
'Specs/createCanvas',
'Specs/createScene',
'Specs/equals',
@@ -72,6 +73,7 @@ defineSuite([
Scene,
ScreenSpaceCameraController,
TweenCollection,
+ SceneTransforms,
createCanvas,
createScene,
equals,
@@ -838,6 +840,41 @@ defineSuite([
});
});
+ it('pickPosition caches results per frame',function(){
+ if (!scene.pickPositionSupported) {
+ return;
+ }
+
+ var rectangle = Rectangle.fromDegrees(-100.0, 30.0, -90.0, 40.0);
+ scene.camera.setView({ destination : rectangle });
+
+ var canvas = scene.canvas;
+ var windowPosition = new Cartesian2(canvas.clientWidth / 2, canvas.clientHeight / 2);
+ spyOn(SceneTransforms, 'transformWindowToDrawingBuffer').and.callThrough();
+
+ expect(scene).toRenderAndCall(function() {
+ scene.pickPosition(windowPosition);
+ expect(SceneTransforms.transformWindowToDrawingBuffer).toHaveBeenCalled();
+
+ scene.pickPosition(windowPosition);
+ expect(SceneTransforms.transformWindowToDrawingBuffer.calls.count()).toEqual(1);
+
+ var rectanglePrimitive = createRectangle(rectangle);
+ rectanglePrimitive.appearance.material.uniforms.color = new Color(1.0, 0.0, 0.0, 1.0);
+
+ var primitives = scene.primitives;
+ primitives.add(rectanglePrimitive);
+ });
+
+ expect(scene).toRenderAndCall(function() {
+ scene.pickPosition(windowPosition);
+ expect(SceneTransforms.transformWindowToDrawingBuffer.calls.count()).toEqual(2);
+
+ scene.pickPosition(windowPosition);
+ expect(SceneTransforms.transformWindowToDrawingBuffer.calls.count()).toEqual(2);
+ });
+ });
+
it('pickPosition throws without windowPosition', function() {
expect(function() {
scene.pickPosition();