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 > Camera class for 3d with theoretical 2Xperformance increase!

#50870 - omaremad - Sun Aug 14, 2005 12:51 am

Hello i found a nice camera class for Opengl which unlike tutorial 10 in nehe allows you to move and rotate the camera without using the stationary camera and rotating scenery trick.

It uses simple algebra no fancy matrixes.

more over i ported it to nds and put touch screen look functions.

The 2X performance increase is based on the fact that it would be ultimately easier to build levels out of seperate quads enabling us to have seperate texture for each quad and thus a proper level which can beloaded from something like a text file.

and we all know that you have to use only 1 texture per triangle group,any way quads mean double the polygon that can be renedered

over all no need to transform the level or enemies!

I am going to build a mini engine with a text file map system and this camera.

this method also makes it easy to implement collision algorithims and such.

any way here is the code

the camera was ported from an apron opengl tutorial

How to use it
Code:


CCamera objCamera; //creates camera

//after scan keys
objCamera.Move_Camera(CAMERASPEED);//move forward
objCamera.Move_Camera(-CAMERASPEED);//move backward
////

// applies the camera vars puy it in main loop after calculating the camera values and before //drawing anything
   gluLookAt(objCamera.mPos.x,  objCamera.mPos.y,  objCamera.mPos.z,   
           objCamera.mView.x, objCamera.mView.y, objCamera.mView.z,   
           objCamera.mUp.x,   objCamera.mUp.y,   objCamera.mUp.z);



the header file put it somewhere and include it
dont forget to setup trig funcs
Code:

#define CAMERASPEED   0.03f            // The Camera Speed

#ifndef PEN_DOWN
#define PEN_DOWN   (((~IPC->buttons) << 6) & (1<<12))
#endif


static void get_pen_delta( int *dx, int *dy )
{
   static int prev_pen[2] = { 0x7FFFFFFF, 0x7FFFFFFF };

   if( PEN_DOWN )
   {
      if( prev_pen[0] != 0x7FFFFFFF )
      {
         *dx = (prev_pen[0] - IPC->touchX);
         *dy = (prev_pen[1] - IPC->touchY);
      }

      prev_pen[0] = IPC->touchX;
      prev_pen[1] = IPC->touchY;
   }
   else
   {
      prev_pen[0] = prev_pen[1] = 0x7FFFFFFF;
      *dx = *dy = 0;
   }
}




//////////////////////////////////////
//The tVector3 Struct
//////////////////////////////////////
typedef struct tVector3               // expanded 3D vector struct
{         
   tVector3() {}   // constructor
   tVector3 (float new_x, float new_y, float new_z) // initialize constructor   
   {x = new_x; y = new_y; z = new_z;}
   // overload + operator so that we easier can add vectors
   tVector3 operator+(tVector3 vVector) {return tVector3(vVector.x+x, vVector.y+y, vVector.z+z);}
   // overload - operator that we easier can subtract vectors
   tVector3 operator-(tVector3 vVector) {return tVector3(x-vVector.x, y-vVector.y, z-vVector.z);}
   // overload * operator that we easier can multiply by scalars
   tVector3 operator*(float number)    {return tVector3(x*number, y*number, z*number);}
   // overload / operator that we easier can divide by a scalar
   tVector3 operator/(float number)    {return tVector3(x/number, y/number, z/number);}
   
   float x, y, z;                  // 3D vector coordinates
}tVector3;


//////////////////////////////////////
//The CCamera Class
//////////////////////////////////////
class CCamera
{
   public:

      tVector3 mPos;   
      tVector3 mView;      
      tVector3 mUp;         

//NEW//////////////////NEW//////////////////NEW//////////////////NEW////////////////
      int mWindowWidth;
      int mWindowHeight;


      // This function let you control the camera with the mouse
      void Mouse_Move();

//NEW//////////////////NEW//////////////////NEW//////////////////NEW////////////////

      void Rotate_View(float x, float y, float z);
      void Move_Camera(float cameraspeed);
      void Position_Camera(float pos_x, float pos_y,float pos_z,
                       float view_x, float view_y, float view_z,
                      float up_x,   float up_y,   float up_z);
};



the main camer file

Code:

#include "main.h"

