diff --git a/Apps/Sandcastle/gallery/Camera.html b/Apps/Sandcastle/gallery/Camera.html
index 8dbbb33272a0..b52641041766 100644
--- a/Apps/Sandcastle/gallery/Camera.html
+++ b/Apps/Sandcastle/gallery/Camera.html
@@ -189,8 +189,35 @@
});
}
+function flyInACity() {
+ Sandcastle.declare(flyInACity);
+
+ var camera = scene.camera;
+ camera.flyTo({
+ destination : Cesium.Cartesian3.fromDegrees(-73.98580932617188, 40.74843406689482, 363.34038727246224),
+ complete : function() {
+ setTimeout(function() {
+ camera.flyTo({
+ destination : Cesium.Cartesian3.fromDegrees(-73.98585975679403, 40.75759944127251, 186.50838555841779),
+ orientation : {
+ heading : Cesium.Math.toRadians(200.0),
+ pitch : Cesium.Math.toRadians(-50.0)
+ },
+ easingFunction : Cesium.EasingFunction.LINEAR_NONE
+ });
+ }, 3000);
+ }
+ });
+}
+
Sandcastle.addToolbarMenu([{
text : 'Camera Options'
+}, {
+ text : 'Fly in a city',
+ onselect : function() {
+ flyInACity();
+ Sandcastle.highlight(flyInACity);
+ }
}, {
text : 'Fly to San Diego',
onselect : function() {
diff --git a/CHANGES.md b/CHANGES.md
index a0dde7454ef5..97000fef604f 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -5,6 +5,7 @@ Change Log
* Breaking changes
* Removed `Scene.fxaaOrderIndependentTranslucency`, which was deprecated in 1.10. Use `Scene.fxaa` which is now `true` by default.
+ * Removed `Camera.clone` that was deprecated in 1.10.
* Deprecated
* The STK World Terrain url `cesiumjs.org/stk-terrain/world` has been deprecated, use `assets.agi.com/stk-terrain/world` instead. A redirect will be in place until 1.14.
* Deprecated `AxisAlignedBoundingBox.intersect` and `BoundingSphere.intersect`. These will be removed in 1.13. Use `.intersectPlane` and, if necessary, `Plane.fromCartesian4`.
@@ -31,6 +32,13 @@ Change Log
* Add `TerrainMesh.orientedBoundingBox` which holds the `OrientedBoundingBox` for the mesh for a single terrain tile.
* Use `OrientedBoundingBox` when rendering terrain and imagery to improve performance of rendering and loading (by up to 50% of terrain/imagery tiles, depending on camera view).
* Fixed 2D and Columbus view lighting issue [#2635](https://github.com/AnalyticalGraphicsInc/cesium/issues/2635).
+* Improved camera flights. [#2825](https://github.com/AnalyticalGraphicsInc/cesium/pull/2825)
+* Fixed camera flights that ended up at the wrong position in Columbus view. [#802](https://github.com/AnalyticalGraphicsInc/cesium/issues/802)
+* Fixed camera flights through the map in 2D. [#804](https://github.com/AnalyticalGraphicsInc/cesium/issues/804)
+* Fixed strange camera flights from opposite sides of the globe. [#1158](https://github.com/AnalyticalGraphicsInc/cesium/issues/1158)
+* Fixed camera flights that wouldn't fly to the home view after zooming out past it. [#1400](https://github.com/AnalyticalGraphicsInc/cesium/issues/1400)
+* Fixed flying to rectangles that cross the IDL in Columbus view and 2D. [#2093](https://github.com/AnalyticalGraphicsInc/cesium/issues/2093)
+* Fixed flights with a pitch of -90 degrees. [#2468](https://github.com/AnalyticalGraphicsInc/cesium/issues/2468)
### 1.10 - 2015-06-01
diff --git a/Source/Core/EasingFunction.js b/Source/Core/EasingFunction.js
index 154c1384b1b7..ef96a6e6d888 100644
--- a/Source/Core/EasingFunction.js
+++ b/Source/Core/EasingFunction.js
@@ -14,8 +14,6 @@ define([
*
* @namespace
* @alias EasingFunction
- *
- * @private
*/
var EasingFunction = {
/**
diff --git a/Source/Scene/Camera.js b/Source/Scene/Camera.js
index dd47c2eea875..2a9001eaaf87 100644
--- a/Source/Scene/Camera.js
+++ b/Source/Scene/Camera.js
@@ -508,6 +508,31 @@ define([
}
}
+ function getHeading(direction, up) {
+ var heading;
+ if (!CesiumMath.equalsEpsilon(Math.abs(direction.z), 1.0, CesiumMath.EPSILON3)) {
+ heading = Math.atan2(direction.y, direction.x) - CesiumMath.PI_OVER_TWO;
+ } else {
+ heading = Math.atan2(up.y, up.x) - CesiumMath.PI_OVER_TWO;
+ }
+
+ return CesiumMath.TWO_PI - CesiumMath.zeroToTwoPi(heading);
+ }
+
+ function getPitch(direction) {
+ return CesiumMath.PI_OVER_TWO - CesiumMath.acosClamped(direction.z);
+ }
+
+ function getRoll(direction, up, right) {
+ var roll = 0.0;
+ if (!CesiumMath.equalsEpsilon(Math.abs(direction.z), 1.0, CesiumMath.EPSILON3)) {
+ roll = Math.atan2(-right.z, up.z);
+ roll = CesiumMath.zeroToTwoPi(roll + CesiumMath.TWO_PI);
+ }
+
+ return roll;
+ }
+
var scratchHPRMatrix1 = new Matrix4();
var scratchHPRMatrix2 = new Matrix4();
@@ -663,19 +688,11 @@ define([
var transform = Transforms.eastNorthUpToFixedFrame(this.positionWC, ellipsoid, scratchHPRMatrix2);
this._setTransform(transform);
- var direction = this.direction;
- var up = this.up;
-
- var heading;
- if (!CesiumMath.equalsEpsilon(Math.abs(direction.z), 1.0, CesiumMath.EPSILON3)) {
- heading = Math.atan2(direction.y, direction.x) - CesiumMath.PI_OVER_TWO;
- } else {
- heading = Math.atan2(up.y, up.x) - CesiumMath.PI_OVER_TWO;
- }
+ var heading = getHeading(this.direction, this.up);
this._setTransform(oldTransform);
- return CesiumMath.TWO_PI - CesiumMath.zeroToTwoPi(heading);
+ return heading;
}
return undefined;
@@ -698,7 +715,7 @@ define([
var transform = Transforms.eastNorthUpToFixedFrame(this.positionWC, ellipsoid, scratchHPRMatrix2);
this._setTransform(transform);
- var pitch = CesiumMath.PI_OVER_TWO - CesiumMath.acosClamped(this.direction.z);
+ var pitch = getPitch(this.direction);
this._setTransform(oldTransform);
@@ -725,15 +742,7 @@ define([
var transform = Transforms.eastNorthUpToFixedFrame(this.positionWC, ellipsoid, scratchHPRMatrix2);
this._setTransform(transform);
- var up = this.up;
- var right = this.right;
- var direction = this.direction;
-
- var roll = 0.0;
- if (!CesiumMath.equalsEpsilon(Math.abs(direction.z), 1.0, CesiumMath.EPSILON3)) {
- roll = Math.atan2(-right.z, up.z);
- roll = CesiumMath.zeroToTwoPi(roll + CesiumMath.TWO_PI);
- }
+ var roll = getRoll(this.direction, this.up, this.right);
this._setTransform(oldTransform);
@@ -2277,14 +2286,21 @@ define([
var scratchFlyToMatrix4 = new Matrix4();
var newOptions = {
destination : undefined,
- direction : undefined,
- up : undefined,
+ heading : undefined,
+ pitch : undefined,
+ roll : undefined,
duration : undefined,
complete : undefined,
cancel : undefined,
- endTransform : undefined
+ endTransform : undefined,
+ maximumHeight : undefined,
+ easingFunction : undefined
};
+ var scratchFlyDirection = new Cartesian3();
+ var scratchFlyUp = new Cartesian3();
+ var scratchFlyRight = new Cartesian3();
+
/**
* Flies the camera from its current position to a new position.
*
@@ -2299,6 +2315,8 @@ define([
* @param {Matrix4} [options.endTransform] Transform matrix representing the reference frame the camera will be in when the flight is completed.
* @param {Boolean} [options.convert=true] When true
, the destination is converted to the correct coordinate system for each scene mode. When false
, the destination is expected
* to be in the correct coordinate system.
+ * @param {Number} [options.maximumHeight] The maximum height at the peak of the flight.
+ * @param {EasingFunction|EasingFunction~Callback} [options.easingFunction] Controls how the time is interpolated over the duration of the flight.
*
* @exception {DeveloperError} If either direction or up is given, then both are required.
*
@@ -2346,42 +2364,52 @@ define([
var isRectangle = defined(destination.west);
if (isRectangle) {
+ if (scene.mode !== SceneMode.SCENE3D && destination.west > destination.east) {
+ destination = Rectangle.MAX_VALUE;
+ }
destination = scene.camera.getRectangleCameraCoordinates(destination, scratchFlyToDestination);
}
- var direction;
- var up;
+ var heading;
+ var pitch;
+ var roll;
var orientation = defaultValue(options.orientation, defaultValue.EMPTY_OBJECT);
if (defined(orientation.heading)) {
- var heading = defaultValue(orientation.heading, 0.0);
- var pitch = defaultValue(orientation.pitch, -CesiumMath.PI_OVER_TWO);
- var roll = defaultValue(orientation.roll, 0.0);
+ heading = orientation.heading;
+ pitch = orientation.pitch;
+ roll = orientation.roll;
+ } else if (defined(orientation.direction)) {
+ var direction = Cartesian3.clone(orientation.direction, scratchFlyDirection);
+ var up = Cartesian3.clone(orientation.up, scratchFlyUp);
- var rotQuat = Quaternion.fromHeadingPitchRoll(heading - CesiumMath.PI_OVER_TWO, pitch, roll, scratchFlyToQuaternion);
- var rotMat = Matrix3.fromQuaternion(rotQuat, scratchFlyToMatrix3);
+ if (scene.mode === SceneMode.SCENE3D) {
+ var ellipsoid = this._projection.ellipsoid;
+ var transform = Transforms.eastNorthUpToFixedFrame(destination, ellipsoid, scratchHPRMatrix1);
+ var invTransform = Matrix4.inverseTransformation(transform, scratchHPRMatrix2);
- direction = Matrix3.getColumn(rotMat, 0, scratchFlyToDirection);
- up = Matrix3.getColumn(rotMat, 2, scratchFlyToUp);
+ Matrix4.multiplyByPointAsVector(invTransform, direction, direction);
+ Matrix4.multiplyByPointAsVector(invTransform, up, up);
+ }
- var ellipsoid = this._projection.ellipsoid;
- var transform = Transforms.eastNorthUpToFixedFrame(destination, ellipsoid, scratchFlyToMatrix4);
+ var right = Cartesian3.cross(direction, up, scratchFlyRight);
- Matrix4.multiplyByPointAsVector(transform, direction, direction);
- Matrix4.multiplyByPointAsVector(transform, up, up);
- } else if (defined(orientation.direction)) {
- direction = orientation.direction;
- up = orientation.up;
+ heading = getHeading(direction, up);
+ pitch = getPitch(direction);
+ roll = getRoll(direction, up, right);
}
newOptions.destination = destination;
- newOptions.direction = direction;
- newOptions.up = up;
+ newOptions.heading = heading;
+ newOptions.pitch = pitch;
+ newOptions.roll = roll;
newOptions.duration = options.duration;
newOptions.complete = options.complete;
newOptions.cancel = options.cancel;
newOptions.endTransform = options.endTransform;
newOptions.convert = isRectangle ? false : options.convert;
+ newOptions.maximumHeight = options.maximumHeight;
+ newOptions.easingFunction = options.easingFunction;
scene.tweens.add(CameraFlightPath.createTween(scene, newOptions));
};
@@ -2469,6 +2497,9 @@ define([
var scratchflyToBoundingSphereDirection = new Cartesian3();
var scratchflyToBoundingSphereUp = new Cartesian3();
var scratchflyToBoundingSphereRight = new Cartesian3();
+ var scratchFlyToBoundingSphereCart4 = new Cartesian4();
+ var scratchFlyToBoundingSphereQuaternion = new Quaternion();
+ var scratchFlyToBoundingSphereMatrix3 = new Matrix3();
/**
* Flys the camera to a location where the current view contains the provided bounding sphere.
@@ -2489,6 +2520,8 @@ define([
* @param {Camera~FlightCompleteCallback} [options.complete] The function to execute when the flight is complete.
* @param {Camera~FlightCancelledCallback} [options.cancel] The function to execute if the flight is cancelled.
* @param {Matrix4} [options.endTransform] Transform matrix representing the reference frame the camera will be in when the flight is completed.
+ * @param {Number} [options.maximumHeight] The maximum height at the peak of the flight.
+ * @param {EasingFunction|EasingFunction~Callback} [options.easingFunction] Controls how the time is interpolated over the duration of the flight.
*/
Camera.prototype.flyToBoundingSphere = function(boundingSphere, options) {
//>>includeStart('debug', pragmas.debug);
@@ -2521,6 +2554,14 @@ define([
Cartesian3.normalize(direction, direction);
up = Matrix4.multiplyByPointAsVector(transform, Cartesian3.UNIT_Z, scratchflyToBoundingSphereUp);
+ if (1.0 - Math.abs(Cartesian3.dot(direction, up)) < CesiumMath.EPSILON6) {
+ var rotateQuat = Quaternion.fromAxisAngle(direction, offset.heading, scratchFlyToBoundingSphereQuaternion);
+ var rotation = Matrix3.fromQuaternion(rotateQuat, scratchFlyToBoundingSphereMatrix3);
+
+ Cartesian3.fromCartesian4(Matrix4.getColumn(transform, 1, scratchFlyToBoundingSphereCart4), up);
+ Matrix3.multiplyByVector(rotation, up, up);
+ }
+
var right = Cartesian3.cross(direction, up, scratchflyToBoundingSphereRight);
Cartesian3.cross(right, direction, up);
Cartesian3.normalize(up, up);
@@ -2535,27 +2576,12 @@ define([
duration : options.duration,
complete : options.complete,
cancel : options.cancel,
- endTransform : options.endTransform
+ endTransform : options.endTransform,
+ maximumHeight : options.maximumHeight,
+ easingFunction : options.easingFunction
});
};
- /**
- * Returns a duplicate of a Camera instance.
- * @deprecated
- * @returns {Camera} The provided result parameter or a new copy of the Camera instance.
- */
- Camera.prototype.clone = function() {
- var camera = new Camera(this._scene);
- camera.position = Cartesian3.clone(this.position);
- camera.direction = Cartesian3.clone(this.direction);
- camera.up = Cartesian3.clone(this.up);
- camera.right = Cartesian3.clone(this.right);
- camera._transform = Matrix4.clone(this.transform);
- camera._transformChanged = true;
- camera.frustum = this.frustum.clone();
- return camera;
- };
-
/**
* @private
*/
diff --git a/Source/Scene/CameraFlightPath.js b/Source/Scene/CameraFlightPath.js
index 78a0fbcf7c20..25dbec8378f8 100644
--- a/Source/Scene/CameraFlightPath.js
+++ b/Source/Scene/CameraFlightPath.js
@@ -3,18 +3,11 @@ define([
'../Core/Cartesian2',
'../Core/Cartesian3',
'../Core/Cartographic',
- '../Core/clone',
'../Core/defaultValue',
'../Core/defined',
'../Core/DeveloperError',
'../Core/EasingFunction',
- '../Core/HermiteSpline',
- '../Core/LinearSpline',
'../Core/Math',
- '../Core/Matrix3',
- '../Core/Matrix4',
- '../Core/Quaternion',
- '../Core/QuaternionSpline',
'./PerspectiveFrustum',
'./PerspectiveOffCenterFrustum',
'./SceneMode'
@@ -22,18 +15,11 @@ define([
Cartesian2,
Cartesian3,
Cartographic,
- clone,
defaultValue,
defined,
DeveloperError,
EasingFunction,
- HermiteSpline,
- LinearSpline,
CesiumMath,
- Matrix3,
- Matrix4,
- Quaternion,
- QuaternionSpline,
PerspectiveFrustum,
PerspectiveOffCenterFrustum,
SceneMode) {
@@ -49,28 +35,6 @@ define([
var CameraFlightPath = {
};
- var c3destination = new Cartesian3();
- var rotMatrix = new Matrix3();
- var viewMat = new Matrix3();
-
- var cqRight = new Cartesian3();
- var cqUp = new Cartesian3();
- function createQuaternion(direction, up, result) {
- Cartesian3.cross(direction, up, cqRight);
- Cartesian3.cross(cqRight, direction, cqUp);
- viewMat[0] = cqRight.x;
- viewMat[1] = cqUp.x;
- viewMat[2] = -direction.x;
- viewMat[3] = cqRight.y;
- viewMat[4] = cqUp.y;
- viewMat[5] = -direction.y;
- viewMat[6] = cqRight.z;
- viewMat[7] = cqUp.z;
- viewMat[8] = -direction.z;
-
- return Quaternion.fromRotationMatrix(viewMat, result);
- }
-
function getAltitude(frustum, dx, dy) {
var near;
var top;
@@ -93,290 +57,159 @@ define([
var scratchCart = new Cartesian3();
var scratchCart2 = new Cartesian3();
- var scratchCart3 = new Cartesian3();
- var scratchCart4 = new Cartesian3();
- var rotMatrixScratch = new Matrix3();
- function createPath3D(camera, ellipsoid, start, up, right, end, duration) {
- // get minimum altitude from which the whole ellipsoid is visible
- var radius = ellipsoid.maximumRadius;
- var frustum = camera.frustum;
- var maxStartAlt = getAltitude(frustum, radius, radius);
- var dot = Cartesian3.dot(Cartesian3.normalize(start, scratchCart), Cartesian3.normalize(end, scratchCart2));
+ function createHeightFunction(camera, destination, startHeight, endHeight, optionAltitude) {
+ var altitude = optionAltitude;
+ var maxHeight;
+
+ if (!defined(optionAltitude)) {
+ var start = camera.position;
+ var end = destination;
+ var up = camera.up;
+ var right = camera.right;
+ var frustum = camera.frustum;
- var points;
- var altitude;
- var incrementPercentage;
- if (Cartesian3.magnitude(start) > maxStartAlt) {
- altitude = radius + 0.6 * (maxStartAlt - radius);
- incrementPercentage = 0.35;
- } else {
var diff = Cartesian3.subtract(start, end, scratchCart);
- altitude = Cartesian3.magnitude(Cartesian3.add(Cartesian3.multiplyByScalar(diff, 0.5, scratchCart2), end, scratchCart2));
var verticalDistance = Cartesian3.magnitude(Cartesian3.multiplyByScalar(up, Cartesian3.dot(diff, up), scratchCart2));
var horizontalDistance = Cartesian3.magnitude(Cartesian3.multiplyByScalar(right, Cartesian3.dot(diff, right), scratchCart2));
- altitude += getAltitude(frustum, verticalDistance, horizontalDistance);
- incrementPercentage = CesiumMath.clamp(dot + 1.0, 0.25, 0.5);
- }
- var aboveEnd = Cartesian3.multiplyByScalar(Cartesian3.normalize(end, scratchCart2), altitude, scratchCart2);
- var afterStart = Cartesian3.multiplyByScalar(Cartesian3.normalize(start, scratchCart), altitude, scratchCart);
-
- var axis, angle, rotation;
- var middle = new Cartesian3();
- if (Cartesian3.magnitude(end) > maxStartAlt && dot > 0.75) {
- middle = Cartesian3.add(Cartesian3.multiplyByScalar(Cartesian3.subtract(start, end, middle), 0.5, middle), end, middle);
- points = [ start, middle, end ];
- } else if (Cartesian3.magnitude(start) > maxStartAlt && dot > 0) {
- middle = Cartesian3.add(Cartesian3.multiplyByScalar(Cartesian3.subtract(start, aboveEnd, middle), 0.5, middle), aboveEnd, middle);
- points = [ start, middle, end ];
- } else {
- points = [ start ];
-
- angle = CesiumMath.acosClamped(Cartesian3.dot(Cartesian3.normalize(afterStart, scratchCart3), Cartesian3.normalize(aboveEnd, scratchCart4)));
- axis = Cartesian3.cross(aboveEnd, afterStart, scratchCart3);
- if (Cartesian3.equalsEpsilon(axis, Cartesian3.ZERO, CesiumMath.EPSILON6)) {
- axis = Cartesian3.UNIT_Z;
- }
+ maxHeight = Math.max(startHeight, endHeight);
+ altitude = Math.min(getAltitude(frustum, verticalDistance, horizontalDistance) * 0.20, 1000000000.0);
+ }
- var increment = incrementPercentage * angle;
- var startCondition = angle - increment;
- for ( var i = startCondition; i > 0.0; i = i - increment) {
- rotation = Matrix3.fromQuaternion(Quaternion.fromAxisAngle(axis, i), rotMatrixScratch);
- points.push(Matrix3.multiplyByVector(rotation, aboveEnd, new Cartesian3()));
- }
+ if (defined(optionAltitude) || maxHeight < altitude) {
+ var power = 8.0;
+ var factor = 1000000.0;
- points.push(end);
- }
+ var s = -Math.pow((altitude - startHeight) * factor, 1.0 / power);
+ var e = Math.pow((altitude - endHeight) * factor, 1.0 / power);
- var times = new Array(points.length);
- var scalar = duration / (points.length - 1);
- for ( var k = 0; k < points.length; ++k) {
- times[k] = k * scalar;
+ return function(t) {
+ var x = t * (e - s) + s;
+ return -Math.pow(x, power) / factor + altitude;
+ };
}
- return HermiteSpline.createNaturalCubic({
- points : points,
- times : times
- });
+ return function(t) {
+ return CesiumMath.lerp(startHeight, endHeight, t);
+ };
}
- var direction3D = new Cartesian3();
- var right3D = new Cartesian3();
- var up3D = new Cartesian3();
- var quat3D = new Quaternion();
-
- function createOrientations3D(path, startDirection, startUp, endDirection, endUp) {
- var points = path.points;
- var orientations = new Array(points.length);
- orientations[0] = createQuaternion(startDirection, startUp);
-
- var point;
- var length = points.length - 1;
- for (var i = 1; i < length; ++i) {
- point = points[i];
- Cartesian3.normalize(Cartesian3.negate(point, direction3D), direction3D);
- Cartesian3.normalize(Cartesian3.cross(direction3D, Cartesian3.UNIT_Z, right3D), right3D);
- Cartesian3.cross(right3D, direction3D, up3D);
- orientations[i] = createQuaternion(direction3D, up3D, quat3D);
+ function adjustAngleForLERP(startAngle, endAngle) {
+ if (CesiumMath.equalsEpsilon(startAngle, CesiumMath.TWO_PI, CesiumMath.EPSILON11)) {
+ startAngle = 0.0;
}
- point = points[length];
- if (defined(endDirection) && defined(endUp)) {
- orientations[length] = createQuaternion(endDirection, endUp);
- } else {
- Cartesian3.normalize(Cartesian3.negate(point, direction3D), direction3D);
- Cartesian3.normalize(Cartesian3.cross(direction3D, Cartesian3.UNIT_Z, right3D), right3D);
- Cartesian3.cross(right3D, direction3D, up3D);
- orientations[length] = createQuaternion(direction3D, up3D, quat3D);
+ if (endAngle > startAngle + Math.PI) {
+ startAngle += CesiumMath.TWO_PI;
+ } else if (endAngle < startAngle - Math.PI) {
+ startAngle -= CesiumMath.TWO_PI;
}
- return new QuaternionSpline({
- points : orientations,
- times : path.times
- });
+ return startAngle;
}
- var scratchStartPosition = new Cartesian3();
- var scratchStartDirection = new Cartesian3();
- var scratchStartUp = new Cartesian3();
- var scratchStartRight = new Cartesian3();
- var currentFrame = new Matrix4();
+ var scratchStart = new Cartesian3();
- function createUpdate3D(scene, destination, duration, direction, up) {
+ function createUpdateCV(scene, duration, destination, heading, pitch, roll, optionAltitude) {
var camera = scene.camera;
- var ellipsoid = scene.mapProjection.ellipsoid;
- var start = camera.cameraToWorldCoordinatesPoint(camera.position, scratchStartPosition);
- var startDirection = camera.cameraToWorldCoordinatesVector(camera.direction, scratchStartDirection);
- var startUp = camera.cameraToWorldCoordinatesVector(camera.up, scratchStartUp);
- var startRight = Cartesian3.cross(startDirection, startUp, scratchStartRight);
+ var start = Cartesian3.clone(camera.position, scratchStart);
+ var startPitch = camera.pitch;
+ var startHeading = adjustAngleForLERP(camera.heading, heading);
+ var startRoll = adjustAngleForLERP(camera.roll, roll);
- var path = createPath3D(camera, ellipsoid, start, startUp, startRight, destination, duration);
- var orientations = createOrientations3D(path, startDirection, startUp, direction, up);
+ var heightFunction = createHeightFunction(camera, destination, start.z, destination.z, optionAltitude);
var update = function(value) {
- var time = value.time;
- var orientation = orientations.evaluate(time);
- Matrix3.fromQuaternion(orientation, rotMatrix);
-
- Matrix4.clone(camera.transform, currentFrame);
- camera._setTransform(Matrix4.IDENTITY);
+ var time = value.time / duration;
- camera.position = path.evaluate(time, camera.position);
- camera.right = Matrix3.getRow(rotMatrix, 0, camera.right);
- camera.up = Matrix3.getRow(rotMatrix, 1, camera.up);
- camera.direction = Cartesian3.negate(Matrix3.getRow(rotMatrix, 2, camera.direction), camera.direction);
+ camera.setView({
+ heading : CesiumMath.lerp(startHeading, heading, time),
+ pitch : CesiumMath.lerp(startPitch, pitch, time),
+ roll : CesiumMath.lerp(startRoll, roll, time)
+ });
- camera._setTransform(currentFrame);
+ Cartesian2.lerp(start, destination, time, camera.position);
+ camera.position.z = heightFunction(time);
};
return update;
}
- var cartScratch1 = new Cartesian3();
- function createPath2D(camera, ellipsoid, start, end, duration) {
- if (CesiumMath.equalsEpsilon(Cartesian2.magnitude(start), Cartesian2.magnitude(end), 10000.0)) {
- return new LinearSpline({
- points : [start, end],
- times : [0.0, duration]
- });
- }
+ var scratchStartCart = new Cartographic();
+ var scratchEndCart = new Cartographic();
+ var scratchCurrentPositionCart = new Cartographic();
- // get minimum altitude from which the whole map is visible
- var radius = ellipsoid.maximumRadius;
- var frustum = camera.frustum;
- var maxStartAlt = getAltitude(frustum, Math.PI * radius, CesiumMath.PI_OVER_TWO * radius);
-
- var points;
- var altitude;
- var incrementPercentage = 0.5;
- if (start.z > maxStartAlt) {
- altitude = 0.6 * maxStartAlt;
- } else {
- var diff = Cartesian3.subtract(start, end, cartScratch1);
- altitude = getAltitude(frustum, Math.abs(diff.y), Math.abs(diff.x));
- }
+ function createUpdate3D(scene, duration, destination, heading, pitch, roll, optionAltitude) {
+ var camera = scene.camera;
+ var projection = scene.mapProjection;
+ var ellipsoid = projection.ellipsoid;
- var aboveEnd = Cartesian3.clone(end);
- aboveEnd.z = altitude;
- var afterStart = Cartesian3.clone(start);
- afterStart.z = altitude;
-
- var middle = new Cartesian3();
- if (end.z > maxStartAlt) {
- middle = Cartesian3.add(Cartesian3.multiplyByScalar(Cartesian3.subtract(start, end, middle), 0.5, middle), end, middle);
- points = [ start, middle, end ];
- } else if (start.z > maxStartAlt) {
- middle = Cartesian3.add(Cartesian3.multiplyByScalar(Cartesian3.subtract(start, aboveEnd, middle), 0.5, middle), aboveEnd, middle);
- points = [ start, middle, end ];
- } else {
- points = [ start ];
-
- var v = Cartesian3.subtract(afterStart, aboveEnd, cartScratch1);
- var distance = Cartesian3.magnitude(v);
- Cartesian3.normalize(v, v);
-
- var increment = incrementPercentage * distance;
- var startCondition = distance - increment;
- for ( var i = startCondition; i > 0.0; i = i - increment) {
- var p = new Cartesian3();
- points.push(Cartesian3.add(Cartesian3.multiplyByScalar(v, i, p), aboveEnd, p));
- }
+ var startCart = Cartographic.clone(camera.positionCartographic, scratchStartCart);
+ var startPitch = camera.pitch;
+ var startHeading = adjustAngleForLERP(camera.heading, heading);
+ var startRoll = adjustAngleForLERP(camera.roll, roll);
- points.push(end);
+ var destCart = ellipsoid.cartesianToCartographic(destination, scratchEndCart);
+ if (destCart.height <= 0.0) {
+ destCart.height = startCart.height;
}
- var times = new Array(points.length);
- var scalar = duration / (points.length - 1);
- for ( var k = 0; k < points.length; ++k) {
- times[k] = k * scalar;
- }
+ startCart.longitude = CesiumMath.zeroToTwoPi(startCart.longitude);
+ destCart.longitude = CesiumMath.zeroToTwoPi(destCart.longitude);
- return HermiteSpline.createNaturalCubic({
- points : points,
- times : times
- });
- }
-
- var direction2D = Cartesian3.negate(Cartesian3.UNIT_Z, new Cartesian3());
- var right2D = new Cartesian3();
- right2D = Cartesian3.normalize(Cartesian3.cross(direction2D, Cartesian3.UNIT_Y, right2D), right2D);
- var up2D = Cartesian3.cross(right2D, direction2D, new Cartesian3());
- var quat = createQuaternion(direction2D, up2D);
-
- function createOrientations2D(camera, path, endDirection, endUp) {
- var points = path.points;
- var orientations = new Array(points.length);
- orientations[0] = createQuaternion(camera.direction, camera.up);
-
- var length = points.length - 1;
- for (var i = 1; i < length; ++i) {
- orientations[i] = quat;
- }
-
- if (defined(endDirection) && defined(endUp)) {
- orientations[length] = createQuaternion(endDirection, endUp);
- } else {
- orientations[length] = quat;
+ var diff = startCart.longitude - destCart.longitude;
+ if (diff < -CesiumMath.PI) {
+ startCart.longitude += CesiumMath.TWO_PI;
+ } else if (diff > CesiumMath.PI) {
+ destCart.longitude += CesiumMath.TWO_PI;
}
- return new QuaternionSpline({
- points : orientations,
- times : path.times
- });
- }
-
- function createUpdateCV(scene, destination, duration, direction, up) {
- var camera = scene.camera;
- var ellipsoid = scene.mapProjection.ellipsoid;
-
- var path = createPath2D(camera, ellipsoid, Cartesian3.clone(camera.position), destination, duration);
- var orientations = createOrientations2D(camera, path, direction, up);
+ var heightFunction = createHeightFunction(camera, destination, startCart.height, destCart.height, optionAltitude);
var update = function(value) {
- var time = value.time;
- var orientation = orientations.evaluate(time);
- Matrix3.fromQuaternion(orientation, rotMatrix);
-
- Matrix4.clone(camera.transform, currentFrame);
- camera._setTransform(Matrix4.IDENTITY);
-
- camera.position = path.evaluate(time, camera.position);
- camera.right = Matrix3.getRow(rotMatrix, 0, camera.right);
- camera.up = Matrix3.getRow(rotMatrix, 1, camera.up);
- camera.direction = Cartesian3.negate(Matrix3.getRow(rotMatrix, 2, camera.direction), camera.direction);
-
- camera._setTransform(currentFrame);
+ var time = value.time / duration;
+
+ var position = scratchCurrentPositionCart;
+ position.longitude = CesiumMath.lerp(startCart.longitude, destCart.longitude, time);
+ position.latitude = CesiumMath.lerp(startCart.latitude, destCart.latitude, time);
+ position.height = heightFunction(time);
+
+ camera.setView({
+ positionCartographic : position,
+ heading : CesiumMath.lerp(startHeading, heading, time),
+ pitch : CesiumMath.lerp(startPitch, pitch, time),
+ roll : CesiumMath.lerp(startRoll, roll, time)
+ });
};
return update;
}
- function createUpdate2D(scene, destination, duration, direction, up) {
+ function createUpdate2D(scene, duration, destination, heading, pitch, roll, optionAltitude) {
var camera = scene.camera;
- var ellipsoid = scene.mapProjection.ellipsoid;
-
- var start = Cartesian3.clone(camera.position);
- start.z = camera.frustum.right - camera.frustum.left;
- var path = createPath2D(camera, ellipsoid, start, destination, duration);
- var orientations = createOrientations2D(camera, path, Cartesian3.negate(Cartesian3.UNIT_Z, new Cartesian3()), up);
+ var start = Cartesian3.clone(camera.position, scratchStart);
+ var startPitch = camera.pitch;
+ var startHeading = adjustAngleForLERP(camera.heading, heading);
+ var startRoll = adjustAngleForLERP(camera.roll, roll);
- var height = camera.position.z;
+ var startHeight = camera.frustum.right - camera.frustum.left;
+ var heightFunction = createHeightFunction(camera, destination, startHeight, destination.z, optionAltitude);
var update = function(value) {
- var time = value.time;
- var orientation = orientations.evaluate(time);
- Matrix3.fromQuaternion(orientation, rotMatrix);
+ var time = value.time / duration;
- camera.position = path.evaluate(time);
- var zoom = camera.position.z;
- camera.position.z = height;
+ camera.setView({
+ heading : CesiumMath.lerp(startHeading, heading, time),
+ pitch : CesiumMath.lerp(startPitch, pitch, time),
+ roll : CesiumMath.lerp(startRoll, roll, time)
+ });
+
+ Cartesian2.lerp(start, destination, time, camera.position);
- camera.right = Matrix3.getRow(rotMatrix, 0, camera.right);
- camera.up = Matrix3.getRow(rotMatrix, 1, camera.up);
- camera.direction = Cartesian3.negate(Matrix3.getRow(rotMatrix, 2, camera.direction), camera.direction);
+ var zoom = heightFunction(time);
var frustum = camera.frustum;
var ratio = frustum.top / frustum.right;
@@ -397,11 +230,30 @@ define([
var scratchCartographic = new Cartographic();
var scratchDestination = new Cartesian3();
+ function emptyFlight(complete, cancel) {
+ return {
+ startObject : {},
+ stopObject : {},
+ duration : 0.0,
+ complete : complete,
+ cancel : cancel
+ };
+ }
+
+ function wrapCallback(controller, cb) {
+ var wrapped = function() {
+ if (typeof cb === 'function') {
+ cb();
+ }
+
+ controller.enableInputs = true;
+ };
+ return wrapped;
+ }
+
CameraFlightPath.createTween = function(scene, options) {
options = defaultValue(options, defaultValue.EMPTY_OBJECT);
var destination = options.destination;
- var direction = options.direction;
- var up = options.up;
//>>includeStart('debug', pragmas.debug);
if (!defined(scene)) {
@@ -410,136 +262,93 @@ define([
if (!defined(destination)) {
throw new DeveloperError('destination is required.');
}
- if ((defined(direction) && !defined(up)) || (defined(up) && !defined(direction))) {
- throw new DeveloperError('If either direction or up is given, then both are required.');
- }
//>>includeEnd('debug');
+ var projection = scene.mapProjection;
+ var ellipsoid = projection.ellipsoid;
+
+ var maximumHeight = options.maximumHeight;
+ var easingFunction = options.easingFunction;
+
if (scene.mode === SceneMode.MORPHING) {
- return {
- startObject : {},
- stopObject: {},
- duration : 0.0
- };
+ return emptyFlight();
}
var convert = defaultValue(options.convert, true);
if (convert && scene.mode !== SceneMode.SCENE3D) {
- var projection = scene.mapProjection;
- var ellipsoid = projection.ellipsoid;
ellipsoid.cartesianToCartographic(destination, scratchCartographic);
destination = projection.project(scratchCartographic, scratchDestination);
}
- var duration = defaultValue(options.duration, 3.0);
- var controller = scene.screenSpaceCameraController;
- controller.enableInputs = false;
-
- var wrapCallback = function(cb) {
- var wrapped = function() {
- if (typeof cb === 'function') {
- cb();
- }
-
- controller.enableInputs = true;
- };
- return wrapped;
- };
- var complete = wrapCallback(options.complete);
- var cancel = wrapCallback(options.cancel);
-
var camera = scene.camera;
var transform = options.endTransform;
if (defined(transform)) {
camera._setTransform(transform);
}
- var frustum = camera.frustum;
- if (scene.mode === SceneMode.SCENE2D) {
- if (Cartesian2.equalsEpsilon(camera.position, destination, CesiumMath.EPSILON6) && (CesiumMath.equalsEpsilon(Math.max(frustum.right - frustum.left, frustum.top - frustum.bottom), destination.z, CesiumMath.EPSILON6))) {
- return {
- startObject : {},
- stopObject: {},
- duration : 0.0,
- complete : complete,
- cancel: cancel
- };
- }
- } else if (Cartesian3.equalsEpsilon(destination, camera.position, CesiumMath.EPSILON6)) {
- return {
- startObject : {},
- stopObject: {},
- duration : 0.0,
- complete : complete,
- cancel: cancel
- };
+ var duration = options.duration;
+ if (!defined(duration)) {
+ duration = Math.ceil(Cartesian3.distance(camera.position, destination) / 1000000.0) + 2.0;
+ duration = Math.min(duration, 3.0);
}
- if (duration <= 0.0) {
- var newOnComplete = function() {
- var position = destination;
- if (scene.mode === SceneMode.SCENE3D) {
- if (!defined(options.direction) && !defined(options.up)){
- dirScratch = Cartesian3.normalize(Cartesian3.negate(position, dirScratch), dirScratch);
- rightScratch = Cartesian3.normalize(Cartesian3.cross(dirScratch, Cartesian3.UNIT_Z, rightScratch), rightScratch);
- } else {
- dirScratch = options.direction;
- rightScratch = Cartesian3.normalize(Cartesian3.cross(dirScratch, options.up, rightScratch), rightScratch);
- }
- upScratch = defaultValue(options.up, Cartesian3.cross(rightScratch, dirScratch, upScratch));
- } else {
- if (!defined(options.direction) && !defined(options.up)){
- dirScratch = Cartesian3.negate(Cartesian3.UNIT_Z, dirScratch);
- rightScratch = Cartesian3.normalize(Cartesian3.cross(dirScratch, Cartesian3.UNIT_Y, rightScratch), rightScratch);
- } else {
- dirScratch = options.direction;
- rightScratch = Cartesian3.normalize(Cartesian3.cross(dirScratch, options.up, rightScratch), rightScratch);
- }
- upScratch = defaultValue(options.up, Cartesian3.cross(rightScratch, dirScratch, upScratch));
- }
+ var mode = scene.mode;
+ var heading = defaultValue(options.heading, 0.0);
+ var pitch = scene.mode !== SceneMode.SCENE2D ? defaultValue(options.pitch, -CesiumMath.PI_OVER_TWO) : -CesiumMath.PI_OVER_TWO;
+ var roll = defaultValue(options.roll, 0.0);
+
+ var controller = scene.screenSpaceCameraController;
+ controller.enableInputs = false;
- Cartesian3.clone(position, camera.position);
- Cartesian3.clone(dirScratch, camera.direction);
- Cartesian3.clone(upScratch, camera.up);
- Cartesian3.clone(rightScratch, camera.right);
+ var complete = wrapCallback(controller, options.complete);
+ var cancel = wrapCallback(controller, options.cancel);
- if (scene.mode === SceneMode.SCENE2D) {
- var zoom = camera.position.z;
- var ratio = frustum.top / frustum.right;
+ var frustum = camera.frustum;
- var incrementAmount = (zoom - (frustum.right - frustum.left)) * 0.5;
- frustum.right += incrementAmount;
- frustum.left -= incrementAmount;
- frustum.top = ratio * frustum.right;
- frustum.bottom = -frustum.top;
- }
+ var empty = scene.mode === SceneMode.SCENE2D;
+ empty = empty && Cartesian2.equalsEpsilon(camera.position, destination, CesiumMath.EPSILON6);
+ empty = empty && CesiumMath.equalsEpsilon(Math.max(frustum.right - frustum.left, frustum.top - frustum.bottom), destination.z, CesiumMath.EPSILON6);
+
+ empty = empty || (scene.mode !== SceneMode.SCENE2D && Cartesian3.equalsEpsilon(destination, camera.position, CesiumMath.EPSILON6));
+
+ if (empty) {
+ return emptyFlight(complete, cancel);
+ }
+
+ var updateFunctions = new Array(4);
+ updateFunctions[SceneMode.SCENE2D] = createUpdate2D;
+ updateFunctions[SceneMode.SCENE3D] = createUpdate3D;
+ updateFunctions[SceneMode.COLUMBUS_VIEW] = createUpdateCV;
+
+ if (duration <= 0.0) {
+ var newOnComplete = function() {
+ var update = updateFunctions[mode](scene, 1.0, destination, heading, pitch, roll, maximumHeight);
+ update({ time: 1.0 });
if (typeof complete === 'function') {
complete();
}
};
- return {
- startObject : {},
- stopObject: {},
- duration : 0.0,
- complete : newOnComplete,
- cancel: cancel
- };
+ return emptyFlight(newOnComplete, cancel);
}
- var update;
- if (scene.mode === SceneMode.SCENE3D) {
- update = createUpdate3D(scene, destination, duration, direction, up);
- } else if (scene.mode === SceneMode.SCENE2D) {
- update = createUpdate2D(scene, destination, duration, direction, up);
- } else {
- update = createUpdateCV(scene, destination, duration, direction, up);
+ var update = updateFunctions[mode](scene, duration, destination, heading, pitch, roll, maximumHeight);
+
+ if (!defined(easingFunction)) {
+ var startHeight = camera.positionCartographic.height;
+ var endHeight = mode === SceneMode.SCENE3D ? ellipsoid.cartesianToCartographic(destination).height : destination.z;
+
+ if (startHeight > endHeight && startHeight > 11500.0) {
+ easingFunction = EasingFunction.CUBIC_OUT;
+ } else {
+ easingFunction = EasingFunction.QUINTIC_IN_OUT;
+ }
}
return {
duration : duration,
- easingFunction : EasingFunction.SINUSOIDAL_IN_OUT,
+ easingFunction : easingFunction,
startObject : {
time : 0.0
},
diff --git a/Source/Widgets/Geocoder/GeocoderViewModel.js b/Source/Widgets/Geocoder/GeocoderViewModel.js
index fe46522240e0..5a5e56a38a24 100644
--- a/Source/Widgets/Geocoder/GeocoderViewModel.js
+++ b/Source/Widgets/Geocoder/GeocoderViewModel.js
@@ -44,7 +44,7 @@ define([
* written to the console reminding you that you must create and supply a Bing Maps
* key as soon as possible. Please do not deploy an application that uses
* this widget without creating a separate key for your application.
- * @param {Number} [options.flightDuration=1.5] The duration of the camera flight to an entered location, in seconds.
+ * @param {Number} [options.flightDuration] The duration of the camera flight to an entered location, in seconds.
*/
var GeocoderViewModel = function(options) {
//>>includeStart('debug', pragmas.debug);
@@ -60,7 +60,7 @@ define([
this._key = BingMapsApi.getKey(options.key);
this._scene = options.scene;
- this._flightDuration = defaultValue(options.flightDuration, 1.5);
+ this._flightDuration = options.flightDuration;
this._searchText = '';
this._isSearchInProgress = false;
this._geocodeInProgress = undefined;
@@ -117,9 +117,10 @@ define([
/**
* Gets or sets the the duration of the camera flight in seconds.
* A value of zero causes the camera to instantly switch to the geocoding location.
+ * The duration will be computed based on the distance when undefined.
*
- * @type {Number}
- * @default 1.5
+ * @type {Number|undefined}
+ * @default undefined
*/
this.flightDuration = undefined;
knockout.defineProperty(this, 'flightDuration', {
@@ -128,7 +129,7 @@ define([
},
set : function(value) {
//>>includeStart('debug', pragmas.debug);
- if (value < 0) {
+ if (defined(value) && value < 0) {
throw new DeveloperError('value must be positive.');
}
//>>includeEnd('debug');
diff --git a/Source/Widgets/HomeButton/HomeButtonViewModel.js b/Source/Widgets/HomeButton/HomeButtonViewModel.js
index c60964f28a66..657df1065c35 100644
--- a/Source/Widgets/HomeButton/HomeButtonViewModel.js
+++ b/Source/Widgets/HomeButton/HomeButtonViewModel.js
@@ -32,10 +32,6 @@ define([
scene.completeMorph();
}
- var direction;
- var right;
- var up;
-
if (mode === SceneMode.SCENE2D) {
scene.camera.flyTo({
destination : Rectangle.MAX_VALUE,
@@ -50,16 +46,12 @@ define([
Cartesian3.normalize(destination, destination);
Cartesian3.multiplyByScalar(destination, mag, destination);
- direction = Cartesian3.normalize(destination, new Cartesian3());
- Cartesian3.negate(direction, direction);
- right = Cartesian3.cross(direction, Cartesian3.UNIT_Z, new Cartesian3());
- up = Cartesian3.cross(right, direction, new Cartesian3());
-
scene.camera.flyTo({
destination : destination,
orientation : {
- direction: direction,
- up : up
+ heading : 0.0,
+ pitch : -Math.PI * 0.5,
+ roll : 0.0
},
duration : duration,
endTransform : Matrix4.IDENTITY
@@ -68,17 +60,15 @@ define([
var maxRadii = scene.globe.ellipsoid.maximumRadius;
var position = new Cartesian3(0.0, -1.0, 1.0);
position = Cartesian3.multiplyByScalar(Cartesian3.normalize(position, position), 5.0 * maxRadii, position);
- direction = new Cartesian3();
- direction = Cartesian3.normalize(Cartesian3.subtract(Cartesian3.ZERO, position, direction), direction);
- right = Cartesian3.cross(direction, Cartesian3.UNIT_Z, new Cartesian3());
- up = Cartesian3.cross(right, direction, new Cartesian3());
+ var pitch = -Math.acos(Cartesian3.normalize(position, new Cartesian3()).z);
scene.camera.flyTo({
destination : position,
duration : duration,
orientation : {
- direction : direction,
- up : up
+ heading : 0.0,
+ pitch : pitch,
+ roll : 0.0
},
endTransform : Matrix4.IDENTITY,
convert : false
@@ -92,7 +82,7 @@ define([
* @constructor
*
* @param {Scene} scene The scene instance to use.
- * @param {Number} [duration=1.5] The duration of the camera flight in seconds.
+ * @param {Number} [duration] The duration of the camera flight in seconds.
*/
var HomeButtonViewModel = function(scene, duration) {
//>>includeStart('debug', pragmas.debug);
@@ -101,8 +91,6 @@ define([
}
//>>includeEnd('debug');
- duration = defaultValue(duration, 1.5);
-
this._scene = scene;
this._duration = duration;
@@ -149,9 +137,10 @@ define([
/**
* Gets or sets the the duration of the camera flight in seconds.
* A value of zero causes the camera to instantly switch to home view.
+ * The duration will be computed based on the distance when undefined.
* @memberof HomeButtonViewModel.prototype
*
- * @type {Number}
+ * @type {Number|undefined}
*/
duration : {
get : function() {
@@ -159,7 +148,7 @@ define([
},
set : function(value) {
//>>includeStart('debug', pragmas.debug);
- if (value < 0) {
+ if (defined(value) && value < 0) {
throw new DeveloperError('value must be positive.');
}
//>>includeEnd('debug');
diff --git a/Specs/Scene/CameraFlightPathSpec.js b/Specs/Scene/CameraFlightPathSpec.js
index 90d7544c9616..75b14818707d 100644
--- a/Specs/Scene/CameraFlightPathSpec.js
+++ b/Specs/Scene/CameraFlightPathSpec.js
@@ -59,24 +59,6 @@ defineSuite([
}).toThrowDeveloperError();
});
- it('create animation throws with just up and no direction', function() {
- expect(function() {
- CameraFlightPath.createTween(scene, {
- destination : Cartesian3.ZERO,
- up : Cartesian3.UNIT_Z
- });
- }).toThrowDeveloperError();
- });
-
- it('create animation throws with just direction and no up', function() {
- expect(function() {
- CameraFlightPath.createTween(scene, {
- destination : Cartesian3.ZERO,
- direction : Cartesian3.UNIT_X
- });
- }).toThrowDeveloperError();
- });
-
it('creates an animation', function() {
var destination = new Cartesian3(1e9, 1e9, 1e9);
var duration = 5.0;
@@ -105,30 +87,35 @@ defineSuite([
var camera = scene.camera;
var startPosition = Cartesian3.clone(camera.position);
- var startDirection = Cartesian3.clone(camera.direction);
- var startUp = Cartesian3.clone(camera.up);
+ var startHeading = camera.heading;
+ var startPitch = camera.pitch;
+ var startRoll = camera.roll;
var endPosition = Cartesian3.negate(startPosition, new Cartesian3());
- var endDirection = Cartesian3.negate(startDirection, new Cartesian3());
- var endUp = Cartesian3.negate(startUp, new Cartesian3());
+ var endHeading = CesiumMath.toRadians(20.0);
+ var endPitch = CesiumMath.toRadians(-45.0);
+ var endRoll = CesiumMath.TWO_PI;
var duration = 5.0;
var flight = CameraFlightPath.createTween(scene, {
destination : endPosition,
- direction : endDirection,
- up : endUp,
+ heading : endHeading,
+ pitch : endPitch,
+ roll : endRoll,
duration : duration
});
flight.update({ time : 0.0 });
expect(camera.position).toEqualEpsilon(startPosition, CesiumMath.EPSILON12);
- expect(camera.direction).toEqualEpsilon(startDirection, CesiumMath.EPSILON12);
- expect(camera.up).toEqualEpsilon(startUp, CesiumMath.EPSILON12);
+ expect(camera.heading).toEqualEpsilon(startHeading, CesiumMath.EPSILON12);
+ expect(camera.pitch).toEqualEpsilon(startPitch, CesiumMath.EPSILON12);
+ expect(camera.roll).toEqualEpsilon(startRoll, CesiumMath.EPSILON12);
flight.update({ time : duration });
expect(camera.position).toEqualEpsilon(endPosition, CesiumMath.EPSILON12);
- expect(camera.direction).toEqualEpsilon(endDirection, CesiumMath.EPSILON12);
- expect(camera.up).toEqualEpsilon(endUp, CesiumMath.EPSILON12);
+ expect(camera.heading).toEqualEpsilon(endHeading, CesiumMath.EPSILON12);
+ expect(camera.pitch).toEqualEpsilon(endPitch, CesiumMath.EPSILON12);
+ expect(camera.roll).toEqualEpsilon(endRoll, CesiumMath.EPSILON12);
});
it('creates an animation in Columbus view', function() {
@@ -141,32 +128,22 @@ defineSuite([
camera.right = Cartesian3.cross(camera.direction, camera.up, new Cartesian3());
var startPosition = Cartesian3.clone(camera.position);
- var startDirection = Cartesian3.clone(camera.direction);
- var startUp = Cartesian3.clone(camera.up);
var projection = scene.mapProjection;
- var destination = Cartesian3.add(startPosition, new Cartesian3(-6e6 * Math.PI, 6e6 * CesiumMath.PI_OVER_FOUR, 100.0), new Cartesian3());
+ var destination = Cartesian3.add(startPosition, new Cartesian3(-6e5 * Math.PI, 6e5 * CesiumMath.PI_OVER_FOUR, 100.0), new Cartesian3());
var endPosition = projection.ellipsoid.cartographicToCartesian(projection.unproject(destination));
- var endDirection = Cartesian3.clone(startDirection);
- var endUp = Cartesian3.negate(startUp, new Cartesian3());
var duration = 5.0;
var flight = CameraFlightPath.createTween(scene, {
destination : endPosition,
- direction : endDirection,
- up : endUp,
duration : duration
});
flight.update({ time : 0.0 });
expect(camera.position).toEqualEpsilon(startPosition, CesiumMath.EPSILON12);
- expect(camera.direction).toEqualEpsilon(startDirection, CesiumMath.EPSILON12);
- expect(camera.up).toEqualEpsilon(startUp, CesiumMath.EPSILON12);
flight.update({ time : duration });
expect(camera.position).toEqualEpsilon(destination, CesiumMath.EPSILON4);
- expect(camera.direction).toEqualEpsilon(endDirection, CesiumMath.EPSILON12);
- expect(camera.up).toEqualEpsilon(endUp, CesiumMath.EPSILON12);
});
it('creates an animation in 2D', function() {
@@ -181,36 +158,26 @@ defineSuite([
var startHeight = camera.frustum.right - camera.frustum.left;
var startPosition = Cartesian3.clone(camera.position);
- var startDirection = Cartesian3.clone(camera.direction);
- var startUp = Cartesian3.clone(camera.up);
var projection = scene.mapProjection;
var destination = Cartesian3.add(startPosition, new Cartesian3(-6e6 * Math.PI, 6e6 * CesiumMath.PI_OVER_FOUR, 100.0), new Cartesian3());
var endPosition = projection.ellipsoid.cartographicToCartesian(projection.unproject(destination));
- var endDirection = Cartesian3.clone(startDirection);
- var endUp = Cartesian3.negate(startUp, new Cartesian3());
var duration = 5.0;
var flight = CameraFlightPath.createTween(scene, {
destination : endPosition,
- direction : endDirection,
- up : endUp,
duration : duration
});
flight.update({ time : 0.0 });
expect(camera.position).toEqualEpsilon(startPosition, CesiumMath.EPSILON12);
- expect(camera.direction).toEqualEpsilon(startDirection, CesiumMath.EPSILON12);
- expect(camera.up).toEqualEpsilon(startUp, CesiumMath.EPSILON12);
- expect(camera.frustum.right - camera.frustum.left).toEqual(startHeight);
+ expect(camera.frustum.right - camera.frustum.left).toEqualEpsilon(startHeight, CesiumMath.EPSILON7);
flight.update({ time : duration });
- expect(camera.position.x).toEqualEpsilon(destination.x, CesiumMath.EPSILON8);
- expect(camera.position.y).toEqualEpsilon(destination.y, CesiumMath.EPSILON8);
- expect(camera.position.z).toEqualEpsilon(startPosition.z, CesiumMath.EPSILON8);
- expect(camera.direction).toEqualEpsilon(endDirection, CesiumMath.EPSILON8);
- expect(camera.up).toEqualEpsilon(endUp, CesiumMath.EPSILON8);
- expect(camera.frustum.right - camera.frustum.left).toEqualEpsilon(destination.z, CesiumMath.EPSILON8);
+ expect(camera.position.x).toEqualEpsilon(destination.x, CesiumMath.EPSILON7);
+ expect(camera.position.y).toEqualEpsilon(destination.y, CesiumMath.EPSILON7);
+ expect(camera.position.z).toEqualEpsilon(startPosition.z, CesiumMath.EPSILON7);
+ expect(camera.frustum.right - camera.frustum.left).toEqualEpsilon(destination.z, CesiumMath.EPSILON7);
});
it('creates a path where the start and end points only differ in height', function() {
@@ -275,7 +242,7 @@ defineSuite([
expect(flight.update).toBeUndefined();
expect(scene.camera.position).not.toEqual(destination);
flight.complete();
- expect(scene.camera.position).toEqual(destination);
+ expect(scene.camera.position).toEqualEpsilon(destination, CesiumMath.EPSILON14);
});
it('duration is 0 when destination is the same as camera position in 2D', function() {
@@ -347,30 +314,25 @@ defineSuite([
camera.right = Cartesian3.cross(camera.direction, camera.up, new Cartesian3());
camera.frustum = createOrthographicFrustum();
+ camera.update(scene.mode);
+
+ var startHeight = camera.frustum.right - camera.frustum.left;
var startPosition = Cartesian3.clone(camera.position);
- var startDirection = Cartesian3.clone(camera.direction);
- var startUp = Cartesian3.clone(camera.up);
var projection = scene.mapProjection;
- var destination = Cartesian3.add(startPosition, new Cartesian3(-6e6 * Math.PI, 6e6 * CesiumMath.PI_OVER_FOUR, 100.0), new Cartesian3());
+ var destination = Cartesian3.add(startPosition, new Cartesian3(-6e5 * Math.PI, 6e5 * CesiumMath.PI_OVER_FOUR, 100.0), new Cartesian3());
var endPosition = projection.ellipsoid.cartographicToCartesian(projection.unproject(destination));
- var endDirection = Cartesian3.clone(startDirection);
- var endUp = Cartesian3.negate(startUp, new Cartesian3());
var flight = CameraFlightPath.createTween(scene, {
destination : endPosition,
- direction : endDirection,
- up : endUp,
duration : 0.0
});
expect(typeof flight.complete).toEqual('function');
flight.complete();
- expect(camera.position.x).toEqualEpsilon(destination.x, CesiumMath.EPSILON8);
- expect(camera.position.y).toEqualEpsilon(destination.y, CesiumMath.EPSILON8);
- expect(camera.direction).toEqualEpsilon(endDirection, CesiumMath.EPSILON8);
- expect(camera.up).toEqualEpsilon(endUp, CesiumMath.EPSILON8);
- expect(camera.frustum.right - camera.frustum.left).toEqualEpsilon(destination.z, CesiumMath.EPSILON8);
+ expect(camera.position.x).toEqualEpsilon(destination.x, CesiumMath.EPSILON7);
+ expect(camera.position.y).toEqualEpsilon(destination.y, CesiumMath.EPSILON7);
+ expect(camera.frustum.right - camera.frustum.left).toEqualEpsilon(destination.z, CesiumMath.EPSILON7);
});
it('creates an animation in Columbus view 0 duration', function() {
@@ -402,25 +364,16 @@ defineSuite([
var camera = scene.camera;
var startPosition = Cartesian3.clone(camera.position);
- var startDirection = Cartesian3.clone(camera.direction);
- var startUp = Cartesian3.clone(camera.up);
-
var endPosition = Cartesian3.negate(startPosition, new Cartesian3());
- var endDirection = Cartesian3.negate(startDirection, new Cartesian3());
- var endUp = Cartesian3.negate(startUp, new Cartesian3());
var flight = CameraFlightPath.createTween(scene, {
destination : endPosition,
- direction : endDirection,
- up : endUp,
duration : 0.0
});
expect(typeof flight.complete).toEqual('function');
flight.complete();
expect(camera.position).toEqualEpsilon(endPosition, CesiumMath.EPSILON12);
- expect(camera.direction).toEqualEpsilon(endDirection, CesiumMath.EPSILON12);
- expect(camera.up).toEqualEpsilon(endUp, CesiumMath.EPSILON12);
});
});
diff --git a/Specs/Scene/CameraSpec.js b/Specs/Scene/CameraSpec.js
index 79a3beec4f59..dc55b83e03fc 100644
--- a/Specs/Scene/CameraSpec.js
+++ b/Specs/Scene/CameraSpec.js
@@ -1031,7 +1031,7 @@ defineSuite([
var target = Cartesian3.fromDegrees(0.0, 0.0);
var offset = new Cartesian3(0.0, -1.0, 0.0);
- var tempCamera = camera.clone();
+ var tempCamera = Camera.clone(camera);
tempCamera.lookAt(target, offset);
expect(tempCamera.position).toEqualEpsilon(offset, CesiumMath.EPSILON11);
@@ -1050,7 +1050,7 @@ defineSuite([
var pitch = CesiumMath.toRadians(-45.0);
var range = 2.0;
- var tempCamera = camera.clone();
+ var tempCamera = Camera.clone(camera);
tempCamera.lookAt(target, new HeadingPitchRange(heading, pitch, range));
tempCamera.lookAtTransform(Matrix4.IDENTITY);
@@ -1085,7 +1085,7 @@ defineSuite([
frustum.top = 1.0;
frustum.bottom = -1.0;
- var tempCamera = camera.clone();
+ var tempCamera = Camera.clone(camera);
tempCamera.frustum = frustum;
tempCamera.update(SceneMode.SCENE2D);
@@ -1110,7 +1110,7 @@ defineSuite([
frustum.top = 1.0;
frustum.bottom = -1.0;
- var tempCamera = camera.clone();
+ var tempCamera = Camera.clone(camera);
tempCamera.frustum = frustum;
tempCamera.update(SceneMode.SCENE2D);
@@ -1143,7 +1143,7 @@ defineSuite([
var offset = new Cartesian3(1.0, 1.0, 0.0);
var transform = Transforms.eastNorthUpToFixedFrame(target, Ellipsoid.UNIT_SPHERE);
- var tempCamera = camera.clone();
+ var tempCamera = Camera.clone(camera);
tempCamera.lookAtTransform(transform, offset);
expect(tempCamera.position).toEqualEpsilon(offset, CesiumMath.EPSILON11);
@@ -1185,7 +1185,7 @@ defineSuite([
var range = 2.0;
var transform = Transforms.eastNorthUpToFixedFrame(target);
- var tempCamera = camera.clone();
+ var tempCamera = Camera.clone(camera);
tempCamera.lookAtTransform(transform, new HeadingPitchRange(heading, pitch, range));
tempCamera.lookAtTransform(Matrix4.IDENTITY);
@@ -1214,7 +1214,7 @@ defineSuite([
frustum.top = 1.0;
frustum.bottom = -1.0;
- var tempCamera = camera.clone();
+ var tempCamera = Camera.clone(camera);
tempCamera.frustum = frustum;
tempCamera.update(SceneMode.SCENE2D);
@@ -1239,7 +1239,7 @@ defineSuite([
frustum.top = 1.0;
frustum.bottom = -1.0;
- var tempCamera = camera.clone();
+ var tempCamera = Camera.clone(camera);
tempCamera.frustum = frustum;
tempCamera.update(SceneMode.SCENE2D);
@@ -1959,13 +1959,16 @@ defineSuite([
var expectedOptions = {
destination : options.destination,
- direction : undefined,
- up : undefined,
+ heading : undefined,
+ pitch : undefined,
+ roll : undefined,
duration : undefined,
complete : undefined,
cancel : undefined,
endTransform : undefined,
- convert : undefined
+ convert : undefined,
+ maximumHeight : undefined,
+ easingFunction : undefined
};
expect(CameraFlightPath.createTween).toHaveBeenCalledWith(scene, expectedOptions);
diff --git a/Specs/Scene/SceneTransformsSpec.js b/Specs/Scene/SceneTransformsSpec.js
index 1c19dd9cc26c..5e707bb792e7 100644
--- a/Specs/Scene/SceneTransformsSpec.js
+++ b/Specs/Scene/SceneTransformsSpec.js
@@ -5,6 +5,7 @@ defineSuite([
'Core/Cartesian3',
'Core/Ellipsoid',
'Core/Math',
+ 'Scene/Camera',
'Specs/createScene'
], function(
SceneTransforms,
@@ -12,6 +13,7 @@ defineSuite([
Cartesian3,
Ellipsoid,
CesiumMath,
+ Camera,
createScene) {
"use strict";
/*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn*/
@@ -21,7 +23,7 @@ defineSuite([
beforeAll(function() {
scene = createScene();
- defaultCamera = scene.camera.clone();
+ defaultCamera = Camera.clone(scene.camera);
});
afterAll(function() {