glutPassiveMotionFunc und glutWarpMousePointer
Möchte ich zur Umsetzung meiner eigenen cursor in eine OpenGL /GLUT-Fenster. Der übliche Weg, dies zu tun ist, um das einfrieren der cursor (also es kann nicht auf die Ränder des Bildschirms), und verfolgen seine position selbst. Ich kann den Bildschirm-cursor unsichtbar mit
glutSetCursor(GLUT_CURSOR_NONE);
dann in meinem glutPassiveMotionFunc Rückruf bewegen Sie den Zeiger zur Mitte des Fensters mit
int centerX = (float)kWindowWidth /2.0;
int centerY = (float)kWindowHeight /2.0;
int deltaX = (x - centerX);
int deltaY = (y - centerY);
mouseX += deltaX /(float)kWindowWidth;
mouseY -= deltaY /(float)kWindowHeight;
glutWarpPointer( centerX, centerY );
Diese arbeiten, dass es hält die Zeiger geklebt, um die Mitte des Fensters. Das problem ist, dass wenn ich die Zeichnung der 'OpenGL' Maus (innerhalb des glutDisplayFunc() callback) ist es extrem ruckelt.
Ich habe sah online und fand, dass es ein Problem sein, wo glutWarpPointer() bewirkt, dass die glutPassiveMotionFunc callback einmal aufgerufen werden, wodurch eine Schleife, aber das scheint nicht zu passieren.
Bin ich auf Mac OS X und ich fand eine post, die sagen, dass CGDisplayMoveCursorToPoint war eine bessere Passform für diese. Aufruf CGDisplayMoveCursorToPoint funktioniert, aber die Bewegung ist noch sehr ruckartig (und ich scheinen, um eine Menge von Veranstaltungen, bei denen x und y beide 0). In jedem Fall möchte ich diese arbeiten auf Linux so gut wie ein Mac, nur die Lösung ist nicht optimal (aber ich bin in Ordnung zu tun unterschiedliche Dinge auf unterschiedliche Systeme).
Habe ich reduziert, um einen Testfall.
#include <stdio.h>
#include <OpenGL/OpenGL.h>
#include <GLUT/GLUT.h>
int curX = 0;
int curY = 0;
void display() {
glClearColor( 0.0, 0.0, 0.0, 1.0 );
glClear( GL_COLOR_BUFFER_BIT );
float vx = (float)curX /300.0 + 0.5;
float vy = (float)curY /300.0 + 0.5;
glColor3f( 1.0, 0.0, 0.0 );
glBegin( GL_POINTS );
glVertex3f( vx, vy, 0.0 );
glEnd();
glutSwapBuffers();
}
void passivemotion( int x, int y ) {
int centerX = 150;
int centerY = 150;
int deltaX = x - centerX;
int deltaY = y - centerY;
curX += deltaX;
curY -= deltaY;
glutWarpPointer( centerX, centerY );
}
void timer( int val ) {
glutTimerFunc( 16, &timer, 0);
glutPostRedisplay();
}
int main (int argc, char * argv[]) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB);
glutInitWindowSize(300,300);
glutCreateWindow("FPS Mouse Sample");
glutDisplayFunc(&display);
glutPassiveMotionFunc(&passivemotion);
glutSetCursor( GLUT_CURSOR_NONE );
glutTimerFunc( 16, &timer, 0 );
glutMainLoop();
return 0;
}
Du musst angemeldet sein, um einen Kommentar abzugeben.
Dank aib für die Tipps. Du hast mich Blick in das disassembly der glutWarpPointer und es wurde klar, was Los war. Aufruf glutWarpPointer CGPostMouseEvent die Ergebnisse in einer Reihe von Nonsens-Veranstaltungen (und es gibt keine Möglichkeit, Ihnen zu überspringen, da Sie nur Maus-Ereignisse pro Bild einmal, die neue "echte" Ereignisse werden zu spät). Die Lösung, die ich gefunden habe, ist nur verziehen, wenn sich der Mauszeiger am Rand des Bildschirms ( der Punkt, nachdem alle, ist zu tun, wie der Punkt niemals erreichen können Sie den Rand des Bildschirms ). In jedem Fall, hier ist der code.
Fand ich ein besserer Ansatz. Was passiert ist, dass das OS unterdrückt Veranstaltungen für etwa 0,25 Sekunden nach dem verformen der Maus. Also, statt einfach anrufen:
Dann wird alles gehen smoothy ohne Stottern.
Müssen Sie möglicherweise:
und fügen Sie diesen Rahmen, um Ihr Projekt oder Ihre compiler-Optionen.
Beachten Sie, dass Sie möglicherweise eine Falle für die Maus verschieben, um die Mitte des Bildschirms, also Ignoriere ich einfach ein Ereignis, wenn es in der Mitte des Bildschirms.
Ich habe nicht allzu viel Erfahrung mit glut, sparen für das red-book-Beispiele, aber es ruckelt weil von dem, was Sie gerade zeichnen, für den cursor, oder wie oft bist du zeichnen? Wenn Sie ziehen Sie einfach eine Stelle, wo der cursor sein soll mit OpenGL-Aufrufe, ist es immer noch ruckelt? Könnte Ihr timing-code ein Problem sein?
Welchen code du aufrufen, den Zeiger zu aktualisieren jeden tick? Ich nehme an, es ist nicht der code, der aufgeführt ist, wie Sie sein würde, die Berechnung des Mittelpunkts jedes mal, anstatt auf ein resize-Ereignis.
Ich entschuldige mich für blind beantworten hier (D. H. mit begrenzten glut Erfahrung).
Ich vermute hier, aber ich vermute, dass die Bewegung ist ruckelig, weil der cursor gezeichnet wird, in Ihrer Anwendung zeichnen-Funktion (display()), anstatt erfolgt durch das OS.
Einer normalen Maus-Zeiger behandelt wird auf der Treiber-Ebene durch XORing der cursor-Bild mit dem frame-buffer-Inhalt-so Blitz schnell, und behandelt mit sehr hoher Priorität von der OS in einer interrupt service routine (die illusion aufrecht zu erhalten von der Reaktionsfähigkeit).
Wenn Sie ziehen Sie es selbst, Sie unterliegt der regelmäßigen scheduling-Mechanismus Ihres OS & gehen Sie durch die regelmäßigen, klaren & Neuzeichnen des gesamten Fensters rigamarole. In diesem Fall, es ist schnell, aber nicht so schnell wie wir es gewohnt sind mit einem Maus-Zeiger aufgrund der oben genannten.
Kurz gesagt, ich bin mir nicht sicher, ob Sie es jemals bekommen werden, so schnell wie man es von Ihnen erwartet (besonders als display-Funktion & app-Logik wird komplexer).
Glück!
Sind Sie durchschnittlich an die Bewegung der Maus über ein paar frames?
Ich kann nicht finden, meinen code für meine vorherigen Projekt, weil ich bei der Arbeit bin.
Aber ich denke, dass ich durchschnittlich die Bewegungen der Maus über ein paar frames, bevor
ich wusste, dass war die Bewegung sehr ruckartig.
Könnte es sein, weil man swapping-Puffer auf eine nicht-doppelt gepufferte Fenster?
Dein Beispiel funktioniert nicht auf meinem Win32-system, es sei denn, ich füge GLUT_DOUBLE zu glutInitDisplayMode().
Edit:
Sind Sie richtig. Aufruf glutWarpPointer() innerhalb der motion-Funktion zu verursachen scheint ein loop auf meiner [win32] - system. Der timer gar nicht bekommen eine chance, zu feuern, es sei denn, ich auf eine Schaltfläche klicken oder so etwas. Ich Wette, die Nachrichten-queue ist überschwemmt mit motion events.
Aufruf von display() rechts von der motion-Funktion scheint nicht zu funktionieren, entweder - dieses mal ist es nicht registrieren, jede Art von Bewegung.
Die einzige Möglichkeit, die ich bekommen konnte, Ihrem Beispiel zu arbeiten, wurde durch die änderung der passive motion callback zu einer aktiv motion Rückruf und aufrufen von display() direkt aus der Funktion. Ich weiß, das ist weit von dem, was Sie haben ursprünglich gedacht, aber zumindest habe ich einige glatte Bewegung auf diese Weise.
Haben Sie versucht, mit einer glutIdleFunc() zum auslösen der Anzeige von updates für Sie? Kann es immer noch nicht funktionieren, mit einer überfluteten message queue, aber es kann einen Versuch Wert sein. Sie konnten auch einen Blick in die Erfassung der Maus über einen API-Aufruf anstelle von manuell wickeln Sie den cursor auf die Mitte des Fensters bei jeder Bewegung.