# OpenGL Issue with 3D Camera Control (OpenGL)

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

## Recommended Posts

I'm having some trouble getting a camera to work as I want. For a 3D scene I'm doing in my graphics programming unit I've got about 100 (it worked with 500000... but with a fps of about 0.075 :p) randomly generated shapes falling down the screen. To finish the program off I have to be able to navigate the scene. Basic camera control is all I need and I have that (forward, back, side to side, up and down). What I've been working on for brownie points is making the camera rotate horizontally on left/right, move forward and backward on up/down and tilt up and down on page up/down. My problem comes when trying to tilt the camera when the line of sight of the camera is not perpendicular to the X or Z axis. I start the camera at position (0,0,5) and have it looking at (0,0,0) (straight down the Z axis, the Z and X axis's being my flat or ground plane). I can tilt the camera and rotate the camera and move back and forth just fine from this starting point. However if I rotate the camera and then try tilting weird things happen, like the camera snapping to an inverted X (X of the point being looked at) value and tilting down at a 45 degree angle. I believe the problem to be that when the Y (look at) value is changed by tilting and either X or Z (look at values) are not 0 both the X and Z values need to change in order to keep the Line of Sight distance (from camera to the point it looks at) the same. But they change by different amounts based on the ratio between them at that specific point. So X=1 and Z=2 would mean the trig value for X would be reduced to 33% and the Z 66%. I think I'm probably doing this a really hard and awkward way. If there is a better way do tell. Anyway, the code:
switch(key)
{
//camera movement
case GLUT_KEY_UP:{
float lOSDx = camLookX - camPosX;  //x distance between points
float iOSDy = camLookY - camPosY;  //y distance between points
float lOSDz = camLookZ - camPosZ;  //z distance between points
//multiply the distance by the speed factor and x1.0 to get the distance to move the camera at the look at point
SetCameraVars(true,1.0*lOSDx*camMoveSpeed,1.0*lOSDx*camMoveSpeed,1.0*lOSDz*camMoveSpeed,1.0*lOSDx*camMoveSpeed,1.0*lOSDx*camMoveSpeed,1.0*lOSDz*camMoveSpeed,0.0,0.0,0.0);
break;}
case GLUT_KEY_DOWN:{
float lOSDx = camLookX - camPosX;  //x distance between points
float iOSDy = camLookY - camPosY;  //y distance between points
float lOSDz = camLookZ - camPosZ;  //z distance between points
//multiply the distance by the speed factor and times by -1.0 (MINUS) to get the distance to move the camera at the look at point
SetCameraVars(true,-1.0*lOSDx*camMoveSpeed,-1.0*lOSDx*camMoveSpeed,-1.0*lOSDz*camMoveSpeed,-1.0*lOSDx*camMoveSpeed,-1.0*lOSDx*camMoveSpeed,-1.0*lOSDz*camMoveSpeed,0.0,0.0,0.0);
break;}
case GLUT_KEY_LEFT:{
camAngle -= 0.035;  //the angle to turn
//use trig to determine the new position of the look at position
UpdateLineOfSight(sin(camAngle), (camLookY - camPosY), -cos(camAngle));
break;}
case GLUT_KEY_RIGHT:{
camAngle += 0.035;  //the angle to turn
//use trig to determine the new position of the look at position
UpdateLineOfSight(sin(camAngle), (camLookY - camPosY), -cos(camAngle));
break;}
case GLUT_KEY_PAGE_UP:{
vCamAngle += 0.035;  //the angle to turn
//use trig to determine the new position of the look at position
UpdateLineOfSight(/*this bit is the problem, i think*/sin(camAngle)*(-sin(vCamAngle)), sin(vCamAngle), (cos(camAngle))*(-cos(vCamAngle)));
break;}
case GLUT_KEY_PAGE_DOWN:{
vCamAngle -= 0.035;  //the angle to turn
//use trig to determine the new position of the look at position
UpdateLineOfSight(/*this bit is the problem, i think*/sin(camAngle)*(-sin(vCamAngle)), sin(vCamAngle), (cos(camAngle))*(-cos(vCamAngle)));
break;}
//to make the above work properly you need to adjust both the x and z values when the y is altered.
//you have to calculate the percentage that x should move compared to z (i.e 50:50 at 45%/(PI/2) camAngle)
//if y is raised the distance from pos.x,z to look.x,z decreses. the opposite when y is lowered
}


The two functions used above:
void SetCameraVars(bool adjust,
float pX, float pY, float pZ,
float lX, float lY, float lZ,
float upX, float upY, float upZ)
{
if (adjust != true)
{
// set variables
camPosX = pX;
camPosY = pY;
camPosZ = pZ;
camLookX = lX;
camLookY = lY;
camLookZ = lZ;
camUpX = upX;
camUpY = upY;
camUpZ = upZ;
}
else
{
//append variables
camPosX += pX;
camPosY += pY;
camPosZ += pZ;
camLookX += lX;
camLookY += lY;
camLookZ += lZ;
camUpX += upX;
camUpY += upY;
camUpZ += upZ;
}
}

void UpdateLineOfSight(float lX, float lY, float lZ)
{
camLookX = camPosX + lX;
camLookY = camPosY + lY;
camLookZ = camPosZ + lZ;
}


To sum it up the camera should: A) rotate horizontally and vertically B) move forward and backwards in whatever direction it is facing C) always remain the same way up And it does wrong: A) Does not tilt correctly if it has been rotated horizontally Oh and thanks.

##### Share on other sites
I've figured it out.

case GLUT_KEY_PAGE_UP:{		if (vCamAngle < ((PI/2.0)-0.035))			vCamAngle += 0.035;  //the angle to turn		//use trig to determine the new position of the look at position		UpdateLineOfSight((cos(vCamAngle))*sin(camAngle), sin(vCamAngle), (cos(vCamAngle))*-cos(camAngle));		break;}	case GLUT_KEY_PAGE_DOWN:{		if (vCamAngle > ((-PI/2.0)+0.035))			vCamAngle -= 0.035;  //the angle to turn		//use trig to determine the new position of the look at position		UpdateLineOfSight((cos(vCamAngle))*sin(camAngle), sin(vCamAngle), (cos(vCamAngle))*-cos(camAngle));		break;}

It was similar to what I had been trying. I starting thinking about it in terms of triangle lengths instead of angles and that brought me to the cos(vCamAngle)*(whatever) which worked (thank god). I also put in a check to make sure the camera doesn't go past vertical.

1. 1
2. 2
3. 3
Rutin
22
4. 4
5. 5
khawk
14

• 9
• 11
• 11
• 23
• 12
• ### Forum Statistics

• Total Topics
633654
• Total Posts
3013169
×