質問

私は、OpenGL / GLUTウィンドウに自分のカーソルを実装したいです。これを行うための通常の方法は、(それが画面の端を打つことはできませんので)カーソルを凍結し、その位置を自分のトラックを維持することです。私が使用して目に見えない画面上のカーソルを作ることができます。

glutSetCursor(GLUT_CURSOR_NONE);

、その後、私のglutPassiveMotionFuncコールバックの内部で使用してウィンドウの中央にポインタを移動

int centerX = (float)kWindowWidth / 2.0;
int centerY = (float)kWindowHeight / 2.0;

int deltaX = (x - centerX);
int deltaY = (y - centerY);

mouseX += deltaX / (float)kWindowWidth;
mouseY -= deltaY / (float)kWindowHeight;

glutWarpPointer( centerX, centerY );

これは、ウィンドウの中央にこだわっのポインタを保持していることで動作します。問題は、それが非常にぎくしゃくしている(glutDisplayFunc()コールバックの内側に)私は「OpenGLの」マウスを描いていたときにということである。

私は、オンラインで見て、glutWarpPointerは()glutPassiveMotionFuncコールバックがループで、その結果、再び呼び出されますが、これは、ここで起きていないようです。

問題が発生することができることを見出しました

私は、Mac OS X上だと私はCGDisplayMoveCursorToPointは、このためのより良いフィット感だったと言ってポストを見つけました。 CGDisplayMoveCursorToPointを呼び出すと、動作しますが、動きはまだ非常にぎくしゃくです(と私は、xとyの両方が0であるイベントをたくさん得るように見える)を。いずれにせよ、私はこれは、Linux上で動作したいだけでなくので、Macの唯一の解決策は理想的ではありません(私は異なるシステムで異なることを行う持っ大丈夫)。

私はテストケースにこれを削減しました。

#include <stdio.h>
#include <OpenGL/OpenGL.h>
#include <GLUT/GLUT.h>

int curX = 0;
int curY = 0;

void display() {
    glClearColor( 0.0, 0.0, 0.0, 1.0 );
    glClear( GL_COLOR_BUFFER_BIT );

    float vx = (float)curX / 300.0 + 0.5;
    float vy = (float)curY / 300.0 + 0.5;

    glColor3f( 1.0, 0.0, 0.0 );
    glBegin( GL_POINTS );
        glVertex3f( vx, vy, 0.0 );
    glEnd();

    glutSwapBuffers();

}

void passivemotion( int x, int y ) {
    int centerX = 150;
    int centerY = 150;

    int deltaX = x - centerX;
    int deltaY = y - centerY;
    curX += deltaX;
    curY -= deltaY;

    glutWarpPointer( centerX, centerY );
}

void timer( int val ) {
    glutTimerFunc( 16, &timer,  0);
    glutPostRedisplay();
}

int main (int argc, char * argv[]) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB);
    glutInitWindowSize(300,300);
    glutCreateWindow("FPS Mouse Sample");
    glutDisplayFunc(&display);
    glutPassiveMotionFunc(&passivemotion);
    glutSetCursor( GLUT_CURSOR_NONE );
    glutTimerFunc( 16, &timer, 0 );
    glutMainLoop();
    return 0;
}
役に立ちましたか?

解決

のヒントのおかげでのAIB。あなたは私glutWarpPointerの分解を検討していましたし、それは何が起こっていたか明らかになりました。ナンセンスイベントの束になり(およびフレームごとに、新たに「本物」のイベントが遅くなります一度あなただけのマウスイベントを取得するので、それらをスキップする方法はありません)glutWarpPointer CGPostMouseEventを呼び出します。私が見つけた解決策は、ポインタが画面の端にあるとき(ポイント、結局、ポイントが画面の端に到達しないことができますようにふりをしている)だけワープにあります。いずれにせよ、ここにコードされています。

int lastX = 150;
int lastY = 150;
void passivemotion( int x, int y ) {    
    int deltaX = x - lastX;
    int deltaY = y - lastY;

    lastX = x;
    lastY = y;

    if( deltaX == 0 && deltaY == 0 ) return;

    int windowX     = glutGet( GLUT_WINDOW_X );
    int windowY     = glutGet( GLUT_WINDOW_Y );
    int screenWidth     = glutGet( GLUT_SCREEN_WIDTH );
    int screenHeight    = glutGet( GLUT_SCREEN_HEIGHT );

    int screenLeft = -windowX;
    int screenTop = -windowY;
    int screenRight = screenWidth - windowX;
    int screenBottom = screenHeight - windowY;

    if( x <= screenLeft+10 || (y) <= screenTop+10 || x >= screenRight-10 || y >= screenBottom - 10) {
        lastX = 150;
        lastY = 150;
        glutWarpPointer( lastX, lastY );
        //  If on Mac OS X, the following will also work (and CGwarpMouseCursorPosition seems faster than glutWarpPointer).
        //  CGPoint centerPos = CGPointMake( windowX + lastX, windowY + lastY );
        //  CGWarpMouseCursorPosition( centerPos );
        // Have to re-hide if the user touched any UI element with the invisible pointer, like the Dock.
        //  CGDisplayHideCursor(kCGDirectMainDisplay);
    }

    curX += deltaX;
    curY -= deltaY;
}

