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

added zoom algorithm that better maintains target point in 3D #4016

Merged
merged 7 commits into from
Jun 28, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Change Log
* Fix "Cannot read property 'x' of undefined" error when calling SceneTransforms.wgs84ToWindowCoordinates in certain cases. [#4022](https://github.com/AnalyticalGraphicsInc/cesium/pull/4022)
* Exposed a parametric ray-triangle intersection test to the API as `IntersectionTests.rayTriangleParametric`.
* Added `unsupportedNodeEvent` to `KmlDataSource` that is fired whenever an unsupported node is encountered.
* Zooming in toward some target point now keeps the target point at the same screen position. [#4016](https://github.com/AnalyticalGraphicsInc/cesium/pull/4016)


### 1.22.2 - 2016-06-14
Expand Down
4 changes: 3 additions & 1 deletion CONTRIBUTORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for details on how to contribute to Cesiu
* [Sergio Flores](https://github.com/relfos)
* [CubeWerx Inc.](http://www.cubewerx.com/)
* [Keith Pomakis](https://github.com/pomakis)
* [Vricon](https://www.vricon.com/)
* [Erik Andersson](https://github.com/e-andersson)

## [Individual CLA](http://www.agi.com/licenses/individual-cla-agi-v1.0.txt)
* [Victor Berchet](https://github.com/vicb)
Expand Down Expand Up @@ -94,4 +96,4 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for details on how to contribute to Cesiu
* [Mati Ostrovsky](https://github.com/mati-o)
* [Tom Novacek](https://github.com/novacto2)
* [Olivier Guyot-Roullot](https://github.com/theOgrable)
* [Dave Whipps](https://github.com/dwhipps)
* [Dave Whipps](https://github.com/dwhipps)
106 changes: 105 additions & 1 deletion Source/Scene/ScreenSpaceCameraController.js
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,21 @@ define([
var scratchZoomAxis = new Cartesian3();
var scratchCameraPositionNormal = new Cartesian3();

// Scratch variables used in zooming algorithm
var scratchTargetNormal = new Cartesian3();
var scratchCameraPosition = new Cartesian3();
var scratchCameraUpNormal = new Cartesian3();
var scratchCameraRightNormal = new Cartesian3();
var scratchForwardNormal = new Cartesian3();
var scratchPositionToTarget = new Cartesian3();
var scratchPositionToTargetNormal = new Cartesian3();
var scratchPan = new Cartesian3();
var scratchCenterMovement = new Cartesian3();
var scratchCenter = new Cartesian3();
var scratchCartesian = new Cartesian3();
var scratchCartesianTwo = new Cartesian3();
var scratchCartesianThree = new Cartesian3();

function handleZoom(object, startPosition, movement, zoomFactor, distanceMeasure, unitPositionDotDirection) {
var percentage = 1.0;
if (defined(unitPositionDotDirection)) {
Expand Down Expand Up @@ -492,6 +507,10 @@ define([

var zoomOnVector = mode === SceneMode.COLUMBUS_VIEW;

if (camera.positionCartographic.height < 2000000) {
rotatingZoom = true;
}

if (!sameStartPosition || rotatingZoom) {
if (mode === SceneMode.SCENE2D) {
var worldPosition = object._zoomWorldPosition;
Expand Down Expand Up @@ -522,7 +541,92 @@ define([
centerPixel.x = canvas.clientWidth / 2;
centerPixel.y = canvas.clientHeight / 2;
var centerPosition = pickGlobe(object, centerPixel, scratchCenterPosition);
if (defined(centerPosition)) {
// If centerPosition is not defined, it means the globe does not cover the center position of screen

if (defined(centerPosition) && camera.positionCartographic.height < 1000000) {

var cameraPosition = scratchCameraPosition;
Cartesian3.clone(camera.position, cameraPosition);
var target = object._zoomWorldPosition;

var targetNormal = scratchTargetNormal;

targetNormal = Cartesian3.normalize(target, targetNormal);

if (Cartesian3.dot(targetNormal, cameraPositionNormal) < 0.0) {
return;
}

var center = scratchCenter;
var forward = scratchForwardNormal;
Cartesian3.clone(camera.direction, forward);
Cartesian3.add(cameraPosition, Cartesian3.multiplyByScalar(forward, 1000, scratchCartesian), center);


var positionToTarget = scratchPositionToTarget;
var positionToTargetNormal = scratchPositionToTargetNormal;
Cartesian3.subtract(target, cameraPosition, positionToTarget);

Cartesian3.normalize(positionToTarget, positionToTargetNormal);

var alpha = Math.acos( -Cartesian3.dot( cameraPositionNormal, positionToTargetNormal ) );
var cameraDistance = Cartesian3.magnitude( cameraPosition );
var targetDistance = Cartesian3.magnitude( target );
var remainingDistance = cameraDistance - distance;
var positionToTargetDistance = Cartesian3.magnitude(positionToTarget);

var gamma = Math.asin( CesiumMath.clamp( positionToTargetDistance / targetDistance * Math.sin(alpha), -1.0, 1.0 ) );
var delta = Math.asin( CesiumMath.clamp( remainingDistance / targetDistance * Math.sin(alpha), -1.0, 1.0 ) );
var beta = gamma - delta + alpha;

var up = scratchCameraUpNormal;
Cartesian3.normalize(cameraPosition, up);
var right = scratchCameraRightNormal;
right = Cartesian3.cross(positionToTargetNormal, up, right);
right = Cartesian3.normalize(right, right );

Cartesian3.normalize( Cartesian3.cross(up, right, scratchCartesian), forward );

// Calculate new position to move to
Cartesian3.multiplyByScalar(Cartesian3.normalize(center, scratchCartesian), (Cartesian3.magnitude(center) - distance), center);
Cartesian3.normalize(cameraPosition, cameraPosition);
Cartesian3.multiplyByScalar(cameraPosition, remainingDistance, cameraPosition);

// Pan
var pMid = scratchPan;
Cartesian3.multiplyByScalar(Cartesian3.add(
Cartesian3.multiplyByScalar(up, Math.cos(beta) - 1, scratchCartesianTwo),
Cartesian3.multiplyByScalar(forward, Math.sin(beta), scratchCartesianThree),
scratchCartesian
), remainingDistance, pMid);
Cartesian3.add(cameraPosition, pMid, cameraPosition);

Cartesian3.normalize(center, up);
Cartesian3.normalize( Cartesian3.cross(up, right, scratchCartesian), forward );

var cMid = scratchCenterMovement;
Cartesian3.multiplyByScalar(Cartesian3.add(
Cartesian3.multiplyByScalar(up, Math.cos(beta) - 1, scratchCartesianTwo),
Cartesian3.multiplyByScalar(forward, Math.sin(beta), scratchCartesianThree),
scratchCartesian
), Cartesian3.magnitude(center), cMid);
Cartesian3.add(center, cMid, center);

// Update camera

// Set new position
Cartesian3.clone(cameraPosition, camera.position);

// Set new direction
Cartesian3.normalize(Cartesian3.subtract(center, cameraPosition, scratchCartesian), camera.direction);
Cartesian3.clone(camera.direction, camera.direction);

// Set new right & up vectors
Cartesian3.cross(camera.direction, camera.up, camera.right);
Cartesian3.cross(camera.right, camera.direction, camera.up);

return;
} else if (defined(centerPosition)) {
var positionNormal = Cartesian3.normalize(centerPosition, scratchPositionNormal);
var pickedNormal = Cartesian3.normalize(object._zoomWorldPosition, scratchPickNormal);
var dotProduct = Cartesian3.dot(pickedNormal, positionNormal);
Expand Down