我想在 OpenGL / GLUT 窗口中实现我自己的光标。执行此操作的常用方法是冻结光标(因此它不会碰到屏幕边缘)并自己跟踪其位置。我可以使用使屏幕光标不可见
glutSetCursor(GLUT_CURSOR_NONE);
然后在我的 glutPassiveMotionFunc 回调中使用
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 );
这样做的原因是它使指针保持在窗口的中间。问题是,当我绘制“OpenGL”鼠标(在 glutDisplayFunc() 回调内部)时,它非常生涩。
我在网上查了一下,发现可能存在 glutWarpPointer() 导致再次调用 glutPassiveMotionFunc 回调,从而导致循环的问题,但这里似乎不会发生这种情况。
我在 Mac OS X 上,我发现一个帖子说 CGDisplayMoveCursorToPoint 更适合这个。调用 CGDisplayMoveCursorToPoint 有效,但运动仍然非常不稳定(我似乎得到了很多 x 和 y 均为 0 的事件)。无论如何,我希望它也能在 Linux 上工作,因此仅 Mac 的解决方案并不理想(但我可以在不同的系统上做不同的事情)。
我已将其简化为测试用例。
#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;
}