Moving Camera Along It's Local Axis

Member
Posts: 227
Joined: 2008.08
Post: #1
For a little background: I am trying to make a simple opengl renderer.
However, I can't get the camera to move along its local axis.
For a simple concept like this you would think I would have no problem in searching for a solution.
Yet, all of the solutions are so cryptic-ly math-ish or C++ class laden.

I need pure C and nothing translates well to my program.
Here is my drawing function(other functions exist but not shown)
Code:
static inline void oeRender(void){
    
    glPushMatrix();
        
        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_ACCUM_BUFFER_BIT);
        
        oePoint3d_t *n=oeCamGetVectors(&oe.cam);//camera normal
                //I had used this for multiplying the camera pos by the vector but recieved strange results
        
        //camera transforms
        
        glRotatef(oe.cam.rot.x,    1,0,0);
        glRotatef(oe.cam.rot.y,    0,1,0);
        glRotatef(oe.cam.rot.z,    0,0,1);
        glTranslatef(oe.cam.x,oe.cam.y,oe.cam.z);//temporary

        //object drawing start
        for (int i = 0; i < oe.count.obj; i++) {
            glPushMatrix();
                
                glTranslatef(oe.obj[i]->x ,    oe.obj[i]->y ,    oe.obj[i]->z );
                glRotatef(oe.obj[i]->rot.x,    1,0,0);
                glRotatef(oe.obj[i]->rot.y,    0,1,0);
                glRotatef(oe.obj[i]->rot.z,    0,0,1);
                
                if(oeObjectOnScreen(oe.obj[i])) oeObjectDraw(oe.obj[i]);
                
            glPopMatrix();
        }
        //object drawing end
        
    glPopMatrix();
    glFlush();
    glfwSwapBuffers();
    
    return;
}

Here is my simple main function:
Code:
void perFrame(void);
oeObject_t cube;

#include "oengine.h"
#define CamTurnSpeed 0.1
#define CamSpeed 0.2

void perFrame(void){
    if(oeKey(GLFW_KEY_ESC)) exit(0);    

    if(oeKey('W')) oe.cam.z-=CamSpeed;
    if(oeKey('S')) oe.cam.z+= CamSpeed;
    if(oeKey('A')) oe.cam.x+= CamSpeed;
    if(oeKey('D')) oe.cam.x-= CamSpeed;
    
    if(oeKey(GLFW_KEY_UP)) oe.cam.rot.x-=CamTurnSpeed;
    if(oeKey(GLFW_KEY_DOWN)) oe.cam.rot.x+=CamTurnSpeed;    
    if(oeKey(GLFW_KEY_RIGHT)) oe.cam.rot.y-=CamTurnSpeed;
    if(oeKey(GLFW_KEY_LEFT)) oe.cam.rot.y+=CamTurnSpeed;
}

int main(void){

    oeInit("OE test",640,480);

    oeRegisterObj(&cube);
    
    glClearColor(1,1,1,1);
    
    oeStart(&perFrame);
    
    return 1;
}
I can get it to turn correct, but it moves it on the global axis.
Quote this message in a reply
Member
Posts: 320
Joined: 2003.06
Post: #2
There are many ways of doing this, but the simplest thing in your case would probably be to:
a) in perFrame function (if w s a or d), use the direction the camera is facing and translate camera position based on that normal and it's right vector
b) in your drawRect, translate then rotate.

Watch out because your camera 'direction' is not a normal vector, it is just 3 rotations. You will need to calculate the direction based on those angles. To do this you probably want to construct a rotation matrix and multiply your default camera direction and right vector by this matrix. Alternatively you could investigate using quaternions to do the same thing. Or... the quickest easiest dirtiest (least accurate, most artifact prone) way is to use trig with the angles on each axis in turn. Might be OK if you have 360° freedom of rotation around y, but less than 180° freedom around x, and no z rotation.

Chopper, iSight Screensavers, DuckDuckDuck: http://majicjungle.com
Quote this message in a reply
Member
Posts: 320
Joined: 2003.06
Post: #3
btw I don't understand quaternions (I tried once I think but then I realised I didn't care!). Just find some code that does axis/angle rotation if you don't want to know the math behind it. This might help, though it's a snippet of C++ code

I am not standing by this code saying this is the fastest best or error free, but it seems to work for me!

