OpenGL global and local coordinate problem.

Member
Posts: 281
Joined: 2009.04
Post: #1
OK, I've attempted my first 3D project written in OpenGL using C. I'm learning how to use glRotate and glTranslate, but I don't see how to choose global or local coordinate systems when using the functions. I did the plane turning on the YZ axis already, and am attempting a very very rudimentry walk-around: when you press forward the plane moves backward, giving the illusion of a 3D world.

I can walk backwards and forwards, but when I try to turn, it all messes up. I think it's because the turn functions are turning the plane on local coordinates.

Thanks in advance.

main.c:

Code:
#include <stdlib.h>
#include <math.h>

#include <GLUT/glut.h>


#include "sfxLite.h" // Thanks loads AnotherJake (J.Peterson)



GLfloat rtri;


typedef unsigned char   Bool;

typedef enum
    {
        ENTER    = 3,
        TAB        = 9,
        RETURN    = 13,
        ESC        = 27,
        SPACE    = 32,
        DEL        = 127,
        UP_ARROW, DOWN_ARROW, LEFT_ARROW, RIGHT_ARROW,
        NUM_KEY_CODES
    } KeyCode;

Bool    key[NUM_KEY_CODES], keyDown[NUM_KEY_CODES], keyUp[NUM_KEY_CODES];
int        lastFrameTime = 0;
float    dt; // delta time (how much time in between frames, used for all movement calculations)






void resetKeyboardInput(void)
{
    int        i;
    
    for (i = 0; i < NUM_KEY_CODES; i++)
    {
        keyDown[i] = false;
        keyUp[i] = false;
    }
}

void keyboard(unsigned char rawKeyCode, int x, int y)
{
    if (rawKeyCode < NUM_KEY_CODES)
    {
        key[rawKeyCode] = true;
        keyDown[rawKeyCode] = true;
    }
}

void keyboardUp(unsigned char rawKeyCode, int x, int y)
{
    if (rawKeyCode < NUM_KEY_CODES)
    {
        key[rawKeyCode] = false;
        keyUp[rawKeyCode] = false;
    }
}

void keyboardSpecial(int rawKeyCode, int x, int y)
{
    switch (rawKeyCode)
    {
        case GLUT_KEY_LEFT:
            key[LEFT_ARROW] = true;
            keyDown[LEFT_ARROW] = true;
            break;
        case GLUT_KEY_UP:
            key[UP_ARROW] = true;
            keyDown[UP_ARROW] = true;
            break;
        case GLUT_KEY_RIGHT:
            key[RIGHT_ARROW] = true;
            keyDown[RIGHT_ARROW] = true;
            break;
        case GLUT_KEY_DOWN:
            key[DOWN_ARROW] = true;
            keyDown[DOWN_ARROW] = true;
            break;
            
            
    }
}

void keyboardSpecialUp(int rawKeyCode, int x, int y)
{
    switch (rawKeyCode)
    {
        case GLUT_KEY_LEFT:
            key[LEFT_ARROW] = false;
            keyUp[LEFT_ARROW] = true;
            break;
        case GLUT_KEY_UP:
            key[UP_ARROW] = false;
            keyUp[UP_ARROW] = true;
            break;
        case GLUT_KEY_RIGHT:
            key[RIGHT_ARROW] = false;
            keyUp[RIGHT_ARROW] = true;
            break;
        case GLUT_KEY_DOWN:
            key[DOWN_ARROW] = false;
            keyUp[DOWN_ARROW] = true;
            break;
            
    }
}



drawGLString(GLfloat x, GLfloat y, char *textString)
{
    int le;
    int qs;
    
    
    glRasterPos2f(x, y);
    le = (int) strlen(textString);
    for (qs = 0; qs < le; qs++)
    {
        glutBitmapCharacter(GLUT_BITMAP_9_BY_15, textString[qs]);
        
    }
}







void display(void)

