Brandon
Brandon

Reputation: 789

How can one achieve a view from a moving object with OpenGL?

I have a car moving around an elliptical track on OpenGL. The top-down view is pretty straight-forward, but I can't seem to figure out the driver's-eye view. Here are the equations that define the position and orientation of the car on the track:

const double M_PI = 4.0*atan(1.0);
carAngle += (M_PI/180.0);
if (carAngle > 2.0*M_PI) {
    carAngle -= 2.0*M_PI;
}
carTwist = (180.0 * atan2(42.5*cos(carAngle), 102.5*sin(carAngle)) / M_PI)-90.0;

These calculations are kept in a Timer Func, and here is the code for the transformations:

// These are the inside/outside unit measurements
// of the track along the major/minor axes.
insideA = 100;
insideB = 40;
outsideA = 105;
outsideB = 45;

glPushMatrix();
glTranslated(cos(carAngle)*(outsideA+insideA)/2.0,
             0.0,
             sin(carAngle)*(outsideB+insideB)/2.0);
glScaled(10.0, 10.0, 10.0);
glRotated(carTwist, 0.0, 1.0, 0.0);
glCallList(vwListID1);
glPopMatrix();

This is viewed with gluLookAt, as follows:

gluLookAt(0.0, 20.0, 0.0, 
          0.0,  0.0, 0.0, 
          0.0,  0.0, 1.0);

This works just fine, and the car moves along the track and turns as expected. Now I want a "camera" view from the car. I am attempting this in a separate window, and I have everything with the second window working fine, except I can't get the view right.

I thought it would be something like:

double x, z, lx, lz;
x = cos(carAngle)*(outsideA+insideA)/2.0;
z = sin(carAngle)*(outsideB+insideB)/2.0;
lx = sin(carTwist);
lz = cos(carTwist);

gluLookAt(x,   1.0, z,
          lx,  1.0, lz,
          0.0, 1.0, 0.0);

The positioning, of course, works just fine, if I look top-down with gluLookAt using x, 20.0, z for the eye coordinates, and x, 0.0, z for the center coordinates, the car stays center screen. Since carTwist is the angle from the positive z-axis to the tangent line of the current car position on the track, the vector [sin(alpha),1,cos(alpha)] should provide a point 1 unit in front of the eye coordinates down the desired line of sight. But this doesn't work at all.

On another note, I tried using model transformations to achieve the same effect, but without luck. I would assume if I reverse the transformations without setting gluLookAt, I should get the desired view. i.e.:

glTranslated(-(cos(carAngle)*(outsideA+insideA)/2.0),
             0.0,
             -(sin(carAngle)*(outsideB+insideB)/2.0));
glRotated(-carTwist, 0.0, 1.0, 0.0);

According to this article, it should provide the same view.

Any help on either approach?

Upvotes: 2

Views: 1357

Answers (1)

kappamaki
kappamaki

Reputation: 676

Your current lx and lz should be the look direction you want, however they are coordinates centered at the origin.

The 4th, 5th, and 6th arguments of gluLookAt specify a point in the scene to look at, not a look direction.

Therefore you will need to add the look direction to the camera position to get a point in the scene to direct your camera at.

Also, since carTwist is in degrees, you will need to convert it to radians for use with cos and sin functions.

double x, z, lx, lz;
x = cos(carAngle)*(outsideA+insideA)/2.0;
z = sin(carAngle)*(outsideB+insideB)/2.0;
lx = x + cos(carTwist * M_PI / 180.0);
lz = z + sin(carTwist * M_PI / 180.0);

Upvotes: 1

Related Questions