/////////////////////////////////////////////////////////////////////////////////////////////////
//                              THE CCAMERA POSITION CAMERA
/////////////////////////////////////////////////////////////////////////////////////////////////
void CCamera::Position_Camera(float pos_x,  float pos_y,  float pos_z,
                       float view_x, float view_y, float view_z,
                       float up_x,   float up_y,   float up_z)
{
   tVector3 vPos   = tVector3(pos_x,  pos_y,  pos_z);
   tVector3 vView   = tVector3(view_x, view_y, view_z);
   tVector3 vUp   = tVector3(up_x,   up_y,   up_z);
   
   mPos  = vPos;                     // set the position
   mView = vView;                     // set the view
   mUp   = vUp;                     // set the up vector
}


/////////////////////////////////////////////////////////////////////////////////////////////////
//                              THE CCAMERA MOVE CAMERA
/////////////////////////////////////////////////////////////////////////////////////////////////
void CCamera::Move_Camera(float cameraspeed)
{
   tVector3 vVector = tVector3(0,0,0);      // init a new view vector
   vVector = mView - mPos;               // Get the view vector
   
   // forward positive cameraspeed and backward negative -cameraspeed.
   mPos.x  = mPos.x  + vVector.x * cameraspeed;
   mPos.z  = mPos.z  + vVector.z * cameraspeed;
   mView.x = mView.x + vVector.x * cameraspeed;
   mView.z = mView.z + vVector.z * cameraspeed;
}


/////////////////////////////////////////////////////////////////////////////////////////////////
//                              THE CCAMERA ROTATE VIEW
/////////////////////////////////////////////////////////////////////////////////////////////////
void CCamera::Rotate_View(float x, float y, float z)
{
   tVector3 vVector = mView - mPos;

   if(x)
   {
      mView.z = (float)(mPos.z + sin(x)*vVector.y + cos(x)*vVector.z);
      mView.y = (float)(mPos.y + cos(x)*vVector.y - sin(x)*vVector.z);
   }
   if(y)
   {
      mView.z = (float)(mPos.z + sin(y)*vVector.x + cos(y)*vVector.z);
      mView.x = (float)(mPos.x + cos(y)*vVector.x - sin(y)*vVector.z);
   }
   if(z)
   {
      mView.x = (float)(mPos.x + sin(z)*vVector.y + cos(z)*vVector.x);      
      mView.y = (float)(mPos.y + cos(z)*vVector.y - sin(z)*vVector.x);
   }
}


//NEW//////////////////NEW//////////////////NEW//////////////////NEW////////////////

/////////////////////////////////////////////////////////////////////////////////////////////////
//                              THE CCAMERA MOUSE MOVE
/////////////////////////////////////////////////////////////////////////////////////////////////
void CCamera::Mouse_Move()
{
   
   float angle_y  = 0.0f;            
   float angle_z  = 0.0f;                     
   
   int pen_delta[2];
   get_pen_delta( &pen_delta[0], &pen_delta[1] );
   // Get the direction from the mouse, and bring the number down to a reasonable amount
   angle_y = (float)( (mid_x - pen_delta[0]) ) / 2;      
   angle_z = (float)( (mid_y - pen_delta[1]) ) / 2;

   // The higher the number(acceleration) is the faster the camera looks around.
   mView.y += angle_z * 2;

   // limit the rotation around the x-axis
   if((mView.y - mPos.y) > 8)  mView.y = mPos.y + 8;
   if((mView.y - mPos.y) <-8)  mView.y = mPos.y - 8;
   
   Rotate_View(0, -angle_y, 0); // Rotate
}

//NEW//////////////////NEW//////////////////NEW//////////////////NEW////////////////

#50881 - connor9 - Sun Aug 14, 2005 5:16 am

Are you using floats though? You'd have to convert everything to fixed point math or else you'll be losing a lot of performance with floats.

#50883 - omaremad - Sun Aug 14, 2005 6:16 am

Im still a noob can you give me the function please.

#50894 - rmco2003 - Sun Aug 14, 2005 9:36 am

can you make a demo for us non-programmers to test out?

#50901 - blt - Sun Aug 14, 2005 11:58 am

- gluLookAt() setup the transformation matrix. "level or enemies" are transformed as usual, but it doesn't hurt performance as you have to transform everything in the end. It's just proper behavior to apply camera transformation in some matrix stack and not do a loadidentity/setupcamera everytime.
- Using float is a killer.
- You can't draw 2000 quads in total, but more around 1500. it's a vertex limit.
- Your explanation reads as nonsense and general misunderstanding to me.

Good luck trying your stuff, though. There's always things to learn.