Chciałbym uzyskać ruchy myszy w wysokiej rozdzielczości i wysokiej szybkości klatek na OSX.Współrzędne myszy wysokiej rozdzielczości i wysokiej szybkości klatek na sekundę w systemie OSX? (Lub inne rozwiązanie?)
"High framerate" = 60 fps lub wyższe (najlepiej> 120)
"wysokiej rozdzielczości" Wartości = subpiksel
Problem
Mam widoku OpenGL działa na temat częstotliwości odświeżania monitora , więc wynosi ~ 60 fps. Używam myszy, aby się rozejrzeć, więc ukryłem kursor myszy i polegam na wartościach delta myszy.
Problem polega na tym, że zdarzenia myszy pojawiają się przy zbyt niskiej liczbie klatek na sekundę, a wartości są przyciągane do liczby całkowitej (całe piksele). Powoduje to "wzburzone" wrażenia wizualne. Oto wizualizacja wartości delta mysz w czasie:
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
To jest typowy (skrócona) krzywa tworzona od użytkownika przesuwając mysz trochę w prawo. Każde x reprezentuje wartość deltaX dla każdej klatki, a ponieważ wartości deltaX są zaokrąglane do liczb całkowitych, ten wykres jest rzeczywiście dość dokładny. Jak widać, wartość deltaX wyniesie 0,000 jednej klatki, a następnie 1.000 następnej, ale potem znów będzie 0.000, a następnie 2.000, a następnie 0.000 ponownie, następnie 3.000, 0.000 i tak dalej.
Oznacza to, że widok obróci 2.000 jednostek o jedną klatkę, a następnie obróci o 0,000 jednostek w następnej, a następnie obróci 3.000 jednostek. Dzieje się tak, gdy mysz jest przeciągana z mniej więcej stałą prędkością. Nie ma nic do powiedzenia, to wygląda na gówno.
Jak mogę 1) zwiększyć liczbę klatek na sekundę myszy? i 2) uzyskać wartości podpikseli?
Dotychczas
Próbowałem następujące:
- (void)mouseMoved:(NSEvent *)theEvent {
CGFloat dx, dy;
dx = [theEvent deltaX];
dy = [theEvent deltaY];
// ...
actOnMouse(dx,dy);
}
dobrze, to jedno było oczywiste. dx
tutaj jest float, ale wartości są zawsze zaokrąglone (0.000, 1.000 itd.). Spowoduje to utworzenie powyższego wykresu.
Następnym krokiem było spróbowanie stuknięcia zdarzeń myszy przed wejściem do WindowServera, pomyślałem. Więc stworzyliśmy CGEventTrap:
eventMask = (1 << kCGEventMouseMoved);
eventTap = CGEventTapCreate(kCGHIDEventTap, kCGHeadInsertEventTap,
0, eventMask, myCGEventCallback, NULL);
//...
myCGEventCallback(...){
double dx = CGEventGetDoubleValueField(event, kCGMouseEventDeltaX);
double dy = CGEventGetDoubleValueField(event, kCGMouseEventDeltaY);
}
Wciąż wartości są n.000
, chociaż uważam, że szybkość wypalania zdarzeń jest nieco wyższa. Ale nadal nie jest to 60 klatek na sekundę. Nadal dostaję powyższy wykres.
Próbowałem także ustawić czułość myszy naprawdę wysoko, a następnie skalować wartości w dół po mojej stronie. Ale wydaje się, że OSX dodaje jakieś przyspieszenie lub coś - wartości stają się naprawdę "niestabilne", a w konsekwencji nieużyteczne, a tempo pożaru jest wciąż zbyt niskie.
Bez powodzenia zacząłem śledzić zdarzenia myszy w króliczej dziurze i dotarłem do IOKit. To dla mnie przerażające. To szalony kapelusznik. Dokumentacja Apple robi się dziwna i zdaje się mówić: "jeśli jesteś w tym głęboko, wszystko, czego naprawdę potrzebujesz, to pliki nagłówkowe".
Więc czytałem pliki nagłówkowe. I znalazłem kilka ciekawych ciekawostek.
W <IOKit/hidsystem/IOLLEvent.h>
na linii 377 nie ma tej struktury:
struct { /* For mouse-down and mouse-up events */
UInt8 subx; /* sub-pixel position for x */
UInt8 suby; /* sub-pixel position for y */
// ...
} mouse;
See, mówi pozycja subpiksel! Ok. Następnie na linii 73 w <IOKit/hidsystem/IOLLParameter.h>
#define kIOHIDPointerResolutionKey "HIDPointerResolution"
Hmm.
Podsumowując, mam wrażenie, że OSX wie o głębokich współrzędnych myszy pod-pikselem i musi być po prostu sposób na odczytanie surowych ruchów myszy w każdej klatce, ale nie mam pojęcia, jak je uzyskać wartości.
Pytania
Erh, więc, o co proszę?
- Czy istnieje sposób na uzyskanie wysokiej liczby klatek na sekundę w systemie OSX? (Przykładowy kod?)
- Czy istnieje sposób uzyskiwania współrzędnych myszy pod-pikseli w systemie OSX? (Przykładowy kod?)
- Czy istnieje sposób odczytu "surowych" delt myszy w każdej klatce? (Tj. nie polegać na zdarzeniu.)
- Lub, w jaki sposób uzyskać NXEvents lub ustawić HIDParameters? Przykładowy kod? (Więc mogę sięgnąć głębiej do tego na własną rękę ...)
(Przepraszam za długi post)