Using gluLookAt() To Rotate Meshes

Started by
4 comments, last by zedz 15 years ago
I would appreciate any advice anyone could provide. I have been using the following code with gluLookAt with wonderful success for a 6DOF camera:

Transformable::Transformable ( )
{ // Init W/ Standard OGL Values:
  Position =  Zero;
  ViewDir =   NegUnitZ;
  Right =     UnitX;
  Up =        UnitY;
  ViewPoint = NegUnitZ;  
  
  ScaleX = 1.0f;
  ScaleY = 1.0f;
  ScaleZ = 1.0f;
}


void Transformable::Move ( Vector Direction )

{

  Position = Position + Direction;
  ViewPoint = Position + ViewDir;

}


void Transformable::MoveForward ( float Distance )

{

  Position  = Position + ViewDir * Distance;
  ViewPoint = Position + ViewDir;

}



void Transformable::MoveRight ( float Distance ) // Strafe Right

{

  Position  = Position + Right * Distance;
  ViewPoint = Position + ViewDir;

}



void Transformable::MoveUpward ( float Distance )

{

  Position  = Position + Up * Distance;

  ViewPoint = Position + ViewDir;
}


void Transformable::RotateX ( float Angle )

{

  ViewDir = ViewDir * cos( Deg2Rad(Angle) ) +  // Rotate ViewDir Around The Right Vector:

            Up      * sin( Deg2Rad(Angle) );


  ViewDir.Normalize ( );
  

  Up = ViewDir.CrossProduct ( Right ) * -1; // Compute The New Up Vector

  ViewPoint = Position + ViewDir; 

}



void Transformable::RotateY ( float Angle )

{

  ViewDir = ViewDir * cos( Deg2Rad(Angle) ) -   // Rotate ViewDir Around The Up Vector:

            Right   * sin( Deg2Rad(Angle) );

  
  ViewDir.Normalize ( );

  Right = ViewDir.CrossProduct ( Up ); // Compute The New Right

  ViewPoint = Position + ViewDir;

}



void Transformable::RotateZ ( float Angle )

{

  Right = Right * cos ( Deg2Rad(Angle) ) +   // Rotate ViewDir Around The Right Vector:

          Up    * sin ( Deg2Rad(Angle) );

  
  Right.Normalize ( );
  

  Up = ViewDir.CrossProduct ( Right ) * -1; // Compute The New Up

  ViewPoint = Position + ViewDir;

}




To Render:

void OpenGL::Render ( Transformable &T )

{

  gluLookAt( T.Position.X, // Since We Know The Up Vector, We Can Easily Use gluLookAt:
             T.Position.Y, 
             T.Position.Z,

             T.ViewPoint.X,
             T.ViewPoint.Y,
             T.ViewPoint.Z,

             T.Up.X, 
             T.Up.Y, 
             T.Up.Z );

}

So just recently, I have been experimenting with using the exact same code to transform arbitrary meshes, with them inheriting Transformable, and rendering like so:

void OpenGLMesh::Render ( ) 
{
  glPushMatrix();
    MyTexture->Call ( );
    ...
        gluLookAt( Position.X, // Since We Know The Up Vector, We Can Easily Use gluLookAt:
                   Position.Y, 
                   Position.Z,

                   ViewPoint.X,
                   ViewPoint.Y,
                   ViewPoint.Z,

                   Up.X, 
                   Up.Y, 
                   Up.Z );

          glEnableClientState(GL_TEXTURE_COORD_ARRAY);
          glEnableClientState(GL_NORMAL_ARRAY);
          glEnableClientState(GL_VERTEX_ARRAY);
          
            glDrawArrays(GL_TRIANGLES, 0, T.size()*3); // VBO, YAY!!!

          glDisableClientState(GL_VERTEX_ARRAY); 
          glDisableClientState(GL_NORMAL_ARRAY);
          glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  glPopMatrix();
}

