glutKeyboardFunc()

Member
Posts: 281
Joined: 2009.04
Post: #1
I'm learning OpenGL and GLUT and my first project is an Asteroids type game. How could I get keypresses of the Arrow Keys with glutKeyboardFunc() ? Huh

See my thread about 3D Game Engine. (I know it's not).

Thanks

~ Bring a Pen ~
Quote this message in a reply
Moderator
Posts: 1,560
Joined: 2003.10
Post: #2
glutSpecialFunc is what you'll actually use to receive arrow key input in GLUT (dunno why they're two separate functions, but it's how the API was designed). The man page will tell you everything you need to know. If you're not familiar with man pages, open Terminal.app and type "man glutSpecialFunc".
Quote this message in a reply
Member
Posts: 281
Joined: 2009.04
Post: #3
I don't get it. void glutSpecialFunc(void (*func)(int key, int x, int y));


Should I use it like: glutSpecialFunc(GLUT_KEY_UP)? What's x and y for? Should I say:

Code:
if glutSpecialFunc(GLUT_KEY_UP)
{
     boolKeyUp=1;
}

Huh

~ Bring a Pen ~
Quote this message in a reply
Moderator
Posts: 3,572
Joined: 2003.06
Post: #4
You can find out the code of most keys pressed (including arrows) with glutSpecialFunc, something like this:

Code:
#include <stdio.h>

...

void keyboard(int key, int x, int y)
{
    printf("key %d\n", key);
}

int main(int argc, char** argv)
{
    glutInit(&argc, argv);
    
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
    glutInitWindowSize(640, 480);
    
    glutCreateWindow("GLUT Program");
    
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutIdleFunc(idle);
    glutSpecialFunc(keyboard); // <-- add this for keyboard
    
    glutMainLoop();
    return EXIT_SUCCESS;
}

Then, after you've figured out which number corresponds to which key you can do something like:
Code:
void keyboard(int key, int x, int y)
{
    //printf("key %d\n", key);
    switch (key)
    {
        case 100:
            printf("left arrow pressed\n");
            break;
        case 101:
            printf("up arrow pressed\n");
            break;
        case 102:
            printf("right arrow pressed\n");
            break;
        case 103:
            printf("down arrow pressed\n");
            break;
    }
}
Quote this message in a reply
Member
Posts: 281
Joined: 2009.04
Post: #5
So I've included that code. I have a few variables that need changing due to that code, e.g.
Code:
shipPosX=shipPosX+10

I tried replacing the printf() statements with that one, but I get errors? I think It's because my variables aren't global, but I don't understand how to make them global. How would I do this, or is there an easier way to do it?

~ Bring a Pen ~
Quote this message in a reply
Moderator
Posts: 3,572
Joined: 2003.06
Post: #6
Local:
Code:
void myFunction(void)
{
    float    shipPosX;
}

Global:
Code:
float    shipPosX;

void myFunction(void)
{
    ;
}
Quote this message in a reply
Moderator
Posts: 1,560
Joined: 2003.10
Post: #7
It sounds like you need a stronger foundation in language concepts before moving on, or you'll keep running into problems like these and not understanding why or having a good way to figure it out without asking for help. This book would be an excellent investment.
Quote this message in a reply
Moderator
Posts: 3,572
Joined: 2003.06
Post: #8
In addition to that, I just noticed that Learn C on the Mac is back in print too. Looks like there's an electronic version of it as well.
Quote this message in a reply
Moderator
Posts: 3,572
Joined: 2003.06
Post: #9
ThemsAllTook Wrote:glutSpecialFunc is what you'll actually use to receive arrow key input in GLUT (dunno why they're two separate functions, but it's how the API was designed).

Oh hey, after putting together a little example code for mikey in another thread, I recalled why one couldn't just use glutSpecialFunc for everything: They reused some of the same ASCII constants for things like arrow keys! I wonder why they did that?
Quote this message in a reply
Member
Posts: 281
Joined: 2009.04
Post: #10
OK, I've got a simple 2D scene with a slightly detailed box with an arrow indicating the direction, and I thought some sort of bullet would be cool. How would I implement the Space Bar or Cmd key into my code?

PS. I've been learning more about C, and got out a book from my local library.

PPS. I Won't be attempting a 3D engine anytime soon, but - just out of interest - I noticed there was a 3-digit coordinate reference for my triangle, if I was building a 3D environment, could I just add a Z-Axis, and a keyboard controller? Is it as easy as that? Huh

~ Bring a Pen ~
Quote this message in a reply
Moderator
Posts: 3,572
Joined: 2003.06
Post: #11
mikey Wrote:OK, I've got a simple 2D scene with a slightly detailed box with an arrow indicating the direction, and I thought some sort of bullet would be cool. How would I implement the Space Bar or Cmd key into my code?
I don't know if you can detect the Cmd key with GLUT. For the space bar, be sure to study the code I posted in that other thread about a "simple rectangle". Here's the post: http://www.idevgames.com/forum/showpost....ostcount=8

mikey Wrote:PPS. I Won't be attempting a 3D engine anytime soon, but - just out of interest - I noticed there was a 3-digit coordinate reference for my triangle, if I was building a 3D environment, could I just add a Z-Axis, and a keyboard controller? Is it as easy as that? Huh
Right, in a 3D environment you make use of the z-axis. You'd probably also want to set up a perspective projection and use depth testing.
Quote this message in a reply
Member
Posts: 281
Joined: 2009.04
Post: #12
OK, I've tried to implement a laser, but It fires all the time. I don't see how it's drawing a line from ShipPosX,ShipPosY to the coordinates specified by direction.

Here's my code:

Code:
/* All code © mikey, iDevGames member.

SPACE GAME

*/


#include <stdlib.h>

#include <GLUT/glut.h>

int dir;
int shipPosX;
int shipPosY;

int amfiring;
amfiring = 1;


shipPosX = 840;
shipPosY = 525;



void fire()
{
    
    if (dir==0)
    {
        glBegin(GL_LINES);
        glVertex3f(shipPosX,shipPosY,0.0f);
        glVertex3f(shipPosX,shipPosY+1000,0.0f);
        glEnd();
    }
    else if (dir==90)
    {
        glBegin(GL_LINES);
        glVertex3f(shipPosX,shipPosY,0.0f);
        glVertex3f(shipPosX+1000,shipPosY,0.0f);
        glEnd();
    }
    else if (dir==180)
    {
        glBegin(GL_LINES);
        glVertex3f(shipPosX,shipPosY,0.0f);
        glVertex3f(shipPosX,shipPosY-1000,0.0f);
        glEnd();
    }
    else if (dir==-90)
    {
        glBegin(GL_LINES);
        glVertex3f(shipPosX,shipPosY,0.0f);
        glVertex3f(shipPosX-1000,shipPosY,0.0f);
        glEnd();
    }
glutSwapBuffers();
    
}

void keyboard(int key, int x, int y)
{
    //printf("key %d\n", key);
    switch (key)
    {
        case 100:
            //lefty
            shipPosX=shipPosX-20;
            dir=-90;
            amfiring = 0;
            break;
        case 101:
            //uppy
            shipPosY=shipPosY+20;
            dir=0;
            amfiring = 0;
            break;
        case 102:
            //righty
            shipPosX=shipPosX+20;
            dir=90;
            amfiring = 0;
            break;
        case 103:
            //downy
            shipPosY=shipPosY-20;
            dir=180;
            amfiring = 0;
            break;
        case 32:
            //spacey
                
            amfiring = 1;
                
            break;
    }
    
}


void display(void)
{
    
    
    
    
    
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
    // This code  is where you put all drawing code. v
    
    // draw the ship @ the position
    // I used to have a velocity, but It didn't work as I hoped.
    
    /*
    shipPosX = shipPosX+shipVelX;
    shipPosY = shipPosY+shipVelY;
    
    */
    
    
    glBegin(GL_LINE_LOOP);
    glVertex3f(shipPosX-40,shipPosY-40, 0.0f);
    glVertex3f(shipPosX+40,shipPosY-40, 0.0f);
    glVertex3f(shipPosX+40, shipPosY+40, 0.0f);
    glVertex3f(shipPosX-40,shipPosY+40,0.0f);
    
    
    
    glEnd();
    glBegin(GL_LINE_LOOP);
    glVertex3f(shipPosX-30,shipPosY-30, 0.0f);
    glVertex3f(shipPosX+30,shipPosY-30, 0.0f);
    glVertex3f(shipPosX+30, shipPosY+30, 0.0f);
    glVertex3f(shipPosX-30,shipPosY+30,0.0f);
    
    glEnd();
    
    if (dir==0)
    {
        glBegin(GL_LINES);
        glVertex3f(shipPosX,shipPosY,0.0f);
        glVertex3f(shipPosX,shipPosY+40,0.0f);
        glEnd();
    }
    else if (dir==90)
    {
        glBegin(GL_LINES);
        glVertex3f(shipPosX,shipPosY,0.0f);
        glVertex3f(shipPosX+40,shipPosY,0.0f);
        glEnd();
    }
    else if (dir==180)
    {
        glBegin(GL_LINES);
        glVertex3f(shipPosX,shipPosY,0.0f);
        glVertex3f(shipPosX,shipPosY-40,0.0f);
        glEnd();
    }
    else if (dir==-90)
    {
            glBegin(GL_LINES);
        glVertex3f(shipPosX,shipPosY,0.0f);
        glVertex3f(shipPosX-40,shipPosY,0.0f);
        glEnd();
    }
    
    
    glEnd();

    // That's the ship drawn

    if (amfiring = 1)
    {
        
        fire();
        
        amfiring = 0;
    }
    
    amfiring = 0;
    
    // drawframe
    glutSwapBuffers();
}

void reshape(int width, int height)
{
    glViewport(0, 0, width, height);
    
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0, width, 0, height);
    glMatrixMode(GL_MODELVIEW);
}


