PDA

View Full Version : Help with camera rotation



blood.angel
02-12-2002, 05:16 AM
Hi, Im trying for weeks now to code a rubixs cube and Im still having trouble with the camera. The user rotates the rubixs cube with the mouse. That I have set up. I have the rubixs cube stationary at the origin and camera is rotated around the cube to the users need. When the user holds down the mouse and moves it up or down, left or right, I want the cube to move in the same diection.
The problem is that is doesnt move the way I want to. Once the camera is rotated around two or more of the axes the cube rotates in the wrong direction.

Now I have tried to solve this by first rotating the current camera position back to a predefined point (my selection is (0,0,7) ), then rotate the camera in the user required direction, then rotate it back to its original position.
However there must be something wrong with my code as after a rotation in two axes it 'jitters' about the one axis.
Heres the code I used:



void Ccamera::unrotate_camera(void)
{

GLfloat vector1[3], vector2[3];

//test to see if the camera is already at the center. If so return.
if( (xposition == 0.0) && (yposition == 0.0) && (zposition == 7.0) )
return;

if ( zposition < 0.0 )
{
if ( yposition < 0.0 )
{
firstangle = fabs(atan(yposition/zposition));
rotate_camera_xaxis(ANTICLOCKWISE, firstangle);
firstdirection = ANTICLOCKWISE;

if ( xposition < 0.0 )
{
secondangle = ONEEIGHTY - fabs(atan(xposition/zposition));
rotate_camera_yaxis(CLOCKWISE, secondangle);
seconddirection = CLOCKWISE;
}
else if ( xposition == 0.0 )
{
secondangle = ONEEIGHTY;
rotate_camera_yaxis(ANTICLOCKWISE, secondangle);
seconddirection = ANTICLOCKWISE;
}
else if ( xposition > 0.0 )
{
secondangle = ONEEIGHTY - fabs(atan(xposition/zposition));
rotate_camera_yaxis(ANTICLOCKWISE, secondangle);
seconddirection = ANTICLOCKWISE;
}


}
else if ( yposition == 0.0 )
{
if ( xposition < 0.0 )
{
secondangle = ONEEIGHTY - fabs(atan(xposition/zposition));
rotate_camera_yaxis(CLOCKWISE, secondangle);
seconddirection = CLOCKWISE;
}
else if ( xposition == 0.0 )
{
secondangle = ONEEIGHTY;
rotate_camera_yaxis(ANTICLOCKWISE, secondangle);
seconddirection = ANTICLOCKWISE;
}
else if ( xposition > 0.0 )
{
secondangle = ONEEIGHTY - fabs(atan(xposition/zposition));
rotate_camera_yaxis(ANTICLOCKWISE, secondangle);
seconddirection = ANTICLOCKWISE;
}

}
else //yposition > 0.0
{
firstangle = fabs(atan(yposition/zposition));
rotate_camera_xaxis(CLOCKWISE, firstangle);
firstdirection = CLOCKWISE;

if ( xposition < 0.0 )
{
secondangle = ONEEIGHTY - fabs(atan(xposition/zposition));
rotate_camera_yaxis(CLOCKWISE, secondangle);
seconddirection = CLOCKWISE;
}
else if ( xposition == 0.0 )
{
secondangle = ONEEIGHTY;
rotate_camera_yaxis(ANTICLOCKWISE, secondangle);
seconddirection = ANTICLOCKWISE;
}
else if ( xposition > 0.0 )
{
secondangle = ONEEIGHTY - fabs(atan(xposition/zposition));
rotate_camera_yaxis(ANTICLOCKWISE, secondangle);
seconddirection = ANTICLOCKWISE;
}
}


}
else if ( zposition == 0.0 )
{
if ( yposition < 0.0 )
{
firstangle = NINETY;
rotate_camera_xaxis(CLOCKWISE, firstangle);
firstdirection = CLOCKWISE;

if ( xposition < 0.0 )
{
secondangle = fabs(atan(xposition/zposition));
rotate_camera_yaxis(CLOCKWISE, secondangle);
seconddirection = CLOCKWISE;
}
else if ( xposition > 0.0 )
{
secondangle = fabs(atan(xposition/zposition));
rotate_camera_yaxis(ANTICLOCKWISE, secondangle);
seconddirection = ANTICLOCKWISE;
}
}
else if ( yposition == 0.0)
{
if ( xposition < 0.0 )
{
secondangle = NINETY;
rotate_camera_yaxis(CLOCKWISE, secondangle);
seconddirection = CLOCKWISE;
}
else if ( xposition > 0.0 )
{
secondangle = NINETY;
rotate_camera_yaxis(ANTICLOCKWISE, secondangle);
seconddirection = ANTICLOCKWISE;
}


}
else if ( yposition > 0.0 )
{
firstangle = NINETY;
rotate_camera_xaxis(ANTICLOCKWISE, firstangle);
firstdirection = ANTICLOCKWISE;

if ( xposition < 0.0 )
{
secondangle = fabs(atan(xposition/zposition));
rotate_camera_yaxis(CLOCKWISE, secondangle);
seconddirection = CLOCKWISE;
}
else if ( xposition > 0.0 )
{
secondangle = fabs(atan(xposition/zposition));
rotate_camera_yaxis(ANTICLOCKWISE, secondangle);
seconddirection = ANTICLOCKWISE;
}

}

}
else if ( zposition > 0.0 )
{
if ( yposition < 0.0 )
{
firstangle = fabs(atan(yposition/zposition));
rotate_camera_xaxis(CLOCKWISE, firstangle);
firstdirection = CLOCKWISE;

if ( xposition < 0.0 )
{
secondangle = fabs(atan(xposition/zposition));
rotate_camera_yaxis(CLOCKWISE, secondangle);
seconddirection = CLOCKWISE;
}
else if ( xposition > 0.0 )
{
secondangle = fabs(atan(xposition/zposition));
rotate_camera_yaxis(ANTICLOCKWISE, secondangle);
seconddirection = ANTICLOCKWISE;
}

}
else if ( yposition == 0.0 )
{
if ( xposition < 0.0 )
{
secondangle = fabs(atan(xposition/zposition));
rotate_camera_yaxis(CLOCKWISE, secondangle);
seconddirection = CLOCKWISE;
}
else if ( xposition > 0.0 )
{
secondangle = fabs(atan(xposition/zposition));
rotate_camera_yaxis(ANTICLOCKWISE, secondangle);
seconddirection = ANTICLOCKWISE;
}


}
else if ( yposition > 0.0 )
{
firstangle = fabs(atan(yposition/zposition));
rotate_camera_xaxis(ANTICLOCKWISE, firstangle);
firstdirection = ANTICLOCKWISE;

if ( xposition < 0.0 )
{
secondangle = fabs(atan(xposition/zposition));
rotate_camera_yaxis(CLOCKWISE, secondangle);
seconddirection = CLOCKWISE;
}
else if ( xposition > 0.0 )
{
secondangle = fabs(atan(xposition/zposition));
rotate_camera_yaxis(ANTICLOCKWISE, secondangle);
seconddirection = ANTICLOCKWISE;
}
}
}


//now that the camera is rotated to the right position we have to orientate it
//so that the up vector is (0,1,0).
//this is done by rotating it around the z axis.

//first test if is already at the proper position
if( (xupvector == 0.0) &amp;&amp; (yupvector == 1.0) &amp;&amp; (zupvector == 0.0) )
return;

vector1[0] = 0.0;
vector1[1] = 1.0;
vector1[2] = 0.0;
vector2[0] = xupvector;
vector2[1] = yupvector;
vector2[2] = zupvector;

cameraangle = dot_product(vector1, vector2);

if (xupvector < 0.0)
{
rotate_camera_zaxis(CLOCKWISE, cameraangle);
cameradirection = CLOCKWISE;
}
else if (xupvector == 0.0)
{
cameraangle = ONEEIGHTY;
rotate_camera_zaxis(ANTICLOCKWISE, ONEEIGHTY);
cameradirection = ANTICLOCKWISE;
}
else // xupvector > 0.0
{
rotate_camera_zaxis(ANTICLOCKWISE, cameraangle);
cameradirection = ANTICLOCKWISE;
}
}

