Jump to content
  • Advertisement
Sign in to follow this  
khakionion

gluLookAt headaches

This topic is 4981 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

This is driving me absolutely insane. Here's my problem: I'm trying to implement a camera with gluLookAt(). I've got two 3D vectors that represent the position of the camera and the position of "where it's looking." I pass these to gluLookAt along with an up vector of (0,1,0). I know, I know that I should be calculating the up vector properly, but I can't seem to find the right way to do it, and this problem of mine seems to be largely irrelevant. See, whenever I move the "target" of the camera along the Y-axis, I start getting this weird "shaking" phenomenon, that gets worse depending on how close to the camera the target is. This weird effect occurs even if the target and camera are aligned along the X- and Y-axes, with nothing more their Z-axis component differing. Here's some code: The begining of the render loop, and the gluLookAt function:
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(50,1,0.10,35);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	gluLookAt(CameraLocation[0],CameraLocation[1],CameraLocation[2], TargetLocation[0],TargetLocation[1],TargetLocation[2], 0,1,0);


For example, my display goes bonkers when CameraLocation is (0.75,1,2) and TargetLocation is (0.75,1,0) but not when CameraLocation is (3,3,3) and TargetLocation is (0,0,0). Am I doing something ridiculously wrong? Any help is greatly appreciated!

Share this post


Link to post
Share on other sites
Advertisement
Going by your code, there's nothing wrong. While I haven't had any problems like this, it could be something to do with the way GLU goes about calculating the matrix and then applying it (the gimbal lock, for instance). In my quest to abolish the need for other libraries, I took it upon myself to create something just like gluLookAt, however, my way is based upon trigonometry, rather than matrices. Here's my code:


/*
THIS IS A REPLACEMENT FOR gluLookAt().
It requires 1 less argument (the 'up' vector), because the positive Y axis is
always 'up', unless you rotate it on the Z axis, which you can do on your own.
It will also fill the array with the rotation angles, that way you can
counter-rotate particles/sprites/etc., so that they always look at you.
*/

GLvoid doLookAtR(GLdouble eyeX,GLdouble eyeY,GLdouble eyeZ,GLdouble centerX,GLdouble centerY,GLdouble centerZ,GLdouble* rs){
GLdouble x = eyeX - centerX;
GLdouble y = eyeY - centerY;
GLdouble z = eyeZ - centerZ;

//lengths = 0, no difference = no rotation
if ((x == y) && (y == z) && (z == 0.0f)) return;
//if looking straight up or down (fix for the gimbal lock - as found in gluLookAt)
if ((x == z) && (z == 0.0f)){
if (y < 0.0f){//if looking straight up
glRotated(-90.0f,1,0,0);
}else{//if looking straight down
glRotated(+90.0f,1,0,0);
}
glTranslated(-x,-y,-z);
return;
}

GLdouble rx = 0.0f;
GLdouble ry = 0.0f;

GLdouble hypA = (x == 0.0f) ? z : hypot(x,z);
GLdouble hypB = (y == 0.0f) ? hypA : hypot(y,hypA);
if (z == 0.0f) hypB = hypot(x,y);

rx = toDegs(asin(y / hypB));
ry = toDegs(asin(x / hypA));

//rotate and translate accordingly
glRotated(rx,1,0,0);
if (z < 0.0f){
ry += 180.0f;
}else{
ry = 360.0f - ry;
}
glRotated(ry,0,1,0);
glTranslated(-eyeX,-eyeY,-eyeZ);

if (rs){
rs[0] = rx;
rs[1] = ry;
}
}

GLvoid doLookAt(GLdouble eyeX,GLdouble eyeY,GLdouble eyeZ,GLdouble centerX,GLdouble centerY,GLdouble centerZ){
return doLookAtR(eyeX,eyeY,eyeZ,centerX,centerY,centerZ,0);
}



