OSX で高解像度、高フレームレートでマウスの動きを取得したいと考えています。
「高フレームレート」 = 60 fps 以上 (できれば > 120)
「高解像度」 = サブピクセル値
問題
ほぼモニターのリフレッシュ レートで実行されている opengl ビューを持っているので、約 60 fps です。マウスを使って周りを見回すので、マウス カーソルを非表示にし、マウスのデルタ値に依存しています。
問題は、マウス イベントが非常に低いフレームレートで発生し、値が整数 (ピクセル全体) にスナップされることです。これにより、「途切れ途切れ」の表示エクスペリエンスが発生します。以下は、時間の経過に伴うマウス デルタ値の視覚化です。
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 などになります。
これは、ビューが 1 フレームで 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 fpsではありません。私はまだ上のチャートを取得します。
また、マウスの感度を非常に高く設定してから、値を縮小してみました。しかし、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;
ほら、サブピクセル位置と書いてあります!Ok。次に、73行目で<IOKit/hidsystem/IOLLParameter.h>
#define kIOHIDPointerResolutionKey "HIDPointerResolution"
うーん。
全体として、OSXはサブピクセルのマウス座標を深く知っているように感じます.フレームごとに生のマウスの動きを読み取る方法が必要ですが、それらの値を取得する方法がわかりません.
質問
ええと、私は何を求めていますか?
- OSXで高フレームレートのマウスイベントを取得する方法はありますか? (サンプルコード?)
- OSXでサブピクセルのマウス座標を取得する方法はありますか? (サンプルコード?)
- フレームごとに「生の」マウスデルタを読み取る方法はありますか? (つまり、イベントに依存しません。)
- または、どのように NXEvents を取得したり、HIDParameters を設定したりできますか? サンプルコード?(だから私は自分でこれをもっと深く掘り下げることができます...)
(長文すみません)