I know this is a lot of code to post but could someone please help me?

blood.angel
02-12-2002, 10:18 AM
Anyone?

Jambolo
02-13-2002, 08:47 PM
Well, one problem is that the dot product returns the cosine of the angle between two unit vectors, not the angle itself.

Jambolo
02-13-2002, 09:05 PM
Another problem is that your use of atan() may result in a divide-by-zero. Use atan2 instead. It's also better because it can tell the difference between -y/-x and y/x and between -y/x and y/-x.

Jambolo
02-13-2002, 09:14 PM
My big question is why are you "un-rotating" the camera? If you want the camera at (0,0,7) looking at (0,0,0) with the up vector parallel to the Y-axis, this code will do it:






glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
gluLookAt( 0.f, 0.f, 7.f, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f );

...draw cube now...

blood.angel
02-14-2002, 09:16 AM
Thanks Jambolo for the reply.
I should have mentioned it but my dot_product() fuction does do an acos within it.

Ill try the atan2 thing you suggested.

And you are getting my roatation problem wrong. The camera rotates around the cube (which is at the origin) and so I want it to 'unrotate' it to a pre defined point (0,0,7) so I can apply the user define rotation, then rotate it back again.

Jambolo
02-14-2002, 10:07 PM
It's not completely clear to me what you are trying to do but I think this code will cover it:





glMatrixMode( GL_MODELVIEW );
glLoadIdentity(); // Reset all transformations
gluLookAt( cx, cy, cz, 0.f, 0.f, 0.f, ux, uy, uz ); // Rotate (actually move) the camera to (cx,cy,cz) pointing at (0,0,0) with up in the direction (ux,uy,uz)
glRotate( angle, ax, ay, az ); // Rotate the cube around the vector (ax,ay,az) by 'angle' degrees
...draw cube now...