PDA

View Full Version : Tracking an object with gluLookAt()



SED
10-08-2000, 11:51 PM
Im wondering how I can track an object in motion with gluLookAt();

If I were rotating a gluSphere() around a point, how would I track it? Ive given the short version of what Im trying to do below...


GLfloat tM[4][4];

struct targetObj
{
GLfloat x, y;
} ball;

struct theCamera
{
GLfloat ex;
GLfloat ey;
GLfloat ez;

GLfloat tx;
GLfloat ty;
GLfloat tz;

GLfloat ux;
GLfloat uy;
GLfloat uz;
} cam;

//Move the red sphere
void IdleTime()
{
int r = 10;
static int a=0;
a++ == 359 ? a=0 : a;
ball.x = r * cos(D2R(a));
ball.y = r * sin(D2R(a));

RenderMain();
}

void RenderMain()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt( cam.ex, cam.ey, cam.ez,
cam.tx, cam.ty, cam.tz,
cam.ux, cam.uy, cam.uz);

glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);

glPushMatrix();
glRotatef(80, 0, 1, 0);
glTranslatef(ball.x, ball.y, 0);
glGetFloatv(GL_MODELVIEW_MATRIX, *tM);
gluSphere(qObj, .25, 30, 30);
glPopMatrix();

//Green sphere @ (0,0,0)
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green);
gluSphere(qObj, .25, 30, 30);
glutSwapBuffers();
}

Someone on the OpenGL news group told me I could extract the current Modelview matrix ( tM[4][4] above ), multiply a zero vector by it and that would give me the spheres position. I tried that but I doesnt track the Sphere. If you multiply a zero vector by a matrix, you simply get the Tx, Ty, Tz in return correct? Can someone fill me in on how this is accomplished? I've tried ditching gluLookAt() and the extracted Tx, Ty & Tz are correct, but when I add gluLookAt the sphere location isnt even close.

Sean

BTW, Im using gluPerspective(50.0f, aspect, .1, 100); in my Resize func.

zed
10-09-2000, 12:47 AM
this seems so simple that its prolly not what u want
"Im wondering how I can track an object in motion with gluLookAt();"
cant u go gluLookAt(..,..,.., objects.x, objects.y,objects.z,......);
now the cameras always looking at the object

edotorpedo
10-09-2000, 04:26 AM
Yes,

zed's solution is DEFINETELY the most simple and elegant solution !

SED
10-09-2000, 07:48 AM
If you'll please look again, you'll see that I'm letting the GL supply the balls Z for me by way of glRotatef(80, 0, 1, 0); Ive added another ball, a blue one orbiting the the red one...

struct targetObj
{
GLfloat x;
GLfloat y;
//No z
};

targetObj redBall, blueBall;

void IdleTime()
{
int r = 10;
static int a=0;
a++ == 359 ? a=0 : a;
redBall.x = r * cos(D2R(a));
redBall.y = r * sin(D2R(a));
//Added to move the blue ball
blueBall.x = (r * .25) * cos(D2R(a));
blueBall.y = (r * .25) * sin(D2R(a));

RenderMain();
}

void RenderMain()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt( cam.ex, cam.ey, cam.ez,
cam.tx, cam.ty, cam.tz,
cam.ux, cam.uy, cam.uz);

glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);

glPushMatrix();
glRotatef(80, 0, 1, 0);
glTranslatef(redBall.x, redBall.y, 0);
gluSphere(qObj, .25, 30, 30);
//Added to transform and render the blue ball
//------------------------------------------------------
glPushMatrix();
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue);
glRotatef(80, 1, 0, 0);
glTranslatef(blueBall.x, blueBall.y, 0);
gluSphere(qObj, .125, 30, 30);
glPopMatrix();
// ------------------------------------------------------
glPopMatrix();

glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green);
gluSphere(qObj, .25, 30, 30);
glutSwapBuffers();
}

So now (AFTER the transformations) the blu balls coordinates have nothing to do with whats in blueBall.x, blueBall.y, and again I dont supply a z coordinate. So I have no z to pass to gluLookAt(), and the I cant simply pass blueBall.x & blueBall.y to it. So now, how do I extract the blue balls coordinates to pass to gluLookAt()?

DFrey
10-09-2000, 08:44 AM
Simple. Get the modelview matrix after doing the ball's transform, then multiply it with the ball's coordinates. The result will be a new vector that contains the ball's current world coordinates.

SED
10-09-2000, 09:05 AM
Ahhh, now that makes more sence. I was told to multiply a ZERO vector by the current Modleview matrix. I didnt give a very good example on my news group post though. Prolly why I got that answer. I'll try your suggestion & see whats what.

thanks DFrey
Sean

DFrey
10-09-2000, 09:30 AM
Actually I just realized I was thinking of something else. What you need to do is multiply that modelview matrix by the w unit vector, (0,0,0,1). Then you'll get the proper coordinates (x,y,z,1). And of course, this means no multiplication at all is necessary, as you can simply extract the coordinates from the modelview matrix itself.
x=matrix[12], y=matrix[13], z=matrix[14]. At least I think those are the right indices.


[This message has been edited by DFrey (edited 10-09-2000).]

SED
10-09-2000, 10:09 AM
DFrey, I think what you are refering to is what I mentioned previously, extracting the Tx, Ty, Tz from the Modelview matrix by multiplying a ZERO vector.

<0,0,0> * M = <Tx, Ty, Tz> ???

Which I could do by just grabing the correct indices out of the matrix, as you mentioned.

Only thing is, I tried both ways, and neither tracks the blue sphere. The camera moves in the general direction (not really), but the blue sphere doesnt stay in the center of the screen.

Heres a link to the source, Ive been compiling, its only 180 or so lines if you, or anyonwe else wants to take a look at it.
http://personal.lig.bellsouth.net/lig/s/_/s_dolan/Track.cpp

Id really like to know how to do this.

Sean

DFrey
10-09-2000, 11:22 AM
Now I see what you are trying to do, and uh, yep, that ain't going to work. See, you are creating a new model matrix based upon where the blue sphere was. But then when you draw the next frame, you again move the blue sphere. So yes it is tracking the blue sphere, it is just that the blue sphere is continually moved away from the new origin.
You need to calculate the view matrix first with respect to the blue sphere then draw the blue sphere without any transforms, then draw the green and red spheres relative to the blue sphere.

[This message has been edited by DFrey (edited 10-09-2000).]

SED
10-09-2000, 01:14 PM
Ok I think Ive bout got it. It works now, the blue sphere stays in the center of the view. You got me thinking about my order of operations. I had to extract the spheres world coordinates BEFORE I called gluLookAt(), but do my rendering after gluLookAt(). Only problem with this is now I have to perform duplicate transform every frame. Because of the very nature of gluSphere() I have to use the GL to transform it into place. I cant use the coordinates I extracted prior to gluLookAt(), because there is no way to tell gluSphere to render @ (X,Y,Z).
I might look up the glu source & see how they did the sphere & add a way to render it, given absolute world coordinates.

Thanks for you help DFrey. Ive got a good idea of what I need to do now. Well alot closer than when I first posted :P

Sean

BTW if you want to look at how Im doing it for now... http://personal.lig.bellsouth.net/lig/s/_/s_dolan/Track.cpp

Yes it still needs LOTS of work, but it does do what I want, just in a round about way .