Skip to content

Commit b937a5c

Browse files
committedMar 24, 2016
Merge pull request #3621 from AnalyticalGraphicsInc/infinite-2D-only
Infinite horizontal scrolling in 2D
2 parents a4a6705 + 7d158ab commit b937a5c

12 files changed

+389
-448
lines changed
 

‎CHANGES.md

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ Change Log
77
* Removed `TileMapServiceImageryProvider`. Use `createTileMapServiceImageryProvider` instead.
88
* Removed `GroundPrimitive.geometryInstance`. Use `GroundPrimitive.geometryInstances` instead.
99
* Removed `definedNotNull`. Use `defined` instead.
10+
* Removed ability to rotate the map in 2D.
1011
* Fixed `TimeIntervalCollection.removeInterval` bug that resulted in too many intervals being removed
1112
* `GroundPrimitive` throws a `DeveloperError` when passed an unsupported geometry type instead of crashing.
1213
* `GeoJsonDataSource` now handles CRS `urn:ogc:def:crs:EPSG::4326`
@@ -23,6 +24,7 @@ Change Log
2324
* Fix bug when upsampling exaggerated terrain where the terrain heights were exaggerated at twice the value. [#3607](https://github.com/AnalyticalGraphicsInc/cesium/issues/3607)
2425
* Fixed a crash that would occur if you added and removed an `Entity` with a path without ever actually rendering it. [#3738](https://github.com/AnalyticalGraphicsInc/cesium/pull/3738)
2526
* Added a new sample to Sandcastle using the Pennsylvania terrain data as shown [here](http://cesiumjs.org/2016/03/15/New-Cesium-Terrain-Service-Covering-Pennsylvania/).
27+
* Added infinite horizontal scrolling in 2D.
2628

2729
### 1.19 - 2016-03-01
2830

‎Source/Scene/Billboard.js

+6-20
Original file line numberDiff line numberDiff line change
@@ -1083,30 +1083,17 @@ define([
10831083
return SceneTransforms.computeActualWgs84Position(frameState, tempCartesian3);
10841084
};
10851085

1086-
var scratchMatrix4 = new Matrix4();
1087-
var scratchCartesian4 = new Cartesian4();
1088-
var scrachEyeOffset = new Cartesian3();
10891086
var scratchCartesian2 = new Cartesian2();
1087+
var scratchCartesian3 = new Cartesian3();
10901088
var scratchComputePixelOffset = new Cartesian2();
10911089

1090+
// This function is basically a stripped-down JavaScript version of BillboardCollectionVS.glsl
10921091
Billboard._computeScreenSpacePosition = function(modelMatrix, position, eyeOffset, pixelOffset, scene, result) {
1093-
// This function is basically a stripped-down JavaScript version of BillboardCollectionVS.glsl
1094-
var camera = scene.camera;
1095-
var view = camera.viewMatrix;
1096-
var projection = camera.frustum.projectionMatrix;
1092+
// Model to world coordinates
1093+
var positionWorld = Matrix4.multiplyByPoint(modelMatrix, position, scratchCartesian3);
10971094

1098-
// Model to eye coordinates
1099-
var mv = Matrix4.multiplyTransformation(view, modelMatrix, scratchMatrix4);
1100-
var positionEC = Matrix4.multiplyByVector(mv, Cartesian4.fromElements(position.x, position.y, position.z, 1, scratchCartesian4), scratchCartesian4);
1101-
1102-
// Apply eye offset, e.g., czm_eyeOffset
1103-
var zEyeOffset = Cartesian3.multiplyComponents(eyeOffset, Cartesian3.normalize(positionEC, scrachEyeOffset), scrachEyeOffset);
1104-
positionEC.x += eyeOffset.x + zEyeOffset.x;
1105-
positionEC.y += eyeOffset.y + zEyeOffset.y;
1106-
positionEC.z += zEyeOffset.z;
1107-
1108-
var positionCC = Matrix4.multiplyByVector(projection, positionEC, scratchCartesian4); // clip coordinates
1109-
var positionWC = SceneTransforms.clipToGLWindowCoordinates(scene, positionCC, result);
1095+
// World to window coordinates
1096+
var positionWC = SceneTransforms.wgs84WithEyeOffsetToWindowCoordinates(scene, positionWorld, eyeOffset, result);
11101097

11111098
// Apply pixel offset
11121099
pixelOffset = Cartesian2.clone(pixelOffset, scratchComputePixelOffset);
@@ -1131,7 +1118,6 @@ define([
11311118
*
11321119
* @exception {DeveloperError} Billboard must be in a collection.
11331120
*
1134-
*
11351121
* @example
11361122
* console.log(b.computeScreenSpacePosition(scene).toString());
11371123
*

‎Source/Scene/Camera.js

+29-74
Original file line numberDiff line numberDiff line change
@@ -826,6 +826,10 @@ define([
826826
frustum.top = ratio * frustum.right;
827827
frustum.bottom = -frustum.top;
828828
}
829+
830+
if (this._mode === SceneMode.SCENE2D) {
831+
clampMove2D(this, this.position);
832+
}
829833
};
830834

831835
var setTransformPosition = new Cartesian3();
@@ -1240,15 +1244,15 @@ define([
12401244
};
12411245

12421246
function clampMove2D(camera, position) {
1243-
var maxX = camera._maxCoord.x * camera.maximumTranslateFactor;
1247+
var maxX = camera._maxCoord.x;
12441248
if (position.x > maxX) {
1245-
position.x = maxX;
1249+
position.x = position.x - maxX * 2.0;
12461250
}
12471251
if (position.x < -maxX) {
1248-
position.x = -maxX;
1252+
position.x = position.x + maxX * 2.0;
12491253
}
12501254

1251-
var maxY = camera._maxCoord.y * camera.maximumTranslateFactor;
1255+
var maxY = camera._maxCoord.y;
12521256
if (position.y > maxY) {
12531257
position.y = maxY;
12541258
}
@@ -1610,7 +1614,7 @@ define([
16101614
var newRight = frustum.right - amount;
16111615
var newLeft = frustum.left + amount;
16121616

1613-
var maxRight = camera._maxCoord.x * camera.maximumZoomFactor;
1617+
var maxRight = camera._maxCoord.x;
16141618
if (newRight > maxRight) {
16151619
newRight = maxRight;
16161620
newLeft = -maxRight;
@@ -2109,8 +2113,7 @@ define([
21092113
position.z = 0.0;
21102114
var cart = projection.unproject(position);
21112115

2112-
if (cart.latitude < -CesiumMath.PI_OVER_TWO || cart.latitude > CesiumMath.PI_OVER_TWO ||
2113-
cart.longitude < - Math.PI || cart.longitude > Math.PI) {
2116+
if (cart.latitude < -CesiumMath.PI_OVER_TWO || cart.latitude > CesiumMath.PI_OVER_TWO) {
21142117
return undefined;
21152118
}
21162119

@@ -2299,63 +2302,6 @@ define([
22992302
return Math.max(pixelSize.x, pixelSize.y);
23002303
};
23012304

2302-
function createAnimation2D(camera, duration) {
2303-
var position = camera.position;
2304-
var translateX = position.x < -camera._maxCoord.x || position.x > camera._maxCoord.x;
2305-
var translateY = position.y < -camera._maxCoord.y || position.y > camera._maxCoord.y;
2306-
var animatePosition = translateX || translateY;
2307-
2308-
var frustum = camera.frustum;
2309-
var top = frustum.top;
2310-
var bottom = frustum.bottom;
2311-
var right = frustum.right;
2312-
var left = frustum.left;
2313-
var startFrustum = camera._max2Dfrustum;
2314-
var animateFrustum = right > camera._max2Dfrustum.right;
2315-
2316-
if (animatePosition || animateFrustum) {
2317-
var translatedPosition = Cartesian3.clone(position);
2318-
2319-
if (translatedPosition.x > camera._maxCoord.x) {
2320-
translatedPosition.x = camera._maxCoord.x;
2321-
} else if (translatedPosition.x < -camera._maxCoord.x) {
2322-
translatedPosition.x = -camera._maxCoord.x;
2323-
}
2324-
2325-
if (translatedPosition.y > camera._maxCoord.y) {
2326-
translatedPosition.y = camera._maxCoord.y;
2327-
} else if (translatedPosition.y < -camera._maxCoord.y) {
2328-
translatedPosition.y = -camera._maxCoord.y;
2329-
}
2330-
2331-
var update2D = function(value) {
2332-
if (animatePosition) {
2333-
camera.position = Cartesian3.lerp(position, translatedPosition, value.time, camera.position);
2334-
}
2335-
if (animateFrustum) {
2336-
camera.frustum.top = CesiumMath.lerp(top, startFrustum.top, value.time);
2337-
camera.frustum.bottom = CesiumMath.lerp(bottom, startFrustum.bottom, value.time);
2338-
camera.frustum.right = CesiumMath.lerp(right, startFrustum.right, value.time);
2339-
camera.frustum.left = CesiumMath.lerp(left, startFrustum.left, value.time);
2340-
}
2341-
};
2342-
2343-
return {
2344-
easingFunction : EasingFunction.EXPONENTIAL_OUT,
2345-
startObject : {
2346-
time : 0.0
2347-
},
2348-
stopObject : {
2349-
time : 1.0
2350-
},
2351-
duration : duration,
2352-
update : update2D
2353-
};
2354-
}
2355-
2356-
return undefined;
2357-
}
2358-
23592305
function createAnimationTemplateCV(camera, position, center, maxX, maxY, duration) {
23602306
var newPosition = Cartesian3.clone(position);
23612307

@@ -2442,9 +2388,7 @@ define([
24422388
}
24432389
//>>includeEnd('debug');
24442390

2445-
if (this._mode === SceneMode.SCENE2D) {
2446-
return createAnimation2D(this, duration);
2447-
} else if (this._mode === SceneMode.COLUMBUS_VIEW) {
2391+
if (this._mode === SceneMode.COLUMBUS_VIEW) {
24482392
return createAnimationCV(this, duration);
24492393
}
24502394

@@ -2453,6 +2397,7 @@ define([
24532397

24542398

24552399
var scratchFlyToDestination = new Cartesian3();
2400+
var scratchFlyToCarto = new Cartographic();
24562401
var newOptions = {
24572402
destination : undefined,
24582403
heading : undefined,
@@ -2553,16 +2498,26 @@ define([
25532498
}
25542499

25552500
var sscc = this._scene.screenSpaceCameraController;
2556-
var ellipsoid = this._scene.mapProjection.ellipsoid;
2557-
var destinationCartographic = Cartographic.fromCartesian(destination);
25582501

2559-
// Make sure camera doesn't zoom outside set limits
2560-
if (defined(sscc)) {
2561-
destinationCartographic.height = CesiumMath.clamp(destinationCartographic.height, sscc.minimumZoomDistance, sscc.maximumZoomDistance);
2502+
if (defined(sscc) || mode === SceneMode.SCENE2D) {
2503+
var ellipsoid = this._scene.mapProjection.ellipsoid;
2504+
var destinationCartographic = ellipsoid.cartesianToCartographic(destination, scratchFlyToCarto);
2505+
var height = destinationCartographic.height;
2506+
2507+
// Make sure camera doesn't zoom outside set limits
2508+
if (defined(sscc)) {
2509+
destinationCartographic.height = CesiumMath.clamp(destinationCartographic.height, sscc.minimumZoomDistance, sscc.maximumZoomDistance);
2510+
}
2511+
2512+
// The max height in 2D might be lower than the max height for sscc.
2513+
if (mode === SceneMode.SCENE2D) {
2514+
var maxHeight = ellipsoid.maximumRadius * Math.PI * 2.0;
2515+
destinationCartographic.height = Math.min(destinationCartographic.height, maxHeight);
2516+
}
25622517

25632518
//Only change if we clamped the height
2564-
if (destinationCartographic.height === sscc.minimumZoomDistance || destinationCartographic.height === sscc.maximumZoomDistance) {
2565-
destination = ellipsoid.cartographicToCartesian(destinationCartographic);
2519+
if (destinationCartographic.height !== height) {
2520+
destination = ellipsoid.cartographicToCartesian(destinationCartographic, scratchFlyToDestination);
25662521
}
25672522
}
25682523

‎Source/Scene/GlobeSurfaceTileProvider.js

-2
Original file line numberDiff line numberDiff line change
@@ -284,8 +284,6 @@ define([
284284

285285
/**
286286
* Called at the beginning of each render frame, before {@link QuadtreeTileProvider#showTileThisFrame}
287-
* or any other functions.
288-
*
289287
* @param {FrameState} frameState The frame state.
290288
*/
291289
GlobeSurfaceTileProvider.prototype.initialize = function(frameState) {

‎Source/Scene/PointPrimitive.js

+4-12
Original file line numberDiff line numberDiff line change
@@ -388,21 +388,13 @@ define([
388388
return SceneTransforms.computeActualWgs84Position(frameState, tempCartesian3);
389389
};
390390

391-
var scratchMatrix4 = new Matrix4();
392391
var scratchCartesian4 = new Cartesian4();
393392

393+
// This function is basically a stripped-down JavaScript version of PointPrimitiveCollectionVS.glsl
394394
PointPrimitive._computeScreenSpacePosition = function(modelMatrix, position, scene, result) {
395-
// This function is basically a stripped-down JavaScript version of PointPrimitiveCollectionVS.glsl
396-
var camera = scene.camera;
397-
var view = camera.viewMatrix;
398-
var projection = camera.frustum.projectionMatrix;
399-
400-
// Model to eye coordinates
401-
var mv = Matrix4.multiplyTransformation(view, modelMatrix, scratchMatrix4);
402-
var positionEC = Matrix4.multiplyByVector(mv, Cartesian4.fromElements(position.x, position.y, position.z, 1, scratchCartesian4), scratchCartesian4);
403-
var positionCC = Matrix4.multiplyByVector(projection, positionEC, scratchCartesian4); // clip coordinates
404-
var positionWC = SceneTransforms.clipToGLWindowCoordinates(scene, positionCC, result);
405-
395+
// Model to world coordinates
396+
var positionWorld = Matrix4.multiplyByVector(modelMatrix, Cartesian4.fromElements(position.x, position.y, position.z, 1, scratchCartesian4), scratchCartesian4);
397+
var positionWC = SceneTransforms.wgs84ToWindowCoordinates(scene, positionWorld, result);
406398
return positionWC;
407399
};
408400

‎Source/Scene/Scene.js

+154-64
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ define([
66
'../Core/Cartesian2',
77
'../Core/Cartesian3',
88
'../Core/Cartesian4',
9+
'../Core/Cartographic',
910
'../Core/Color',
1011
'../Core/ColorGeometryInstanceAttribute',
1112
'../Core/createGuid',
@@ -28,6 +29,7 @@ define([
2829
'../Core/mergeSort',
2930
'../Core/Occluder',
3031
'../Core/ShowGeometryInstanceAttribute',
32+
'../Core/Transforms',
3133
'../Renderer/ClearCommand',
3234
'../Renderer/ComputeEngine',
3335
'../Renderer/Context',
@@ -68,6 +70,7 @@ define([
6870
Cartesian2,
6971
Cartesian3,
7072
Cartesian4,
73+
Cartographic,
7174
Color,
7275
ColorGeometryInstanceAttribute,
7376
createGuid,
@@ -90,6 +93,7 @@ define([
9093
mergeSort,
9194
Occluder,
9295
ShowGeometryInstanceAttribute,
96+
Transforms,
9397
ClearCommand,
9498
ComputeEngine,
9599
Context,
@@ -1319,9 +1323,9 @@ define([
13191323
}
13201324

13211325
var transformFrom2D = new Matrix4(0.0, 0.0, 1.0, 0.0,
1322-
1.0, 0.0, 0.0, 0.0,
1323-
0.0, 1.0, 0.0, 0.0,
1324-
0.0, 0.0, 0.0, 1.0);
1326+
1.0, 0.0, 0.0, 0.0,
1327+
0.0, 1.0, 0.0, 0.0,
1328+
0.0, 0.0, 0.0, 1.0);
13251329
transformFrom2D = Matrix4.inverseTransformation(transformFrom2D, transformFrom2D);
13261330

13271331
function executeCommand(command, scene, context, passState, renderState, shaderProgram, debugFramebuffer) {
@@ -1490,9 +1494,11 @@ define([
14901494
executeCommand(environmentState.skyAtmosphereCommand, scene, context, passState);
14911495
}
14921496

1497+
var useWebVR = scene._useWebVR && scene.mode !== SceneMode.SCENE2D;
1498+
14931499
if (environmentState.isSunVisible) {
14941500
environmentState.sunDrawCommand.execute(context, passState);
1495-
if (scene.sunBloom && !scene._useWebVR) {
1501+
if (scene.sunBloom && !useWebVR) {
14961502
var framebuffer;
14971503
if (environmentState.useGlobeDepthFramebuffer) {
14981504
framebuffer = scene._globeDepth.framebuffer;
@@ -1644,76 +1650,170 @@ define([
16441650
}
16451651
}
16461652

1647-
function executeViewportCommands(scene, passState) {
1653+
function updateAndExecuteCommands(scene, passState, backgroundColor, picking) {
16481654
var context = scene._context;
16491655

16501656
var viewport = passState.viewport;
16511657

16521658
var frameState = scene._frameState;
16531659
var camera = frameState.camera;
1660+
var mode = frameState.mode;
1661+
1662+
if (scene._useWebVR && mode !== SceneMode.SCENE2D) {
1663+
updatePrimitives(scene);
1664+
createPotentiallyVisibleSet(scene);
1665+
updateAndClearFramebuffers(scene, passState, backgroundColor, picking);
1666+
executeComputeCommands(scene);
1667+
1668+
// Based on Calculating Stereo pairs by Paul Bourke
1669+
// http://paulbourke.net/stereographics/stereorender/
16541670

1655-
if (scene._useWebVR) {
1656-
if (frameState.mode !== SceneMode.SCENE2D) {
1657-
// Based on Calculating Stereo pairs by Paul Bourke
1658-
// http://paulbourke.net/stereographics/stereorender/
1671+
viewport.x = 0;
1672+
viewport.y = 0;
1673+
viewport.width = context.drawingBufferWidth * 0.5;
1674+
viewport.height = context.drawingBufferHeight;
16591675

1660-
viewport.x = 0;
1661-
viewport.y = 0;
1662-
viewport.width = context.drawingBufferWidth * 0.5;
1663-
viewport.height = context.drawingBufferHeight;
1676+
var savedCamera = Camera.clone(camera, scene._cameraVR);
16641677

1665-
var savedCamera = Camera.clone(camera, scene._cameraVR);
1678+
var near = camera.frustum.near;
1679+
var fo = near * 5.0;
1680+
var eyeSeparation = fo / 30.0;
1681+
var eyeTranslation = Cartesian3.multiplyByScalar(savedCamera.right, eyeSeparation * 0.5, scratchEyeTranslation);
16661682

1667-
var near = camera.frustum.near;
1668-
var fo = near * 5.0;
1669-
var eyeSeparation = fo / 30.0;
1670-
var eyeTranslation = Cartesian3.multiplyByScalar(savedCamera.right, eyeSeparation * 0.5, scratchEyeTranslation);
1683+
camera.frustum.aspectRatio = viewport.width / viewport.height;
16711684

1672-
camera.frustum.aspectRatio = viewport.width / viewport.height;
1685+
var offset = 0.5 * eyeSeparation * near / fo;
16731686

1674-
var offset = 0.5 * eyeSeparation * near / fo;
1687+
Cartesian3.add(savedCamera.position, eyeTranslation, camera.position);
1688+
camera.frustum.xOffset = offset;
16751689

1676-
Cartesian3.add(savedCamera.position, eyeTranslation, camera.position);
1677-
camera.frustum.xOffset = offset;
1690+
executeCommands(scene, passState);
16781691

1679-
executeCommands(scene, passState);
1692+
viewport.x = passState.viewport.width;
16801693

1681-
viewport.x = passState.viewport.width;
1694+
Cartesian3.subtract(savedCamera.position, eyeTranslation, camera.position);
1695+
camera.frustum.xOffset = -offset;
16821696

1683-
Cartesian3.subtract(savedCamera.position, eyeTranslation, camera.position);
1684-
camera.frustum.xOffset = -offset;
1697+
executeCommands(scene, passState);
16851698

1686-
executeCommands(scene, passState);
1699+
Camera.clone(savedCamera, camera);
1700+
} else {
1701+
viewport.x = 0;
1702+
viewport.y = 0;
1703+
viewport.width = context.drawingBufferWidth;
1704+
viewport.height = context.drawingBufferHeight;
16871705

1688-
Camera.clone(savedCamera, camera);
1706+
if (mode !== SceneMode.SCENE2D) {
1707+
executeCommandsInViewport(true, scene, passState, backgroundColor, picking);
16891708
} else {
1690-
viewport.x = 0;
1691-
viewport.y = 0;
1692-
viewport.width = context.drawingBufferWidth * 0.5;
1693-
viewport.height = context.drawingBufferHeight;
1709+
execute2DViewportCommands(scene, passState, backgroundColor, picking);
1710+
}
1711+
}
1712+
}
16941713

1695-
var savedTop = camera.frustum.top;
1714+
var scratch2DViewportCartographic = new Cartographic(Math.PI, CesiumMath.PI_OVER_TWO);
1715+
var scratch2DViewportMaxCoord = new Cartesian3();
1716+
var scratch2DViewportSavedPosition = new Cartesian3();
1717+
var scratch2DViewportTransform = new Matrix4();
1718+
var scratch2DViewportCameraTransform = new Matrix4();
1719+
var scratch2DViewportEyePoint = new Cartesian3();
1720+
var scratch2DViewportWindowCoords = new Cartesian3();
16961721

1697-
camera.frustum.top = camera.frustum.right * (viewport.height / viewport.width);
1698-
camera.frustum.bottom = -camera.frustum.top;
1722+
function execute2DViewportCommands(scene, passState, backgroundColor, picking) {
1723+
var context = scene.context;
1724+
var frameState = scene.frameState;
1725+
var camera = scene.camera;
1726+
var viewport = passState.viewport;
16991727

1700-
executeCommands(scene, passState);
1728+
var maxCartographic = scratch2DViewportCartographic;
1729+
var maxCoord = scratch2DViewportMaxCoord;
17011730

1702-
viewport.x = passState.viewport.width;
1731+
var projection = scene.mapProjection;
1732+
projection.project(maxCartographic, maxCoord);
17031733

1704-
executeCommands(scene, passState);
1734+
var position = Cartesian3.clone(camera.position, scratch2DViewportSavedPosition);
1735+
var transform = Matrix4.clone(camera.transform, scratch2DViewportCameraTransform);
1736+
var frustum = camera.frustum.clone();
17051737

1706-
camera.frustum.top = savedTop;
1707-
camera.frustum.bottom = -savedTop;
1708-
}
1738+
camera._setTransform(Matrix4.IDENTITY);
1739+
1740+
var viewportTransformation = Matrix4.computeViewportTransformation(viewport, 0.0, 1.0, scratch2DViewportTransform);
1741+
var projectionMatrix = camera.frustum.projectionMatrix;
1742+
1743+
var x = camera.positionWC.y;
1744+
var eyePoint = Cartesian3.fromElements(Math.sign(x) * maxCoord.x - x, 0.0, -camera.positionWC.x, scratch2DViewportEyePoint);
1745+
var windowCoordinates = Transforms.pointToGLWindowCoordinates(projectionMatrix, viewportTransformation, eyePoint, scratch2DViewportWindowCoords);
1746+
1747+
windowCoordinates.x = Math.floor(windowCoordinates.x);
1748+
1749+
var viewportX = viewport.x;
1750+
var viewportWidth = viewport.width;
1751+
1752+
if (x === 0.0 || windowCoordinates.x <= 0.0 || windowCoordinates.x >= context.drawingBufferWidth) {
1753+
executeCommandsInViewport(true, scene, passState, backgroundColor, picking);
1754+
} else if (windowCoordinates.x > context.drawingBufferWidth * 0.5) {
1755+
viewport.width = windowCoordinates.x;
1756+
1757+
camera.frustum.right = maxCoord.x - x;
1758+
1759+
executeCommandsInViewport(true, scene, passState, backgroundColor, picking);
1760+
1761+
viewport.x += windowCoordinates.x;
1762+
1763+
camera.position.x = -camera.position.x;
1764+
1765+
var right = camera.frustum.right;
1766+
camera.frustum.right = -camera.frustum.left;
1767+
camera.frustum.left = -right;
1768+
1769+
frameState.cullingVolume = camera.frustum.computeCullingVolume(camera.positionWC, camera.directionWC, camera.upWC);
1770+
context.uniformState.update(frameState);
1771+
1772+
executeCommandsInViewport(false, scene, passState, backgroundColor, picking);
17091773
} else {
1710-
viewport.x = 0;
1711-
viewport.y = 0;
1712-
viewport.width = context.drawingBufferWidth;
1713-
viewport.height = context.drawingBufferHeight;
1774+
viewport.x += windowCoordinates.x;
1775+
viewport.width -= windowCoordinates.x;
17141776

1715-
executeCommands(scene, passState);
1777+
camera.frustum.left = -maxCoord.x - x;
1778+
1779+
executeCommandsInViewport(true, scene, passState, backgroundColor, picking);
1780+
1781+
viewport.x = viewport.x - viewport.width;
1782+
1783+
camera.position.x = -camera.position.x;
1784+
1785+
var left = camera.frustum.left;
1786+
camera.frustum.left = -camera.frustum.right;
1787+
camera.frustum.right = -left;
1788+
1789+
frameState.cullingVolume = camera.frustum.computeCullingVolume(camera.positionWC, camera.directionWC, camera.upWC);
1790+
context.uniformState.update(frameState);
1791+
1792+
executeCommandsInViewport(false, scene, passState, backgroundColor, picking);
17161793
}
1794+
1795+
camera._setTransform(transform);
1796+
Cartesian3.clone(position, camera.position);
1797+
camera.frustum = frustum.clone();
1798+
1799+
viewport.x = viewportX;
1800+
viewport.width = viewportWidth;
1801+
}
1802+
1803+
function executeCommandsInViewport(firstViewport, scene, passState, backgroundColor, picking) {
1804+
if (!firstViewport) {
1805+
scene.frameState.commandList.length = 0;
1806+
}
1807+
1808+
updatePrimitives(scene);
1809+
createPotentiallyVisibleSet(scene);
1810+
1811+
if (firstViewport) {
1812+
updateAndClearFramebuffers(scene, passState, backgroundColor, picking);
1813+
executeComputeCommands(scene);
1814+
}
1815+
1816+
executeCommands(scene, passState);
17171817
}
17181818

17191819
function updateEnvironment(scene) {
@@ -1738,6 +1838,7 @@ define([
17381838
scene._depthPlane.update(frameState);
17391839
}
17401840
}
1841+
17411842
function updatePrimitives(scene) {
17421843
var frameState = scene._frameState;
17431844

@@ -1753,12 +1854,14 @@ define([
17531854
var context = scene._context;
17541855
var environmentState = scene._environmentState;
17551856

1857+
var useWebVR = scene._useWebVR && scene.mode !== SceneMode.SCENE2D;
1858+
17561859
// Preserve the reference to the original framebuffer.
17571860
environmentState.originalFramebuffer = passState.framebuffer;
17581861

17591862
// Manage sun bloom post-processing effect.
17601863
if (defined(scene.sun) && scene.sunBloom !== scene._sunBloom) {
1761-
if (scene.sunBloom && !scene._useWebVR) {
1864+
if (scene.sunBloom && !useWebVR) {
17621865
scene._sunPostProcess = new SunPostProcess();
17631866
} else if(defined(scene._sunPostProcess)){
17641867
scene._sunPostProcess = scene._sunPostProcess.destroy();
@@ -1808,7 +1911,7 @@ define([
18081911
scene._fxaa.clear(context, passState, clearColor);
18091912
}
18101913

1811-
if (environmentState.isSunVisible && scene.sunBloom && !scene._useWebVR) {
1914+
if (environmentState.isSunVisible && scene.sunBloom && !useWebVR) {
18121915
passState.framebuffer = scene._sunPostProcess.update(passState);
18131916
} else if (useGlobeDepthFramebuffer) {
18141917
passState.framebuffer = scene._globeDepth.framebuffer;
@@ -1932,22 +2035,12 @@ define([
19322035
passState.blendingEnabled = undefined;
19332036
passState.scissorTest = undefined;
19342037

1935-
var viewport = passState.viewport;
1936-
viewport.x = 0;
1937-
viewport.y = 0;
1938-
viewport.width = context.drawingBufferWidth;
1939-
viewport.height = context.drawingBufferHeight;
1940-
19412038
if (defined(scene.globe)) {
19422039
scene.globe.beginFrame(frameState);
19432040
}
19442041

19452042
updateEnvironment(scene);
1946-
updatePrimitives(scene);
1947-
createPotentiallyVisibleSet(scene);
1948-
updateAndClearFramebuffers(scene, passState, defaultValue(scene.backgroundColor, Color.BLACK));
1949-
executeComputeCommands(scene);
1950-
executeViewportCommands(scene, passState);
2043+
updateAndExecuteCommands(scene, passState, defaultValue(scene.backgroundColor, Color.BLACK));
19512044
resolveFramebuffers(scene, passState);
19522045
executeOverlayCommands(scene, passState);
19532046

@@ -2130,10 +2223,7 @@ define([
21302223

21312224
var passState = this._pickFramebuffer.begin(scratchRectangle);
21322225

2133-
updatePrimitives(this);
2134-
createPotentiallyVisibleSet(this);
2135-
updateAndClearFramebuffers(this, passState, scratchColorZero, true);
2136-
executeCommands(this, passState);
2226+
updateAndExecuteCommands(this, passState, scratchColorZero, true);
21372227
resolveFramebuffers(this, passState);
21382228

21392229
var object = this._pickFramebuffer.end(scratchRectangle);
@@ -2420,4 +2510,4 @@ define([
24202510
};
24212511

24222512
return Scene;
2423-
});
2513+
});

‎Source/Scene/SceneTransforms.js

+127-47
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ define([
99
'../Core/DeveloperError',
1010
'../Core/Math',
1111
'../Core/Matrix4',
12+
'../Core/Transforms',
1213
'./SceneMode'
1314
], function(
1415
BoundingRectangle,
@@ -20,6 +21,7 @@ define([
2021
DeveloperError,
2122
CesiumMath,
2223
Matrix4,
24+
Transforms,
2325
SceneMode) {
2426
'use strict';
2527

@@ -32,7 +34,10 @@ define([
3234

3335
var actualPositionScratch = new Cartesian4(0, 0, 0, 1);
3436
var positionCC = new Cartesian4();
35-
var viewProjectionScratch = new Matrix4();
37+
var scratchViewport = new BoundingRectangle();
38+
39+
var scratchWindowCoord0 = new Cartesian2();
40+
var scratchWindowCoord1 = new Cartesian2();
3641

3742
/**
3843
* Transforms a position in WGS84 coordinates to window coordinates. This is commonly used to place an
@@ -54,6 +59,33 @@ define([
5459
* }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
5560
*/
5661
SceneTransforms.wgs84ToWindowCoordinates = function(scene, position, result) {
62+
return SceneTransforms.wgs84WithEyeOffsetToWindowCoordinates(scene, position, Cartesian3.ZERO, result);
63+
};
64+
65+
var scratchCartesian4 = new Cartesian4();
66+
var scratchEyeOffset = new Cartesian3();
67+
68+
function worldToClip(position, eyeOffset, camera, result) {
69+
var viewMatrix = camera.viewMatrix;
70+
71+
var positionEC = Matrix4.multiplyByVector(viewMatrix, Cartesian4.fromElements(position.x, position.y, position.z, 1, scratchCartesian4), scratchCartesian4);
72+
73+
var zEyeOffset = Cartesian3.multiplyComponents(eyeOffset, Cartesian3.normalize(positionEC, scratchEyeOffset), scratchEyeOffset);
74+
positionEC.x += eyeOffset.x + zEyeOffset.x;
75+
positionEC.y += eyeOffset.y + zEyeOffset.y;
76+
positionEC.z += zEyeOffset.z;
77+
78+
return Matrix4.multiplyByVector(camera.frustum.projectionMatrix, positionEC, result);
79+
}
80+
81+
var scratchMaxCartographic = new Cartographic(Math.PI, CesiumMath.PI_OVER_TWO);
82+
var scratchProjectedCartesian = new Cartesian3();
83+
var scratchCameraPosition = new Cartesian3();
84+
85+
/**
86+
* @private
87+
*/
88+
SceneTransforms.wgs84WithEyeOffsetToWindowCoordinates = function(scene, position, eyeOffset, result) {
5789
//>>includeStart('debug', pragmas.debug);
5890
if (!defined(scene)) {
5991
throw new DeveloperError('scene is required.');
@@ -64,23 +96,102 @@ define([
6496
//>>includeEnd('debug');
6597

6698
// Transform for 3D, 2D, or Columbus view
67-
var actualPosition = SceneTransforms.computeActualWgs84Position(scene.frameState, position, actualPositionScratch);
99+
var frameState = scene.frameState;
100+
var actualPosition = SceneTransforms.computeActualWgs84Position(frameState, position, actualPositionScratch);
68101

69102
if (!defined(actualPosition)) {
70103
return undefined;
71104
}
72105

73-
// View-projection matrix to transform from world coordinates to clip coordinates
106+
// Assuming viewport takes up the entire canvas...
107+
var canvas = scene.canvas;
108+
var viewport = scratchViewport;
109+
viewport.x = 0;
110+
viewport.y = 0;
111+
viewport.width = canvas.clientWidth;
112+
viewport.height = canvas.clientHeight;
113+
74114
var camera = scene.camera;
75-
var viewProjection = Matrix4.multiply(camera.frustum.projectionMatrix, camera.viewMatrix, viewProjectionScratch);
76-
Matrix4.multiplyByVector(viewProjection, Cartesian4.fromElements(actualPosition.x, actualPosition.y, actualPosition.z, 1, positionCC), positionCC);
115+
var cameraCentered = false;
77116

78-
if ((positionCC.z < 0) && (scene.mode !== SceneMode.SCENE2D)) {
79-
return undefined;
117+
if (frameState.mode === SceneMode.SCENE2D) {
118+
var projection = scene.mapProjection;
119+
var maxCartographic = scratchMaxCartographic;
120+
var maxCoord = projection.project(maxCartographic, scratchProjectedCartesian);
121+
122+
var cameraPosition = Cartesian3.clone(camera.position, scratchCameraPosition);
123+
var frustum = camera.frustum.clone();
124+
125+
var viewportTransformation = Matrix4.computeViewportTransformation(viewport, 0.0, 1.0, new Matrix4());
126+
var projectionMatrix = camera.frustum.projectionMatrix;
127+
128+
var x = camera.positionWC.y;
129+
var eyePoint = Cartesian3.fromElements(Math.sign(x) * maxCoord.x - x, 0.0, -camera.positionWC.x);
130+
var windowCoordinates = Transforms.pointToGLWindowCoordinates(projectionMatrix, viewportTransformation, eyePoint);
131+
132+
if (x === 0.0 || windowCoordinates.x <= 0.0 || windowCoordinates.x >= canvas.clientWidth) {
133+
cameraCentered = true;
134+
} else {
135+
if (windowCoordinates.x > canvas.clientWidth * 0.5) {
136+
viewport.width = windowCoordinates.x;
137+
138+
camera.frustum.right = maxCoord.x - x;
139+
140+
positionCC = worldToClip(actualPosition, eyeOffset, camera, positionCC);
141+
SceneTransforms.clipToGLWindowCoordinates(viewport, positionCC, scratchWindowCoord0);
142+
143+
viewport.x += windowCoordinates.x;
144+
145+
camera.position.x = -camera.position.x;
146+
147+
var right = camera.frustum.right;
148+
camera.frustum.right = -camera.frustum.left;
149+
camera.frustum.left = -right;
150+
151+
positionCC = worldToClip(actualPosition, eyeOffset, camera, positionCC);
152+
SceneTransforms.clipToGLWindowCoordinates(viewport, positionCC, scratchWindowCoord1);
153+
} else {
154+
viewport.x += windowCoordinates.x;
155+
viewport.width -= windowCoordinates.x;
156+
157+
camera.frustum.left = -maxCoord.x - x;
158+
159+
positionCC = worldToClip(actualPosition, eyeOffset, camera, positionCC);
160+
SceneTransforms.clipToGLWindowCoordinates(viewport, positionCC, scratchWindowCoord0);
161+
162+
viewport.x = viewport.x - viewport.width;
163+
164+
camera.position.x = -camera.position.x;
165+
166+
var left = camera.frustum.left;
167+
camera.frustum.left = -camera.frustum.right;
168+
camera.frustum.right = -left;
169+
170+
positionCC = worldToClip(actualPosition, eyeOffset, camera, positionCC);
171+
SceneTransforms.clipToGLWindowCoordinates(viewport, positionCC, scratchWindowCoord1);
172+
}
173+
174+
Cartesian3.clone(cameraPosition, camera.position);
175+
camera.frustum = frustum.clone();
176+
177+
Cartesian2.clone(scratchWindowCoord0, result);
178+
if (result.x < 0.0 || result.x > canvas.clientWidth) {
179+
result.x = scratchWindowCoord1.x;
180+
}
181+
}
80182
}
81183

82-
result = SceneTransforms.clipToGLWindowCoordinates(scene, positionCC, result);
83-
result.y = scene.canvas.clientHeight - result.y;
184+
if (frameState.mode !== SceneMode.SCENE2D || cameraCentered) {
185+
// View-projection matrix to transform from world coordinates to clip coordinates
186+
positionCC = worldToClip(actualPosition, eyeOffset, camera, positionCC);
187+
if (positionCC.z < 0 && frameState.mode !== SceneMode.SCENE2D) {
188+
return undefined;
189+
}
190+
191+
result = SceneTransforms.clipToGLWindowCoordinates(viewport, positionCC, result);
192+
}
193+
194+
result.y = canvas.clientHeight - result.y;
84195
return result;
85196
};
86197

@@ -104,33 +215,12 @@ define([
104215
* }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
105216
*/
106217
SceneTransforms.wgs84ToDrawingBufferCoordinates = function(scene, position, result) {
107-
//>>includeStart('debug', pragmas.debug);
108-
if (!defined(scene)) {
109-
throw new DeveloperError('scene is required.');
110-
}
111-
112-
if (!defined(position)) {
113-
throw new DeveloperError('position is required.');
114-
}
115-
//>>includeEnd('debug');
116-
117-
// Transform for 3D, 2D, or Columbus view
118-
var actualPosition = SceneTransforms.computeActualWgs84Position(scene.frameState, position, actualPositionScratch);
119-
120-
if (!defined(actualPosition)) {
218+
result = SceneTransforms.wgs84ToWindowCoordinates(scene, position, result);
219+
if (!defined(result)) {
121220
return undefined;
122221
}
123222

124-
// View-projection matrix to transform from world coordinates to clip coordinates
125-
var camera = scene.camera;
126-
var viewProjection = Matrix4.multiply(camera.frustum.projectionMatrix, camera.viewMatrix, viewProjectionScratch);
127-
Matrix4.multiplyByVector(viewProjection, Cartesian4.fromElements(actualPosition.x, actualPosition.y, actualPosition.z, 1, positionCC), positionCC);
128-
129-
if ((positionCC.z < 0) && (scene.mode !== SceneMode.SCENE2D)) {
130-
return undefined;
131-
}
132-
133-
return SceneTransforms.clipToDrawingBufferCoordinates(scene, positionCC, result);
223+
return SceneTransforms.transformWindowToDrawingBuffer(scene, result, result);
134224
};
135225

136226
var projectedPosition = new Cartesian3();
@@ -173,24 +263,17 @@ define([
173263

174264
var positionNDC = new Cartesian3();
175265
var positionWC = new Cartesian3();
176-
var viewport = new BoundingRectangle();
177266
var viewportTransform = new Matrix4();
178267

179268
/**
180269
* @private
181270
*/
182-
SceneTransforms.clipToGLWindowCoordinates = function(scene, position, result) {
183-
var canvas = scene.canvas;
184-
271+
SceneTransforms.clipToGLWindowCoordinates = function(viewport, position, result) {
185272
// Perspective divide to transform from clip coordinates to normalized device coordinates
186273
Cartesian3.divideByScalar(position, position.w, positionNDC);
187274

188-
// Assuming viewport takes up the entire canvas...
189-
viewport.width = canvas.clientWidth;
190-
viewport.height = canvas.clientHeight;
191-
Matrix4.computeViewportTransformation(viewport, 0.0, 1.0, viewportTransform);
192-
193275
// Viewport transform to transform from clip coordinates to window coordinates
276+
Matrix4.computeViewportTransformation(viewport, 0.0, 1.0, viewportTransform);
194277
Matrix4.multiplyByPoint(viewportTransform, positionNDC, positionWC);
195278

196279
return Cartesian2.fromCartesian3(positionWC, result);
@@ -199,15 +282,12 @@ define([
199282
/**
200283
* @private
201284
*/
202-
SceneTransforms.clipToDrawingBufferCoordinates = function(scene, position, result) {
285+
SceneTransforms.clipToDrawingBufferCoordinates = function(viewport, position, result) {
203286
// Perspective divide to transform from clip coordinates to normalized device coordinates
204287
Cartesian3.divideByScalar(position, position.w, positionNDC);
205288

206-
// Assuming viewport takes up the entire canvas...
207-
BoundingRectangle.clone(scene._passState.viewport, viewport);
208-
Matrix4.computeViewportTransformation(viewport, 0.0, 1.0, viewportTransform);
209-
210289
// Viewport transform to transform from clip coordinates to drawing buffer coordinates
290+
Matrix4.computeViewportTransformation(viewport, 0.0, 1.0, viewportTransform);
211291
Matrix4.multiplyByPoint(viewportTransform, positionNDC, positionWC);
212292

213293
return Cartesian2.fromCartesian3(positionWC, result);

‎Source/Scene/ScreenSpaceCameraController.js

+13-90
Original file line numberDiff line numberDiff line change
@@ -495,12 +495,19 @@ define([
495495
var worldPosition = object._zoomWorldPosition;
496496
var endPosition = camera.position;
497497

498-
if (!Cartesian3.equals(worldPosition, endPosition)) {
498+
if (!Cartesian3.equals(worldPosition, endPosition) && camera.positionCartographic.height < object._maxCoord.x * 2.0) {
499+
var savedX = camera.position.x;
500+
499501
var direction = Cartesian3.subtract(worldPosition, endPosition, scratchZoomDirection);
500502
Cartesian3.normalize(direction, direction);
501503

502504
var d = Cartesian3.distance(worldPosition, endPosition) * distance / (camera.getMagnitude() * 0.5);
503505
camera.move(direction, d * 0.5);
506+
507+
if ((camera.position.x < 0.0 && savedX > 0.0) || (camera.position.x > 0.0 && savedX < 0.0)) {
508+
pickedPosition = camera.getPickRay(startPosition, scratchZoomPickRay).origin;
509+
object._zoomWorldPosition = Cartesian3.clone(pickedPosition, object._zoomWorldPosition);
510+
}
504511
}
505512
} else if (mode === SceneMode.SCENE3D) {
506513
var cameraPositionNormal = Cartesian3.normalize(camera.position, scratchCameraPositionNormal);
@@ -587,97 +594,13 @@ define([
587594
handleZoom(controller, startPosition, movement, controller._zoomFactor, camera.getMagnitude());
588595
}
589596

590-
var twist2DStart = new Cartesian2();
591-
var twist2DEnd = new Cartesian2();
592-
function twist2D(controller, startPosition, movement) {
593-
if (defined(movement.angleAndHeight)) {
594-
singleAxisTwist2D(controller, startPosition, movement.angleAndHeight);
595-
return;
596-
}
597-
598-
var scene = controller._scene;
599-
var camera = scene.camera;
600-
var canvas = scene.canvas;
601-
var width = canvas.clientWidth;
602-
var height = canvas.clientHeight;
603-
604-
var start = twist2DStart;
605-
start.x = (2.0 / width) * movement.startPosition.x - 1.0;
606-
start.y = (2.0 / height) * (height - movement.startPosition.y) - 1.0;
607-
start = Cartesian2.normalize(start, start);
608-
609-
var end = twist2DEnd;
610-
end.x = (2.0 / width) * movement.endPosition.x - 1.0;
611-
end.y = (2.0 / height) * (height - movement.endPosition.y) - 1.0;
612-
end = Cartesian2.normalize(end, end);
613-
614-
var startTheta = CesiumMath.acosClamped(start.x);
615-
if (start.y < 0) {
616-
startTheta = CesiumMath.TWO_PI - startTheta;
617-
}
618-
var endTheta = CesiumMath.acosClamped(end.x);
619-
if (end.y < 0) {
620-
endTheta = CesiumMath.TWO_PI - endTheta;
621-
}
622-
var theta = endTheta - startTheta;
623-
624-
camera.twistRight(theta);
625-
}
626-
627-
function singleAxisTwist2D(controller, startPosition, movement) {
628-
var rotateRate = controller._rotateFactor * controller._rotateRateRangeAdjustment;
629-
630-
if (rotateRate > controller._maximumRotateRate) {
631-
rotateRate = controller._maximumRotateRate;
632-
}
633-
634-
if (rotateRate < controller._minimumRotateRate) {
635-
rotateRate = controller._minimumRotateRate;
636-
}
637-
638-
var scene = controller._scene;
639-
var camera = scene.camera;
640-
var canvas = scene.canvas;
641-
642-
var phiWindowRatio = (movement.endPosition.x - movement.startPosition.x) / canvas.clientWidth;
643-
phiWindowRatio = Math.min(phiWindowRatio, controller.maximumMovementRatio);
644-
645-
var deltaPhi = rotateRate * phiWindowRatio * Math.PI * 4.0;
646-
647-
camera.twistRight(deltaPhi);
648-
}
649-
650597
function update2D(controller) {
651-
var tweens = controller._tweens;
652-
if (controller._aggregator.anyButtonDown) {
653-
tweens.removeAll();
654-
}
655-
656-
var scene = controller._scene;
657-
var camera = scene.camera;
658-
659-
if (!tweens.contains(controller._tween)) {
660-
if (!Matrix4.equals(Matrix4.IDENTITY, camera.transform)) {
661-
reactToInput(controller, controller.enableRotate, controller.translateEventTypes, twist2D, controller.inertiaSpin, '_lastInertiaSpinMovement');
662-
reactToInput(controller, controller.enableZoom, controller.zoomEventTypes, zoom2D, controller.inertiaZoom, '_lastInertiaZoomMovement');
663-
} else {
664-
reactToInput(controller, controller.enableTranslate, controller.translateEventTypes, translate2D, controller.inertiaTranslate, '_lastInertiaTranslateMovement');
665-
reactToInput(controller, controller.enableZoom, controller.zoomEventTypes, zoom2D, controller.inertiaZoom, '_lastInertiaZoomMovement');
666-
reactToInput(controller, controller.enableRotate, controller.tiltEventTypes, twist2D, controller.inertiaSpin, '_lastInertiaTiltMovement');
667-
}
668-
}
669-
670-
if (!controller._aggregator.anyButtonDown &&
671-
(!defined(controller._lastInertiaZoomMovement) || !controller._lastInertiaZoomMovement.active) &&
672-
(!defined(controller._lastInertiaTranslateMovement) || !controller._lastInertiaTranslateMovement.active) &&
673-
!tweens.contains(controller._tween)) {
674-
var tween = camera.createCorrectPositionTween(controller.bounceAnimationTime);
675-
if (defined(tween)) {
676-
controller._tween = tweens.add(tween);
677-
}
598+
if (!Matrix4.equals(Matrix4.IDENTITY, controller._scene.camera.transform)) {
599+
reactToInput(controller, controller.enableZoom, controller.zoomEventTypes, zoom2D, controller.inertiaZoom, '_lastInertiaZoomMovement');
600+
} else {
601+
reactToInput(controller, controller.enableTranslate, controller.translateEventTypes, translate2D, controller.inertiaTranslate, '_lastInertiaTranslateMovement');
602+
reactToInput(controller, controller.enableZoom, controller.zoomEventTypes, zoom2D, controller.inertiaZoom, '_lastInertiaZoomMovement');
678603
}
679-
680-
tweens.update();
681604
}
682605

683606
var pickGlobeScratchRay = new Ray();

‎Specs/Scene/CameraSpec.js

+2-64
Original file line numberDiff line numberDiff line change
@@ -1772,9 +1772,6 @@ defineSuite([
17721772
var p = camera.pickEllipsoid(windowCoord);
17731773
var c = ellipsoid.cartesianToCartographic(p);
17741774
expect(c).toEqual(new Cartographic(0.0, 0.0, 0.0));
1775-
1776-
p = camera.pickEllipsoid(Cartesian2.ZERO);
1777-
expect(p).toBeUndefined();
17781775
});
17791776

17801777
it('pick rotated map in 2D', function() {
@@ -1937,7 +1934,7 @@ defineSuite([
19371934
expect(camera.createCorrectPositionTween(0.05)).not.toBeDefined();
19381935
});
19391936

1940-
it('animates position to visible map in 2D', function() {
1937+
it('does not animate in 2D', function() {
19411938
var frustum = new OrthographicFrustum();
19421939
frustum.near = 1.0;
19431940
frustum.far = 2.0;
@@ -1953,70 +1950,11 @@ defineSuite([
19531950
var factor = 1000.0;
19541951
var dx = max.x * factor;
19551952
var dy = max.y * factor;
1956-
var tweens = new TweenCollection();
19571953

19581954
camera.moveUp(dy);
19591955
camera.moveRight(dx);
19601956

1961-
var correctAnimation = camera.createCorrectPositionTween(0.05);
1962-
expect(correctAnimation).toBeDefined();
1963-
var animation = tweens.add(correctAnimation);
1964-
while(tweens.contains(animation)) {
1965-
tweens.update();
1966-
}
1967-
1968-
expect(camera.position.x).toEqual(max.x);
1969-
expect(camera.position.y).toEqual(max.y);
1970-
1971-
camera.moveDown(dy);
1972-
camera.moveLeft(dx);
1973-
1974-
correctAnimation = camera.createCorrectPositionTween(0.05);
1975-
expect(correctAnimation).toBeDefined();
1976-
animation = tweens.add(correctAnimation);
1977-
while(tweens.contains(animation)) {
1978-
tweens.update();
1979-
}
1980-
1981-
expect(camera.position.x).toEqual(-max.x);
1982-
expect(camera.position.y).toEqual(-max.y);
1983-
});
1984-
1985-
it('animates frustum in 2D', function() {
1986-
var frustum = new OrthographicFrustum();
1987-
frustum.near = 1.0;
1988-
frustum.far = 2.0;
1989-
frustum.left = -2.0;
1990-
frustum.right = 2.0;
1991-
frustum.top = 1.0;
1992-
frustum.bottom = -1.0;
1993-
camera.frustum = frustum;
1994-
1995-
camera.update(SceneMode.SCENE2D);
1996-
1997-
var max = scene.mapProjection.project(new Cartographic(Math.PI, CesiumMath.toRadians(85.05112878)));
1998-
var factor = 1000.0;
1999-
var dx = max.x * factor;
2000-
var tweens = new TweenCollection();
2001-
2002-
camera.zoomOut(dx);
2003-
2004-
var right = frustum.right;
2005-
var top = frustum.top;
2006-
2007-
var correctAnimation = camera.createCorrectPositionTween(0.05);
2008-
expect(correctAnimation).toBeDefined();
2009-
var animation = tweens.add(correctAnimation);
2010-
while(tweens.contains(animation)) {
2011-
tweens.update();
2012-
}
2013-
2014-
expect(frustum.right).toBeLessThan(right);
2015-
expect(frustum.right).toBeGreaterThan(max.x);
2016-
expect(frustum.left).toEqual(-frustum.right);
2017-
expect(frustum.top).toBeLessThan(top);
2018-
expect(frustum.top).toBeGreaterThan(max.y);
2019-
expect(frustum.bottom).toEqual(-frustum.top);
1957+
expect(camera.createCorrectPositionTween(0.05)).not.toBeDefined();
20201958
});
20211959

20221960
it('animates position to visible map in Columbus view', function() {

‎Specs/Scene/SceneSpec.js

+23
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ defineSuite([
8080
scene.debugCommandFilter = undefined;
8181
scene.fxaa = false;
8282
scene.primitives.removeAll();
83+
scene.morphTo3D();
8384
});
8485

8586
afterAll(function() {
@@ -530,6 +531,28 @@ defineSuite([
530531
s.destroyForSpecs();
531532
});
532533

534+
it('renders map twice when in 2D', function() {
535+
scene.morphTo2D(0.0);
536+
537+
var rectangle = Rectangle.fromDegrees(-180.0, -90.0, 180.0, 90.0);
538+
539+
var rectanglePrimitive1 = createRectangle(rectangle, 0.0);
540+
rectanglePrimitive1.appearance.material.uniforms.color = new Color(1.0, 0.0, 0.0, 1.0);
541+
542+
var primitives = scene.primitives;
543+
primitives.add(rectanglePrimitive1);
544+
545+
scene.camera.setView({
546+
destination : new Cartesian3(Ellipsoid.WGS84.maximumRadius * Math.PI + 10000.0, 0.0, 10.0),
547+
convert : false
548+
});
549+
550+
var pixels = scene.renderForSpecs();
551+
expect(pixels[0]).not.toEqual(0);
552+
expect(pixels[1]).toEqual(0);
553+
expect(pixels[2]).toEqual(0);
554+
});
555+
533556
it('copies the globe depth', function() {
534557
var scene = createScene();
535558
if (defined(scene._globeDepth)) {

‎Specs/Scene/SceneTransformsSpec.js

+13-7
Original file line numberDiff line numberDiff line change
@@ -166,13 +166,16 @@ defineSuite([
166166

167167
// Update scene state
168168
scene.morphTo2D(0);
169-
scene.initializeFrame();
169+
scene.renderForSpecs();
170170

171171
var position = Cartesian3.fromDegrees(0,0);
172-
173172
var windowCoordinates = SceneTransforms.wgs84ToWindowCoordinates(scene, position);
174-
expect(windowCoordinates.x).toEqualEpsilon(0.5, CesiumMath.EPSILON2);
175-
expect(windowCoordinates.y).toEqualEpsilon(0.5, CesiumMath.EPSILON2);
173+
174+
expect(windowCoordinates.x).toBeGreaterThan(0.0);
175+
expect(windowCoordinates.y).toBeGreaterThan(0.0);
176+
177+
expect(windowCoordinates.x).toBeLessThan(1.0);
178+
expect(windowCoordinates.y).toBeLessThan(1.0);
176179
});
177180

178181
it('returns correct drawing buffer position in 2D', function() {
@@ -181,9 +184,12 @@ defineSuite([
181184
scene.renderForSpecs();
182185

183186
var position = Cartesian3.fromDegrees(0,0);
184-
185187
var drawingBufferCoordinates = SceneTransforms.wgs84ToDrawingBufferCoordinates(scene, position);
186-
expect(drawingBufferCoordinates.x).toEqualEpsilon(0.5, CesiumMath.EPSILON2);
187-
expect(drawingBufferCoordinates.y).toEqualEpsilon(0.5, CesiumMath.EPSILON2);
188+
189+
expect(drawingBufferCoordinates.x).toBeGreaterThan(0.0);
190+
expect(drawingBufferCoordinates.y).toBeGreaterThan(0.0);
191+
192+
expect(drawingBufferCoordinates.x).toBeLessThan(1.0);
193+
expect(drawingBufferCoordinates.y).toBeLessThan(1.0);
188194
});
189195
}, 'WebGL');

‎Specs/Scene/ScreenSpaceCameraControllerSpec.js

+16-68
Original file line numberDiff line numberDiff line change
@@ -307,8 +307,15 @@ defineSuite([
307307

308308
it('zoom out in 2D', function() {
309309
setUp2D();
310+
311+
var frustum = camera.frustum;
312+
frustum.right = 1000.0;
313+
frustum.left = -frustum.right;
314+
frustum.top = frustum.right * (canvas.clientHeight / canvas.clientWidth);
315+
frustum.bottom = -frustum.top;
316+
310317
var position = Cartesian3.clone(camera.position);
311-
var frustumDiff = camera.frustum.right - camera.frustum.left;
318+
var frustumDiff = frustum.right - frustum.left;
312319
var startPosition = new Cartesian2(canvas.clientWidth / 2, canvas.clientHeight / 2);
313320
var endPosition = new Cartesian2(canvas.clientWidth / 2, canvas.clientHeight / 4);
314321

@@ -335,8 +342,15 @@ defineSuite([
335342

336343
it('zoom out in 2D with wheel', function() {
337344
setUp2D();
345+
346+
var frustum = camera.frustum;
347+
frustum.right = 1000.0;
348+
frustum.left = -frustum.right;
349+
frustum.top = frustum.right * (canvas.clientHeight / canvas.clientWidth);
350+
frustum.bottom = -frustum.top;
351+
338352
var position = Cartesian3.clone(camera.position);
339-
var frustumDiff = camera.frustum.right - camera.frustum.left;
353+
var frustumDiff = frustum.right - frustum.left;
340354

341355
simulateMouseWheel(-120);
342356
updateController();
@@ -432,72 +446,6 @@ defineSuite([
432446
expect(camera.frustum.bottom).toEqual(-camera.frustum.top);
433447
});
434448

435-
it('rotate counter-clockwise in 2D', function() {
436-
setUp2D();
437-
var position = Cartesian3.clone(camera.position);
438-
var startPosition = new Cartesian2(canvas.clientWidth / 4, canvas.clientHeight / 2);
439-
var endPosition = new Cartesian2(canvas.clientWidth / 2, canvas.clientHeight / 4);
440-
441-
moveMouse(MouseButtons.MIDDLE, startPosition, endPosition);
442-
updateController();
443-
expect(position.x).toEqual(camera.position.x);
444-
expect(position.y).toEqual(camera.position.y);
445-
expect(position.z).toEqual(camera.position.z);
446-
447-
expect(camera.direction).toEqualEpsilon(Cartesian3.negate(Cartesian3.UNIT_Z, new Cartesian3()), CesiumMath.EPSILON15);
448-
expect(camera.up).toEqualEpsilon(Cartesian3.negate(Cartesian3.UNIT_X, new Cartesian3()), CesiumMath.EPSILON15);
449-
expect(camera.right).toEqualEpsilon(Cartesian3.UNIT_Y, CesiumMath.EPSILON15);
450-
});
451-
452-
it('rotate clockwise in 2D', function() {
453-
setUp2D();
454-
var position = Cartesian3.clone(camera.position);
455-
var startPosition = new Cartesian2(canvas.clientWidth / 2, canvas.clientHeight / 4);
456-
var endPosition = new Cartesian2(canvas.clientWidth / 4, canvas.clientHeight / 2);
457-
458-
moveMouse(MouseButtons.MIDDLE, startPosition, endPosition);
459-
updateController();
460-
expect(position.x).toEqual(camera.position.x);
461-
expect(position.y).toEqual(camera.position.y);
462-
expect(position.z).toEqual(camera.position.z);
463-
464-
expect(camera.direction).toEqualEpsilon(Cartesian3.negate(Cartesian3.UNIT_Z, new Cartesian3()), CesiumMath.EPSILON15);
465-
expect(camera.up).toEqualEpsilon(Cartesian3.UNIT_X, CesiumMath.EPSILON15);
466-
expect(camera.right).toEqualEpsilon(Cartesian3.negate(Cartesian3.UNIT_Y, new Cartesian3()), CesiumMath.EPSILON15);
467-
});
468-
469-
it('rotates counter-clockwise with mouse position at bottom of the screen', function() {
470-
setUp2D();
471-
var position = Cartesian3.clone(camera.position);
472-
var startPosition = new Cartesian2(3 * canvas.clientWidth / 4, 3 * canvas.clientHeight / 4);
473-
var endPosition = new Cartesian2(canvas.clientWidth / 4, 3 * canvas.clientHeight / 4);
474-
475-
moveMouse(MouseButtons.MIDDLE, startPosition, endPosition);
476-
updateController();
477-
expect(position.x).toEqual(camera.position.x);
478-
expect(position.y).toEqual(camera.position.y);
479-
expect(position.z).toEqual(camera.position.z);
480-
481-
expect(camera.direction).toEqualEpsilon(Cartesian3.negate(Cartesian3.UNIT_Z, new Cartesian3()), CesiumMath.EPSILON15);
482-
expect(camera.up).toEqualEpsilon(Cartesian3.negate(Cartesian3.UNIT_X, new Cartesian3()), CesiumMath.EPSILON15);
483-
expect(camera.right).toEqualEpsilon(Cartesian3.UNIT_Y, CesiumMath.EPSILON15);
484-
});
485-
486-
it('adds an animation to correct position or zoom in 2D', function() {
487-
setUp2D();
488-
var position = Cartesian3.clone(camera.position);
489-
var startPosition = new Cartesian2(0, canvas.clientHeight / 2);
490-
var endPosition = new Cartesian2(canvas.clientWidth, canvas.clientHeight / 2);
491-
492-
moveMouse(MouseButtons.LEFT, startPosition, endPosition);
493-
updateController();
494-
expect(position.x).toBeGreaterThan(camera.position.x);
495-
expect(position.y).toEqual(camera.position.y);
496-
expect(position.z).toEqual(camera.position.z);
497-
498-
expect(controller._tweens.length).toEqual(1);
499-
});
500-
501449
it('translate right in Columbus view', function() {
502450
setUpCV();
503451
var position = Cartesian3.clone(camera.position);

0 commit comments

Comments
 (0)
Please sign in to comment.