Rendering Objects

Say I have a spaceship (camera) and another ship I want to render.
How do I render the 2nd ship from the viewpoint of the first ship when I have two positions in space (one for each ship) and two quaternions representing the ships orientations?

Thanks

This sounds like a case for gluLookAt as follows;


  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  gluLookAt(0.0, 0.0, 5.0,       /* camera is at (0,0,5) */
            3.0, 1.0, 0.0,       /* 2nd ship is at (3,1,0) */
            0.0, 1.0, 0.);       /* up is in positive Y direction */
  
  /* start drawing your scene */

Of course the numbers will be your global scene cooridinates from your ships actual locations. The “up” vector is the orientation of the camera … see another openGL post for more explaination

Also, OpenGL does not use quaternions; it uses matricies. If you’re using shaders, you need to figure out the best way to use the quaternions. If you’re using the fixed pipeline (or using matricies in your shaders), check out this article.

Yeah I should have thought of gluLookAt(). Thanks guys.

Problem. The camera isn’t looking directly at the second ship. Its orientation is determined by another quaternion.

A while back I was playing with Sean O’Neil’s procedural Universe projects.

He has a very nice set of Matrix and Quaternion functions, and an excellent Camera class. You might find his project and source worth a look. :slight_smile:

From Maths - AxisAngle to Matrix I speculate you can get the up vector from the following:


given the spaceship's quaternion 
q(theta,(nx,ny,nz))=(cos(theta/2),sin(theta/2)(nx,ny,nz))
with nx^2+ny^2+nz^2=1 condition satisfied

c =cos(theta) // be careful of factor of  theta/2 above!
s = sin(theta)
t = 1 - c

[R] = 
t*nx*nx + c 	t*nx*ny - nz*s 	t*nx*nz + ny*s
t*nx*ny + nz*s 	t*ny*ny + c 	t*ny*nz - nx*s
t*nx*nz - ny*s 	t*ny*nz + nx*s 	t*nz*nz + c

// so up direction in global cooridinates is determined by a rotation	
up = [R]*(0,1,0) ie the middle column of R
   = (t*nx*ny - nz*s, t*ny*ny + c, t*ny*nz + nx*s)

So back to your original question – you want to look out the spaceship along its orientation quaternion n-vector (rather than just at ship 2 like I first thought):


  eye = spaceship (camera) location in global cooridinates
  center = eye + (nx,ny,nz) // yes vector add eye with n!
  up = (t*nx*ny - nz*s,t*ny*ny + c,t*ny*nz + nx*s)
  gluLookAt(eyeX,eyeY,eyeZ,
            centerX,centerY,centerZ,
            upX,upY,upZ)


*** WARNING *** Note, I am just speculating here since I haven’t tested this or confirmed with an openGL sim the above. I would expect you to think about this and confirm or deny this :slight_smile: In other words don’t take this as the correct answer just a first pass idea of how you might find the up vector. The eye and center determination I have no doubt about, it is just the determination of the up vector as described in global coordinates that needs confirmation.

Thanks for the replies. But one last question. Now I have the gluLookAt() working right, how do I actually draw the 2nd ship? The reason its causing problems for me is that glTranslatef() is relative to the “camera”, and not to global world coordinates.

Thanks

