Voglio implementare il mio cursore in una finestra OpenGL/GLUT. Il solito modo per farlo è congelare il cursore (in modo che non possa colpire i bordi dello schermo) e tenere traccia della sua posizione da solo. Posso fare il cursore sullo schermo invisibile utilizzandoglutPassiveMotionFunc e glutWarpMousePointer
glutSetCursor(GLUT_CURSOR_NONE);
e poi all'interno della mia richiamata glutPassiveMotionFunc spostare il puntatore al centro della finestra utilizzando
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);
Questo funziona in quanto mantiene il puntatore attaccato al al centro della finestra. Il problema è che quando disegno il mouse "OpenGL" (all'interno del callback glutDisplayFunc()) è estremamente a scatti.
Ho cercato online e ho scoperto che può esserci un problema in cui glutWarpPointer() provoca il richiamo del callback glutPassiveMotionFunc, risultante in un ciclo, ma questo non sembra accadere qui.
Sono su Mac OS X e ho trovato un post che diceva che CGDisplayMoveCursorToPoint si adattava meglio a questo. Chiamare CGDisplayMoveCursorToPoint funziona ma il movimento è ancora molto a scatti (e mi sembra di ottenere molti eventi in cui xey sono entrambi 0). In ogni caso, mi piacerebbe che funzionasse anche su Linux, quindi una soluzione solo per Mac non è l'ideale (ma sto bene dovendo fare cose diverse sui diversi sistemi).
Ho ridotto questo a un banco di prova.
#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;
}
Felice che tu abbia funzionato. +1 per pubblicare la tua soluzione e una buona spiegazione. Sembra che non ero nemmeno vicino! :) –
L'ho risolto girando un po 'prima di chiamare glutWarpPointer e ignoing gli eventi del mouse fino alla riga successiva. –