Sign in to follow this  
angry

Camera Matrix

Recommended Posts

edit: Read my post at post 8 for a better explanation. I'm not really sure how to describe my problem, however, I will do my best. I have this camera class which has only one matrix which contains it's orientation and position in the world. The negative z-axis of the camera matrix tell which direction the camera is looking at. Now if I multiply this camera matrix with the world matrix, which is an identity matrix, it will change the current reference system to the cameras reference system, right? So if I then create and move any objects in the scene they will all be moved relative to the camera and it's reference system, but I want them to move by the world reference system. Anyone know how I can do that? It should be a really simple task, really, but I can't figure it out. [Edited by - angry on June 13, 2005 4:20:59 AM]

Share this post


Link to post
Share on other sites
If I do it this way:

// render
world.identity();
camera.rotate(0.0, yRot, 0.0);
camera.translate(0.0, 0.0, zPos);
world = world * camera.inverse();

object.rotate(0.0, 45.0, 0.0);
object.translate(0.0, 0.0, -5.0); // z goes into the screen

world = world * object;
// do the same for other objects...



the objects in the scene will rotate and not the camera. So if I change place of rotate and translate for the camera, it will rotate the camera, though you won't be able to move towards the axis it's facing. It will only move in the z axis of the world.

Any ideas, of how I can make my camera move in the direction it's negative z-axis i facing?

Share this post


Link to post
Share on other sites
Think about it this way. The camera's orientation/position matrix transforms the camera's space into world space. That is, a position in the camera's space is transformed into world space by multiplying it by the camera's orientation/position matrix. Now, to transform a world space position into to the camera's space, you do the opposite -- multiply it by the inverse of the camera's orientation/position matrix.

The inverse of the camera's orientation/position matrix is called the view matrix.

The world matrix in D3D transforms model coordinates into world space. It is not related to the camera. It is used to move objects around in world space. In OpenGL, the world matrix is combined with the view matrix and called the model-view matrix.

So, in D3D use the world matrix to move objects around, and set the view matrix according to the camera's orientation/position. In OpenGL, set the model-view matrix according to the camera's orientation/position first, then use push, pop, rotate, translate, etc. to position objects.

Share this post


Link to post
Share on other sites
Hmm... I'm using openGL, and to me it seems like im doing just as you say I should do... Here's the real code:

// in render method
...
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

camera.identity();
camera.transform.rotate(0.0f, rotY, 0.0f); // rotY is changed by the left and right arrows on the keyboard
camera.transform.translate(0.0f, 0.0f, posZ); // posZ is changed by the up and down arrows on the keyboard
glLoadMatrixf(camera.transform.inverse());

glPushMatrix();
glTranslatef(-1.0f, 0.0f, 0.0f);
drawWireBox(2.0f, 0.4f, 1.0f);
glPopMatrix();





, but still my camera won't move in the direction it's z-axis is facing...

[Edited by - angry on June 12, 2005 5:53:45 AM]

Share this post


Link to post
Share on other sites
You probably want to rotate then translate, but really that depends on how your operations concatenate matrices. In OpenGL notation/convention, transformation A followed by transformation B should result in AB, not BA.

Share this post


Link to post
Share on other sites
If I rotate the camera before I translate it, the rendered object will spin around, and not the camera. And if I translate and then rotate the camera, it will rotate the camera, but still just move forward and backwards and not in the direction it's negative z-axis is facing, or where it's negative z-axis should be facing, ehm...

Share this post


Link to post
Share on other sites
As John mentioned, it's not completely clear from your code how your camera matrix is constructed, so it's difficult to give specific advice on how to fix the problem.

Here's a brief description of how my camera is set up - perhaps it will be helpful to you in some way.

The camera is an object just like everything else. It has an orientation, and a position. The orientation is a 3x3 matrix, and the position is a vector. These can of course be combined into a 4x4 matrix when necessary.

The columns (for consistency with OpenGL) of the matrix are the direction vectors (local axes) of the object. You can move your object by adjusting the position vector by multiples of these vectors. In your case you would use the negative of the third column.

To transform a vertex from the local space of an object into the local space of the camera, you would first multiply it by the object's transformation matrix, and then by the camera's inverse transformation matrix:

vWorld = objectMatrix * vLocal
vCamera = inverse(cameraMatrix) * vWorld

Or:

vCamera = inverse(cameraMatrix) * objectMatrix * vLocal

Or:

vCamera = M * vLocal

Where:

M = inverse(cameraMatrix) * objectMatrix

So the OpenGL sequence might look something like this:

cameraInverseMatrix = inverse(cameraMatrix);
glLoadIdentity();
glMultMatrix(cameraInverseMatrix);
glMultMatrix(objectMatrix);

I don't know if any of that will be helpful to you, but feel free to ask if you have questions about any of the above.

Share this post


Link to post
Share on other sites
Im getting more and more confused, as when I see your examples it looks just like what I'm doing...

My matrix/transform class looks like this, it's a 4x4 matrix:

edit: oh, and I have compared the results of my rotate() and translate() methods with the glTranslate and glRotate functions, and the matrix results are the same. So there shouldn't be any errors in my translate, rotate and multiply methods.