If you are using gluLookAt correctly it should be first then you draw your scene ie ship 1 and 2 both given by GLOBAL coordinates.


  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  gluLookAt(eyeX,eyeY,eyeZ,
            centerX,centerY,centerZ,
            upX,upY,upZ);
  
  /* start drawing your scene */
  glPushMatrix();
    glTranslatef(ship one location in global coordinates);
    glRotatef(ship ones rotation);
    drawShipOne();
  glPopMatrix();

  glPushMatrix();
    glTranslatef(ship two location in global coordinates);
    glRotatef(ship two's rotation);
    drawShipTwo();
  glPopMatrix();

Note the order of operations (Translate,Rotate) is important. If you do (Rotate,Translate) I suspect that may be causing a problem. Or if you are not using push/pop that may also explain your problem.

Can you post the relevant parts of your code ie code near the gluLookAt and the drawing scene code? That may help the readers to debug your problem better.

glPushMatrix();
glLoadIdentity();
gluLookAt(Pos->x, Pos->y, Pos->z,
In.x, In.y, In.z,
Up.x, Up.y, Up.z);

while (i!=AlienShip.end())
{
glPushMatrix();
glTranslatef(i->Pos.x, i->Pos.y, i->Pos.z);
glMultMatrixf((GLfloat *)m);
i->ShipModel->Draw();
glPopMatrix();
++i;
}

glPopMatrix();

Your code looks like I would expect-- except the top and bottom Push/Pop pair. Usually the gluLookAt is called at the very beginning of the scene drawing function, only once, immediately after the glMatrixMode(GL_MODELVIEW); glLoadIdentity(); pair. This negates the need to have your outermost push/pop pair. I more expected the code to look like this;


void draw_scene() {
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

  glMatrixMode(GL_MODELVIEW); 
  glLoadIdentity();
  gluLookAt(Pos->x, Pos->y, Pos->z,
              In.x,   In.y,   In.z,
              Up.x,   Up.y,   Up.z);

  while (i!=AlienShip.end())
  {
   glPushMatrix();
     glTranslatef(i->Pos.x, i->Pos.y, i->Pos.z);
     glMultMatrixf((GLfloat *)m);
     i->ShipModel->Draw();
   glPopMatrix();
   ++i;
  }
}

  • Is your m matrix purely a rotation? In other words does it have the form (with the last row and column precisely as shown with 0’s and 1, and the rij any numerical value)?

m=[r00  r01  	r02  	0
   r10 	r11 	r12 	0
   r20 	r21 	r22 	0
   0 	0 	0 	1]

  • A simple test is to comment out the line “glMultMatrixf((GLfloat *)m);” and see if the ships show up at the “correct” locations ignoring thier rotation orientations which then would be wrong.

  • Is your ShipObject::Draw() defined such that the ship’s vertices are centered at the origin (0,0,0)?

the Matrix “m” is purely a rotation, yes, in the form you describe above. The ship shows up in the correct location, but when i move the camera view around, the ship doesn’t move around right.
I’m not sure how to describe how it acts without showing a demo.
The ship objects vertices are centered at the origin, yes.
I’ll just say this, when I run the program, and rotate the camera left or right, the ship in view rotates appropriately. It’s when I pitch the camera it stuffs up.

Thanks.

Ok, your answers make me think that you are drawing things correctly so we should revisit gluLookAt again. I am proposing a new way to do this.

Suppose your ship with a camera mounted in the cockpit looks like:

This is the ship as drawn in local coordinates (ie no rotations/translations applied) which helps to define the definitions of the camera. Note, the XYZ coordinate definition just right of the ships cockpit.

Based on this particular ship’s definition vertices shown in the picture, the camera looking out the cockpit must be defined as:


focus_local = (0,1,0); // camera looks up along along y-axis
    up_local = (0,0,1); // the lens is in the XZ-plane, top of camera is at +z and bottom of camera is at -z

//side note, since I don't know how you represent rotations,
//above is true if you represent rotations with a 3x3 matrix.
//
//you will have to add the "w" coordinate = 1 if you 
//represent rotations with a 4x4 rotation matrix
focus_local = (0,1,0,w=1); // camera looks up along along y-axis
    up_local = (0,0,1,w=1); // the lens is in the XZ-plane, top of camera is at +z and bottom of camera is at -z


  • WARNING * If your ship is defined in local coordinates differently then you will have to orient the camera in local coordinates to match or initial drawing.

Now lets move onto drawing the scene: This ship must have an orientation quaternion that you have translated into an openGL rotation matrix, lets call it M_ship. And this same ship is located in global coordinates at


Pos=(Pos->x, Pos->y, Pos->z)

What is is the “In” vector? The camera direction in global cooridinates is the original focus_local rotated by the same rotation as the ship itself; M_shipfocus_local. And the “in” vector is any point starting at the ship’s “Pos” along the camera direction "M_shipfocus_local" so


In = Pos+M_ship*focus_local;

What is the " Up" vector in global coordinates required by gluLookAt? This is the camera’s “up” direction in local cooridinates rotated by the same rotation as the ship itself.


Up = M_ship*up_local;

So putting it all together you now have what you need to use gluLookAt.


void draw_scene() {
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

  In = Pos+M_ship*focus_local; // you need to do explicit Matrix times Vector
  Up = M_ship*up_local;

  glMatrixMode(GL_MODELVIEW); 
  glLoadIdentity();
  gluLookAt(Pos->x, Pos->y, Pos->z, // Location in global coordinates of the Ship with camera
              In.x,   In.y,   In.z, // In = Pos+M_ship*focus_local
              Up.x,   Up.y,   Up.z); // Up = M_ship*up_local

  while (i!=AlienShip.end())
  {
   glPushMatrix();
     glTranslatef(i->Pos.x, i->Pos.y, i->Pos.z);
     glMultMatrixf((GLfloat *)m);
     i->ShipModel->Draw();
   glPopMatrix();
   ++i;
  }
}


PS The BLENDER drawing is something I downloaded off the web. The author requests credit be given whenever shown publicly. So here it is
///////////////////////////////////////////////////////////
"Have Fun with This StarCruiser.

You can use it like you want to, but if you public a file, which
inkluding this Stare-Cruiser, I want you to tell my Name.

greeds
Patrick Fokenthaler (DonFokn)

Contact:
ICQ: 257682533"

I had a little time to think, and realized that I hadn’t drawn the ship with the camera. You need to draw it after use of gluLookAt.

Nor did I account for the fact that the camera is not at the origin of the figure shown above. In local coordinates of the ship, the camera is at


camera_pos_local = (0,0.25,.75) // of course this depends 
                                // on the particular ship
                                // geometry, you will have
                                // different numbers

The effect of this camera offset is expressed in “In” and a new “Eye” Position used in gluLookAt. The code would be generalized as follows;


void draw_scene() 
{
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

  Eye = Pos+M_ship*(            camera_pos_local);
  In  = Pos+M_ship*(focus_local+camera_pos_local);
  Up  =     M_ship*up_local;

  glMatrixMode(GL_MODELVIEW); 
  glLoadIdentity();
  gluLookAt(  Eyex,   Eyey,   Eyez,
              In.x,   In.y,   In.z, 
              Up.x,   Up.y,   Up.z); 

  while (i!=AlienShip.end())
  {
   glPushMatrix();
     glTranslatef(i->Pos.x, i->Pos.y, i->Pos.z);
     glMultMatrixf((GLfloat *)m);
     i->ShipModel->Draw();
   glPopMatrix();
   ++i;
  }

  //draw ship with camera
  glPushMatrix();
    glTranslatef(Pos->x, Pos->y, Pos->z);
    glMultMatrixf((GLfloat *)M_ship);
    Ship_having_camera->Draw();
  glPopMatrix();
}

Thanks for help you’ve given here. I’ll eventually get this thing working.

Thanks again.

I have learned a lot form people on openGL forums so I try to help when I can :slight_smile:

When you do verify or find a solution it may help others if you post it here. I am sure lots of people are working on similar quaternion problems and could benefit from your efforts.

Anyhow, if I get a chance to expand my code suggested above and it works I will post it here … stay tuned.