他のヒント

私はより良いアプローチを発見しました。何が起こっていることは、あなたがマウスをワープした後、OSが約0.25秒のイベントを抑制することです。だから、代わりにだけ呼び出します:

#ifdef __APPLE__
CGSetLocalEventsSuppressionInterval(0.0);
#endif

そして、すべてがいずれかの吃音せずにスムージーを移動します。

あなたは含める必要があります:

#include <ApplicationServices/ApplicationServices.h>

とプロジェクトにしたり、コンパイラオプションには、このフレームワークを追加します。

それは画面の中央にある場合ので、私はちょうどイベントを無視し、あなたが画面の中央に移動し、マウスのイベントを取得することがあります。

私は赤い本の例のために保存し、供給過剰とあまりにも多くの経験を持っていないが、それはあなたがカーソルの描画をしている、またはどのくらいの頻度あなたがそれを描いているのか理由でぎくしゃくしているのですか?あなただけのカーソルがOpenGLの呼び出しを使用してことになっているポイントを描画した場合、それはまだぎくしゃくしていますか?あなたのタイミングコードが問題だろうか?

どのようなコードを、あなたは、すべてのダニポインタを更新するように求めていますか?私はそれはあなたが代わりのサイズ変更イベントに、中心点を毎回計算されるように記載されたコードではないと仮定します。

盲目的にここに答えるための

私の謝罪(すなわち、限られた供給過剰の経験を持ちます)。

私はここで推測しているが、私はカーソルがOSで扱うのではなく、アプリケーションの描画機能(表示())に描かれているので、動きがぎくしゃくしていることを疑うます。

正常マウスポインタは、フレームバッファの内容とカーソル画像のXORをとることにより、ドライバレベルで処理される - このように雷迅速、及び(応答性の錯覚を維持するために、割り込みサービスルーチン内でOSによって非常に高い優先度で処理します)。

あなたはそれを自分で描くときは、

、あなたはあなたのOSの定期的なスケジューリングメカニズムの対象としている&定期明らか経る&ウィンドウ全体のrigamaroleを再描画します。この場合、それはできるだけ早く我々は、上記によるマウスポインタでに慣れていると高速ですが、ありません。

要するに、私はあなたがあなたがそれは(あなたの表示機能&アプリのロジックが複雑になり、特にとして)であることを期待ほど高速であることを得るだろうかわからない。

グッドラック!

あなたはいくつかのフレームの上にマウスの動きを平均化していますか? 私は仕事で午前ので、私は私の以前のプロジェクトのために私のコードを見つけることができません。 しかし、私は前に、数フレームの上にマウスの動きを平均化だと思います 私は動きが非常にぎくしゃくしたということでした。

あなたは非ダブルバッファのウィンドウにバッファを交換しているので、それが可能だろうか?

私はglutInitDisplayMode()。にGLUT_DOUBLEを追加しない限り、あなたの例では、私のWin32のシステム上では動作しません。

編集ます:

あなたは正しいです。運動機能の中からglutWarpPointer()を呼び出すと、私の[win32の]システム上のループを引き起こしているようです。私は、ボタンか何かをクリックしない限り、タイマーでも発射する機会を得ることはありません。私は、メッセージキューがモーションイベントが殺到している賭けている。

モーション機能から

の呼び出し表示()右のいずれか、動作するようには思えない - この時間は、それが運動のいずれかの種類を登録するには失敗した。

私は仕事にあなたの例を得ることができる唯一の方法は、直接その関数からのアクティブなのモーション・コールバックと呼び出し元の表示()にのパッシブの運動のコールバックを変更することでした。私は、これははるかにあなたが本来意図したものからですけど、少なくとも私はこのようにいくつかの滑らかな動きを得ています。

あなたはあなたのために、表示の更新をトリガするglutIdleFuncを()使用してみましたか?それはまだ浸水メッセージキューでは動作しないかもしれませんが、それは試してみる価値があるかもしれません。また、API呼び出しを使用して、マウスをキャプチャする代わりに、手動ですべての運動で、ウィンドウの中央にカーソルをラップに見ることができます。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top