Strange rotation issue

Hello,

I hope someone can help me, I have been looking at this for a while, and have managed to confuse myself with this little problem. I have a program that succefully(well almost) provides 6 degrees of movement(rotation around x, y, and z axis of camera and movement in x, y, and z axis of camera).

When I rotate up and down(around x axis) and left to right(around z axis) things work fine for a bit, but then the camera seems to start to rotate around the y axis. There is no way to do a y axis rotation in my code. I think it comes from the fact that I do some transformations to write some text to the screen, and exit out of these transfomation incorrectly. I am going to try an show the relevant snippets of code.

Thanks for any help or ideas.

-Drew

==================================

glViewport( 0, 0, width, height);
Vector3 eVec( eye.x, eye.y, eye.z );
m[0] = u.x; m[4] = u.y; m[8] = u.z; m[12] = -eVec.dot( u );
m[1] = v.x; m[5] = v.y; m[9] = v.z; m[13] = -eVec.dot( v );
m[2] = n.x; m[6] = n.y; m[10] = n.z; m[14] = -eVec.dot( n );
m[3] = 0; m[7] = 0; m[11] = 0; m[15] = 1.0;
glMatrixMode( GL_MODELVIEW );
glLoadMatrixf( m );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluPerspective( viewAngle, aspect, nearDist, farDist );

glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

displayPoints();
createFloor();
createHead();
createBody();
createRightArm();
createLeftArm();
createWaist();
createLeftLeg();
createRightLeg();
createClub();

glMatrixMode( GL_PROJECTION );
glPushMatrix();

glLoadIdentity();
gluOrtho2D( 0, width, 0, height );
glScalef( 1, -1, 1 );
glTranslatef( 0, -height, 0 );
glMatrixMode( GL_MODELVIEW );

// start doing transformation to write text
// to screen

glPushMatrix();
glLoadIdentity();

if( showFrame == 1 )
{
outputText.renderBitMapString( width * 0.8, 20, GLUT_BITMAP_HELVETICA_10, string );
}

showInfo(); //writes more text to screen

// done writing to screen. Now undo
// transformations to set up for next redraw

glPopMatrix();

glMatrixMode( GL_PROJECTION );
glPopMatrix();
glMatrixMode( GL_MODELVIEW );

glutSwapBuffers();
redisplay();

You don’t show how you calculate the values for your modelview matrix and that is likely to be the cause of your problems.

Here is another problem: you are drawing your scene while the matrix mode is PROJECTION. That may or may not work.

If you are going to reload the projection and modelview matrices every frame then there is no reason for those pushes and pops.

On the other hand, it is probably better to set the projection matrix once in your reshape function, instead of every frame, and wrap the ortho text code in a push/pop.

Finally, the number one reason for rotations starting out ok, then screwing up is gimble lock.

i think this phenomenon is called drift. a friend of mine experienced it while using quaternions. normalizing your matrices usually helps. i keep track of right, up and look vectors in my engine and normalize them each time through the loop to prevent this from happening.

b

I would say you acumulate some roundoff error in your calculation of (n.x, n.y, n.z), but if you actually renormalize this matrix every frame (!! do you really need to do that every frame ?? In worst case, I do it once in 20 frames) perhaps there is a bug in this calculus.
Please, send the whole computation of n.x,n.y and n.z.

[This message has been edited by rixed (edited 08-09-2002).]

I am going to include my Camera class at the bottom of this e-mail because a couple of people asked for how I computed the modelview matrix and how I computed n.x, n.y, n.z.

As for drawing it in projection mode, I tried commenting out the first glMatrixMode(GL_PROJECTION), because I didn’t think that was nexccesary either, but then nothing ever appears on my screen. And I couldn’t figure out if it was because I was looking at the wrong place, or what. I have a call to normalize in my code at almost evey stage, which looks like the following:
void Vector3::normalize( void )
{
double sizeSq = x * x + y * y + z * z;
if( sizeSq < 0.0000001 )
{
return;
}
float scaleFactor = 1.0 / (float) sqrt( sizeSq );
x *= scaleFactor;
y *= scaleFactor;
z *= scaleFactor;
}

