Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Flyto options #5070

Merged
merged 12 commits into from
Mar 13, 2017
75 changes: 68 additions & 7 deletions Apps/Sandcastle/gallery/Camera.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<body class="sandcastle-loading" data-sandcastle-bucket="bucket-requirejs.html">
<style>
@import url(../templates/bucket.css);

#viewChanged, #cameraChanged {
display: none;
background-color: red;
Expand Down Expand Up @@ -141,7 +141,7 @@

function setHeadingPitchRoll() {
Sandcastle.declare(setHeadingPitchRoll);

var camera = viewer.camera;
camera.setView({
destination : Cesium.Cartesian3.fromDegrees(-75.5847, 40.0397, 1000.0),
Expand Down Expand Up @@ -171,7 +171,7 @@
Sandcastle.declare(viewInICRF);

viewer.camera.flyHome(0);

clock.multiplier = 3 * 60 * 60;
scene.preRender.addEventListener(icrf);
scene.globe.enableLighting = true;
Expand All @@ -184,7 +184,7 @@

function cameraEvents() {
Sandcastle.declare(cameraEvents);

var camera = viewer.camera;
removeStart = camera.moveStart.addEventListener(function() {
viewChanged.style.display = 'block';
Expand All @@ -211,7 +211,7 @@

function flyInACity() {
Sandcastle.declare(flyInACity);

var camera = scene.camera;
camera.flyTo({
destination : Cesium.Cartesian3.fromDegrees(-73.98580932617188, 40.74843406689482, 363.34038727246224),
Expand All @@ -230,6 +230,54 @@
});
}

function losAngelesToTokyo(adjustPitch) {
var camera = scene.camera;

var tokyoOptions = {
destination : Cesium.Cartesian3.fromDegrees(139.8148, 35.7142, 20000.0),
orientation: {
heading : Cesium.Math.toRadians(15.0),
pitch : Cesium.Math.toRadians(-60),
roll : 0.0
},
duration: 20,
flyOverLongitude: Cesium.Math.toRadians(60.0)
};

var laOptions = {
destination : Cesium.Cartesian3.fromDegrees(-117.729, 34.457, 10000.0),
duration: 5,
orientation: {
heading : Cesium.Math.toRadians(-15.0),
pitch : -Cesium.Math.PI_OVER_FOUR,
roll : 0.0
}
};

laOptions.complete = function() {
setTimeout(function() {
camera.flyTo(tokyoOptions);
}, 1000);
};

if (adjustPitch) {
tokyoOptions.pitchAdjustHeight = 1000;
laOptions.pitchAdjustHeight = 1000;
}

camera.flyTo(laOptions);
}

function flyOverLongitude(adjustPitch) {
Sandcastle.declare(flyOverLongitude);
losAngelesToTokyo();
}

function flyOverLongitudeWithPitch() {
Sandcastle.declare(flyOverLongitudeWithPitch);
losAngelesToTokyo(true);
}

Sandcastle.addToolbarMenu([{
text : 'Camera Options'
}, {
Expand Down Expand Up @@ -298,7 +346,20 @@
cameraChanges();
Sandcastle.highlight(cameraChanges);
}
}]);
}, {
text : 'Fly from Los Angeles to Tokyo via Europe',
onselect : function() {
flyOverLongitude();
Sandcastle.highlight(flyOverLongitude);
}
}, {
text : 'Look down during exaggerated flight',
onselect : function() {
flyOverLongitudeWithPitch();
Sandcastle.highlight(flyOverLongitudeWithPitch);
}
}
]);

Sandcastle.reset = function() {
scene.completeMorph();
Expand All @@ -311,7 +372,7 @@
removeEnd();

viewChanged.style.display = 'none';

removeStart = undefined;
removeEnd = undefined;
}
Expand Down
4 changes: 4 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ Change Log

### 1.32 - 2017-04-03

* Added `Camera.flyTo` and `Camera.flyToBoundingSphere` options [#5070](https://github.com/AnalyticalGraphicsInc/cesium/pull/5070)
* `flyOverLongitude` to select one of two possible on Globe paths which camera should fly.
* `flyOverLongitudeWeight` to set a threshold: how many times the `flyOverLongitude` way can be than shortest path.
* `pitchAdjustHeight` to adjust camera pitch during exaggerated flights, to keep Earth in viewport.
* Added the event `Viewer.trackedEntityChanged`, which is raised when the value of `viewer.trackedEntity` changes. [#5060](https://github.com/AnalyticalGraphicsInc/cesium/pull/5060)
* Added `Camera.DEFAULT_OFFSET` for default view of objects with bounding spheres [#4936](https://github.com/AnalyticalGraphicsInc/cesium/pull/4936)
* Fix crunch compressed textures in IE11. [#5057](https://github.com/AnalyticalGraphicsInc/cesium/pull/5057)
Expand Down
16 changes: 14 additions & 2 deletions Source/Scene/Camera.js
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ define([
Camera.DEFAULT_VIEW_FACTOR = 0.5;

/**
* The default heading/pitch/range that is used when the camera flies to a location that contains a bounding sphere.
* The default heading/pitch/range that is used when the camera flies to a location that contains a bounding sphere.
* @type HeadingPitchRange
*/
Camera.DEFAULT_OFFSET = new HeadingPitchRange(0.0, -CesiumMath.PI_OVER_FOUR, 0.0);
Expand Down Expand Up @@ -2570,6 +2570,9 @@ define([
* @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 {Number} [options.pitchAdjustHeight] If camera flyes higher than that value, adjust pitch duiring the flight to look down, and keep Earth in viewport.
* @param {Number} [options.flyOverLongitude] There are always two ways between 2 points on globe. This option force camera to choose fight direction to fly over that longitude.
* @param {Number} [options.flyOverLongitudeWeight] Fly over the lon specifyed via flyOverLongitude only if that way is not longer than short way times flyOverLongitudeWeight.
* @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.
Expand Down Expand Up @@ -2665,6 +2668,9 @@ define([
newOptions.endTransform = options.endTransform;
newOptions.convert = isRectangle ? false : options.convert;
newOptions.maximumHeight = options.maximumHeight;
newOptions.pitchAdjustHeight = options.pitchAdjustHeight;
newOptions.flyOverLongitude = options.flyOverLongitude;
newOptions.flyOverLongitudeWeight = options.flyOverLongitudeWeight;
newOptions.easingFunction = options.easingFunction;

var scene = this._scene;
Expand Down Expand Up @@ -2778,6 +2784,9 @@ define([
* @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 {Number} [options.pitchAdjustHeight] If camera flyes higher than that value, adjust pitch duiring the flight to look down, and keep Earth in viewport.
* @param {Number} [options.flyOverLongitude] There are always two ways between 2 points on globe. This option force camera to choose fight direction to fly over that longitude.
* @param {Number} [options.flyOverLongitudeWeight] Fly over the lon specifyed via flyOverLongitude only if that way is not longer than short way times flyOverLongitudeWeight.
* @param {EasingFunction|EasingFunction~Callback} [options.easingFunction] Controls how the time is interpolated over the duration of the flight.
*/
Camera.prototype.flyToBoundingSphere = function(boundingSphere, options) {
Expand Down Expand Up @@ -2835,7 +2844,10 @@ define([
cancel : options.cancel,
endTransform : options.endTransform,
maximumHeight : options.maximumHeight,
easingFunction : options.easingFunction
easingFunction : options.easingFunction,
flyOverLongitude : options.flyOverLongitude,
flyOverLongitudeWeight : options.flyOverLongitudeWeight,
pitchAdjustHeight : options.pitchAdjustHeight
});
};

Expand Down
134 changes: 109 additions & 25 deletions Source/Scene/CameraFlightPath.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,31 @@ define([
var scratchCart = new Cartesian3();
var scratchCart2 = new Cartesian3();

function createPitchFunction(startPitch, endPitch, heightFunction, pitchAdjustHeight) {
if (defined(pitchAdjustHeight) && heightFunction(0.5) > pitchAdjustHeight) {
var startHeight = heightFunction(0.0);
var endHeight = heightFunction(1.0);
var middleHeight = heightFunction(0.5);

var d1 = middleHeight - startHeight;
var d2 = middleHeight - endHeight;

return function(time) {
var altitude = heightFunction(time);
if (time <= 0.5) {
var t1 = (altitude - startHeight) / d1;
return CesiumMath.lerp(startPitch, -CesiumMath.PI_OVER_TWO, t1);
}

var t2 = (altitude - endHeight) / d2;
return CesiumMath.lerp(-CesiumMath.PI_OVER_TWO, endPitch, 1 - t2);
};
}
return function(time) {
return CesiumMath.lerp(startPitch, endPitch, time);
};
}

function createHeightFunction(camera, destination, startHeight, endHeight, optionAltitude) {
var altitude = optionAltitude;
var maxHeight = Math.max(startHeight, endHeight);
Expand Down Expand Up @@ -137,10 +162,27 @@ define([
return update;
}

function useLongestFlight(startCart, destCart) {
if (startCart.longitude < destCart.longitude) {
startCart.longitude += CesiumMath.TWO_PI;
} else {
destCart.longitude += CesiumMath.TWO_PI;
}
}

function useShortestFlight(startCart, destCart) {
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;
}
}

var scratchStartCart = new Cartographic();
var scratchEndCart = new Cartographic();

function createUpdate3D(scene, duration, destination, heading, pitch, roll, optionAltitude) {
function createUpdate3D(scene, duration, destination, heading, pitch, roll, optionAltitude, optionFlyOverLongitude, optionFlyOverLongitudeWeight, optionPitchAdjustHeight) {
var camera = scene.camera;
var projection = scene.mapProjection;
var ellipsoid = projection.ellipsoid;
Expand All @@ -154,34 +196,73 @@ define([
startCart.longitude = CesiumMath.zeroToTwoPi(startCart.longitude);
destCart.longitude = CesiumMath.zeroToTwoPi(destCart.longitude);

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;
}
var useLongFlight = false;

var heightFunction = createHeightFunction(camera, destination, startCart.height, destCart.height, optionAltitude);
if (defined(optionFlyOverLongitude)) {
var hitLon = CesiumMath.zeroToTwoPi(optionFlyOverLongitude);

function update(value) {
var time = value.time / duration;
var lonMin = Math.min(startCart.longitude, destCart.longitude);
var lonMax = Math.max(startCart.longitude, destCart.longitude);

var position = Cartesian3.fromRadians(
CesiumMath.lerp(startCart.longitude, destCart.longitude, time),
CesiumMath.lerp(startCart.latitude, destCart.latitude, time),
heightFunction(time)
);
var hitInside = (hitLon >= lonMin && hitLon <= lonMax);

camera.setView({
destination : position,
orientation: {
heading : CesiumMath.lerp(startHeading, heading, time),
pitch : CesiumMath.lerp(startPitch, pitch, time),
roll : CesiumMath.lerp(startRoll, roll, time)
if (defined(optionFlyOverLongitudeWeight)) {
// Distance inside (0...2Pi)
var din = Math.abs(startCart.longitude - destCart.longitude);
// Distance outside (0...2Pi)
var dot = CesiumMath.TWO_PI - din;

var hitDistance = hitInside ? din : dot;
var offDistance = hitInside ? dot : din;

if (hitDistance < offDistance * optionFlyOverLongitudeWeight && !hitInside) {
useLongFlight = true;
}
});
} else if (!hitInside) {
useLongFlight = true;
}
}
return update;

if (useLongFlight) {
useLongestFlight(startCart, destCart);
} else {
useShortestFlight(startCart, destCart);
}

var heightFunction = createHeightFunction(camera, destination, startCart.height, destCart.height, optionAltitude);
var pitchFunction = createPitchFunction(startPitch, pitch, heightFunction, optionPitchAdjustHeight);

// Isolate scope for update function.
// to have local copies of vars used in lerp
// Othervise, if you call nex
// createUpdate3D (createAnimationTween)
// before you played animation, variables will be overwriten.
function isolateUpdateFunction() {
var startLongitude = startCart.longitude;
var destLongitude = destCart.longitude;
var startLatitude = startCart.latitude;
var destLatitude = destCart.latitude;

return function update(value) {
var time = value.time / duration;

var position = Cartesian3.fromRadians(
CesiumMath.lerp(startLongitude, destLongitude, time),
CesiumMath.lerp(startLatitude, destLatitude, time),
heightFunction(time)
);

camera.setView({
destination : position,
orientation: {
heading : CesiumMath.lerp(startHeading, heading, time),
pitch : pitchFunction(time),
roll : CesiumMath.lerp(startRoll, roll, time)
}
});
};
}
return isolateUpdateFunction();
}

function createUpdate2D(scene, duration, destination, heading, pitch, roll, optionAltitude) {
Expand Down Expand Up @@ -264,6 +345,9 @@ define([
var projection = scene.mapProjection;
var ellipsoid = projection.ellipsoid;
var maximumHeight = options.maximumHeight;
var flyOverLongitude = options.flyOverLongitude;
var flyOverLongitudeWeight = options.flyOverLongitudeWeight;
var pitchAdjustHeight = options.pitchAdjustHeight;
var easingFunction = options.easingFunction;

if (convert && mode !== SceneMode.SCENE3D) {
Expand Down Expand Up @@ -318,7 +402,7 @@ define([

if (duration <= 0.0) {
var newOnComplete = function() {
var update = updateFunctions[mode](scene, 1.0, destination, heading, pitch, roll, maximumHeight);
var update = updateFunctions[mode](scene, 1.0, destination, heading, pitch, roll, maximumHeight, flyOverLongitude, flyOverLongitudeWeight, pitchAdjustHeight);
update({ time: 1.0 });

if (typeof complete === 'function') {
Expand All @@ -328,7 +412,7 @@ define([
return emptyFlight(newOnComplete, cancel);
}

var update = updateFunctions[mode](scene, duration, destination, heading, pitch, roll, maximumHeight);
var update = updateFunctions[mode](scene, duration, destination, heading, pitch, roll, maximumHeight, flyOverLongitude, flyOverLongitudeWeight, pitchAdjustHeight);

if (!defined(easingFunction)) {
var startHeight = camera.positionCartographic.height;
Expand Down
Loading