Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I remember I once composed a FPS viewing transformation, as a composition of 3 rotations, each with an angle as a parameter. The first angle specified the left/right rotation around the y-axis, the second angle the up/down rotation around the x-axis, and the third around the z-axis. The viewing transformation was therefore specified by 3 angles. Naturally, this transformation had a gimbal lock, depending in what order the transformation were performed. What should I look at to derive my viewing transformation without the gimbal lock? I know the "lookAt" method already, but I consider that cumbersome.

EDIT:

MY first guess is to do the first 2 transformations to get a viewing direction and then the axis-angle rotation on this axis.

share|improve this question
    
I know the "lookAt" method already, but I consider that cumbersome. Any insight on that please? –  Krom Stern Sep 8 at 9:35
    
@KromStern It is an old GLU function, AFAIK, and GLU is deprecated. Also, the interface is cumbersome, in my view. –  user1095108 Sep 8 at 9:40
    
gluLookAt is just a method of constructing a matrix opengl.org/wiki/GluLookAt_code, not much different from any other matrix construction methods (perspective, orthographic, rotation, etc) –  Krom Stern Sep 8 at 9:51
    
@KromStern I just don't like its interface, as regards FPSs. The function is generic, but I want it to be FPS-specific. Maybe propose a better method to construct a FPS viewing matrix? –  user1095108 Sep 8 at 10:00
    
What exactly you don't like in specifying eyePosition3D, targetPosition3D and upVector3D ? –  Krom Stern Sep 8 at 12:02

2 Answers 2

I honestly do not get this FPS/Arcball/Whatever camera nonsense that is going on. Just implement a general purpose camera, with either a transformation as 4x4 matrix or a position as R3 vector and orientation as a 3x3 matrix or quaternion. Then think about how that camera is moving though space.

For example I have implemented a general purpose camera with a a 4x4 matrix. The view matrix setup is straight forward:

mat4 transform;

// get column vectors x, y, z from transform
vec3 x = transform[0];
vec3 y = transform[1];
vec3 z = transform[2];

// set x, y, z as inverse into the matrix
// NOTE: column and rows are swapped
mat4 orientation(x[0], y[0], z[0], 0,
                 x[1], y[1], z[1], 0,
                 x[2], y[2], z[2], 0,
                    0,    0,    0, 1);

vec3 p = transform[3];

mat4 translation(    1,     0,     0, 0,
                     0,     1,     0, 0, 
                     0,     0,     1, 0,
                 -p[0], -p[1], -p[2], 1);

mat4 view = orientation * translation;

See no need to pass the anything though lookat or whatever. BTW the code is basically what lookat does, except it needs to compute x, y and z form eye, center and up and p is eye.

Now to the FPS part. The actual logic is a bit more complicated since you need to collide something, like a capsule with the world, but I will outline the basics with the help of "fyling".

The basic jest is you handle the rotation as follows:

// assuming (0, 0, 1) is up and (1, 0, 0) is forward
float x, y; // mouse input

// NOTE: again columns and rows are swapped in code
mat4 yaw( cos(x), sin(x), 0, 0,
         -sin(x), cos(x), 0, 0,
               0,      0, 1, 0,
               0,      0, 0, 1);

mat4 pitch( cos(y), 0, -sin(y), 0,
                 0, 1,       0, 0,
            sin(y), 0,  cos(y), 0,
                 0, 0,       0, 0);

transform = transform * pitch * yaw; 

The motion is similar:

// only forward

float speed;
float dt; // time difference since last frame


float ds = speed * dt;
mat4 translate( 1, 0,  0, 0,
                0, 1,  0, 0,
                0, 0,  1, 0,
               ds, 0,  0, 1);

transform = transform * translate; 

If you need answers how to handle transformations the Matrix and Quaternion FAQ is always very helpfull.

share|improve this answer
    
assumptions, assumptions, I'll post my own solution too, if I manage to arrive at it, but for now, your // assuming (0, 0, 1) is up and (1, 0, 0) is forward are exactly what I want to avoid. –  user1095108 Apr 10 at 10:00
    
What is wrong about clarifying the underlying assumptions in the code. It is not that hard to swap z with y and x with -z. The given assumptions does not mean the camera if facing this way now, just that the given transformation code thinks the input is expected that way. (It does not change the fact that the camera starts out looking down the z axis from the start.) –  rioki Apr 10 at 10:04
    
Well, swapping is not hard, yes, but it is kind of lame. I mean, I did not say, that I was not able to make a viewing transformation, I just wanted a more generic one, sophisticated, if you like. I'll put my thinking hat on and write something up soon. –  user1095108 Apr 10 at 10:54
    
This is a general case camera, it will not get more generic. The movement is an example of how you can move it. Also, instead of writing quips about my answer, how about actually contributing a an answer that is better than mine. –  rioki Apr 10 at 12:08

I'm using this transform:

x' = [cos(phi), 0, sin(phi)]
y' = [-sin(phi)sin(theta),cos(theta),cos(phi)sin(theta)]
z' = [-sin(phi)cos(theta),-sin(theta),cos(phi)cos(theta)]

Write these expressions into rows and you've got yourself a transformation matrix. The third parameter (rotation around the z' axis), can be handled like this:

x'' = x'cos(alpha) + y'sin(alpha)
y'' = -x'sin(alpha) + y'cos(alpha)
z'' = z'

Where x', y' and z' are vectors. No gimbal lock as far as I can see.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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