class Transform
{
public:
float m[16];

public:
inline Transform();
inline Transform(const float* fmatrix);
inline Transform(const Transform& transform);

inline Transform& operator = (const float* fmatrix);
inline Transform& operator = (const Transform& transform);
inline Transform& operator*= (const Transform& transform);

inline Transform operator * (const Transform& transform);

inline float& operator [] (unsigned int i);
inline const float& operator [] (unsigned int i) const;

inline operator float*();
inline operator const float*() const;

inline void identity();
inline Transform& multiply(const Transform&);
static Transform& multiply(Transform&, const Transform&, const Transform&);
Transform inverse();
void invert();

void translate(float x, float y, float z);
void rotate(float x, float y, float z);

inline void reset();

protected:
inline void copy(const float* fmatrix);
inline void copy(const Transform& transform);
};
//---------------------------------------------------------------------
inline Transform& Transform::multiply(const Transform& transform)
{
return multiply(*this, *this, transform);
}
//---------------------------------------------------------------------
Transform& Transform::multiply(Transform& mr, const Transform& m1, const Transform& m2)
{
float res[16];
res[ 0] = m2[ 0]*m1[0] + m2[ 1]*m1[4] + m2[ 2]*m1[ 8] + m2[ 3]*m1[12];
res[ 1] = m2[ 0]*m1[1] + m2[ 1]*m1[5] + m2[ 2]*m1[ 9] + m2[ 3]*m1[13];
res[ 2] = m2[ 0]*m1[2] + m2[ 1]*m1[6] + m2[ 2]*m1[10] + m2[ 3]*m1[14];
res[ 3] = m2[ 0]*m1[3] + m2[ 1]*m1[7] + m2[ 2]*m1[11] + m2[ 3]*m1[15];

res[ 4] = m2[ 4]*m1[0] + m2[ 5]*m1[4] + m2[ 6]*m1[ 8] + m2[ 7]*m1[12];
res[ 5] = m2[ 4]*m1[1] + m2[ 5]*m1[5] + m2[ 6]*m1[ 9] + m2[ 7]*m1[13];
res[ 6] = m2[ 4]*m1[2] + m2[ 5]*m1[6] + m2[ 6]*m1[10] + m2[ 7]*m1[14];
res[ 7] = m2[ 4]*m1[3] + m2[ 5]*m1[7] + m2[ 6]*m1[11] + m2[ 7]*m1[15];

res[ 8] = m2[ 8]*m1[0] + m2[ 9]*m1[4] + m2[10]*m1[ 8] + m2[11]*m1[12];
res[ 9] = m2[ 8]*m1[1] + m2[ 9]*m1[5] + m2[10]*m1[ 9] + m2[11]*m1[13];
res[10] = m2[ 8]*m1[2] + m2[ 9]*m1[6] + m2[10]*m1[10] + m2[11]*m1[14];
res[11] = m2[ 8]*m1[3] + m2[ 9]*m1[7] + m2[10]*m1[11] + m2[11]*m1[15];

res[12] = m2[12]*m1[0] + m2[13]*m1[4] + m2[14]*m1[ 8] + m2[15]*m1[12];
res[13] = m2[12]*m1[1] + m2[13]*m1[5] + m2[14]*m1[ 9] + m2[15]*m1[13];
res[14] = m2[12]*m1[2] + m2[13]*m1[6] + m2[14]*m1[10] + m2[15]*m1[14];
res[15] = m2[12]*m1[3] + m2[13]*m1[7] + m2[14]*m1[11] + m2[15]*m1[15];

mr.copy(res);
return mr;
}
//---------------------------------------------------------------------
Transform Transform::inverse()
{
Transform trans(*this);

register float r00, r01, r02,
r10, r11, r12,
r20, r21, r22;

r00 = trans[0]; r01 = trans[1]; r02 = trans[2];
r10 = trans[4]; r11 = trans[5]; r12 = trans[6];
r20 = trans[8]; r21 = trans[9]; r22 = trans[10];

// partially compute the inverse of the rotation matrix
trans[0] = r11*r22 - r12*r21;
trans[1] = r02*r21 - r01*r22;
trans[2] = r01*r12 - r02*r11;

// compute the determinant of the rotation matrix
register float oneOverDet = 1.0f / (r00*trans[0] + r10*trans[1] + r20*trans[2]);
r00 *= oneOverDet;
r10 *= oneOverDet;
r20 *= oneOverDet;

trans[ 0]*= oneOverDet;
trans[ 1]*= oneOverDet;
trans[ 2]*= oneOverDet;
trans[ 3] = 0.0f;
trans[ 4] = r12*r20 - r10*r22;
trans[ 5] = r00*r22 - r02*r20;
trans[ 6] = r02*r10 - r00*r12;
trans[ 7] = 0.0f;
trans[ 8] = r10*r21 - r11*r20;
trans[ 9] = r01*r20 - r00*r21;
trans[10] = r00*r11 - r01*r10;
trans[11] = 0.0f;
trans[15] = 1.0f;

// compute the inverse of the translation part of the matrix
register float tx, ty, tz;
tx = trans[12];
ty = trans[13];
tz = trans[14];

trans[12] = -(tx*trans[0] + ty*trans[4] + tz*trans[ 8]);
trans[13] = -(tx*trans[1] + ty*trans[5] + tz*trans[ 9]);
trans[14] = -(tx*trans[2] + ty*trans[6] + tz*trans[10]);

return trans;
}
//---------------------------------------------------------------------
void Transform::translate(float x, float y, float z)
{
Transform mTran;
mTran.identity();

mTran[12] = x;
mTran[13] = y;
mTran[14] = z;

multiply(mTran);
}
//---------------------------------------------------------------------
void Transform::rotate(float x, float y, float z)
{
Transform rot, res;
res.identity();

rot.identity();
rot[ 5] = angle_cos(x); rot[ 6] = angle_sin(x);
rot[ 9] =-angle_sin(x); rot[10] = angle_cos(x);
res.multiply(rot);

rot.identity();
rot[ 0] = angle_cos(y); rot[ 2] =-angle_sin(y);
rot[ 8] = angle_sin(y); rot[10] = angle_cos(y);
res.multiply(rot);

rot.identity();
rot[ 0] = angle_cos(z); rot[ 1] = angle_sin(z);
rot[ 4] =-angle_sin(z); rot[ 5] = angle_cos(z);
res.multiply(rot);

multiply(res);
}