void idle(void)
{
    glutPostRedisplay();
}

int main(int argc, char** argv)
{
    glutInit(&argc, argv);
    
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
    glutInitWindowSize(1680,1050);
    
    glutCreateWindow("GLUT Program");
    
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutIdleFunc(idle);
    glutSpecialFunc(keyboard); // <-- add this for keyboard

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

// Keyboard Routines\\

__

Quote:Right, in a 3D environment you make use of the z-axis. You'd probably also want to set up a perspective projection and use depth testing
Honestly, do you think (I would really like to) I would be capable of starting a 3D environment: A plane? maybe a cube or two in the centre of that plane? I mean, perspective and depth testing can't be too hard?

~ Bring a Pen ~
Quote this message in a reply
Moderator
Posts: 3,572
Joined: 2003.06
Post: #13
This is an extremely common pitfall in C: if (amfiring = 1)

It should be if (amfiring == 1)

Also, initialize your globals right where you declare them, like so:

Code:
int shipPosX = 840;
int shipPosY = 525;

int amfiring = 1;

Also, you should only call glutSwapBuffers(); once. You have another call in fire(), which you should remove.

Finally, do be sure to study that code I put together for you in that other thread. It will help you greatly with your keyboard input, which you will no doubt find useful since your laser beam will only appear for one frame with your current technique. And my example also includes a little Boolean typedef you can use instead of 1 or 0.
Quote this message in a reply
Member
Posts: 281
Joined: 2009.04
Post: #14
Thanks AnotherJake! D'oh! '==' D'oh!

Please see my edit above.

~ Bring a Pen ~
Quote this message in a reply
Moderator
Posts: 3,572
Joined: 2003.06
Post: #15
mikey Wrote:Honestly, do you think (I would really like to) I would be capable of starting a 3D environment: A plane? maybe a cube or two in the centre of that plane? I mean, perspective and depth testing can't be too hard?

You have a lot more to learn to be able to tackle it. To see what I mean by that, here's how you draw a spinning colored cube with lighting and depth testing (Controls: move with w, a, s, d, q, a, and reset with r. Toggle coloring with c):

Code:
#include <stdlib.h>
#include <math.h>
#include <GLUT/glut.h>

static const GLfloat    cubeVerts[] =
{
    -0.5f,-0.5f, 0.5f,    // front
     0.5f,-0.5f, 0.5f,
     0.5f, 0.5f, 0.5f,
    -0.5f, 0.5f, 0.5f,
    -0.5f,-0.5f, 0.5f,
     0.5f, 0.5f, 0.5f,
     0.5f,-0.5f,-0.5f,    // rear
    -0.5f,-0.5f,-0.5f,
    -0.5f, 0.5f,-0.5f,
     0.5f, 0.5f,-0.5f,
     0.5f,-0.5f,-0.5f,
    -0.5f, 0.5f,-0.5f,
    -0.5f, 0.5f, 0.5f,    // top
     0.5f, 0.5f, 0.5f,
     0.5f, 0.5f,-0.5f,
    -0.5f, 0.5f,-0.5f,
    -0.5f, 0.5f, 0.5f,
     0.5f, 0.5f,-0.5f,
    -0.5f,-0.5f,-0.5f,    // bottom
     0.5f,-0.5f,-0.5f,
     0.5f,-0.5f, 0.5f,
    -0.5f,-0.5f, 0.5f,
    -0.5f,-0.5f,-0.5f,
     0.5f,-0.5f, 0.5f,
     0.5f,-0.5f, 0.5f,    // right
     0.5f,-0.5f,-0.5f,
     0.5f, 0.5f,-0.5f,
     0.5f, 0.5f, 0.5f,
     0.5f,-0.5f, 0.5f,
     0.5f, 0.5f,-0.5f,
    -0.5f,-0.5f,-0.5f,    // left
    -0.5f,-0.5f, 0.5f,
    -0.5f, 0.5f, 0.5f,
    -0.5f, 0.5f,-0.5f,
    -0.5f,-0.5f,-0.5f,
    -0.5f, 0.5f, 0.5f,
};

static const GLfloat    cubeNormals[] =
{
     0.0f, 0.0f, 1.0f,    // front
     0.0f, 0.0f, 1.0f,
     0.0f, 0.0f, 1.0f,
     0.0f, 0.0f, 1.0f,
     0.0f, 0.0f, 1.0f,
     0.0f, 0.0f, 1.0f,
     0.0f, 0.0f,-1.0f,    // rear
     0.0f, 0.0f,-1.0f,
     0.0f, 0.0f,-1.0f,
     0.0f, 0.0f,-1.0f,
     0.0f, 0.0f,-1.0f,
     0.0f, 0.0f,-1.0f,
     0.0f, 1.0f, 0.0f,    // top
     0.0f, 1.0f, 0.0f,
     0.0f, 1.0f, 0.0f,
     0.0f, 1.0f, 0.0f,
     0.0f, 1.0f, 0.0f,
     0.0f, 1.0f, 0.0f,
     0.0f,-1.0f, 0.0f,    // bottom
     0.0f,-1.0f, 0.0f,
     0.0f,-1.0f, 0.0f,
     0.0f,-1.0f, 0.0f,
     0.0f,-1.0f, 0.0f,
     0.0f,-1.0f, 0.0f,
     1.0f, 0.0f, 0.0f,    // right
     1.0f, 0.0f, 0.0f,
     1.0f, 0.0f, 0.0f,
     1.0f, 0.0f, 0.0f,
     1.0f, 0.0f, 0.0f,
     1.0f, 0.0f, 0.0f,
    -1.0f, 0.0f, 0.0f,    // left
    -1.0f, 0.0f, 0.0f,
    -1.0f, 0.0f, 0.0f,
    -1.0f, 0.0f, 0.0f,
    -1.0f, 0.0f, 0.0f,
    -1.0f, 0.0f, 0.0f
};

static const GLubyte    cubeColors[] =
{
    255,   0, 255, 255,        // front (magenta)
    255,   0, 255, 255,
    255,   0, 255, 255,
    255,   0, 255, 255,
    255,   0, 255, 255,
    255,   0, 255, 255,
    255,   0,   0, 255,        // rear (red)
    255,   0,   0, 255,
    255,   0,   0, 255,
    255,   0,   0, 255,
    255,   0,   0, 255,
    255,   0,   0, 255,
      0,   0, 255, 255,        // top (blue)
      0,   0, 255, 255,
      0,   0, 255, 255,
      0,   0, 255, 255,
      0,   0, 255, 255,
      0,   0, 255, 255,
      0, 255, 255, 255,        // bottom (cyan)
      0, 255, 255, 255,
      0, 255, 255, 255,
      0, 255, 255, 255,
      0, 255, 255, 255,
      0, 255, 255, 255,
      0, 255,   0, 255,        // right (green)
      0, 255,   0, 255,
      0, 255,   0, 255,
      0, 255,   0, 255,
      0, 255,   0, 255,
      0, 255,   0, 255,
    255, 255,   0, 255,        // left (yellow)
    255, 255,   0, 255,
    255, 255,   0, 255,
    255, 255,   0, 255,
    255, 255,   0, 255,
    255, 255,   0, 255
};

enum
{
    false,
    true
};

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];
Bool    showColors = true;
int        lastFrameTime = 0;
float    dt; // delta time (how much time in between frames, used for all movement calculations)
float    x = 0.0f, y = 0.0f, z = 0.0f, xRot = 0.0f, yRot = 0.0f;

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)
{
    // "key" is cached locally so that it stays down until the next key up event
    if (key['a'])
        x -= 5.0f * dt;
    if (key['d'])
        x += 5.0f * dt;
    if (key['q'])
        y += 5.0f * dt;
    if (key['z'])
        y -= 5.0f * dt;
    if (key['w'])
        z -= 5.0f * dt;
    if (key['s'])
    {
        z += 5.0f * dt;
        
        // don't let it go behind the camera
        if (z > 0.0f)
            z = 0.0f;
    }
    if (key['r'])
    {
        // reset
        x = y = z = 0.0f;
    }
    
    if (keyDown['c'])
        showColors = !showColors;
    
    xRot += 90.0f * dt;
    while (xRot > 360.0f)
        xRot -= 360.0f;
    yRot += 90.0f * dt;
    while (yRot > 360.0f)
        yRot -= 360.0f;
}

