Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 6 of 6

Thread: Issue with multiple keys pressed

  1. #1
    Junior Member Newbie
    Join Date
    Jan 2018
    Posts
    7

    Issue with multiple keys pressed

    In this program, I can press up to 3 characters('s' 'e' and 'f') simultaneously. The issue I have is when I release the most recently pressed button and I have at least one button still pressed. The remaining pressed keys no longer trigger the display update. It works if I release any other button other than the most recently pressed. I watch the console to keep track of which buttons are pressed. Any help is appreciated. Thanks.

    Code cpp:
    #include <GL/gl.h>
    #include <GL/glu.h>
    #include <GL/glut.h>
    #include <stdbool.h>
     
    bool keyStates[256];     //Key state values 
     
     
    void display(void)
    {
       printf("KeyPressed %d%d%d\n", keyStates['s'], keyStates['e'], keyStates['f']);
     
       glClearColor(1.0f, 0.0f, 0.0f, 1.0f); // Clear the background of our window to red  
       glClear(GL_COLOR_BUFFER_BIT);          // Clear the colour buffer (more buffers later on)  
       glLoadIdentity();                      // Load the Identity Matrix to reset our drawing locations  
     
     
     
       glFlush();                              // Flush the OpenGL buffers to the window  
    }
     
    void reshape (int w, int h)
    {
       glViewport (0, 0, (GLsizei) w, (GLsizei) h); 
       glMatrixMode (GL_PROJECTION);
       glLoadIdentity ();
       gluPerspective(65.0, (GLfloat) w/(GLfloat) h, 1.0, 20.0);
       glMatrixMode(GL_MODELVIEW);
       glLoadIdentity();
       glTranslatef (0.0, 0.0, -5.0);
    }
     
    void keyPressed (unsigned char key, int x, int y)
    {
        keyStates[key] = true;         // Set the state of the current key to pressed  
        glutPostRedisplay();
     
    }
     
    void keyUp (unsigned char key, int x, int y)
    {
        keyStates[key] = false;     // Set the state of the current key to not pressed  
        glutPostRedisplay();
    }
     
     
    int main(int argc, char** argv)
    {
       glutInit(&argc, argv);
       glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB);
       glutInitWindowSize (500, 500); 
       glutInitWindowPosition (100, 100);
       glutCreateWindow (argv[0]);
       glClearColor (0.0, 0.0, 0.0, 0.0);
       glShadeModel (GL_FLAT);
       glutDisplayFunc(display); 
       glutReshapeFunc(reshape);
       glutKeyboardUpFunc(keyUp);
       glutKeyboardFunc(keyPressed);
       glutMainLoop();
       return 0;
    }
    Last edited by Dark Photon; 01-08-2018 at 06:03 AM.

  2. #2
    Member Regular Contributor
    Join Date
    Jul 2012
    Posts
    459
    Several possibilities:

    Might be a glut limitation.
    Might be your keyboard limitation (most likely). If you are under Linux, use xinput to try to check that. An exemple is shown as an answer here. There might have something similar under Windows.

  3. #3
    Junior Member Newbie
    Join Date
    Jan 2018
    Posts
    7
    Thanks for the suggestions, I will try more options.

  4. #4
    Junior Member Newbie
    Join Date
    Jan 2018
    Posts
    7

    Solution found, I think

    After doing some more research, I realized that I need to use the glutIdleFunc and check if any keys are pressed inside the idle function. If there are any keys pressed, the glutPostRedisplay function is called, to redraw the window. The keyPressed and keyUp functions just change the boolean state for the key in the key event. The idle function is called quite often, so one has to decide how much delay they want between glutPostRedisplay calls. My previous technique failed because under specific circumstances, the glutPostRedisplay wasn't being called by continuously pressed keys, although the program knew that they were still pressed. Using the idle function ensures that redisplays will be done if desired conditions are met. Thank you for your suggestions, Silence. Here were the links I found that said to use idle function:

    https://www.gamedev.net/forums/topic...ses-in-opengl/
    http://www.swiftless.com/tutorials/opengl/keyboard.html

    New Code:

    Code cpp:
    #include <GL/gl.h>
    #include <GL/glu.h>
    #include <GL/glut.h>
    #include <stdbool.h>
    #include <stdio.h>
     
    bool keyStates[256];     //Key state values 
     
     
    void display(void)
    {
       printf("KeyPressed %d%d%d\n", keyStates['s'], keyStates['e'], keyStates['f']);
     
       glClearColor(1.0f, 0.0f, 0.0f, 1.0f); // Clear the background of our window to red  
       glClear(GL_COLOR_BUFFER_BIT);          // Clear the colour buffer (more buffers later on)  
       glLoadIdentity();                      // Load the Identity Matrix to reset our drawing locations  
     
       glFlush();                              // Flush the OpenGL buffers to the window  
    }
     
    void idle()
    {
        if(keyStates['s'] || keyStates['e'] || keyStates['f']){
            printf("KeyPressed %d%d%d\n", keyStates['s'], keyStates['e'], keyStates['f']);
            glutPostRedisplay();
        }
    }
     
    void reshape (int w, int h)
    {
       glViewport (0, 0, (GLsizei) w, (GLsizei) h); 
       glMatrixMode (GL_PROJECTION);
       glLoadIdentity ();
       gluPerspective(60, (GLfloat)w / (GLfloat)h, 1.0, 100.0); // Set the Field of view angle (in degrees), the aspect ratio of our window, and the new and far planes  
       glMatrixMode(GL_MODELVIEW);
     
    }
     
    void keyPressed (unsigned char key, int x, int y)
    {
        keyStates[key] = true;         // Set the state of the current key to pressed
     
    }
     
    void keyUp (unsigned char key, int x, int y)
    {
        keyStates[key] = false;     // Set the state of the current key to not pressed  
     
    }
     
     
    int main(int argc, char** argv)
    {
       glutInit(&argc, argv);
       glutInitDisplayMode (GLUT_SINGLE);
       glutInitWindowSize (500, 500); 
       glutInitWindowPosition (100, 100);
       glutCreateWindow (argv[0]);
       glutDisplayFunc(display); 
       glutReshapeFunc(reshape);
       glutIdleFunc(idle);
       glutKeyboardUpFunc(keyUp);
       glutKeyboardFunc(keyPressed);
       glutMainLoop();
     
    }
    Last edited by Dark Photon; 01-08-2018 at 06:55 PM.

  5. #5
    Junior Member Newbie
    Join Date
    Jan 2018
    Posts
    7
    So my next step is to research timers.

  6. #6
    Senior Member OpenGL Guru
    Join Date
    Jun 2013
    Posts
    3,003
    I wouldn't have an idle callback which doesn't do significant work (e.g. one which simply calls glutPostRedisplay()), as this guarantees 100% usage of a CPU core. The idle callback is invoked repeatedly while no events are pending.

    If you want continuous animation at the monitor's refresh rate (or as fast as the system can handle if it can't keep up with the refresh rate), call glutPostRedisplay() from the display callback.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •