Jan 6th, 2011, 06:51 AM
[WPF] 3D Orbit camera with 'infinite' mouse movement
First of all, I couldn't find a codebank forum dedicated to WPF so I posted it in C# instead (since the code is C#). If that's not right, feel free to move it.
I am completely new to WPF so if there are some things wrong with my submission, let me know
Anyway, my first ever WPF project has to include a small simple 3D scene where the user can orbit around using his mouse. I couldn't find many examples on controlling the camera with the mouse, and the ones that I could find offered camera rotation in 3 directions: pitch, yaw and roll. I didn't want my camera to roll, I merely wanted pitch and yaw (and the possibility to zoom), so with the help of jemidiah I pieced together something that works quite well, and decided to submit it here so others can use it or learn how to do it.
So this is a control that you can load some 3d models into and you can use the mouse (by holding the right mouse button) to hover around them. You cannot 'move', and the camera always points toward the middle of the scene, but you can rotate around the scene and look at it from all sides.
You can also zoom via the scroll wheel.
Additionally, your mouse movement is not restrained to the viewport window only. When you hold down the right button, your mouse cursor is hidden and you can move your mouse as far as you want, or at least until you run out of desktop space or get dizzy
Finally you can change the zoom and the pitch and yaw (rotation) via code too, via the Zoom, Pitch and Yaw methods.
Oh yeah, to load a model I added an AddModel method that accepts a Model3D object, as that is all I will need, but you might want to expose the entire Viewport3D object so that you can also add lights, etc, since I just left those in from an example I used.
Finally, here's a short video that shows an earlier version (I can't make a new video right now). It does not have the 'infinite movement' yet, and the video is called Mouse Fail because I used it to compare it to another video which demonstrates a problem I was having, so don't mind that
The basis of how it works is pretty simple: I made a UserControl with a regular Viewport3D control, and on top of that a Canvas (to capture mouse events from).
When the mouse is moved, the amount of movement is measured and from this a pitch and yaw angle is calculated. Then, the camera is rotated using a bunch of RotateTransform3D operations. Credits for this part go largely to jemidiah as I couldn't figure it out on my own Thanks!
To enable 'infinitely long movement', I simply reset the mouse position to the center of the viewport after every movement. Since the mouse cursor is hidden and it's only the relative movement of the mouse that matters, you won't notice this at all and it feels very natural.
So yeah... I uploaded the C# project containing the UserControl and a MouseUtilities class (simply a class with static methods that call the GetCursorPos and SetCursorPos APIs). It was made in .NET 4 but I converted it down to 3.5 and tested it in VS2008 and it seems to work fine.
Click Here to Expand Forum to Full Width