Sign in to follow this  
Revelation60

Moving camera matrix around own axis

Recommended Posts

Hi, To rotate my camera matrix I use this piece of code:
inline void Rotate(float angle, float x, float y, float z) // x, y and z are rotations in radians
    {
        matrix4f rot;

		vector3f rotvec(x, y, z);
		rotvec.Normalize();

		rot.LoadIdentity();

		float c = cosf(angle);
		float s = sinf(angle);
		rot.m[0]  = rotvec.x * rotvec.x * (1 - c) + c;
		rot.m[1]  = rotvec.y * rotvec.x * (1 - c) + rotvec.z * s;
		rot.m[2]  = rotvec.x * rotvec.z * (1 - c) - rotvec.y * s;
		rot.m[4]  = rotvec.x * rotvec.y * (1 - c) - rotvec.z * s;
		rot.m[5]  = rotvec.y * rotvec.y * (1 - c) + c;
		rot.m[6]  = rotvec.y * rotvec.z * (1 - c) + rotvec.x * s;
		rot.m[8]  = rotvec.x * rotvec.z * (1 - c) + rotvec.y * s;
		rot.m[9]  = rotvec.y * rotvec.z * (1 - c) - rotvec.x * s;
		rot.m[10]  = rotvec.z * rotvec.z * (1 - c) + c;

        Multiply(rot); // this = this * rot

    }
Only, this does not do as I want to. When it rotates, it seems to rotate around the world origin (0, 0, 0) and not around the camera's own axis (which is translated from the origin). I want to have an FPS-like camera. The matrix I use is a 4*4 matrix, so it has the translation in it. What am I doing wrong?

Share this post


Link to post
Share on other sites
Your comment says that x, y, and z are 'rotations in radians', but your code says that they are the axis components of an axis-angle pair. Something is amiss :)

Can you show how you're using the function? Where do the values for x, y, and z come from?

Also, an axis can't really be 'translated from the origin', so there may be some other things that you're confused about as well.

Share this post


Link to post
Share on other sites
Oops, I commented it wrongly and I've made another mistake. I meant that the angle was in radians. x, y, z are the members of a vector that gives the direction on how to rotate with 'angle' degrees.

Furthermore, this is not the function I call. I call the very similar one:


inline void RotateWorld(float angle, float x, float y, float z) // angle is rotation in radians
{
matrix4f rot, rotfinal;

vector3f rotvec(x, y, z);
rotvec.Normalize(); // important, fixme: check if necessary

rotfinal.LoadIdentity();

rot.LoadIdentity();

float c = cosf(angle);
float s = sinf(angle);
rot.m[0] = rotvec.x * rotvec.x * (1 - c) + c;
rot.m[1] = rotvec.y * rotvec.x * (1 - c) + rotvec.z * s;
rot.m[2] = rotvec.x * rotvec.z * (1 - c) - rotvec.y * s;
rot.m[4] = rotvec.x * rotvec.y * (1 - c) - rotvec.z * s;
rot.m[5] = rotvec.y * rotvec.y * (1 - c) + c;
rot.m[6] = rotvec.y * rotvec.z * (1 - c) + rotvec.x * s;
rot.m[8] = rotvec.x * rotvec.z * (1 - c) + rotvec.y * s;
rot.m[9] = rotvec.y * rotvec.z * (1 - c) - rotvec.x * s;
rot.m[10] = rotvec.z * rotvec.z * (1 - c) + c;

matrix4f mat;
mat.Copy(*this);

mat = rot * mat;

this->Copy(mat);


}


like this: SceneCamera.RotateWorld(MOVEANGLE, 0, 1, 0); // around y-axis

I had to use this function to use the world y-axis and not the camera y-axis.

But what happens is that now I seem to move around the world axis with my camera, so actually it is the same as the earth oribiting around the sun and not - what I want - the earth orbiting around its own axis but still using the world's (0, 1, 0) as rotation vector.

[Edited by - Revelation60 on January 4, 2008 5:36:54 AM]

Share this post


Link to post
Share on other sites
Quote:
Original post by Revelation60
Oops, I commented it wrongly and I've made another mistake. I meant that the angle was in radians. x, y, z are the members of a vector that gives the direction on how to rotate with 'angle' degrees.

Furthermore, this is not the function I call. I call the very similar one:


