Я бы хотел получить движения мыши с высоким разрешением и высокой частотой кадров в OSX.
«Высокая частота кадров» = 60 кадров в секунду или выше (предпочтительно> 120)
«Высокое разрешение» = значения субпикселей
Проблема
У меня есть представление 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 выглядит странно и, кажется, говорит: «Если вы так глубоко, все, что вам действительно нужно, это файлы заголовков».
Итак, я читал файлы заголовков. И я нашел несколько интересных моментов.
В
в строке 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 в
#define kIOHIDPointerResolutionKey "HIDPointerResolution"
Хмм.
В общем, у меня такое ощущение, что OSX знает о субпиксельных координатах мыши в глубине души, и это просто должно быть способ читать необработанные движения мыши в каждом кадре, но я просто не знаю, как получить эти значения.
Вопросы
Эээ, так что я прошу?
(Извините за длинный пост)