Quiero implementar mi propio cursor en una ventana de OpenGL/GLUT. La forma habitual de hacerlo es congelar el cursor (para que no pueda golpear los bordes de la pantalla) y hacer un seguimiento de su posición usted mismo. Puedo hacer que el cursor en pantalla invisible utilizandoglutPassiveMotionFunc y glutWarpMousePointer
glutSetCursor(GLUT_CURSOR_NONE);
y luego dentro de mi devolución de llamada glutPassiveMotionFunc mover el puntero a la mitad de la ventana usando
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);
Esto funciona en el que se mantiene el puntero pegado a la medio de la ventana. El problema es que cuando dibujo el mouse 'OpenGL' (dentro de la devolución de llamada glutDisplayFunc()) es extremadamente espasmódico.
He buscado en línea y he descubierto que puede haber un problema donde glutWarpPointer() hace que la devolución de llamada glutPassiveMotionFunc sea llamada nuevamente, lo que da como resultado un bucle, pero parece que esto no ocurre aquí.
Estoy en Mac OS X y encontré una publicación que decía que CGDisplayMoveCursorToPoint era una mejor opción para esto. Llamar a CGDisplayMoveCursorToPoint funciona pero el movimiento sigue siendo muy desigual (y parece que tengo muchos eventos en los que xey son ambos 0). En cualquier caso, me gustaría que esto también funcione en Linux, por lo que una solución Mac única no es ideal (pero estoy bien tener que hacer cosas diferentes en los diferentes sistemas).
He reducido esto a un caso de prueba.
#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;
}
Me alegro de que lo haya hecho funcionar. +1 para publicar su solución y una buena explicación. Parece que ni siquiera estaba cerca! :) –
Lo arreglé volteando un poco antes de llamar a glutWarpPointer e ignorar los eventos del mouse hasta la próxima línea. –