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]);

GLUquadricObj *quadObj = gluNewQuadric();

gluCylinder(quadObj,0.2,0.2,2,50,50);

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];

}

glLoadIdentity();

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:

glLoadIdentity();

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]);

GLUquadricObj *quadObj = gluNewQuadric();

gluCylinder(quadObj,0.2,0.2,2,50,50);

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

GLUquadricObj *quadObj = gluNewQuadric();

gluCylinder(quadObj,0.2,0.2,2,50,50);

glPopMatrix();

MastahYodah

05-04-2009, 03:06 PM

That helped, thanks a lot!

Powered by vBulletin® Version 4.2.5 Copyright © 2018 vBulletin Solutions Inc. All rights reserved.