void setPerspective(GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar)
{
    GLfloat xmin, xmax, ymin, ymax;
    
    ymax = zNear * tanf(fovy * M_PI / 360.0f);
    ymin = -ymax;
    xmin = ymin * aspect;
    xmax = ymax * aspect;
    
    glFrustum(xmin, xmax, ymin, ymax, zNear, zFar);
}

void display(void)
{
    update();
    
    if (lastFrameTime == 0)
    {
        lastFrameTime = glutGet(GLUT_ELAPSED_TIME);
    }
    int now = glutGet(GLUT_ELAPSED_TIME);
    int elapsedMilliseconds = now - lastFrameTime;
    dt = elapsedMilliseconds / 1000.0f;
    lastFrameTime = now;
    
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable(GL_CULL_FACE);
    glEnable(GL_DEPTH_TEST);
    
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    setPerspective(75.0f, (float)glutGet(GLUT_WINDOW_WIDTH) / (float)glutGet(GLUT_WINDOW_HEIGHT), 0.1f, 1000.0f);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    
    // move camera back a bit by moving the entire scene back
    glTranslatef(0.0f, 0.0f, -2.0f);
    
    // make a light
    float    diffuse = 1.0f;
    float    ambient = 0.1f;
    float    specular = 1.0f;
    float    lightDiffuse[] = { diffuse, diffuse, diffuse, 1.0f };
    float    lightAmbient[] = { ambient, ambient, ambient, 1.0f };
    float    lightSpecular[] = { specular, specular, specular, 1.0f };
    float    lightPosition[] = { 2.0f, 4.0f, 2.0f, 0.0f };
    glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiffuse);
    glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmbient);
    glLightfv(GL_LIGHT0, GL_SPECULAR, lightSpecular);
    glEnable(GL_LIGHT0);
    glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
    glEnable(GL_LIGHTING);
    glEnable(GL_COLOR_MATERIAL);
    
    // draw a cube
    glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
    glEnableClientState(GL_NORMAL_ARRAY);
    glEnableClientState(GL_VERTEX_ARRAY);
    glNormalPointer(GL_FLOAT, 0, cubeNormals);
    if (showColors)
    {
        glEnableClientState(GL_COLOR_ARRAY);
        glColorPointer(4, GL_UNSIGNED_BYTE, 0, cubeColors);
    }
    else
    {
        glDisableClientState(GL_COLOR_ARRAY);
    }
    glVertexPointer(3, GL_FLOAT, 0, cubeVerts);
    glPushMatrix();
        glTranslatef(x, y, z);
        glRotatef(xRot, 1.0f, 0.0f, 0.0f);
        glRotatef(yRot, 0.0f, 1.0f, 0.0f);
        glDrawArrays(GL_TRIANGLES, 0, 36);
    glPopMatrix();
    
    // finished with this frame
    glutSwapBuffers();
    
    // do this to clear the key ups and key downs for each frame
    resetKeyboardInput();
}

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


void idle(void)
{
    glutPostRedisplay();
}

int main(int argc, char** argv)
{
    glutInit(&argc, argv);
    
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
    glutInitWindowSize(640, 480);
    
    glutCreateWindow("Spinning Cube");
    
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutIdleFunc(idle);
    
    glutKeyboardFunc(keyboard);
    glutKeyboardUpFunc(keyboardUp);
    glutSpecialFunc(keyboardSpecial);
    glutSpecialUpFunc(keyboardSpecialUp);
    
    glutMainLoop();
    return EXIT_SUCCESS;
}
Quote this message in a reply
Post Reply