{
    
    // WAV sound loads

    
    
    
    
    
    
    
        
    
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    //glLoadIdentity();    
    glEnable (GL_BLEND);
    
    glClearDepth(1.0f);                            // Depth Buffer Setup
    glEnable(GL_DEPTH_TEST);                        // Enables Depth Testing
    glDepthFunc(GL_LEQUAL);                            // The Type Of Depth Test To Do
    
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);            // Really Nice Perspective Calculations


    
        
    
    
    
    
    glBegin(GL_QUADS);                    // Start Drawing A Triangle
    glColor3f(0.0f,1.0f,0.0f);            // Set Top Point Of Triangle To Red
    glVertex3f( -100.0f, -1.0f, -100.0f);    
    glColor3f(1.0f,0.0f,0.0f);// First Point Of The Triangle
            // Set Left Point Of Triangle To Green
    glVertex3f(-100.0f,-1.0f, 100.0f);        
    glColor3f(0.0f,1.0f,0.0f);// Second Point Of The Triangle
        // Set Right Point Of Triangle To Blue
    glVertex3f( 100.0f,-1.0f, 100.0f);
    glColor3f(0.5f,0.0f,1.0f);
    glVertex3f( 100.0f,-1.0f,-100.0f);// Third Point Of The Triangle
    glEnd();                        // Done Drawing The Triangle
    
    
                // Decrease The Rotation Variable For The Quad     ( NEW )
                    

    if (rtri>1)
    {
        rtri = 0;
    }
    else {
        
        
        rtri=1.0f;                        // Increase The Rotation Variable For The Triangle ( NEW )
    }
    
    
    
    
    // "key" is cached locally so that it stays down until the next key up event
    if (key[LEFT_ARROW])
    {
                    
                    glRotatef(rtri,0.0f,0.2f,-0.0f);    
        
    }
    if (key[RIGHT_ARROW])
    {    
        
                
                        glRotatef(rtri,0.0f,0.2f,0.0f);    
    
        
        
    }
    if (key[UP_ARROW])
    {
            
        glTranslatef(0.0f,0.0f,0.2f);    
    }
    if (key[DOWN_ARROW])
    {
        
        glTranslatef(0.0f,0.0f,-0.2f);    
    }
    if (key[SPACE])
    {
        
    }
    
    
    // laser score bar
    
    
    
    
    
    /*
    
     if (shipVelX > 2 )
     {
     shipVelX = 2;
     }
     if (shipVelX < -2)
     {
     shipVelX = -2;
     }
    
     if (shipVelY > 2 )
     {
     shipVelY = 2;
     }
     if (shipVelY < -2 )
     {
     shipVelY = -2;
     }
    
     */
    
        
    glutSwapBuffers();
    resetKeyboardInput();
    
}

void reshape(int width, int height)
{
    glViewport(0, 0, width, height);
    
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
                // Move Into The Screen And Left

    gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);
    glMatrixMode(GL_MODELVIEW);
}


void idle(void)
{
    glutPostRedisplay();
}

int main(int argc, char** argv)
{
    glutInit(&argc, argv);
    
    // sounds, yay!
    
    ///
    ///
    ///
    
    
        
    
    
    ///
    ///
    ///
    
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
    //glutInitWindowSize(1680,1050);
    glutInitWindowSize(640, 480);
    
    glutCreateWindow("FATAL ERROR");
    
    glutDisplayFunc(display);
    
    glRasterPos2i(10, 10);
    
    HideCursor();
    glTranslatef(-1.5f,0.0f,-6.0f);                // Move Into The Screen And Left

    
    
    glutReshapeFunc(reshape);
    glutIdleFunc(idle);
    glutFullScreen();
    
    glutKeyboardFunc(keyboard);
    glutKeyboardUpFunc(keyboardUp);
    glutSpecialFunc(keyboardSpecial);
    glutSpecialUpFunc(keyboardSpecialUp);
    
    // init and load sounds

    
    
    
    //glutFullScreen();
    glutMainLoop();
    return EXIT_SUCCESS;
}

~ Bring a Pen ~
Quote this message in a reply
Moderator
Posts: 3,577
Joined: 2003.06
Post: #2
That's getting pretty messy. You should do it something like this instead (wasd to move around, qz up and down, and arrows to look around):
Code:
#include <stdlib.h>
#include <math.h>
#include <stdbool.h>
#include <GLUT/glut.h>

#define DEG_TO_RAD        0.0174532925199f
#define ROT_VELOCITY    90.0f
#define MOVE_VELOCITY    25.0f

GLfloat        heading = 0.0f, pitch = 0.0f, x = 0.0f, y = 20.0f, z = 0.0f;

