Refresh rate of mouse coordinates

Started by CJL, April 27, 2014, 04:59:56

Previous topic - Next topic

CJL

I am grabbing the position of the mouse via the Mouse.getx() and Mouse.gety() methods.

However, I have noticed that the refresh rate for these functions is lower than I would like.  No matter how frequently I poll the mouse position, I typically only see the values getting updated about 10 times per second.

I have tried sampling rates between 100Hz and 10000Hz with no change in performance.  I get the worst performance when I move the mouse either in a straight line up and down or a straight line from side to side.  I get close to acceptable performance when I move the mouse diagonally.

I am wondering if I am missing something obvious or if this is typical behavior.  A long search on google and on this forum didn't turn up anything useful.

I am not sure if it would make a difference, but I am running Ubuntu.  The application I built is running on an 8 core 4GHz machine with a low workload, so I don't think it has do with the hardware being unable to keep up.

My method:

while(true) {

    Mouse.poll();
    int xP = Mouse.xPos();

    doSomethingWithTheData(xP);

    waitForSomeTime(); //Enforce a specific frame rate here
}



Cornix

Are you sure that the mouse you are using is actually capable of returning data that fast?
Some mice are slower and some are faster.

broumbroum

There's something to do with the thread priority.
I set the thread priority to .setPriority(MaxPriority) to get better results.
Other may execute simultaneously, hence the polling Thread must leave a "gap", by Thread.yield() and let other Thread to execute, like the AWTThread which may update devices (like the display) events.
Thread.setPriority(max);
// define Frame per Second
double framerate = 50;
while(true) {
 
 // Mouse read and execute
 long tick = System.nanoTime(); //  1/10^9 sec 
 Mouse.poll();

 Mouse.next();
 
 // yield to let other threads to execute (by priority)
 Thread.yield();

 // wait for _at most_ the framerate you defined (this'll be the "SYNC")
 if(sync)
   waitNanos(Math.max(0,(10^9)/framerate - (System.nanoTime() - tick))); 

}

ERR: edited sync time was wrong

kappa

To get really nice smooth mouse movement you should use interpolation and prediction when drawing the mouse from the polled values, this is a much nice way to get smoother mouse movement than to increase the poll rate.

broumbroum

I understand what you mean by interpolation, but it is already enabled by the device driver, isn't it.

If the poll rate is fast enough, I can get a smooth and accurate movement of the Mouse.

My mind is it depends on _when_ should we poll on the device within the thread cycles (before or after the display buffer read/write).


CJL

Quote from: Cornix on April 27, 2014, 07:09:18
Are you sure that the mouse you are using is actually capable of returning data that fast?
Some mice are slower and some are faster.

I am using the R.A.T. 7, which is typically marketed to gamers.  (http://www.cyborggaming.com/prod/rat7.htm)  Anyways, when I move the cursor around on the desktop the movement is smooth and the response has no latency.

kappa

Another thing to note is that mouse position is reported as int's so relying on just that you'll never get proper smoothness (regardless of what the driver does). Therefore if you are drawing your own you'll need to use interpolation and prediction so your mouse moves every frame at float/double precision. The other option is not to grab and draw your own mouse but to use the native cursor by setting your own cursor icon.

CJL

Quote from: broumbroum on April 27, 2014, 11:38:30
There's something to do with the thread priority. I set the thread priority to .setPriority(MaxPriority) to get better results.

I did as you said.  However, I did not see any significant change in the behavior of my system.  I did, however, check to see how often I was entering the loop.  It appears that I am entering the loop as frequently as I thought I was (i.e. 1000 times per second), however the values returned by Mouse.getx() and Mouse.gety() only get updated about 10 times per second.  

Example behavior:  I move the mouse slowly across the screen.  I poll the mouse position and get X=300.  I continue to poll the mouse position, but for the next fifty cycles or so I see no changes in X.  The next time I poll X, I get X=311.  Even though my mouse movement was continuous and I was polling at a very high rate, Mouse.getx() only shows updated values "once in a while".

CJL

Quote from: kappa on April 27, 2014, 14:28:01
Another thing to note is that mouse position is reported as int's so relying on just that you'll never get proper smoothness (regardless of what the driver does). Therefore if you are drawing your own you'll need to use interpolation and prediction so your mouse moves every frame at float/double precision.

I understand what you mean here, but I am not even getting as smooth of movement as I should with integer coordinates.  On average, there are about 5 pixel "jumps" between each time Mouse.getx() updates and periodically large 15+ pixel "jumps".

Quote from: kappa on April 27, 2014, 14:28:01
The other option is not to grab and draw your own mouse but to use the native cursor by setting your own cursor icon.

I will look into this.

Edit: I took a closer look at my code.  I am pretty sure I am using the native cursor already.  The cursor itself moves across the screen very smoothly.  I am attempting to use cursor position to rotate the camera and this is not smooth.

CJL

Quote from: broumbroum on April 27, 2014, 11:58:58
My mind is it depends on _when_ should we poll on the device within the thread cycles (before or after the display buffer read/write).

My application is threaded so this happens asynchronously from the display buffer reads and writes.  I am updating the display buffer at approximately 60Hz and I am checking for input at approximately 1000Hz.

CJL

I discovered the problem and now I feel a bit silly.   :-[

So I am using the observer pattern.  However, I was updating the position of the x coordinate every time the y coordinate was updated and vise versa.

Thanks everybody for your advice!

broumbroum

My opinion is not to rely on asynchronous threads for such poll() -> getX() -> drawX(). They're thoughtfully linked each other back-to-back...
Interleaving is a way to try (with or without interpolation, never mind), because it is slightly easier to render for the CPU/GPU pairs. I would interleave each even-odd frame rendering with a mouse polling (that could be the observer pattern anyway).

I would make asynchronous other independent tasks, like networking, or file output etc...