Jump to content
  • Advertisement
Sign in to follow this  
Elof Valantor

OpenGL Issue with 3D Camera Control (OpenGL)

This topic is 3600 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

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 this post


Link to post
Share on other sites
Advertisement
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.

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!