Ava Bahari
Ava Bahari

Reputation: 59

How write GLUT keyboard functions?

I wrote the code below, but at runtime, when I press keys, the program doesn't work.
I want to write a program that draws a triangle when the user presses right_key and alt_key. But this doesn't work at all. It always shows a black screen.

#include <GL/glut.h>
void init (void)
{
    glClearColor(0.0,0.0,0.0,0.0);
    glMatrixMode(GL_PROJECTION);
    gluOrtho2D(0.0,200.0,0.0,200.0);
}
float red=1,green=1,blue=1;
void processSpecialKeys(int key, int x, int y) {
    if(key=='0')
        exit(0);
    int mod;
    if(key== GLUT_KEY_RIGHT) {
        mod = glutGetModifiers();
        if (mod==GLUT_ACTIVE_ALT) {
            red = 1.0; green = 0.0; blue = 0.0;
            glColor3f(red,green,blue);
            glBegin(GL_TRIANGLES);
            glVertex2f(0,0);
            glVertex2f(0,100);
            glVertex2f(50,100);
            glEnd();
        }
    }
}
void display(void)
{
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
    glFlush();
}
int main(int argc, char **argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
    glutInitWindowPosition(50,20);
    glutInitWindowSize(400, 300);
    glutCreateWindow("A simple example");
    init();
    glutDisplayFunc(display);
    glutSpecialFunc(processSpecialKeys);
    glutMainLoop();
}

Upvotes: 3

Views: 37041

Answers (3)

Software_Designer
Software_Designer

Reputation: 8587

OK it works now. I've modified your code to enable ALT or SHIFT or CTRL. The code prints out the scancodes of the keys. To print the ALT, CTRL OR SHIFT scancode, simply press ALT or SHIFT or CTRL in combination with other keys. Otherwse GLUT won't register it.

#include <stdio.h>
#include <GL/glut.h>

float red=1,green=1,blue=1;



void init (void)
{
    glClearColor(0.0,0.0,0.0,0.0);
    glMatrixMode(GL_PROJECTION);
    gluOrtho2D(0.0,200.0,0.0,200.0);
}


void process_SHIFT_ALT_CTRL(unsigned char key, int x, int y) 
{
    // Press ALT or  SHIFT or  CTRL in combination with other keys.
    printf("key_code =%d  \n",key);

    int mod = glutGetModifiers();

    if (mod != 0) //ALT=4  SHIFT=1  CTRL=2
    {      
          switch(mod)
          {
             case 1 :  printf("SHIFT key %d\n",mod);  break;
             case 2 :  printf("CTRL  key %d\n",mod);  break;
             case 4 :  printf("ALT   key %d\n",mod);  break;
             mod=0;
          }
    }
}


void process_Normal_Keys(int key, int x, int y) 
{
     switch (key) 
    {    
       case 27 :      break;
       case 100 : printf("GLUT_KEY_LEFT %d\n",key);   break;
       case 102: printf("GLUT_KEY_RIGHT %d\n",key);  ;  break;
       case 101   : printf("GLUT_KEY_UP %d\n",key);  ;  break;
       case 103 : printf("GLUT_KEY_DOWN %d\n",key);  ;  break;
    }

}


void display(void)
{
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
    glFlush();
}


int main(int argc, char **argv)
{

    printf("Press ALT or  SHIFT or  CTRL in combination with other keys. \n\n");

    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
    glutInitWindowPosition(800,20);
    glutInitWindowSize(400, 300);
    glutCreateWindow("A simple example");
    init();

    // famous GLUT callback functions

    glutDisplayFunc(display);


    glutSpecialFunc( process_Normal_Keys );
    glutKeyboardFunc( process_SHIFT_ALT_CTRL );  


    glutMainLoop();

return 0;
}

Upvotes: 6

Mario
Mario

Reputation: 36477

This won't work that way, because the calls to your keyboard callback will be run asynchronously.

That means, you won't see a triangle drawn, unless the keystroke happens to be processed right between glClear() and glFlush(), which will happen rather seldomly and only for one single frame.

What you have to do is rather straightforward: Upon processing the keystroke, save that status, e.g. set a boolean variable to true/false depending on the key input.

Then check for that in display() and draw the triangle, if requested.

Pseudo code example:

bool status = false;

inputhandler(key)
{
    if(key == KEY_A)
        status = true
    else if(KEY == KEY_S)
        status = false;
}

displayhandler()
{
    clear();
    if(status)
        drawTriangle();
    flush();
}

main()
{
    //... init etc.
    glutDisplayFunc(&displayhandler);
    glutSpecialFunc(&inputhandler);
}

On further notes, if you'd like to get into OpenGL programming without having to worry about handling other stuff around that, I'd recommend using a premade library handling windows, inputs, etc. for you, e.g. SFML or SDL. They work similar to glut, but they're in general more powerful and will still allow you to run OpenGL calls directly, while offering simplified event handling.

Upvotes: 3

user97370
user97370

Reputation:

You can't generate graphics commands in the keyboard callback. Set some piece of global state when the key you're interested is pressed and use the information in the display code.

The way to debug problems like this is to use printf statements in the code you think isn't working. Here adding a printf in the keyboard handler would soon tell you that the code is being executed but the triangle not being drawn. That might have lead you to think about when a graphics command is possible and when it isn't.

Upvotes: 1

Related Questions