paintstripper
paintstripper

Reputation: 97

Camera rotation (OpenGL)

I am having trouble with a camera class I am trying to use in my program. When I change the camera_target of the gluLookAt call, my whole terrain is rotating instead of just the camera rotating like it should.

Here is some code from my render method:

camera->Place();

    ofSetColor(255, 255, 255, 255);

 //draw axis lines
 //x-axis
 glBegin(GL_LINES);
 glColor3f(1.0f,0.0f,0.0f);
 glVertex3f(0.0f,0.0f,0.0f);
 glVertex3f(100.0f, 0.0f,0.0f);
 glEnd();

 //y-axis
 glBegin(GL_LINES);
 glColor3f(0.0f,1.0f,0.0f);
 glVertex3f(0.0f,0.0f,0.0f);
 glVertex3f(0.0f, 100.0f,0.0f);
 glEnd();

 //z-axis
 glBegin(GL_LINES);
 glColor3f(0.0f,0.0f,1.0f);
 glVertex3f(0.0f,0.0f,0.0f);
 glVertex3f(0.0f, 0.0f,100.0f);
 glEnd();

 glColor3f(1,1,1);

 terrain->Draw();

And the rotate and place methods from my camera class:

void Camera::RotateCamera(float h, float v){
hRadians += h;
vRadians += v;

cam_target.y = cam_position.y+(float)(radius*sin(vRadians));
cam_target.x = cam_position.x+(float)(radius*cos(vRadians)*cos(hRadians));
cam_target.z = cam_position.z+(float)(radius*cos(vRadians)*sin(hRadians));

cam_up.x = cam_position.x-cam_target.x;
cam_up.y = ABS(cam_position.y+(float)(radius*sin(vRadians+PI/2))) ;
cam_up.z = cam_position.z-cam_target.z;
}

void Camera::Place() {
//position, camera target, up vector
gluLookAt(cam_position.x, cam_position.y, cam_position.z, cam_target.x, cam_target.y, cam_target.z, cam_up.x, cam_up.y, cam_up.z);
}

The problem is that the whole terrain is moving around the camera, whereas the camera should just be rotating.

Thanks for any help!

EDIT - Found some great tutorials and taking into account the answers on here, I make a better camera class. Thanks guys

Upvotes: 2

Views: 10155

Answers (3)

andand
andand

Reputation: 17507

From the POV of the terrain, yes, the camera is rotating. But, since your view is from the POV of the camera, when you rotate the camera, it appears that the terrain is rotating. This is the behavior that gluLookAt() is intended to produce. If there is something else that you expected, you will need to rotate only the geometry that you want rotated, and not try to rotate using gluLookAt().

Update 1: Based on the discussion below, try this:

void Camera::RotateCamera(float h, float v)
{ 
  hRadians += h; 
  vRadians += v; 

  cam_norm.x = cos(vRadians) * sin(hRadians); 
  cam_norm.y = -sin(vRadians);
  cam_norm.z = cos(vRadians) * sin(hRadians); 

  cam_up.x = sin(vRadians) * sin(hRadians);
  cam_up.y = cos(vRadians);
  cam_up.z = sin(vRadians) * cos(hRadians);
} 

void Camera::Place()
{ 
  //position, camera target, up vector 
  gluLookAt(cam_pos.x, cam_pos.y, cam_pos.z,
            cam_pos.x+cam_norm.x, cam+pos.y+cam_norm.y, camp_pos.z+cam_norm.z,
            cam_up.x, cam_up.y, cam_up.z); 
} 

Separating the camera normal (the direction the camera is looking) from the position allows you to independently change the position, pan and tilt... that is, you can change the position without having to recompute the normal and up vectors.

Disclaimer: This is untested, just what I could do on the back of a sheet of paper. It assumes a right handed coordinate system and that pan rotation is applied before tilt.

Update 2: Derived using linear algebra rather than geometry... again, untested, but I have more confidence in this.

Upvotes: 1

JustBoo
JustBoo

Reputation: 1741

Should it not be?:

cam_up.x = cam_target.x - cam_position.x;

cam_up.y = ABS(cam_position.y+(float)(radius*sin(vRadians+PI/2))) ;

cam_up.z = cam_target.z - cam_position.z;

Perhaps you should normalize cam_up as well. HTH

Upvotes: 0

Ole Dittmann
Ole Dittmann

Reputation: 1774

Well, rotating the camera or orbiting the terrain around the camera looks essentially the same. If you want to orbit the camera around a fixed terrain point you have to modify the camera position, not the target.

Upvotes: 0

Related Questions