Alex Rivera | Logout

glutPassiveMotionFunc and glutWarpMousePointer

Asked 2009-04-08T00:01:52.103
9

I want to implement my own cursor in an OpenGL / GLUT window. The usual way to do this is to freeze the cursor (so it can't hit the edges of the screen) and keep track of its position yourself. I can make the onscreen cursor invisible using

glutSetCursor(GLUT_CURSOR_NONE);

and then inside of my glutPassiveMotionFunc callback move the pointer to the middle of the window using

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 );

This works in that it keeps the pointer stuck to the middle of the window. The problem is that when I am drawing the 'OpenGL' mouse (inside of the glutDisplayFunc() callback) it is extremely jerky.

I have looked online and found that there can be an issue where glutWarpPointer() causes the glutPassiveMotionFunc callback to be called again, resulting in a loop, but this doesn't seem to happen here.

I'm on Mac OS X and I found a post saying that CGDisplayMoveCursorToPoint was a better fit for this. Calling CGDisplayMoveCursorToPoint works but the movement is still very jerky (and I seem to get a lot of events where x and y are both 0). In any case, I'd like this to work on Linux as well so a Mac only solution is not ideal (but I'm okay having to do different things on the different systems).

I've reduced this to a testcase.

#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();

    glutSwapB
Edit
Report

1 Answer

0

I'm guessing here, but I suspect that the motion is jerky because the cursor is drawn in your application's draw function (display()), rather than handled by the OS.

A normal mouse pointer is handled at the driver level by XORing the cursor image with the frame buffer contents--thus lightning quick, and handled with very high priority by the OS in an interrupt service routine (to maintain the illusion of responsiveness).

When you draw it yourself, you're subject to the regular scheduling mechanism of your OS & go through the regular clear & redraw the whole window rigamarole. In this case, it's fast but not as fast as we're used to with a mouse pointer due to the above.

In short, I'm not sure you'll ever get it to be as fast as you expect it to be (particularly as your display function & app logic gets more complex).

Good luck!

answered 2009-04-08T02:21:41.083

Your Answer