Skip to content

Commit

Permalink
Merge pull request #5070 from kiselev-dv/flyto-options
Browse files Browse the repository at this point in the history
Flyto options
  • Loading branch information
bagnell authored Mar 13, 2017
2 parents e21278b + 29f351b commit 33f3c6f
Show file tree
Hide file tree
Showing 6 changed files with 379 additions and 34 deletions.
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

0 comments on commit 33f3c6f

Please sign in to comment.