Pan toward pointer while changing range with mousewheel

(ENU=EastNorthUp frame, HPR=HeadingPitchRoll)

Currently pointer location has no bearing when using mousewheel to change altitude. It seems most map services do take into account the pointer position. You’ll notice that the lat/lon under the pointer is constant when changing altitude. Even Google Maps in Earth mode does this at low altitudes (but only approximately at high altitudes.)

Cesium already has functions that can determine the lat/lon under the pointer. Some possible methods:

Method 1: keeps target on the same part of the screen but doesn’t maintain ENU HPR

-Simply move the camera.position in a straight line in Earth-Fixed Cartesian toward that point.

-While maintaining Earth-Fixed HPR, not ENU HPR (basically keep camera.direction,camera.right,camera,up vectors constant.)

Method 2: keeps ENU HPR but doesn’t keep target on the same part of the screen

-Simply move the camera.position in a straight line in Earth-Fixed Cartesian toward that point.

-While maintaining ENU HPR.

-Problem: the lat/lon under the pointer will keep shifting

Method 3: keeps ENU HPR and keeps target on the same part of the screen

Probably involves moving the camera along a bizarre curve. If the other methods don’t ‘pan out’ the logic for this method should probably be pursued.

Method1 was not only easy to implement (well repetitive adding a parameter to a bunch of functions) but has good results!

Scene/ScreenSpaceCameraController.js function zoom3D

First off base ray off of the pointer location, not the center of the screen

//var ray = camera.getPickRay(windowPosition, zoomCVWindowRay);
var ray = camera.getPickRay(startPosition, zoomCVWindowRay);

``

Second make sure intersection is actually calculated

if(1) //(defined(controller._globe) && height < controller.minimumPickingTerrainHeight)
{
intersection = controller._globe.pick(ray, scene, zoomCVIntersection);
}

``

Introduce a new parameter ray at the end

handleZoom(controller, startPosition, movement, controller._zoomFactor, distance, Cartesian3.dot(unitPosition, camera.direction),ray);

``

Scene/ScreenSpaceCameraController.js function handleZoom

Introduce a new parameter ray at the end

function handleZoom(object, startPosition, movement, zoomFactor, distanceMeasure, unitPositionDotDirection,ray) {

``

Introduce a new parameter ray at the end

object._scene.camera.zoomIn(distance,ray);

``

Scene/Camera.js function Camera.prototype.zoomIn

Introduce a new parameter ray at the end

Camera.prototype.zoomIn = function(amount,ray) {

``

Introduce a new parameter ray at the end
zoom3D(this, amount,ray);

``

Scene/Camera.js function Camera.prototype.zoomIn

Re-write this function as follows

function zoom3D(camera, amount,ray) {

if(defined(ray))
{
camera.move(ray.direction,amount);
}
else
{camera.move(camera.direction, amount);}
}

``

I’ll add some videos showing how well it works.

1 Like

Actually it doesn’t matter about intersection, what matters is changing how ray is created
//var ray = camera.getPickRay(windowPosition, zoomCVWindowRay);
var ray = camera.getPickRay(startPosition, zoomCVWindowRay);

``

And passing ray to the various functions (just it’s direction property is used.)

Here’s a video of it in action

Hyper,

That looks pretty awesome. Any plans on opening a PR to get this into Cesium proper? I know you’ve had a lot of other ideas too and I don’t want to see them go to waste.

Thanks,

Matt

Thanks for the comments Matt, I appreciate it!

The video demonstrates method 1 that I wrote about earlier. It is a simple method that works well as long as you don’t mind a roll angle in the ENU frame being introduced. Though the camera’s orientation remains fixed relative to the world Earth frame, it is changing all 3 HPR angles in the ENU frame for each location traveled through.

Actually while writing this and trying it again something just occurred to me. After zooming toward a point, to retain a local ENU 0 roll, spin the camera around the vector that the camera traveled along so that roll is back to 0. This will keep that point you’re zooming to on the same point on the screen while retaining 0 roll. This isn’t quite the same as method 3 (which retains all 3 HPR) but it should go well with Cesium’s 0 roll control system using the 2D mouse. If this works well in practice I’ll be sure to place it into a PR for Cesium.

When you double-click a point on the ground in National Map, it zooms in and moves that point to the center of the screen. Try it here:

http://nationalmap.nicta.com.au/

I think this can be generalized to mouse-wheel zooming, and I’ve had it on my to-do list forever to do that and incorporate it into Cesium itself. I’m not sure when I’ll get to that, but here’s the code in case it helps anyone in the meantime:

https://github.com/NICTA/nationalmap/blob/b472cc9248ec7f8db4be308a19843b7c34b946b5/src/viewer/AusGlobeViewer.js#L509

Kevin

Double-clicking to put the point under the pointer to the center of the screen while zooming is a very useful feature! I noticed you can hold shift to reverse the zoom direction. I hope it becomes a part of Cesium as well.

Though for mouse-wheel it would be nice to adopt the convention of keeping the point under the pointer at the same part of the screen while zooming. Though most of these map engines (like OSM and MapQuest) use 2D orthographic projection, Google Maps in Earth mode which is perspective projection does this as well (except at very high altitudes.) This pans toward that point, but not all the way there so that it’s moved to the center. People sometimes use it just to pan around a little while the zooming.

I don't know if its the correct place to post an issue regarding the mouse wheel zooming in the pointer direction. If I'm wrong, I apologize. I've noticed that current implementation (1.13) will tilt the camera if mouse pointer is not centered on the Earth (even if tilt is disabled in ScrenSpaceTransform). To reproduce it:
1) Center on Europe
2) Zoom in on Siberia with mouse wheel
3) Zoom out and you will notice that the whole earth is tilted (north pole not looking up anymore)

Any hint for avoiding this?

Bests,

Josef

Hello,

Sorry, I don’t think there is any way around this behavior. We’ve generally had really positive feedback about the new zooming functionality, but we’ll take a look at it if other users find this to be a problem.

Best,

Hannah