Pan, rotate and zoom in on 3D model

Started by
5 comments, last by DavidBurns 9 years, 7 months ago

Hi.

I'm displaying a mesh object in a WPF Viewport3D, and would like to be able to manipulate the view, using the mouse, in a similar fashion to many programs that display 3D models (e.g. openSCAD, STL viewers, blender, etc.).

I have a Point3D for the cameraPosition, and a Vector3D for the lookDirection. I also have a directional light source pointing in the lookDirection.

I had a go at each; zoom's the only one I got working alright, which is simply: cameraPosition = zoomFactor * (cameraPosition - lookedAtPoint) + lookedAtPoint; (I've set lookedAtPoint = cameraPosition - cameraPosition.toVector().length * lookDirection / lookDirection.length)

My results are not like those in real 3D model viewer software. Does anyone know the equations for pan, rotate and zoom normally used (given dX/dY/dScroll of the mouse)?

Advertisement

These are done with basic matrix operations - you should get acquainted with them.

This is what I think most 3D editors do:

- zoom scales the projection matrix

- rotate rotates the camera around the position of the object (translate view matrix so that origin is same as position of object; rotate; translate back)

- pan moves the camera in a plane which is perpendicular to the lookAt vector (just translate the view matrix).

Thanks for the reply. I haven't done any 3D graphics before, so I don't know what the projection/view/etc. matrices are, or how they're accessed or applied to the Viewport3D object.

The information re the panning moving the camera along a plane for panning is helpful, and is what I guessed was the case.

I have found code that can calculate the projection matrix, but none to apply it. In any case, I'll see if what I can do with the projection matrix tonight.


I have found code that can calculate the projection matrix, but none to apply it. In any case, I'll see if what I can do with the projection matrix tonight.

I'm not sure what library/engine you are using, but if you're already rendering objects, it means that it already applies a projection matrix for you. In that case, for zooming, check if you can change the width and height of the viewing frustum at the near plane (while keeping the FOV constant). Then you can just multiply these by the zoom factor.

For panning, check if you have vectors for "cameraRight" and "cameraUp". Then to pan the camera, you can just move the camera's position along these vectors: for example, to move in the X screen direction, multiply the normalized cameraRight vector with the amount to move, which is the amount the mouse was moved in the X direction, then add the resulting vector (from the multiplication) to the camera's position. Do the same with cameraUp & mouse-Y.

For rotation, if you can't access the view matrix directly, you have to rotate each of the cameraRight, CameraUp and cameraLookAt vectors.

Note: rotation can also be done around the center of the world's coordinate system instead of around an (selected) object.

I'm using C#, .NET, System.Windows.Media.Media3D and displaying in a WPF Viewport3D.

The zoom is easy: cameraPosition = zoomWheelChange * (cameraPosition - lookedAtPoint) + lookedAtPoint;

The pan is also easy, thanks to your last post: cameraVect += (cameraUp * diff.Y * .001 + cameraRight * diff.X * -.001) * distToOrigin;

Where cameraRight is simply the direction of Vector3D.CrossProduct(camera.LookDirection, camera.UpDirection);

I've tried a bunch of different manipulations of the camera position and the lookDirection, without luck. The most recent attempt was to rotate the camera around the lookedAtPoint, and update the lookDirection to look from the camera to the old lookedAtPoint. The result is similar to panning, which was surprising.


The zoom is easy: cameraPosition = zoomWheelChange * (cameraPosition - lookedAtPoint) + lookedAtPoint;

This is not really "zoom". You are just moving the camera back/forward. Zoom is when you scale the view while keeping the camera at the same position.


The most recent attempt was to rotate the camera around the lookedAtPoint, and update the lookDirection to look from the camera to the old lookedAtPoint. The result is similar to panning, which was surprising.

This should work... try rotating faster or bringing the camera closer to the lookedAtPoint to notice the difference, maybe? Or maybe your calculations are wrong?

I'm happy with my "zoom" simply moving the camera; it looks pretty good. The pan also just moves the camera, and finally, when I work out my issues, the rotate will do this.

I'm glad that approach will work, as it's easy to understand. I'll check my calculations for rotation on some simple numerical examples, and may have some more meaningful questions (or an answer).

Thanks for your time.

This topic is closed to new replies.

Advertisement