got some problems with my camera class

hi. i’m working on a small 3d engine atm and just wrote vector, matrix and quaternion classes to calculate transformations and rotations. i’m sure these classes work correct as they are inspired by the ones of several open source engines.

in my camera class i have functions to translate and rotate the view, but it’s not working the way it should: translations work fine, but the camera is always rotated around the global axis and not its own axis. i guess it’s a simple mistake because i’m still new to this quaternion stuff, so maybe you see what’s i’m doing wrong:

using the mouse and keyboard the player calls functions to rotate (vxQuaternion Rotation) and translate (vxVector Translation) the camera

inline void SetTranslation( const vxVector &translation ) { Translation = translation; }
inline void Translate( const vxVector &translation ) { Translation += translation; }
inline vxVector &GetTranslation() { return Translation; }

inline void SetRotation( const vxQuaternion& rotation ) { Rotation = rotation; }
inline void Rotate( const vxQuaternion& rotation ) { Rotation *= rotation; }
inline vxQuaternion &GetRotation() { return Rotation; }

and this is my camera’s render routine:

void vxCamera::Render( bool wireframe )
{
// Create a matrix from the rotation and translation and apply it
glLoadMatrixf( vxMatrix(Rotation, Translation) );

// Render world
World->Render( wireframe );
}

so what am i doing wrong? thanks in advance! :slight_smile:

I think the issue may be that in order to apply a camera matrix, you need to apply the observer’s inverse transformation.

You can construct a simple matrix using unit vectors and translation to place a vertex in the world, but since the world has to be moved into the camera’s coordinate system, you need to use the inverse of the observer’s transformation matrix.

Now if that doesn’t solve the issue, I think you’ll need to post some more code.

you need to use the inverse of the observer’s transformation matrix
so how can i construct this matrix? would it simply be the inverted camera matrix? thx so far btw :slight_smile:

I’m not too good at matrix math, I’m afraid.
I just use gluLookAt with the translation and a couple of components from my rotation matrix.

But I don’t think the inverse is the same as the transpose.

In OGL terms, the normal matrix would be constructed by means of glTranslate(pos) then 3 glRotates, the inverse would be constructed by the negative actions in the reverse order.
That bit of info might help you out.
Also, I believe the redbook has some info on matrices.

No ! the inverse of a matrix is not the transpose of this matrix.

When doing row major matrix (the maths default way), the transpose of the matrix will provide a matrix suitable for gl purpose (column major).

The invert of a matrix is the matrix that, when multiplied with the original matrix, will result in the identity matrix: M*M-1=Id.

For doing the rotation around your local camera axis, you’ll need to do some maths. The simplest way is to rotate first (when on the origin) then translate, without multiplying the matrices. And that, in fact, doesn’t require the use of matrices, which is better (less calculations to do).

Hope that helps.

If, and only if, the matrix is composed out of rotations ONLY, then the inverse is equal the transpose…

For doing the rotation around your local camera axis, you’ll need to do some maths. The simplest way is to rotate first (when on the origin) then translate, without multiplying the matrices.
i tried it this way and the rotation worked fine - but then the TRANSLATION was in global space… so if i do it this way, how can i calculate the right direction to move the camera?

thx so far :smiley:

That’s where those nice matrix and vector classes you made come in:

When moving the camera:

  1. calculate rotation matrix for camera’s rotation (the forward matrix) (You only need to do this when the camera rotation has changed)
  2. multiply the camera movement by that matrix and add to the current camera position (the movement may be in three axes, but they can be combined into one vector)

When rendering:

  1. when you set up the modelview matrix, do as you’re doing now

(Take it from me: you don’t want to store a camera position local to its own coordinate system)

uhm i’m afraid i don’t understand the 2nd step correctly… because now the camera spins insanely around^^ this is what my render routine looks like now:

void vxCamera::Render( bool wireframe )
{
// Create matrix from rotation
vxMatrix Matrix = vxMatrix(Rotation);

// Multiply translation by that matrix
Translation = vxVector( Matrix*Translation );

// Add that to the current camera position
Matrix += Translation;

// Apply matrix
glLoadMatrixf( Matrix );

// Render world
World->Render( wireframe );
}

thanks for your patience with me :smiley:

Actually, that’s why I said “movement”, not translation.

Keep the camera position separate, and global.
When rotating the camera, keep a rotation matrix around. (It pays to keep that around because you’re probably not rotating all the time, and it’s free).
When processing a movement command (whether that is from the keyboard or the mouse or whatever), apply that rotation matrix to the movement vector (which could have “forward”, “right” and “up” components), and add the result (a vector) to the camera position.
Use the camera rotation and the camera position to setup your view.
BTW: I get the impression you’re still not taking the inverse when setting up the view.

Hello,

i have written a litte camera class for navigating through a 3d-world.
it calculates the position, view-vector and the ‘up-vector’ for the gluLookAt-function :
navigator.h
navigator.cpp

Example use :

in the init function :

Navigator* nav = new Navigator(-4, 0, 0);
nav->setViewPos(0, 0, 0);
nav->setDelta(10.0f, 5.0f);

in the display function :

gluLookAt(nav->getX()    , nav->getY()    , nav->getZ()    ,
              nav->getViewX(), nav->getViewY(), nav->getViewZ(), 
              nav->getUpX()  , nav->getUpY()  , nav->getUpZ());

in the keyboard functions :

void keyboard(unsigned char key, int x, int y) {
    switch (key) {
        case 'a' :
            nav->stepLeft();
            break;  
        case 'd' :
            nav->stepRight();
            break;
        case 'w' :
            nav->turnUp();
            break;    
        case 's' :
            nav->turnDown();
            break;
    }
    
    glutPostRedisplay();
}

void keyboard2(int key, int x, int y) {
    switch (key) {
        case GLUT_KEY_LEFT :
            nav->turnLeft();
            break;  
        case GLUT_KEY_RIGHT :
            nav->turnRight();
            break;
        case GLUT_KEY_DOWN :
            nav->stepForward();
            break;      
        case GLUT_KEY_UP :
            nav->stepBackward();
            break;          
        case GLUT_KEY_PAGE_DOWN :
            nav->stepDown();
            break;    
        case GLUT_KEY_PAGE_UP :
            nav->stepUp();
            break;        
    }
    glutPostRedisplay();    
}

Dj3hut1