It seemed to work perfectly, until I noticed that instead of rotating about its Right vector for RotateX, like it does for my camera, it rotates only about the absolute X axis. It has the same symptom for the other two rotation types. 1. Why is only rotating about the X, Y, Z, directions, instead of about its own orthogonal basis? 2. Can I fix it to rotate about its own orthogonal bases? 3. Is this a disgusting abuse of gluLookAt? Is there a similar function that is less intended for camera viewpoints? Thanks! Greg
Thanks!Greg
Advertisement
Try replacing this:
gluLookAt(    Position.X,    Position.Y,     Position.Z,    ViewPoint.X,    ViewPoint.Y,    ViewPoint.Z,    Up.X,     Up.Y,     Up.Z);
With this:
float m[16];m[0] = Right.x;m[1] = Right.y;m[2] = Right.z;m[3] = 0.f;m[4] = Up.x;m[5] = Up.y;m[6] = Up.z;m[7] = 0.f;m[8] = ViewDir.x;m[9] = ViewDir.y;m[10] = ViewDir.z;m[11] = 0.f;m[12] = Position.x;m[13] = Position.y;m[14] = Position.z;m[15] = 1.f;glMultMatrixf(m);
And see if that fixes it.

In short, yes, you are abusing gluLookAt(), and that's (probably) why it isn't working as you expect. gluLookAt() doesn't just build a transform from the input eye, target, and up vectors, it builds an *inverted* transform. This is exactly what you want when setting up the view transform (because the goal is to transform the geometry into the local space of the camera), but it's not what you want when setting up a model transform.
>>. Is this a disgusting abuse of gluLookAt? Is there a similar function that is less intended for camera viewpoints?

yes :)

have a look here
http://www.j3d.org/matrix_faq/matrfaq_latest.html
section transforms

there are many ways to construct a rotation matrix
eg with an direction vector (like I think youre doing now)
u nmeed to do a couple of crossproducts
Quote:Original post by jyk
Try replacing this:
gluLookAt(    Position.X,    Position.Y,     Position.Z,    ViewPoint.X,    ViewPoint.Y,    ViewPoint.Z,    Up.X,     Up.Y,     Up.Z);
With this:
float m[16];m[0] = Right.x;m[1] = Right.y;m[2] = Right.z;m[3] = 0.f;m[4] = Up.x;m[5] = Up.y;m[6] = Up.z;m[7] = 0.f;m[8] = ViewDir.x;m[9] = ViewDir.y;m[10] = ViewDir.z;m[11] = 0.f;m[12] = Position.x;m[13] = Position.y;m[14] = Position.z;m[15] = 1.f;glMultMatrixf(m);
And see if that fixes it.

In short, yes, you are abusing gluLookAt(), and that's (probably) why it isn't working as you expect. gluLookAt() doesn't just build a transform from the input eye, target, and up vectors, it builds an *inverted* transform. This is exactly what you want when setting up the view transform (because the goal is to transform the geometry into the local space of the camera), but it's not what you want when setting up a model transform.


Wow, that nearly works ! The model is rotating as it should, but has been flipped (inside-out) over the Z axis.
Thanks!Greg
Aha! Just needed a negative. :-D

float m[16];m[0] = Right.X;m[1] = Right.Y;m[2] = Right.Z;m[3] = 0.f;m[4] = Up.X;m[5] = Up.Y;m[6] = Up.Z;m[7] = 0.f;m[8] = -ViewDir.X;m[9] = -ViewDir.Y;m[10] = -ViewDir.Z;m[11] = 0.f;m[12] = Position.X;m[13] = Position.Y;m[14] = Position.Z;m[15] = 1.f;glMultMatrixf(m);    



Thank you both very very very much! I was ready to tear my hair out!

Dazed and relieved,
Greg
Thanks!Greg
just a reminder if later on u notice your models looking strange.

watch out since u havent orthonormalized the matrix this will lead to a squewed matrix depending on the right,up,forward directions

forward = (0,0,1);
up = (0,1,0);
right = (1,0,0);

is no problems since the forwrda+right vectors are on the plane thats perpendicular to the up vector

but if forward is (0,0.707,0.707), up=(0,1,0), right=(1,0,0)
is gonna look wonky.

This topic is closed to new replies.

Advertisement