Я хотел бы получить движения мыши с высоким разрешением и высокой частотой кадров на OSX.Координаты с высоким разрешением и высокой частотой кадров на OSX? (Или другое решение?)
«Высокая частота кадров» = 60 кадров в секунду или выше (предпочтительно> 120)
«Высокое разрешение» значения = Subpixel
Проблема
У меня есть вид OPENGL работает на о частоте обновления монитора , поэтому ~ 60 кадров в секунду. Я использую мышь, чтобы осмотреться, поэтому я спрятал курсор мыши, и я полагаюсь на значения дельта мыши.
Проблема заключается в том, что события мыши происходят со слишком низкой частотой кадров, а значения привязаны к целому (целые пиксели). Это вызывает «прерывистый» просмотр. Вот визуализация значений мышей дельты с течением времени:
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
Это типичный (укороченный) кривой, создаваемые от пользователя, перемещая мышь немного вправо. Каждое x представляет значение deltaX для каждого кадра, а так как значения deltaX округлены до целых чисел, этот график на самом деле довольно точен. Как мы видим, значение deltaX будет равно 0,000 на один кадр, а затем на 1.000 следующий, но затем он будет равен 0.000, а затем 2.000, а затем 0.000 снова, затем 3.000, 0.000 и т. Д.
Это означает, что вид повернет 2.000 единиц на один кадр, а затем повернет на 0,000 единиц дальше, а затем повернет 3.000 единиц. Это происходит, когда мышь перетаскивается с большей или меньшей постоянной скоростью. Невероятно сказать, это выглядит как дерьмо.
Итак, как я могу 1) увеличить частоту кадров мыши? и 2) получить субпиксельные значения?
До сих пор
Я попытался следующие:
- (void)mouseMoved:(NSEvent *)theEvent {
CGFloat dx, dy;
dx = [theEvent deltaX];
dy = [theEvent deltaY];
// ...
actOnMouse(dx,dy);
}
Ну, это один был очевиден. dx
здесь float, но значения всегда округлены (0.000, 1.000 и т. Д.). Это создает график выше.
Итак, следующим шагом было попытаться нажать события мыши, прежде чем они войдут в WindowServer, подумал я. Таким образом, я создал CGEventTrap:
eventMask = (1 << kCGEventMouseMoved);
eventTap = CGEventTapCreate(kCGHIDEventTap, kCGHeadInsertEventTap,
0, eventMask, myCGEventCallback, NULL);
//...
myCGEventCallback(...){
double dx = CGEventGetDoubleValueField(event, kCGMouseEventDeltaX);
double dy = CGEventGetDoubleValueField(event, kCGMouseEventDeltaY);
}
Еще значения являются n.000
, хотя я считаю, что скорость стрельбы события немного выше. Но это все равно не до 60 кадров в секунду. Я все еще получаю диаграмму выше.
Я также попытался установить чувствительность мыши очень высоко, а затем масштабировать значения на моей стороне. Но, похоже, OSX добавляет какое-то ускорение или что-то - значения становятся действительно «неустойчивыми» и, следовательно, непригодными для использования, а темп огня по-прежнему слишком низок.
Не повезло, я начал следить за событиями мыши по кроличьей дыре, и я приехал в IOKit. Это страшно для меня. Это безумный шотландец. Документация Apple становится странной и, кажется, говорит: «Если вы так глубоко, все, что вам действительно нужно, это файлы заголовков».
Так что я читал файлы заголовков. И я нашел несколько интересных лакомых кусочков.
В <IOKit/hidsystem/IOLLEvent.h>
на линии 377 есть эта структура:
struct { /* For mouse-down and mouse-up events */
UInt8 subx; /* sub-pixel position for x */
UInt8 suby; /* sub-pixel position for y */
// ...
} mouse;
Престол, это говорит позиция субпикселя! ОК. Затем по линии 73 в <IOKit/hidsystem/IOLLParameter.h>
#define kIOHIDPointerResolutionKey "HIDPointerResolution"
Хм.
В целом, я чувствую, что OSX знает о субпиксельных координатах мыши в глубине, и просто нужно читать способ чтения движений мыши в каждом кадре, но я просто не знаю, как получить эти значения.
Вопросы
Пуэр, так, что я прошу?
- Есть ли способ получить события с высокой частотой кадров в OSX? (Пример кода?)
- Есть ли способ получить координаты подпиксельной мыши в OSX? (Пример кода?)
- Есть ли способ чтения «необработанных» мышей дельт в каждом кадре? (Ie не полагаться на событие.)
- Или, как я могу получить NXEvents или установить HIDParameters? Пример кода? (Таким образом, я могу копать глубже в это сам ...)
(Извините за длинный пост)