Creating a CS style camera

Started by
4 comments, last by DaBookshah 17 years, 1 month ago
Hello, I'm just making a CS style camera for navigation through my 3D world (using openGL but that has little relevance here). My camera is a 'lookat' camera which holds an up vector, a center point and a look at point. I have the strafe done, but I am trying to implement the mouse look. Every time the mouse moves, I would like to rotate the camera with respect to how far it moved from the last position. My question: how can I find the current X Y and Z angles of the camera and then increment it with respect to the mouse movement? My current coord system is right handed with the Z vector being used as up. *One thing I have tried is this: create a transformation that rotates the camera to the original 0,0,0 degrees, perform the increment, then do the inverse transformation back. This did not seem to work Any Ideas?
"Only two things are infinite, the universe and human stupidity, and I'm not sure about the former." - Albert Einstein (1879-1955) That is so very true...
Advertisement
The way I handled this is by using a function to lock the mouse cursor to the center of the screen (Don't remember how off the top of my head, shouldn't be too hard), and every frame get how far it moved from the center, then update the angle of the camera based on that.
bit like that?

It's usually very simple. You just have two angles, 'elevation', and 'rotation' I call them. Basically, polar coordinates. When the mouse moves, you increment the angles.

These angles give you the view direction Dir. Then the 'strafe' direction is the vector perpendicalar to the view direction, and the Vector(0, 1, 0). Then the camera up vector is the Strafe vector cross the view direction.

// camera 'Dir' vector.// Dir = Vector(cos(rot)*cos(elev), sin(elev), sin(rot)*cos(elev));Dir.x = cos(rotation) * cos(elevation);Dir.y = sin(elevation);Dir.z = sin(rotation) * cos(elevation);// Camera 'strafe' vector.// Strafe = Vector(0, 1, 0) x Dir. // -> Normalised, it gives Strafe = Vector(-sin(rot), 0, cos(rot));Strafe.x = -sin(rotation);Strafe.y = 0.0f;Strafe.z = cos(rotation);// camera 'Up' vector.// No need to normalise afterwards (both vectors are guaranteed to be at 90 degrees and of length = 1).Up = Dir.CrossProduct(Strafe);// camera 'target' vector.// target = pos + dir * some_distance (doesn't really matter what distance).Target = Position + Dir * 100.0f


The rotation angle is wrapped in the range [-180, 180] degrees. In this example, the elevation angle does not have to clamped. There is no singularity when you are looking straight up, but it's recommended to clamp the elevation angle in the range [-90, 90] degrees.

Everything is better with Metal.

BTW, the mouse movement is returned by the DirectX inputs (in DirectInput.h/cpp). It's a 'relative motion' device. DirectX doesn not tell you the position of the mouse, rather, the speed of movement of the mouse, in pixels. You work out the position yourself. In your case, you don't even need to do that, you just take the mouse speed directly from DirectX.

Not sure what the Windows message WM_MOUSEMOVE does, but I think it's pretty much the same.

EDIT : Actually no. It's returning the position of the cursor, which is basically useless.

Everything is better with Metal.

I use wm_mousemove, and grab the position of the cursor, store it, then re-center the cursor. If you re-center the cursor after each check, you have the cursor position is equal to the delta since the last check.
Quote:Original post by SimmerD
I use wm_mousemove, and grab the position of the cursor, store it, then re-center the cursor. If you re-center the cursor after each check, you have the cursor position is equal to the delta since the last check.


I can go one better. I use raw input, which gives you the relative mouse motion, along with this to restrict the cursor to lie in a 1x1 box in the center of the screen. Probably marginally faster.

This topic is closed to new replies.

Advertisement