-
Notifications
You must be signed in to change notification settings - Fork 301
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
feat(globeControls): zoom on mouse position while using wheel #2041
Conversation
From what i understand of this PR, the purpose is that when you zoom in or out, the terrain under the mouse should always stay the same. I tried this PR on a globe view. I noticed that zooming in on the mouse position seems to work when you are at close range but not at all when you are far enought and the zoom out never stay at the mouse position. |
Thanks for the feedback. I use zoom coordinates interpolated between the mouse position and the camera position that's why we don't go directly to the mouse position. This allows us to have a smoother transition. The behaviour is similar to the globe view of Google Maps. This alpha parameter (interpolation factor) is fixed but depending on feedback, could be edited before release. Concerning the zoom out, the factor is different (dezoom_interp) to avoid brutal rotation while zooming out. Same as alpha, this could be edited before release. I could even make these values as parameters of globecontrols, then the user could decide of the zoom behaviour. |
@ftoromanoff @AnthonyGlt @jailln I think it would be great to integrate it in iTowns. Also for navigation under the ground or in hidden globe mode. |
With your PR, the target position doesn't stay under the mouse cursor. cursor.mp4In the same condition with google earth, the target position stay under the cursor and doesn't come out of the screen. cursorgoogleearth.mp4 |
I was referring to Google Maps (cf attached record). If this isn't an appropriate solution, an alternative could be implemented to have a similar zoom as Google Earth instead. Currenctly, I used a bit of a mix of the zoom function from the planarControls (interpolation) and the double click zoom from the globeControls (travel -> lookAtCoordinate). map.mp4 |
it's good feature that improves the user experience. |
It's now implemented. I store the coordinates when the wheel button is clicked to zoom at the precise mouse location. But it's not really a "dolly" anymore. dolly.mp4 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Your PR is good way to add this feature
In the future we will have to think about how to solve the issue of the pointer shift when zooming.
This issue is accentuated when the zoomFactor
is increased
src/Controls/GlobeControls.js
Outdated
if (camPos.x * point.x < 0) { // Correct rotation at 180th meridian by using 0 <= longitude <=360 | ||
if (camPos.x - point.x > 180) { point.x += 360; } else if (point.x - camPos.x > 180) { camPos.x += 360; } | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a lookAtCoordinate
issue, it's not support a correct rotation at 180th meridian by using 0 <= longitude <=360
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No it's for the lerp method (interpolation). At the 180th meridian, we have values going from -179 to 179 (-179, -180/180, 179). So when interpolating a value between, for example, -170 and 172, we will obtain a value of 1 instead of the expecting -179.
To avoid that, I add 360 (to keep the same value modulo 360) and interpolate on positive values only. Then I substract the 360 to get the value back between -180 and 180.
src/Controls/GlobeControls.js
Outdated
// Store first position of mouse when dolly | ||
if (!dollyOrigin) { | ||
dollyOrigin = this.view.getPickingPositionFromDepth(event.viewCoords); // mouse position | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could you use pickedPosition
instead of dollyOrigin
, it seems to have a duplicate use
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes you're right, I could use pickedPosition
.
this.view.getPickingPositionFromDepth(event.viewCoords, pickedPosition); // mouse position
But I need something to know if I'm doing a dolly (cf next comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
StateControl
should handle dolly state?
src/Controls/GlobeControls.js
Outdated
this.updateTarget(); | ||
const delta = -event.delta; | ||
this.dolly(delta); | ||
var point = dollyOrigin ?? this.view.getPickingPositionFromDepth(event.viewCoords); // mouse position |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a case where the dollyOrigin
is null
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could you rename point
with explicit name, pickedPoint
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If dolly, then I don't update pickedPoint
value. So I can use a boolean instead of dollyOrigin
. What do you think ?
var point = dollyOrigin ?? this.view.getPickingPositionFromDepth(event.viewCoords); // mouse position | |
var pickedPoint = dollyFlag ? pickedPosition : this.view.getPickingPositionFromDepth(event.viewCoords); // mouse position |
src/Controls/GlobeControls.js
Outdated
@@ -759,26 +770,36 @@ class GlobeControls extends THREE.EventDispatcher { | |||
} | |||
} | |||
|
|||
handleZoom(event) { | |||
handleZoom(event, dollyOrigin) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't remember if there's a change of state for the zoom?
to handle the state zoom
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no state change for the zoom. I need to disguish between a regular zoom and a dolly one. Maybe I could
handleZoom(event, dollyOrigin) { | |
handleZoom(event, dollyFlag) { |
with dollyFlag
used to know if I need to update pickedPosition
value
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no state change for the zoom. I need to disguish between a regular zoom and a dolly one. Maybe I could
This would seem to confirm that StateControl
should manage its two states?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in my last commit, i've used directly the event type to distinguish between the 2 zoom
@Desplandis rebased 👍 |
6b70062
to
c55cd1e
Compare
@Desplandis rebased 👍 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi ! Thanks for the improvement on zoom ! There is just one functional issue and a few remarks on form listed in my review.
Also, when you'll rebase your commits, could you add a breaking change note in the commit message ?
src/Controls/GlobeControls.js
Outdated
} | ||
point.lerp( // point interpol between mouse cursor and cam pos | ||
camPos, | ||
(event.delta > 0 ? this.zoomInScale : this.zoomOutScale), // interpol factor |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could directly use zoomScale
defined on line 768 instead of having to check event.delta
again.
c55cd1e
to
05ea375
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for your commit that indeed fixes the issue when zooming over minDistance
value.
Trying out the example again, I came upon a glitch that occurs when zooming with the mouse wheel while orbiting (with ctrl+drag
). On master
branch, one can do so as you can test on view_3d_map
example
When doing the same on your branch, I noticed that the camera moves strangely. Moreover, if I keep orbiting after having rolled the mouse wheel, the camera zooms out. The zoom should not be affected by an orbit movement.
I found out this is due to this line in lookAtCoordinates
method which you call in your new handleZoom
. It modifies cameraTarget
which is used as a reference in handlePanoramic
, thus for orbit movement. Removing this line fixes the issue I mention but brings out some more issues, notably with "dolly" movement (wheel-click + drag
)
@mgermerie we could just cancel the Panoramic once the zoom is triggered (looks like how it's handled in Google Earth), WDYT ? in itowns/src/Controls/StateControl.js Lines 394 to 401 in 8de37c9
|
@AnthonyGlt I agree with you on that point, we should disable this behavior (is this really used BTW?) to mimic the one in Earth and to decrease the complexity of state handling. @mgermerie Any thoughts? |
2bbb9cb
to
06e7874
Compare
@Desplandis squashed 🎾 |
@AnthonyGlt Your proposition is ok for me in terms of how to code it. |
BREAKING CHANGE: disabled multi actions when zooming
06e7874
to
412ec12
Compare
@mgermerie I've added the breaking change to the commit Thank you for your review |
Description
In globe view, zoom to the cursor position while using mousewheel.
Motivation and Context
Linked issue: #2011