Mi piacerebbe ottenere movimenti del mouse in alta risoluzione e frame rate elevato su OSX.Coordinate del mouse framerate ad alta risoluzione e alta su OSX? (O altra soluzione?)
"High framerate" = 60 fps o superiore (preferibilmente> 120)
"ad alta risoluzione" Valori = subpixel
Problema
Ho una vista OpenGL in esecuzione a circa la frequenza di aggiornamento del monitor , quindi è ~ 60 fps. Io uso il mouse per guardarmi intorno, quindi ho nascosto il cursore del mouse e sto facendo affidamento sui valori delta del mouse.
Il problema è che gli eventi del mouse arrivano a un framerate troppo basso e i valori vengono spezzati all'intero (pixel interi). Ciò provoca un'esperienza di visione "scomoda". Ecco una visualizzazione di valori delta topo nel tempo:
mouse delta X
^ xx
2 | x x x x xx
| x x x x xx x x x
0 |x-x-x--xx-x-x-xx--x-x----x-xx-x-----> frame
|
-2 |
v
Questo è un tipico (abbreviato) curva creata dall'utente spostando il mouse un po 'a destra. Ogni x rappresenta il valore deltaX per ciascun fotogramma e poiché i valori deltaX sono arrotondati ai numeri interi, questo grafico è in realtà abbastanza preciso. Come possiamo vedere, il valore deltaX sarà 0.000 un fotogramma, quindi 1.000 il successivo, ma poi sarà nuovamente 0.000, quindi 2.000, quindi nuovamente 0.000, quindi 3.000, 0.000 e così via.
Ciò significa che la vista ruoterà 2.000 unità per fotogramma, quindi ruoterà 0.000 unità il successivo e quindi ruoterà 3.000 unità. Questo accade mentre il mouse viene trascinato con una velocità più o meno costante. Nedless per dire, questo sembra merda.
Quindi, come posso 1) aumentato il framerate dell'evento del mouse? e 2) ottenere valori subpixel?
Finora
ho provato la seguente:
- (void)mouseMoved:(NSEvent *)theEvent {
CGFloat dx, dy;
dx = [theEvent deltaX];
dy = [theEvent deltaY];
// ...
actOnMouse(dx,dy);
}
Beh, questo era evidente. dx
qui è float, ma i valori sono sempre arrotondati (0.000, 1.000 ecc.). Questo crea il grafico sopra.
Quindi il passo successivo era cercare di toccare gli eventi del mouse prima che entrassero nel WindowServer, ho pensato. Così ho creato un CGEventTrap:
eventMask = (1 << kCGEventMouseMoved);
eventTap = CGEventTapCreate(kCGHIDEventTap, kCGHeadInsertEventTap,
0, eventMask, myCGEventCallback, NULL);
//...
myCGEventCallback(...){
double dx = CGEventGetDoubleValueField(event, kCGMouseEventDeltaX);
double dy = CGEventGetDoubleValueField(event, kCGMouseEventDeltaY);
}
Ancora valori sono n.000
, anche se credo che il tasso di sparare evento è un po 'più alto. Ma non è ancora a 60 fps. Ho ancora il grafico sopra.
Ho anche provato ad impostare la sensibilità del mouse molto alta, quindi ridimensionare i valori sul mio lato. Ma sembra che OSX aggiunga una sorta di accelerazione o qualcosa - i valori diventano veramente "instabili" e di conseguenza inutilizzabili, e la velocità di fuoco è ancora troppo bassa.
Senza fortuna, ho iniziato a seguire gli eventi del mouse nella tana del coniglio, e sono arrivato a IOKit. Questo è spaventoso per me. È il cappellaio matto. La documentazione di Apple diventa strana e sembra dire "se sei così in fondo, tutto ciò di cui hai veramente bisogno sono i file di intestazione".
Quindi ho letto i file di intestazione. E ho trovato alcune curiosità interessanti.
In <IOKit/hidsystem/IOLLEvent.h>
on line 377 c'è questa struct:
struct { /* For mouse-down and mouse-up events */
UInt8 subx; /* sub-pixel position for x */
UInt8 suby; /* sub-pixel position for y */
// ...
} mouse;
Sede, si dice posizione sub-pixel! Ok. Poi sulla linea 73 in <IOKit/hidsystem/IOLLParameter.h>
#define kIOHIDPointerResolutionKey "HIDPointerResolution"
Hmm.
Tutto sommato, ho la sensazione che OSX conosca le coordinate del mouse sub-pixel in profondità, e ci deve essere solo un modo per leggere i movimenti grezzi del mouse ogni fotogramma, ma non ho idea di come ottenere quelli valori.
Domande
Erh, quindi, che cosa sto chiedendo?
- C'è un modo per ottenere eventi del mouse framerate elevati in OSX? (Esempio di codice?)
- C'è un modo per ottenere coordinate del mouse sub-pixel in OSX? (Esempio di codice?)
- C'è un modo di leggere il deltato "raw" delta ogni frame? (Ie non si basano su un evento.)
- Oppure, come ottengo NXEvents o come impostato HIDParameters? Codice di esempio? (Così posso scavare più in profondità per conto mio ...)
(Ci scusiamo per lungo post)