tags:

views:

228

answers:

3

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

A: 

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.

kaptnole
A: 

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.

andand
I thought that it was supposed to give a "panning" shot with the camera in one position, not orbiting around the target. How do I go about doing this?
paintstripper
Okay, I see what you're saying now. Assuming there are no other transformations on the terrain, and you are orbiting around the terrain, then your camera position is changing. Look in your code for places where your camera position is changing or where there are other transformations that could be moving the terrain. Your call to gluLookAt() appears to be correct, given what you have posted.
andand
@paintstripper: One other thing, the way I typically use gluLookAt() for a camera class is to give it a position (X, Y, Z) and an orientation (Y, P, R) (for yaw, pitch and roll, though you could use Rx, Ry, and Rz for rotation about X, Y, and Z respectively). I then apply the respective rotations for the normal vector (0, 0, 1) and the up vector (0, 1, 0). Again, I don't see anything intrinsicly wrong with the way you've done it, though I could use a better understanding of your thoughts for computing cam_up.y.
andand
Most of the camera code is from here:http://www.gamedev.net/reference/articles/article2160.asp
paintstripper
@paintstripper: What behavior do you get when you hard code cam_up as (0, 1, 0) and just pan the camera to the left and right (i.e. adjust hRadians, but leave vRadians at 0)?
andand
Seems to work much better. I tried with simple code - glLoadIdentity(); glRotatef(roll, 0.0f, 0.0f, 1.0f); glRotatef(pitch, 1.0f, 0.0f, 0.0f); glRotatef(yaw, 0.0f, 1.0f, 0.0f); glTranslatef(-xpos, -ypos, -zpos);and it works well.
paintstripper
@paintstripper: I updated my answer based on this discussion. I think the approach at the article is suspect.
andand
A: 

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

JustBoo