PDA

View Full Version : A fly-through camera with an object in front?

MastahYodah
05-03-2009, 08:59 PM
Hi everyone,

I am pretty new to openGL, and I managed to get a fly-through camera to work. Now I have an issue with keeping a cylinder in front of the camera. The way my fly-through camera works is that I update the values in gluLookAt() accordingly, and it works fine. Then I try to translate the cylinder to the point that I'm looking at:

glPushMatrix();
glTranslatef(a[0], a[1], a[2]);
glPopMatrix();

(where a[0], a[1], a[2] are the 4th, 5th and 6th argument of gluLookAt()), and the cylinder only stays in front of the camera if I move forwards of backwards. The moment I do movements such as yaw and pitch, it distorts gets out of the picture. Can anyone help? Thank you.

dletozeun
05-04-2009, 02:46 AM
The target position might be invalid, how do you compute this one?

MastahYodah
05-04-2009, 07:36 AM
I compute it by updating the look-at vector n[] and it works fine. In the beginning I declare the vectors, where u, v and n are the vectors representing the coordinate system of the camera:
GLfloat e[] = {0.0, 1.0, 1.0, 1.0};
GLfloat a[] = {0.0, 0.0, 0.0, 1.0};
GLfloat n[] = {0.0,0.0, 1.0, 0.0};
GLfloat v[] = {0.0, 1.0, 0.0, 0.0};
GLfloat u[] = {1.0, 0.0, 0.0, 0.0};

Then in the keyboard function I modify u, v and n accordingly:

// move with pitch
if (key == 'O' || key == 'o') {

xTemp = v[0];
yTemp = v[1];
zTemp = v[2];
v[0]=cos(alpha)*xTemp - sin(alpha)*n[0];
v[1]=cos(alpha)*yTemp - sin(alpha)*n[1];
v[2]=cos(alpha)*zTemp - sin(alpha)*n[2];
n[0]=sin(alpha)*xTemp + cos(alpha)*n[0];
n[1]=sin(alpha)*yTemp + cos(alpha)*n[1];
n[2]=sin(alpha)*zTemp + cos(alpha)*n[2];

}
if (key == 'K' || key == 'k') {

xTemp = v[0];
yTemp = v[1];
zTemp = v[2];
v[0]=cos(alpha)*xTemp + sin(alpha)*n[0];
v[1]=cos(alpha)*yTemp + sin(alpha)*n[1];
v[2]=cos(alpha)*zTemp + sin(alpha)*n[2];
n[0]=-sin(alpha)*xTemp + cos(alpha)*n[0];
n[1]=-sin(alpha)*yTemp + cos(alpha)*n[1];
n[2]=-sin(alpha)*zTemp + cos(alpha)*n[2];

}

// move with yaw
if (key == 'A' || key == 'a') {

xTemp = u[0];
yTemp = u[1];
zTemp = u[2];
u[0]=cos(alpha)*xTemp + sin(alpha)*n[0];
u[1]=cos(alpha)*yTemp + sin(alpha)*n[1];
u[2]=cos(alpha)*zTemp + sin(alpha)*n[2];
n[0]=-sin(alpha)*xTemp + cos(alpha)*n[0];
n[1]=-sin(alpha)*yTemp + cos(alpha)*n[1];
n[2]=-sin(alpha)*zTemp + cos(alpha)*n[2];

}

if (key == 'D' || key == 'd') {

xTemp = u[0];
yTemp = u[1];
zTemp = u[2];
u[0]=cos(alpha)*xTemp - sin(alpha)*n[0];
u[1]=cos(alpha)*yTemp - sin(alpha)*n[1];
u[2]=cos(alpha)*zTemp - sin(alpha)*n[2];
n[0]=sin(alpha)*xTemp + cos(alpha)*n[0];
n[1]=sin(alpha)*yTemp + cos(alpha)*n[1];
n[2]=sin(alpha)*zTemp + cos(alpha)*n[2];

}

// move forwards and backwards.

int s = 1;

int i;
if (key == 'S' || key == 's') {
for (i=0; i<3; i++) {
e[i] += s*n[i];

}
}
if (key == 'W' || key == 'w') {
for (i=0; i<3; i++) {
e[i] -= s*n[i];

}
}

Then in the display function I compute the a[] point by adding e[] to n[], and I update gluLookAt():

for (i = 0; i < 4; i++) {
a[i] = e[i] + n[i];
}
gluLookAt(e[0],e[1],e[2],a[0],a[1],a[2],v[0],v[1],v[2]);

dletozeun
05-04-2009, 08:06 AM
That looks correct at first sight.

I notice that you call glPushMatrix before translating your cylinder. What is the matrix state before pushing it? (<s>It should be equal to identity</s>).

MastahYodah
05-04-2009, 08:26 AM
So after I load the identity I call gluLookAt() with updated values:

gluLookAt(e[0],e[1],e[2],a[0],a[1],a[2],v[0],v[1],v[2]);

Then, I draw a rectangular box that I need (it's in a display list), then I draw the particles generated by particleDisplay,
and after that, I draw the cylinder with its translation property; it's the cylinder that I need to have in front of me as I fly around the world:

//rectangular box.
glPushMatrix();
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, none);
glCallList(BOX);
glPopMatrix();

//Particles...
glPushMatrix();
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess1);
particleDisplay();
glPopMatrix();

//Cylinder
glPushMatrix();
glTranslatef(a[0], a[1], a[2]);
glPopMatrix();

skynet
05-04-2009, 10:53 AM
instead of trying to place the cylinder in the world, so the camera can "see" it, why not do it the other way around place the camera temporarly so, that it always looks at the standard-cyclinder (which is positioned somewhere around the origin)?

//Cylinder
glPushMatrix();
glLoadIdentity(); // place camera at origin, looking down -z
glTranslatef(0, 0, -100); // move camera slightly back (by pushing the world forward), so it can see the cyclinder