gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

DS development > Trying to make a camera system

#104223 - DiscoStew - Wed Sep 27, 2006 6:33 am

I've been at this for a while, and even though I've only starting OpenGL in the past few days, I am getting frustrated because I am really unsure about whether or not I'm even doing this right, and I would appreciate any help that could get me pointed in the right direction if possible.

What I am trying to do in my program is make a freely moveable camera with attributes of having a 3D position and 3 axises to tilt in any direction. My problem deals with the camera position and the object positions in the scene, though I may go into other things that perhaps might be changed to help fix those problems.

As far as making the camera affected by it axis, I have the following code...
Code:
gluLookAtf32( camPos.x, camPos.y, camPos.z, camPos.x, camPos.y, camPos.z - 4096, 0, 4096, 0 );
glRotatef32i( camLookAng.y, 0, 4096, 0 );
glRotatef32i( camLookAng.x, 4096, 0, 0 );
glRotatef32i( camLookAng.z, 0, 0, 4096 );

...which pretty much allows my camera to look at any angle from it's position. This seems to work until I either look straight down or straight up (which if I have read correctly creates problems unless you adjust the Up vector?), but enough of that, as I am more concerned with actual positioning.

As that function shows, I have the coordinates for the camera, as well as a place to look at that is 1 unit ahead of it, but when I go to place objects in the scene by translation, they seem to go off where the camera is, like that is where (0,0,0) is. It could be something very simple in my project that I have overlooked, but out of all the examples and tutorials I've seen, I have not seen anything that could help against this. All I want is to have my camera to not be fixed at (0,0,0), but have everything go off of that point and not the camera. Here is my actual code...
Code:
int main( void )
{

   *code here for initialization, cut out to not make this large*

   GLvector camPos = { 0, 4096, 0 };

   // Set our viewport to be the same size as the screen
   glViewPort( 0, 0, 255, 191 );
   
   // Specify the Clear Color and Depth
   glClearColor( 0, 255, 0 );

   glClearDepth( 0x7FFF );

   while(1) {

      // Reset the screen and setup the view
      glReset();

      glMatrixMode( GL_PROJECTION );
            
      gluPerspective( 35, 256.0 / 192.0, 0.1, 100 );
            
      gluLookAtf32( camPos.x, camPos.y, camPos.z, camPos.x, camPos.y, camPos.z - 4096, 0, 4096, 0 );
      glRotatef32i( camLookAng.y, 0, 4096, 0 );
      glRotatef32i( camLookAng.x, 4096, 0, 0 );
      glRotatef32i( camLookAng.z, 0, 0, 4096 );
      
         
      glColor3b( 255, 255, 255 );                  // Set the color..not in nehe source...ds gl default will be black

      // Set the current matrix to be the model matrix
      glMatrixMode( GL_MODELVIEW );
      
      //Push our original Matrix onto the stack (save state)
      glPushMatrix();

      //ds specific, several attributes can be set here   
      glPolyFmt( POLY_ALPHA(31) | POLY_CULL_NONE );
      
      DrawGLScene();
      
      // Pop our Matrix from the stack (restore state)
      glPopMatrix( 1 );

      // flush to screen   
      glFlush();

      //a handy little built in function to wait for a screen refresh
      swiWaitForVBlank();

   }
   return 0;
}

int DrawGLScene(void)
{
   glLoadIdentity();
   glTranslate3f32( 0, 0, -8192 );
   glRotatef32i(0, 0, 4096, 0);
   glRotatef32i(0, 4096, 0, 0);
   glRotatef32i(0, 0, 0, 4096);
   glCallList( cube );

   return TRUE;                              // Keep Going

}

_________________
DS - It's all about DiscoStew

#104253 - Zed0 - Wed Sep 27, 2006 1:54 pm

I'm unsure about this but if you can move the surrounding objects around but not the camera couldn't you just move them negatively to get the same effect as moving the camera?

i.e. intead of
Code:
glTranslate3f32( 1, 2, 3 );

you would use
Code:
glTranslate3f32( -1, -2, -3 );

_________________
__Zed0__
FlasheMe'd Silver DS - GBAMP-CF - 512MB CF Card - R4DS - 2GB Micro SD Card

#104256 - DiscoStew - Wed Sep 27, 2006 2:46 pm

Heh, this morning as I woke up, I had this same idea. So you mean instead of moving the camera, move the objects just the opposite?

I think I see where this is going. Perhaps I can keep my "camPos", but not actually use it for setting the camera position, but instead use those coordinates and find the difference from that and the objects I want displayed, and position that way? So do something like this?...