Code:
Vector multiplyQuaternions(Vector quaternion1, Vector quaternion2)
{
    Vector result;

    result[0] = quaternion1[3]*quaternion2[0] + quaternion1[0]*quaternion2[3] + quaternion1[1]*quaternion2[2] - quaternion1[2]*quaternion2[1];
    result[1] = quaternion1[3]*quaternion2[1] - quaternion1[0]*quaternion2[2] + quaternion1[1]*quaternion2[3] + quaternion1[2]*quaternion2[0];
    result[2] = quaternion1[3]*quaternion2[2] + quaternion1[0]*quaternion2[1] - quaternion1[1]*quaternion2[0] + quaternion1[2]*quaternion2[3];
    result[3] = quaternion1[3]*quaternion2[3] - quaternion1[0]*quaternion2[0] - quaternion1[1]*quaternion2[1] - quaternion1[2]*quaternion2[2];
  
    return result;
}

Vector quaternionConjugate(Vector quat)
{
    Vector result = quat;
    result[0] = -quat[0];
    result[1] = -quat[1];
    result[2] = -quat[2];
    return result;
}

Vector rotate(float angle, Vector axis_)
{
    float *vector = _vector;
    float *axis = axis_._vector;
    Vector quat_vector, quat_axis, result;
    
    float halfAngle = angle * 0.5f;
    float sinHalfAngle = sin(halfAngle);

    quat_axis[0] = axis[0] * sinHalfAngle;
    quat_axis[1] = axis[1] * sinHalfAngle;
    quat_axis[2] = axis[2] * sinHalfAngle;
    quat_axis[3] = cos(halfAngle);

    quat_vector[0] = vector[0];
    quat_vector[1] = vector[1];
    quat_vector[2] = vector[2];
    quat_vector[3] = 0;

    result = multiplyQuaternions(multiplyQuaternions(quat_axis, quat_vector), quaternionConjugate(quat_axis));

    return Vector(result[0], result[1], result[2]);
}

Chopper, iSight Screensavers, DuckDuckDuck: http://majicjungle.com
Quote this message in a reply
Member
Posts: 227
Joined: 2008.08
Post: #4
I was thinking of option (a) along time ago, but I would want to put that in to my oeRender function.

ps. drawRect? WTF?
Quote this message in a reply
Member
Posts: 320
Joined: 2003.06
Post: #5
They weren't options, you need to do both. And sorry, by drawRect I meant oeRender.

Chopper, iSight Screensavers, DuckDuckDuck: http://majicjungle.com
Quote this message in a reply
Member
Posts: 227
Joined: 2008.08
Post: #6
I ended up doing this:
Code:
void oeCamMove(oePoint3d_t p){
    oeRotate(&p,&oe.cam.rot);

    oe.cam.x+=p.x;
    oe.cam.y+=p.y;
    oe.cam.z+=p.z;
        
}
Code:
void perFrame(void);
oeObject_t cube;

#include "oengine.h"
#define CamTurnSpeed 0.1
#define CamSpeed 0.1

void perFrame(void){
    if(oeKey(GLFW_KEY_ESC)) exit(0);    

    if(oeKey('W')) oeCamMove(0,0,CamSpeed);
    if(oeKey('S')) oeCamMove(0,0,-CamSpeed);
    if(oeKey('A')) oeCamMove(CamSpeed,0,0);
    if(oeKey('D')) oeCamMove(-CamSpeed,0,0);
    
    if(oeKey(GLFW_KEY_UP)) oe.cam.rot.x-=CamTurnSpeed;
    if(oeKey(GLFW_KEY_DOWN)) oe.cam.rot.x+=CamTurnSpeed;    
    if(oeKey(GLFW_KEY_RIGHT)) oe.cam.rot.y-=CamTurnSpeed;
    if(oeKey(GLFW_KEY_LEFT)) oe.cam.rot.y+=CamTurnSpeed;
}

int main(void){

    oeInit("OE test",640,480);

    oeRegisterObj(&cube);
    
    glClearColor(1,1,1,1);
    
    oeStart(&perFrame);
    
    return 1;
}

Works perfect!
Thank you father! LOL!!
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  OpenGL global and local coordinate problem. mikey 4 4,076 May 26, 2009 08:48 AM
Last Post: mikey
  Axis-Angle Rotations DoG 2 2,769 Apr 21, 2006 05:16 PM
Last Post: DoG
  glFog and axis problem tigakub 2 3,745 Mar 25, 2005 06:32 PM
Last Post: tigakub