Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

How can I make rotation and translation on a local camera axis in OpenGL? I want to make camera like "aeroplane" camera with a pitch yaw and roll. I want to have good explanation on everything!

Can the solution be with gluLookAt maybe and be without gimbal lock?

share|improve this question

1 Answer 1

Please feel free to tell me if every step is understandable. If it's not i will add more explanation.

Active variables -------------------------------------------------------------------------------------------------

  1. camera_drot={Rotation arou x(right) axe, -\- y(up) axe, -\- z(forward) axe} [radians]
  2. camera_dtra={Translation by x(right) axe, -\- y(up) axe, -\- z(forward) axe}

Code:

float camera_drot[3]={0,0,0};
float camera_dtra[3]={0,0,0};

float camera_place[3]={0,0,0};
float camera_right[3]={1,0,0};
float camera_up[3]={0,1,0};
float camera_forward[3]={0,0,-1};

Algoritem of transformation ------------------------------------------------------------------------------------

  1. I will delete camera_ for better view. :)
  2. If you rotate camera's axis around x axe you must rotate y and z axe (example).
  3. After the rotation its vital to make sure the forward,up,right acis is rectangular and all axis must have length "1"! If we dont make Orthonormality(forward,right,up) the errors in computers computation will sums up really fast! Belive me!
  4. After the Orthonormality we can translate cameras place in local system of cameras axis.
  5. The good old gluLookAt() the simplest thing to comunicate with OpenGL obout cameras properties.

Code:

if(drot[0]!=0){
    MYRotation(right,up,drot[0]);      //#Rotate up axis oround right for drot[0] radians
    MYRotation(right,forward,drot[0]);
    drot[0]=0;}
if(drot[1]!=0){
    MYRotation(up,right,drot[1]);
    MYRotation(up,forward,drot[1]);
    drot[1]=0;}
if(drot[2]!=0){
    MYRotation(forward,right,drot[2]);
    MYRotation(forward,up,drot[2]);
    drot[2]=0;}

Orthonormality(forward,right,up);

if(dtra[0]!=0){
    MYTranslation(right,place,dtra[0]);
    dtra[0]=0;}
if(dtra[1]!=0){
    MYTranslation(up,place,dtra[1]);
    dtra[1]=0;}
if(dtra[2]!=0){
    MYTranslation(forward,place,dtra[2]);
    dtra[2]=0;}

glLoadIdentity();
gluLookAt(place[0],place[1],place[2],
          place[0]+forward[0],place[1]+forward[1],place[2]+forward[2],
          up[0],up[1],up[2]);

MY Functions --------------------------------------------------------------------------------------------------------

Orthonormality

  1. Normalize vec0! If we normalize vec0 we simplify many things!
  2. Projected vec1 on ortogonal space of vec0 vector.orthogonal complement Visual what we do in number 2 ^^^^
  3. After a projection we have to normalize new vec1!
  4. And in this step we find vec3 with Gram–Schmidt process
  5. Final step is normalize vec3.

Code:

static void Orthonormality(float vec0[3],float vec1[3],float vec2[3]){
    //1
    float normalize = pow(vec0[0]*vec0[0]+vec0[1]*vec0[1]+vec0[2]*vec0[2],-0.5);
    if(normalize!=1){
        vec0[0]=vec0[0]*normalize;
        vec0[1]=vec0[1]*normalize;
        vec0[2]=vec0[2]*normalize;}

    //2
    float x1=vec1[0];
    float y1=vec1[1];
    float z1=vec1[2];

    vec1[0]=x1*(vec0[1]*vec0[1] + vec0[2]*vec0[2]) - vec0[0]*(vec0[1]*y1 + vec0[2]*z1);
    vec1[1]=-vec0[0]*x1*vec0[1] + vec0[0]*vec0[0]*y1 + vec0[2]*(y1*vec0[2] - vec0[1]*z1);
    vec1[2]=-(vec0[0]*x1 + vec0[1]*y1)*vec0[2] + (vec0[0]*vec0[0] + vec0[1]*vec0[1])*z1;

    //3
    normalize = pow(vec1[0]*vec1[0]+vec1[1]*vec1[1]+vec1[2]*vec1[2],-0.5);
    vec1[0]=vec1[0]*normalize;
    vec1[1]=vec1[1]*normalize;
    vec1[2]=vec1[2]*normalize;

    //4
    float x0x2_y0y2_z0z2=vec0[0]*vec2[0] + vec0[1]*vec2[1] + vec0[2]*vec2[2];
    float x1x2_y1y2_z1z2=vec1[0]*vec2[0] + vec1[1]*vec2[1] + vec1[2]*vec2[2];
    vec2[0] = vec2[0] - vec0[0]*x0x2_y0y2_z0z2 - vec1[0]*x1x2_y1y2_z1z2; 
    vec2[1] = vec2[1] - vec0[1]*x0x2_y0y2_z0z2 - vec1[1]*x1x2_y1y2_z1z2; 
    vec2[2] = vec2[2] - vec0[2]*x0x2_y0y2_z0z2 - vec1[2]*x1x2_y1y2_z1z2;

    //5
    normalize = pow(vec2[0]*vec2[0]+vec2[1]*vec2[1]+vec2[2]*vec2[2],-0.5);
    vec2[0]=vec2[0]*normalize;
    vec2[1]=vec2[1]*normalize;
    vec2[2]=vec2[2]*normalize;
    }

MYRotation

Rotate vec around line for drot radians.

static void MYRotation(float line[3],float vec[3],float drot){
    float ux=line[0]*vec[0];    
    float vy=line[1]*vec[1];    
    float wz=line[2]*vec[2];    
    float uu=pow(line[0],2);    
    float vv=pow(line[1],2);    
    float ww=pow(line[2],2);    
    float uxvywz=ux+vy+wz;    
    float sa=sin(drot);    
    float ca=cos(drot);    
    vec[0]=line[0]*uxvywz+(vec[0]*(vv+ww)-line[0]*(vy+wz))*ca+(-line[2]*vec[1]+line[1]*vec[2])*sa;    
    vec[1]=line[1]*uxvywz+(vec[1]*(uu+ww)-line[1]*(ux+wz))*ca+( line[2]*vec[0]-line[0]*vec[2])*sa;    
    vec[2]=line[2]*uxvywz+(vec[2]*(uu+vv)-line[2]*(ux+vy))*ca+(-line[1]*vec[0]+line[0]*vec[1])*sa;
    }

MYTranslation

Translate vec for line*dtra

static void MYTranslation(float line[3],float vec[3],float dtra){
    vec[0]+=line[0]*dtra;
    vec[1]+=line[1]*dtra;
    vec[2]+=line[2]*dtra;}
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.