Qt: Verzögerung von key***Event bei geringer Framerate



  • Hallo.

    Ich messe die Zeit zwischen keyPressEvent und keyReleaseEvent und bewege dementsprechend weit meine Kamera um eine sanfte Bewegung unabhängig von der Framerate zu erreichen.
    Leider wird naturgemäß keyPressEvent und keyReleaseEvent immer nach oder vor paintGL ausgelöst. Daher kommt es vor dass ich schon längst die Taste losgelassen habe und der Event erst Sekunden später ausgelöst wird, da das Programm noch mit ::paintGL beschäftigt ist.

    Nun habe ich mir überlegt evtl. die Tastenzustände in einem parallel laufenden thread x mal pro Sekunde abzufragen, leider steht Qt keine solche Funktion zur verfügung. (nur keyPress/ReleaseEvent 😞 )
    Muss ich nun plattformabhängige ( 😡 ) Funktionen wie getKeyState/XQueryKeymap nutzen?

    Hat vll irgendjemand eine schöne Idee? 😞

    Danke



  • OGLWidget ? Code?



  • QKeyEvent::isAutoRepeat() schon mal angeschaut?
    Ansonsten braucht man Code. Ich kann mir ungefähr vorstellen, wie das bei dir ausschaut, aber bevor ich Schreiben anfange und es stimmt dann doch nicht, wart ich lieber 😛



  • Ohne Code gehts einfach nicht ^^ Okay ... dann probier ichs:

    glwidget_t::glwidget_t() : QGLWidget(), m_pressedKeys(0)
    {
       //Der timer updated das bild so lange eine taste gedrückt ist
       m_autoUpdateTimer = new QTimer(this);
       autoUpdateTimer->setSingleShot(false);
       connect(autoUpdateTimer,SINGAL(timeout()), this, SLOT(updateGL()));
    }
    
    void glwidget_t::paintGL()
    {
       camera.zoome();
       camera.translate();
       camera.rotate();
    
       /* Hier kommt das malen einer aufwendigen Szene */
    }
    
    void glwidget_t::keyPressEvent(QKeyEvent* event)
    {
       //Auto repeat unbrauchbar! Zeit bis autorepeat einsetzt und geschwindigkeit von autorepeat ist abhängig von system und ist mit Qt völlig unerreichbar zudem wird löst es auch nur ein VERZÖGERTES keyEvent aus!
       if(event->isAutoRepeat()) return; 
    
       float tspeed = /*berechnung der geschw. abhängig von größe sichtfeld*/
    
       switch(event->key())
       {
       case Qt::Key_A:
          camera.setTranslationSpeed(-tspeed,X_AXIS);
          break;
       };
    
       if(++m_pressedKeys > 0) m_autoUpdateTimer->start(30); 
       //Verzögerung 30ms da sonst _vermutlich_ viel Rechenzeit aufs malen drauf geht und auch so keyEvent verzögerungen auftreten... 
       //Warum genau ein start(0) meine kameraführung völlig unbrauchbar macht weiß ich nicht genau
       //niedrige fps sind ok, aber keine schwammige kameraführung!
    
    }
    
    void glwidget_t::keyReleaseEvent(QKeyEvent* event)
    {
        case(event->key())
        {
        case Qt::Key_A:
           camera.setTranslationSpeed(0,X_AXIS);
           break;
        };
    
        if(--m_pressedKeys == 0) m_autoUpdateTimer->stop();
    }
    

    So wenn ich nun zur Zeit t=0 auf A drücke passiert folgendes:
    setTranslationSpeed (keyPressEvent) startet,resettet camera seine innere Uhr und verschiebt die camera in camera.translate() (paintGL) entsprechend stark.
    Lasse ich A los, sorgt das setTranslationspeed (keyReleaseEvent) für das speichern der aktuellen position und resettet die uhr.

    Beispiel niedrige fps:
    Drücke A zur Zeit t=0
    paintGL braucht 2 sek
    Ich lasse A nach 500ms los
    keyReleaseEvent wird erst nach 2 sek ausgeführt. Für das program ist es so als hätte ich 2 sekunden lang A gedrückt. Die mindest bewegungsdistanz ist also direkt abhängig von den fps!

    Ungenaue Kameraführung tritt auch schon auf wenn paintGL gerade mal 200ms braucht!



  • //Warum genau ein start(0) meine kameraführung völlig unbrauchbar macht weiß ich nicht genau

    API:

    void QTimer::start ( int msec )   [slot]
        Starts or restarts the timer with a timeout interval of msec milliseconds.
    
    interval : int
    
        This property holds the timeout interval in milliseconds.
        The default value for this property is 0. A QTimer with a timeout interval of 0 will time out as soon as all the events in the window system's event queue have been processed.
    

    Weil du dann sofort einen Timerevent erhätst, der dann versucht connect(autoUpdateTimer,SINGAL(timeout()), this, SLOT(updateGL())); zu machen ... das zeichnet >1ms und dann haste sofort wieder 5 events ...

    Du benutzt vermutlich schon Display Lists um deine Zeichenoperationen zu beschleunigen? Ich weiss nicht wie du die Kamera implementierst, aber eigentlich muss der ja -wenn dein Kameraobjekt die "Kamera" von GL darstellt nur einige Matrixoperationen auf GL_MODELVIEW anwenden und neu darstellen ... nicht alles wieder komplett neu "Zeichnen" - das kann nicht so lange dauern?



  • Also wenn ich das selbe Objekt in blender öffne ist die performance ebenso schlecht. Dennoch kann ich anständig zoomen. aber ich habe den Eindruck dass blender bei druck auf + und - immer einen festen schritt zoomt ... vll abhängig von der ausdehnung der selektion oder der ganzen szene....
    vielleicht sollte ich auch auf Maus umsteigen und rotation/translation abhängig von der Mausposition machen, denn die schert sich zum glück nicht um frames 😉

    😕



  • "das selbe Object in Blender" ... usw.

    Du stellst also nur 1 Objekt(statische Scene, ändert sich nicht) dar und "fliegst" mit der Camera drum rum / rein ? In meinem 3D Spiele Projekt haben wir mit Blender/Irrlicht gearbeitet ... ein Performance Problem damals waren vor allem die (anfänglich) sehr Hohe Zahl an Vertices/Triangles. Blender verleitet dazu. Gib doch mal ein paar "Metainfos" über das, was du machst 😉


Anmelden zum Antworten