typedef enum
{
    ENTER    = 3,
    TAB        = 9,
    RETURN    = 13,
    ESC        = 27,
    SPACE    = 32,
    DEL        = 127,
    UP_ARROW, DOWN_ARROW, LEFT_ARROW, RIGHT_ARROW,
    NUM_KEY_CODES
} KeyCode;

bool    key[NUM_KEY_CODES], keyDown[NUM_KEY_CODES], keyUp[NUM_KEY_CODES];
int        lastFrameTime = 0;
float    dt;

void resetKeyboardInput(void)
{
    int        i;
    
    for (i = 0; i < NUM_KEY_CODES; i++)
    {
        keyDown[i] = false;
        keyUp[i] = false;
    }
}

void keyboard(unsigned char rawKeyCode, int x, int y)
{
    if (rawKeyCode < NUM_KEY_CODES)
    {
        key[rawKeyCode] = true;
        keyDown[rawKeyCode] = true;
    }
}

void keyboardUp(unsigned char rawKeyCode, int x, int y)
{
    if (rawKeyCode < NUM_KEY_CODES)
    {
        key[rawKeyCode] = false;
        keyUp[rawKeyCode] = false;
    }
}

void keyboardSpecial(int rawKeyCode, int x, int y)
{
    switch (rawKeyCode)
    {
        case GLUT_KEY_LEFT:
            key[LEFT_ARROW] = true;
            keyDown[LEFT_ARROW] = true;
            break;
        case GLUT_KEY_UP:
            key[UP_ARROW] = true;
            keyDown[UP_ARROW] = true;
            break;
        case GLUT_KEY_RIGHT:
            key[RIGHT_ARROW] = true;
            keyDown[RIGHT_ARROW] = true;
            break;
        case GLUT_KEY_DOWN:
            key[DOWN_ARROW] = true;
            keyDown[DOWN_ARROW] = true;
            break;
            
            
    }
}

void keyboardSpecialUp(int rawKeyCode, int x, int y)
{
    switch (rawKeyCode)
    {
        case GLUT_KEY_LEFT:
            key[LEFT_ARROW] = false;
            keyUp[LEFT_ARROW] = true;
            break;
        case GLUT_KEY_UP:
            key[UP_ARROW] = false;
            keyUp[UP_ARROW] = true;
            break;
        case GLUT_KEY_RIGHT:
            key[RIGHT_ARROW] = false;
            keyUp[RIGHT_ARROW] = true;
            break;
        case GLUT_KEY_DOWN:
            key[DOWN_ARROW] = false;
            keyUp[DOWN_ARROW] = true;
            break;
            
    }
}

void update(void)
{    
    if (key[LEFT_ARROW])
    {
        heading -= ROT_VELOCITY * dt;
        while (heading < 0.0f)
            heading += 360.0f;
    }
    if (key[RIGHT_ARROW])
    {
        heading += ROT_VELOCITY * dt;
        while (heading > 360.0f)
            heading -= 360.0f;
    }
    if (key[UP_ARROW])
    {
        pitch += ROT_VELOCITY * dt;
        if (pitch > 45.0f)
            pitch = 45.0f;
    }
    if (key[DOWN_ARROW])
    {
        pitch -= ROT_VELOCITY * dt;
        if (pitch < -45.0f)
            pitch = -45.0f;
    }
    if (key['w'])
    {
        x += cos(DEG_TO_RAD * (heading - 90.0f)) * MOVE_VELOCITY * dt;
        z += sin(DEG_TO_RAD * (heading - 90.0f)) * MOVE_VELOCITY * dt;
    }
    if (key['s'])
    {
        x -= cos(DEG_TO_RAD * (heading - 90.0f)) * MOVE_VELOCITY * dt;
        z -= sin(DEG_TO_RAD * (heading - 90.0f)) * MOVE_VELOCITY * dt;
    }
    if (key['a'])
    {
        x -= cos(DEG_TO_RAD * heading) * MOVE_VELOCITY * dt;
        z -= sin(DEG_TO_RAD * heading) * MOVE_VELOCITY * dt;
    }
    if (key['d'])
    {
        x += cos(DEG_TO_RAD * heading) * MOVE_VELOCITY * dt;
        z += sin(DEG_TO_RAD * heading) * MOVE_VELOCITY * dt;
    }
    if (key['q'])
    {
        y += MOVE_VELOCITY * dt;
    }
    if (key['z'])
    {
        y -= MOVE_VELOCITY * dt;
    }
}