I only kept the methods that might be of interest, so there's nothing missing in the real source...

And how I use it with openGL is shown in my previous post.

Share this post


Link to post
Share on other sites
Uhm... I guess I need to explain my problem even more, as this shouldn't be much of a problem for anyone except me on this forum =) So here comes another explanation...

What I Want?
I want to rotate my camera's coordinate space so that I then can translate it by it's local z-axis only and by that way make the camera move forward relative to it's own coordinate space, but to somewhere else relative to the world coordinate space. For example:

camera.matrix.rotate(0.0, 90.0, 0.0); // rotate the camera's space by 90
degrees so that it's z-axis where it's x-axis used to be, and it x-axis is
where it's z-axis used to be.

camera.matrix.translate(0.0, 0.0, 10.0); // translate the camera by 10 units
on it's z-axis, which is where it's x-axis used to be since I rotated the
coordinate space of the camera. So relative to the world coordinate space
it will move along the world's x-axis.


How Am I Currently Trying To Do It?
I have this camera class which contains a 4x4 matrix, and that is the only data structure it contains. It looks like this in source:

class Transformable
{
public:
Matrix44 matrix;
};

class Camera: public Transformable
{
};

class SomeModelOrWhatever: public Transformable
{
};

So as you can see it doesn't contain alot of other members that keep track of rotation, angles and positions as all camera tutorials I've found around the net. Instead I want my matrix to do that job.
So in my render method I do the following:

//.. render()
if( GetKeyState(VK_LEFT)&0x80 ) yRot = yRot + 5;
if( GetKeyState(VK_RIGHT)&0x80 ) yRot = yRot - 5;
if( GetKeyState(VK_UP)&0x80 ) zPos = zPos - 1; // negative z-axis goes into screen
if( GetKeyState(VK_DOWN)&0x80 ) zPos = zPos + 1;

glLoadIdentity();
camera.matrix.rotate(0.0f, yRot, 0.0f);
camera.matrix.translate(0.0f, 0.0f, zPos);
glMultMatrixf(camera.matrix); // i've tried both the inverse and normal and neither works

glPushMatrix();
glTranslatef(-1.0f, 0.0f, 0.0f);
drawWireBox(1.0f, 1.0f, 1.0f);
glPopMatrix();

// SwapBuffers()













I myself thinks that the problem lies in how I translate my camera or that I am multiplying the objects matrices with the camera's local matrix and not it's world matrix.
Anyways, if you look at those camera tutorials which doesn't use matrices and instead uses members with names like, position, yaw, pitch, heading, and such they look something like this:

// in render
// NOTE that these are just fantasy numbers! And does probably not work. It's only for you to get the idea.
float camX = cos(camera.xRotation) * speed;
float camY = sin(camera.yRotation) * speed;
float camZ = sin(camera.zRotation) * speed;

glRotatef(camera.lookAtX, 1.0f, 0.0f, 0.0f);
glRotatef(camera.lookAtY, 0.0f, 1.0f, 0.0f);
glRotatef(camera.lookAtZ, 0.0f, 0.0f, 1.0f);
glTranslatef(camX, camY, camZ);













And as you can see they translate the camera by exact coordinates while I rely on local coordinates, ehh... i think... As my camera works like so; it first rotates it's coordinate space and then translates by a single axis.

camera.matrix.rotate(0.0f, rotY, 0.0f); // rotate camera's coordinate space
camera.matrix.translate(0.0f, 0.0f, posZ); // translate camera's position along it's z-axis
´
And in the above example, that shows how most camera tutorials handle their cameras, they rotate the camera's coordinate space, and then translates it by it's world coordinates, i think...



So from my own conclusion, I guess the question is; how can I extract my camera's world coordinates from it's matrix?

[Edited by - angry on June 13, 2005 4:58:57 AM]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this