2
\$\begingroup\$

I am trying to implement a zoom in/out navigation mode in a openGL 3dViewer. I was able to implement zoom functionality centered at screen center just by moving eye towards the center in perspective mode.

Now i am trying to do the zoom centered at arbitrary position under the cursor. I am unable to figure out how should i move my camera forward and backward such that point under cursor remains at the same screen coordinates after zoom in/out. Any help would be appreciated.

Below are the images which show the desired effect. Just to mention, I am working in a perspective mode with eye target and up vectors to control camera.

Same effect i found in google sketchup and 'zoom to mouse position' setting in blender.

cursor position before zoom

cursor position after zoom

\$\endgroup\$
  • \$\begingroup\$ This question is slightly confusing. Your cursor isn't going to change screen coordinates, unless you personally move the mouse. Are you saying that you want the zoom feature to center on the cursor when zooming? \$\endgroup\$ – Evan May 11 '14 at 12:18
  • \$\begingroup\$ @Evan not the cursor, the 'point under the cursor'. \$\endgroup\$ – falstro May 11 '14 at 12:26
  • \$\begingroup\$ The question is basically how to dolly the camera to get closer, while keeping a specific world space point fixed on screen. (Which incidentally means moving directly towards that point) \$\endgroup\$ – falstro May 11 '14 at 12:32
1
\$\begingroup\$

In order for an object to remain stationary in your field of view, it has to move directly towards you, or directly away from you. Incidentally, this is why mid-air collisions with airplanes are so nasty, our eyes are trained to see movement in our field of view, and an airplane on a collision course would remain stationary. Bit I digress.

What you need to do is figure out the world space coordinates of the point 'under the cursor'. If you're just displaying a rectangle this should be fairly easy. If you're displaying a full 3D-scene, things get more complicated, and you need to figure out what you're actually pointing at. There are a number of ways to do this, but it would be more suitable for a separate question. Once you have the world space coordinates of the 'point under the cursor' you need to translate the camera along the vector from the camera to that point, note that this will be moving the camera sideways.

Strictly speaking, when using a perspective transformation, a point on screen corresponds to an angle in world space, if you move along the track to the point, but do not turn the camera, the angle from the camera's forward-looking vector (center of the screen) and your target point will remain the same.

\$\endgroup\$
  • \$\begingroup\$ Thanks for the answer. If i understood you right, i have to set the world point under the cursor as my target and move camera in eye-target direction. But if i do that point under the cursor will come to the center of the screen which is not desirable. \$\endgroup\$ – user3228921 May 11 '14 at 12:58
  • \$\begingroup\$ @user3228921 Yes, you understood correctly, and no, if you don't turn the camera, only move it, the point under the cursor will not move on the screen. \$\endgroup\$ – falstro May 11 '14 at 12:59
  • \$\begingroup\$ I have to move the camera closer to the object under the cursor with each zoom action by mouse wheel. Its ok even if my target point changes as long as it comes closer to the point under cursor with each zoom action. In perspective mode if move the camera forward or backward angle which it used to point the object before zoom will not be pointing it anymore after zoom. \$\endgroup\$ – user3228921 May 11 '14 at 13:10
  • \$\begingroup\$ @user3228921 I'm not sure exactly what you're trying to say. The idea is to keep the angle to your 'point-under-cursor' (or 'target' as I call it) constant. By keeping the orientation of the camera constant so the forward-vector doesn't change, and only moving it ('translating it', or 'dolly', however you want to call it) along the eye-target vector, that angle to your target will remain constant, but you will get closer so stuff will get bigger. Note that this is not what you normally call 'zoom' (where the field of view is reduced) \$\endgroup\$ – falstro May 11 '14 at 13:29
  • \$\begingroup\$ Thanks for your answer. you are right i must not call it zoom. By 'target' i mean that some point on forward-vector where camera is focusing. If i make the point-under-cursor my target, my glulookat(eye, target, up) will directly place target at screen center whis is not desirable. I will try translating my camera along the track to the point. \$\endgroup\$ – user3228921 May 11 '14 at 17:27
0
\$\begingroup\$

I have achieved this by following this algorithm,

  1. Calculate the screen point of the 3D point under the mouse cursor (the point that needs to be on fixed location) before move the camera. (Say screen point as Pt2DScr and 3D point under mouse Pt3D1)
  2. Move camera along camera Z axis. That's mean zoom to center of the viewport.
  3. Calculate current 3D point which is under Pt2DScr, say Pt3D2.
  4. Calculate the difference between Pt3D1 and Pt3D2 by (Pt3D1 - Pt3D2), say Pt3DOffset
  5. Move the camera by the amount of Pt3DOffset.

Note that you will need a fixed plane to calculate Pt3D1 and Pt3D2 which normal vector of the plane parallel to the camera z axis (plane always face to the camera)

Hope this will help to somebody!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.