void display(void)
{
    // calculate delta time
    if (lastFrameTime == 0)
    {
        lastFrameTime = glutGet(GLUT_ELAPSED_TIME);
    }
    int now = glutGet(GLUT_ELAPSED_TIME);
    int elapsedMilliseconds = now - lastFrameTime;
    dt = elapsedMilliseconds / 1000.0f;
    lastFrameTime = now;

    update();

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glClearDepth(1.0f);

    glEnable (GL_BLEND);
    glEnable(GL_DEPTH_TEST);

    glLoadIdentity();

    // virtual "camera" is first tranform(s) in scene
    glRotatef(pitch, 1.0f, 0.0f, 0.0f);
    glRotatef(heading, 0.0f, 1.0f, 0.0f);
    glTranslatef(-x, -y, -z);

    glBegin(GL_QUADS);
        glColor3f(0.0f,1.0f,0.0f);
        glVertex3f( -100.0f, -1.0f, -100.0f);    

        glColor3f(1.0f,0.0f,0.0f);
        glVertex3f(-100.0f,-1.0f, 100.0f);        

        glColor3f(0.0f,1.0f,0.0f);
        glVertex3f( 100.0f,-1.0f, 100.0f);

        glColor3f(0.5f,0.0f,1.0f);
        glVertex3f( 100.0f,-1.0f,-100.0f);
    glEnd();

    glutSwapBuffers();
    resetKeyboardInput();
}

void reshape(int width, int height)
{
    glViewport(0, 0, width, height);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    gluPerspective(45.0f, (GLfloat)width / (GLfloat)height, 0.1f, 1000.0f);
    glMatrixMode(GL_MODELVIEW);
}

void idle(void)
{
    glutPostRedisplay();
}

int main(int argc, char** argv)
{
    glutInit(&argc, argv);

    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
    glutInitWindowSize(640, 480);
    glutCreateWindow("FATAL ERROR");

    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutIdleFunc(idle);

    glutKeyboardFunc(keyboard);
    glutKeyboardUpFunc(keyboardUp);
    glutSpecialFunc(keyboardSpecial);
    glutSpecialUpFunc(keyboardSpecialUp);

    HideCursor();
    glutFullScreen();
    glutMainLoop();
    return EXIT_SUCCESS;
}

It's better to clear the modelview matrix every frame instead of stacking up transforms frame after frame. You have to use a small amount of trigonometry to figure out x and z positions every frame.

Also, it is important to always use delta time (dt for short) for all movement calculations so that velocities are consistent across different frame rates.
Quote this message in a reply
Member
Posts: 281
Joined: 2009.04
Post: #3
Thanks, and I've now enabled the player to look with his mouse! I can't seem to code a HUD though. I try glTranslate(0.0f,0.0f,0.0f); but it draws the HUD in the 'sky'. How can I draw a HUD?

~ Bring a Pen ~
Quote this message in a reply
Moderator
Posts: 3,577
Joined: 2003.06
Post: #4
glTranslate(0.0f,0.0f,0.0f); won't do anything. Remember that all transforms are relative to what is currently on the matrix stack. Too much to explain all at once right now to do a HUD, but what you'd want to do is change your projection matrix to an ortho projection, then switch back to the modelview matrix and clear it with glLoadIdentity and probably turn off depth testing (or else clear the depth buffer). Then you could draw a 2D HUD over your 3D scene.
Quote this message in a reply
Member
Posts: 281
Joined: 2009.04
Post: #5
Ok then, thanks anyway. Smile

~ Bring a Pen ~
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  OpenGL Alpha Channel Problem Moganza 1 3,130 Jan 19, 2013 08:25 AM
Last Post: sealfin
  iPad, OpenGL ES, and XCode Instruments problem! Bandit 0 3,940 Dec 13, 2010 01:21 PM
Last Post: Bandit
  Simple OpenGL ES problem soulstorm 3 4,228 May 14, 2009 03:53 PM
Last Post: AnotherJake
  Opengl picking problem (zip file) papillon68 1 4,505 Mar 1, 2009 08:49 PM
Last Post: chronus
  Texture coordinate problem Oddity007 0 2,030 Jan 21, 2009 06:20 PM
Last Post: Oddity007