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

## 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);
gluPerspective(50,1,0.10,35);
glMatrixMode(GL_MODELVIEW);
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 on other sites
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 isalways '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 cancounter-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 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 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 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 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.