I appreciate all your help so far.

-Drew

-------- camera.cpp ------------

#include “Camera.h”

void Camera::setModelViewMatrix( void )
{
float m[16];

Vector3 eVec( eye.x, eye.y, eye.z );
m[0] = u.x;	m[4] = u.y;	m[8] = u.z;		m[12] = -eVec.dot( u );
m[1] = v.x;	m[5] = v.y;	m[9] = v.z;		m[13] = -eVec.dot( v );
m[2] = n.x;	m[6] = n.y; m[10] = n.z;	m[14] = -eVec.dot( n );
m[3] = 0;	m[7] = 0;	m[11] = 0;		m[15] = 1.0;
glMatrixMode( GL_MODELVIEW );
glLoadMatrixf( m );

}

void Camera::set( Point3 Eye, Point3 look, Vector3 up )
{
eye.set( Eye );
n.set( eye.x - look.x, eye.y - look.y, eye.z - look.z );
u.set( up.cross( n ) );
n.normalize();
u.normalize();
v.set( n.cross( u ) );
setModelViewMatrix();
}

void Camera::set( float eyeX, float eyeY, float eyeZ,
float lookX, float lookY, float lookZ,
float upX, float upY, float upZ )
{

Vector3 up;
up.set( upX, upY, upZ );

eye.set( eyeX, eyeY, eyeZ );
n.set( eyeX - lookX, eyeY - lookY, eyeZ - lookZ );
u.set( up.cross( n ) );
n.normalize();
u.normalize();
v.set( n.cross( u ) );
setModelViewMatrix();

}

void Camera::slide( float delU, float delV, float delN )
{
eye.x += delU * u.x + delV * v.x + delN * n.x;
eye.y += delU * u.y + delV * v.y + delN * n.y;
eye.z += delU * u.z + delV * v.z + delN * n.z;
setModelViewMatrix();
}

void Camera::roll( float angle )
{
float cs = cos( 3.14159265 / 180 * angle );
float sn = sin( 3.14159265 / 180 * angle );
Vector3 t = u;

u.set( cs * t.x - sn * v.x, 
	   cs * t.y - sn * v.y, 
	   cs * t.z - sn * v.z );
v.set( sn * t.x + cs * v.x, 
	   sn * t.y + cs * v.y, 
	   sn * t.z + cs * v.z );
setModelViewMatrix();

}

void Camera: itch( float angle )
{
float cs = cos( 3.14159265 / 180 * angle );
float sn = sin( 3.14159265 / 180 * angle );
Vector3 t = v;

v.set( cs * t.x + sn * n.x, 
	   cs * t.y + sn * n.y, 
	   cs * t.z + sn * n.z );
n.set( cs * n.x - sn * t.x, 
	   cs * n.y - sn * t.y, 
	   cs * n.z - sn * t.z );
setModelViewMatrix();

}

void Camera::yaw( float angle )
{
float cs = cos( 3.14159265 / 180 * angle );
float sn = sin( 3.14159265 / 180 * angle );
Vector3 t = n;

n.set( cs * t.x + sn * u.x, 
	   cs * t.y + sn * u.y, 
	   cs * t.z + sn * u.z );
u.set( cs * u.x - sn * t.x, 
	   cs * u.y - sn * t.y, 
	   cs * u.z - sn * t.z );
setModelViewMatrix();

}

void Camera::setShape( float vAng, float asp, float nearD, float farD )
{
viewAngle = vAng;
aspect = asp;
nearDist = nearD;
farDist = farD;

glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluPerspective( viewAngle, aspect, nearDist, farDist );

}

Camera::Camera() { }

Camera::~Camera() { }

You might have a problem when you call Camera::set(). If the direction of n is close to the direction of up, then you are going to get a lot of error and up.cross(n) may return a vector whose magnitude is small enough that u.normalize() fails.

Shouldn’t it be

n = look - eye

rather than

n = eye - look

?