Try it, and let me know if it fixes your problem (otherwise I'm out of ideas). Just to let you know, toDegs() is a macro I use to convert radians into degrees.

Share this post


Link to post
Share on other sites
Hi, This is the way that I calculate pitch, roll, and yaw. Then pass these resultant vectors (with my vector position) to gluLookAt.

Try it:

//////////////////////////////////////////////////////////////////
// Name: CCAMERA::ApplyPitch - public
// Description: Do Pitch rotations to the z and y axis
// Arguments: Pitch angle(degrees) from main
//////////////////////////////////////////////////////////////////
inline void ApplyPitch(float theta)
{
// Apply x-rotation to z and y axes
m_upTemp[0] = m_vecUp[0];
m_upTemp[1] = m_vecUp[1];
m_upTemp[2] = m_vecUp[2];

if( ( theta >= 360.0f) || ( theta <= -360.0f ) )
theta = 0.0f;

float sinPitch= (float)sinf( DEG_TO_RAD( theta ) );
float cosPitch= (float)cosf( DEG_TO_RAD( theta ) );

//apply pitch to the up vector
m_vecUp[0]=m_upTemp[0]*cosPitch-m_vecForward[0]*sinPitch;
m_vecUp[1]=m_upTemp[1]*cosPitch-m_vecForward[1]*sinPitch;
m_vecUp[2]=m_upTemp[2]*cosPitch-m_vecForward[2]*sinPitch;

//apply pitch to the forward vector
m_vecForward[0]=m_upTemp[0]*sinPitch+m_vecForward[0]*cosPitch;
m_vecForward[1]=m_upTemp[1]*sinPitch+m_vecForward[1]*cosPitch;
m_vecForward[2]=m_upTemp[2]*sinPitch+m_vecForward[2]*cosPitch;

m_vecForward.Normalize();
m_vecUp.Normalize();

}//end ApplyPitch

//////////////////////////////////////////////////////////////////
// Name: CCAMERA::ApplyRoll - public
// Description: Do Roll rotations to the x and y axis
// Arguments: Roll angle(degrees) from main
//////////////////////////////////////////////////////////////////
inline void ApplyRoll(float theta)
{
// Apply z-rotation to x and y axes
m_sideTemp[0] = m_vecSide[0];
m_sideTemp[1] = m_vecSide[1];
m_sideTemp[2] = m_vecSide[2];

if( ( theta >= 360.0f) || ( theta <= -360.0f ) )
theta = 0.0f;

float cosRoll = (float)cosf( DEG_TO_RAD( theta ) );
float sinRoll = (float)sinf( DEG_TO_RAD( theta ) );

m_vecSide[0]=m_sideTemp[0]*cosRoll-m_vecUp[0]*sinRoll;
m_vecSide[1]=m_sideTemp[1]*cosRoll-m_vecUp[1]*sinRoll;
m_vecSide[2]=m_sideTemp[2]*cosRoll-m_vecUp[2]*sinRoll;

m_vecUp[0]=m_sideTemp[0]*sinRoll+m_vecUp[0]*cosRoll;
m_vecUp[1]=m_sideTemp[1]*sinRoll+m_vecUp[1]*cosRoll;
m_vecUp[2]=m_sideTemp[2]*sinRoll+m_vecUp[2]*cosRoll;

m_vecSide.Normalize();
m_vecUp.Normalize();

}//end ApplyRoll

//////////////////////////////////////////////////////////////////
// Name: CCAMERA::ApplyYaw - public
// Description: Do Yaw Y axis rotations to the x and z axis
// Arguments: Yaw angle(degrees) from main
//////////////////////////////////////////////////////////////////
inline void ApplyYaw(float theta)
{
// Apply y-rotation to x and z axes
m_sideTemp[0] = m_vecSide[0];
m_sideTemp[1] = m_vecSide[1];
m_sideTemp[2] = m_vecSide[2];

if( ( theta >= 360.0f) || ( theta <= -360.0f ) )
theta = 0.0f;

float cosYaw = (float)cosf( DEG_TO_RAD( theta ) );
float sinYaw = (float)sinf( DEG_TO_RAD( theta) );

m_vecSide[0]=m_sideTemp[0]*cosYaw+m_vecForward[0]*sinYaw;
m_vecSide[1]=m_sideTemp[1]*cosYaw+m_vecForward[1]*sinYaw;
m_vecSide[2]=m_sideTemp[2]*cosYaw+m_vecForward[2]*sinYaw;

m_vecForward[0]=-m_sideTemp[0]*sinYaw+m_vecForward[0]*cosYaw;
m_vecForward[1]=-m_sideTemp[1]*sinYaw+m_vecForward[1]*cosYaw;
m_vecForward[2]=-m_sideTemp[2]*sinYaw+m_vecForward[2]*cosYaw;

m_vecForward.Normalize();
m_vecSide.Normalize();

}//end ApplyYaw




Then pass all like so:


//////////////////////////////////////////////////////////////////
// Name: CCAMERA::SetViewMatrix - public
// Description: Set the view matrix using the gluLookAt
// utility function, and the calculations from
// ComputeViewMatrix
//////////////////////////////////////////////////////////////////
inline void SetViewMatrix( void )
{
//Let OpenGL calculate the viewing matrix
gluLookAt(m_vecEyePos[0], m_vecEyePos[1], m_vecEyePos[2],
m_vecLookAt[0], m_vecLookAt[1], m_vecLookAt[2],
m_vecUp[0], m_vecUp[1], m_vecUp[2]);}




Hope this helps.

J

Share this post


Link to post
Share on other sites
try adding a small epsilion value to one of the positions
eg
glulookat(cam.x+0.001,cam.y+0.001,cam.z+0.001,dest.x,dest.y,dest.z, 0,1,0 );

Share this post


Link to post
Share on other sites
try adding a small epsilion value to one of the positions
eg
glulookat(cam.x+0.001,cam.y+0.001,cam.z+0.001,dest.x,dest.y,dest.z, 0,1,0 );

Share this post


Link to post
Share on other sites
I tried adding the doLookAt function to my code and using it instead of gluLookAt, and the problem was the same.

I also tried adding an epsilon value, and it didn't help. Argh.

What I'm going to do is try to use quaternions instead, and hope that the problem just happens to disappear in the process. I'll post the results tonight.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!