inline void RotateWorld(float angle, float x, float y, float z) // angle is rotation in radians
{
matrix4f rot, rotfinal;

vector3f rotvec(x, y, z);
rotvec.Normalize(); // important, fixme: check if necessary

rotfinal.LoadIdentity();

rot.LoadIdentity();

float c = cosf(angle);
float s = sinf(angle);
rot.m[0] = rotvec.x * rotvec.x * (1 - c) + c;
rot.m[1] = rotvec.y * rotvec.x * (1 - c) + rotvec.z * s;
rot.m[2] = rotvec.x * rotvec.z * (1 - c) - rotvec.y * s;
rot.m[4] = rotvec.x * rotvec.y * (1 - c) - rotvec.z * s;
rot.m[5] = rotvec.y * rotvec.y * (1 - c) + c;
rot.m[6] = rotvec.y * rotvec.z * (1 - c) + rotvec.x * s;
rot.m[8] = rotvec.x * rotvec.z * (1 - c) + rotvec.y * s;
rot.m[9] = rotvec.y * rotvec.z * (1 - c) - rotvec.x * s;
rot.m[10] = rotvec.z * rotvec.z * (1 - c) + c;

matrix4f mat;
mat.Copy(*this);

mat = rot * mat;

this->Copy(mat);


}


like this: SceneCamera.RotateWorld(MOVEANGLE, 0, 1, 0); // around y-axis

I had to use this function to use the world y-axis and not the camera y-axis.

But what happens is that now I seem to move around the world axis with my camera, so actually it is the same as the earth oribiting around the sun and not - what I want - the earth orbiting around its own axis but still using the world's (0, 1, 0) as rotation vector.
It sounds like you might be applying the camera translation and rotation transforms in the wrong order.

Perhaps you could post the code where you actually assemble your camera matrix...

Share this post


Link to post
Share on other sites
Well, in my draw procedure I just call:

glMultMatrixf(SceneCamera.m);

The m is the actual array.


In the update function I take care of the input:



if (Engine.KeyDown['W'])
SceneCamera.Translate(0, 0, MOVESPEED);

float MOUSEROTFACTOR = 0.04f;
float dx = Engine.MouseInfo.CurrentMouseX - Engine.MouseInfo.PreviousMouseX;
float dy = Engine.MouseInfo.CurrentMouseY - Engine.MouseInfo.PreviousMouseY;



SceneCamera.Rotate(dy * MOUSEROTFACTOR, 1, 0, 0);
SceneCamera.RotateWorld(dx * MOUSEROTFACTOR, 0, 1, 0);


the SceneCamera.Translate:


inline void Translate(float x, float y, float z)
{
matrix4f trans;

trans.LoadIdentity();
trans.m[12] = x;
trans.m[13] = y;
trans.m[14] = z;

Multiply(trans);
}


I hope this helps!

Share this post


Link to post
Share on other sites
Ok, I think I have fixed the orbit problem. The only question remaining is how to rotate the camera around the world's y axis instead of its own axis?

Changing the multiplication order Cam = Cam * Rot into Cam = Rot * Cam doesn't do the trick because then I start orbiting again.

Share this post


Link to post
Share on other sites
I guess it is: new_cam = cam * roty(angle)^-1 = cam * roty(angle)_t (transposed) = cam * roty(-angle)

in this way every point x will transform like u = new_cam * x = cam * (roty(-angle) * x) = cam * x'
x is rotated around y-world axis by (-angle)

Share this post


Link to post
Share on other sites
Hi,
I noticed a strange behaviour of the camera, it rotates wrong when the mouse is moved.
I noticed that inside the function processMousePassiveMotion, the matrix SceneCamera continues to accumulate rotation around x and y axis every time u move the mouse:

void processMousePassiveMotion(int x, int y) {

float MOUSEROTSPEED = 0.05;

int dx = x - prevposx;
int dy = y - prevposy;
SceneCamera.Rotate(-dy * MOUSEROTSPEED, 0, 0);
SceneCamera.Rotate(0, -dx * MOUSEROTSPEED, 0);

prevposx = x;
prevposy = y;
}

In this way, assuming to not translate your camera,
NewSceneCamera = SceneCamera * Rx1*Ry1*Rx2*Ry2*Rx3*Ry3 (whenever the mouse moves) while I guess it would be better to have
NewSceneCamera = SceneCamera * (Rx1*Rx2*Rx3..) * (Ry1*Ry2*Ry3...), it's the same as updating every time the angles of rotations (angle_x,angle_y) and multiplay your scene camera by Rx(angle_x) * Ry(angle_y)

I'm not sure if it was the original problem...

Share this post


Link to post
Share on other sites
Hi,
I saw that your Multiply and Rotate functions treat m as a row-major matrix,


...
for(int i=0;i<4;i++)

{

for(int j=0;j<4;j++)

{

for(int k=0;k<4;k++)

{

X[i][j][k] = m[i * 4 + k] * m1.m[k * 4 + j];

result.m[i * 4 + j] += X[i][j][k];

}

}

}
...

...and then u pass m to glMultMatrix which is column-major

glMultMatrixf(SceneCamera.m);

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