Code:
camPos = { 0, 4096, 0 };    //Camera is 1 unit above origin
.
.
glLookAtf32( 0, 0, 0, 0, 0, -4096, 0, 4096, 0 };   //Camera at origin looking down -z
.
.
glLoadIdentity();
objDif.x = objPos.x - camPos.x;
objDif.y = objPos.y - camPos.y;
objDif.z = objPos.z - camPos.z;
glTranslate3f32( objDif.x, objDif.y, objDif.z );
.
.
glCallList( cube );
.
.

I'm currently unable to test this code right now, but would this work? And what about when I tilt the camera along it's 3 axises? Would those affect this object offset too, or not?
_________________
DS - It's all about DiscoStew

#104278 - silent_code - Wed Sep 27, 2006 6:03 pm

dude, just call glTranslate and glRotate with the respective negative values:

Code:

setCamera(pos, ang)
{
   glLoadIdentity();
   glRotatef(-ang.x, 1.0f, 0.0f, 0.0f);
   glRotatef(-ang.y, 0.0f, 1.0f, 0.0f);
   glRotatef(-ang.z, 0.0f, 0.0f, 1.0f);
   glTranslatef(-pos.x, -pos.y, -pos.z);
}


that way you can transform the virtual camera at the beginning of the frame and everything else will transform relative to that. well, that's just the theory. you should use the matrix stack in addition to that (for hierarchies) and quaternions for rotations, otherwise, if you used euler angles your system would suffer from gimbal lock (look that one up).

hope i could help a bit (i didn't read all you guys wrote, so i'm sorry if i'm echoing someone else).

#104281 - DiscoStew - Wed Sep 27, 2006 6:09 pm

Well, after having tried these changes to my code, it seems that positioning of the objects works well, but the problem now is that the camera doesn't adjust itself by its axises anymore.

With the cube I had before, when the camera was point down -z, it was positioned down that too, and it looked fine, but when I go to change any axis, the cube remains fixed in it's orientation and position as well. Seems to me that the camera, when set at it's position and direction, becomes the focus point, and everything goes off that when I use glLoadIdentity, which I assume is what it is meant to do.

Maybe I should try what I did with positioning to work like that with direction as well.

EDIT:

silent_code,

I'll try your approach. Seems almost like what I thought up. Like I said, I'm still learning about OpenGL, so I guess I have a lot to learn.
_________________
DS - It's all about DiscoStew

#104294 - silent_code - Wed Sep 27, 2006 8:58 pm

it's not that hard once you get the idea. you can also create an orbiting camera easily that way:

Code:

setOrbCamera(pos, ang, target)
{
   glLoadIdentity();
   glTranslatef(pos.x, pos.y, pos.z);
   glRotatef(ang.x, 1.0f, 0.0f, 0.0f);
   glRotatef(ang.y, 0.0f, 1.0f, 0.0f);
   glRotatef(ang.z, 0.0f, 0.0f, 1.0f);
   glTranslatef(-target.x, -target.y, -target.z);
}


easy, isn't it? this is quite basic aswell, but it works. again, you better use quaternions for rotations (ever wondered about the layout of glRotate? you can do all rotations with just one call with the help of 'em ;D ).

this cam rotates around the target position and the cameras position is the offset. also note that the cam allways looks at the target.

if you want to leave the cameras position as it's position you can also implement a short function that will aim the cam at the target (sort of "look at"). i leave that for you, as an exercise. ;)

i don't see any need for more math than necessary. this code and the above will be enough for fps or rts or racing games. when it comes to real 6-dof cameras you will need the rotation upgrade for sure.
actually, this is working code i have in top down shooters, fps, tools and heck nows what else.

btw: the tombraider camera system was one of the first games i know of that used quaternions for the camera's rotation. so they are pretty good documented on the net. plus they are know for about nearly 200 years or so...

good luck!

#104305 - sajiimori - Wed Sep 27, 2006 10:40 pm

About using quaternions, it really depends on the situation. Most of the time, I convert Euler angles straight to 3x3 matrices in one step.

#104308 - silent_code - Wed Sep 27, 2006 11:03 pm

as i said, it's only (not literally 'only') for real 6 degree of freedom camera rotations.
but you're right, 3x3 matrices (sometimes called rotation matrices) will be enough most of the time. the code i posted will also do the job. i ran only once into a situation where i *really* needed quaternions... but having them *can* make your life easier. use your tools wisely.

#104355 - DiscoStew - Thu Sep 28, 2006 8:00 am

thx silent_code, it seems to work for what I need at the moment. I'm sure I'll need to change to quaternions at some point, but not right now. I'd need to understand them first before even attempting it.
_________________
DS - It's all about DiscoStew

#105796 - silent_code - Wed Oct 11, 2006 10:58 pm

:)