Skip to main content
gamedev.net
🔒 Locked

Camera Code?

Started by Metorical 1 reply 1.3k views
Original Post
Metorical
Metorical
Hi, I''d appreciate any help you can offer me solving this little problem. I am programming a camera system to look around in OpenGL. For my camera I store its position, a vector which points the way in which the camera looks and its up vector. I can move my camera around quite easily but I''m having lots of problems rotating the view. Here is what I''m doing: A) I calculate how far the mouse has moved from the centre of the screen and reset the cursor to the centre. B) I use these values to rotate the vector which tells the camera which way it is looking. The problem is that as I rotate it the axises of the camera change and I can''t use my lovely matrix rotation transformation thing. How can I effectively look down my vector and rotate it in that axis. -Meto
sjelkjd
sjelkjd
An easy solution is to represent your view angle in polar coordinates, and record position. So you keep a theta(rotation around y axis) and a phi(angle from xz plane). Also store a position.

This lets you compute a look-at vector, which you can use to move forward, to the right(by crossing with up vector), or to render with gluLookAt

[edited by - sjelkjd on March 20, 2003 5:56:47 PM]
Trienco
Trienco
you already have a position and an up vector. thats half the transformation matrix.
now store a front vector instead of a look at (look at - position).
then get a right vector (cross product front x up) and you have the complete matrix for the cam.

having the matrix you can opengl do the rotation and be sure youll always have an orthonormal matrix without having to make sure rounding errors wont screw it up. opengl functions are probably more optimized than the slow sin/cos stuff.
just load your matrix onto the stack, rotate, fetch the result (translating is too easy to bother matrix operations with it).

good things: rotations are local, so rotating up (vector 1,0,0) will rotate around the cams right axis. to rotate around a global axis (for example y axis in typical ego shooter), just use the transposed vector.

glulookat is nice, but in fact you have to extract the look at vector to call it and... it will do the following:
calculate the front vector and right vector to build the matrix you already had and then invert it. inverting it in this special case is easy. the rotation part is transposed and the translation inverted.

ill show some code. it might sound complicated but the code is very short and it works.


      
//m_Transform is the matrix float[16]

//set it to identity

memset(m_Transform, 0, 16*sizeof(float));
m_Transform[0] = 1.0f;
m_Transform[5] = 1.0f;
m_Transform[10] = 1.0f;
m_Transform[15] = 1.0f;

//invert matrix

float viewmatrix[16]={
m_Transform[0], m_Transform[4], m_Transform[8], 0,
m_Transform[1], m_Transform[5], -m_Transform[9], 0,
m_Transform[2], m_Transform[6], -m_Transform[10], 0,

-(m_Transform[0]*m_Transform[12] +
m_Transform[1]*m_Transform[13] +
m_Transform[2]*m_Transform[14]),

-(m_Transform[4]*m_Transform[12] +
m_Transform[5]*m_Transform[13] +
m_Transform[6]*m_Transform[14]),

-(m_Transform[8]*m_Transform[12] +
m_Transform[9]*m_Transform[13] +
m_Transform[10]*m_Transform[14]), 1
};
glLoadMatrixf(viewmatrix);

//or shorter glulookat version

gluLookAt(m_Transform[12], m_Transform[13], m_Transform[14],
m_Transform[8]+m_Transform[12], m_Transform[9]+m_Transform[13],
m_Transform[10]+m_Transform[14],
m_Transform[4], m_Transform[5], m_Transform[6]);

//move camera.. direction axes are x=0, y=1, z=2

int i = f_Direction * 4;
m_Transform[12] += m_Transform[i] * f_Speed;
m_Transform[13] += m_Transform[i+1] * f_Speed;
m_Transform[14] += m_Transform[i+2] * f_Speed;

//special rotation for shooter style

//more general version would specify axis

//this one gets mouse movements (x,y)

glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadMatrixf(m_Transform);
//rotates around global y axis, so its the transposed


glRotatef(x, m_Transform[1],m_Transform[5],m_Transform[9]);
//rotates around local x axis

glRotatef(y, 1,0,0);
glGetFloatv(GL_MODELVIEW_MATRIX, m_Transform);
glPopMatrix();


those rotations are done at the same time, because they are independent. because order matters you would usually apply them immediately in the order they arrive. general version for local rotations (no guarantees)


    
//gets axis (axe) as above (x=0, y=1, z=2) and degree (deg)

float vec[3]={0,0,0};
vec[axe]=1;
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadMatrixf(m_Transform);
glRotatef(deg, vec[0],vec[1],vec[2]);
glGetFloatv(GL_MODELVIEW_MATRIX, m_Transform);
glPopMatrix();


of course, if anybody knows a smaller 6dof matrix camera class or can see any problems i missed -> let me know ,-)

and of course, if you dont like all the array indices flying around:
float* Right=m_Transform[0];
float* Up=m_Transform[4];
float* Front=m_Transform[8];
float* Position=m_Transform[12];

maybe something like:
const int X=0; etc. to access with Camera.Up[X];

or this one:
struct vec {float x,y,z};
vec* Right=m_Transform[0];

Camera.Right->x;

[edited by - Trienco on March 21, 2003 3:39:39 AM]
f@dzhttp://festini.device-zero.de

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.