2012-04-16 6 views
3

OpenGlとHaskellを使って、マウスをクリックしたときとどこでクリックするかを描くプログラムを書いています。ただし、プログラムをクリックすると直ちに終了し、矩形が描画されます。Haskellのグラフィックスプログラムが早すぎる閉じる

import Graphics.Rendering.OpenGL 
import Graphics.UI.GLUT 
import Graphics.UI.GLUT.Callbacks.Window 

main = do 
    (progname, _) <- getArgsAndInitialize 
    createWindow progname 
    keyboardMouseCallback $= Just myKeyboardMouseCallback 
    displayCallback $= display 
    mainLoop 

myKeyboardMouseCallback key keyState modifiers (Position x y) = 
    case (key, keyState) of 
    (MouseButton LeftButton, Down) -> do 
     clear[ColorBuffer] 
     let x = x :: GLfloat 
     let y = y :: GLfloat 
     renderPrimitive Quads $ do 
     color $ (Color3 (1.0::GLfloat) 0 0) 
     vertex $ (Vertex3 (x::GLfloat) y 0) 
     vertex $ (Vertex3 (x::GLfloat) (y+0.2) 0) 
     vertex $ (Vertex3 ((x+0.2)::GLfloat) (y+0.2) 0) 
     vertex $ (Vertex3 ((x+0.2)::GLfloat) y 0) 
     flush 
    _ -> return() 

display = do 
    clear [ColorBuffer] 
    renderPrimitive Lines $ do 
    flush 

プログラムは、早期のいずれかの方法で終了させる何かがあるのか​​、これは私がこれを行うことができない私に告げるのコンピュータだけの方法ですか?

答えて

5

あなたがしようとしていることはできません。 OpenGLプログラムでは、OpenGLコンテキストでのみ描画コマンドを発行できます。このコンテキストは常に特定のスレッドにバインドされ、GLUT内のdisplayCallbackの本体でのみアクティブになります。これは、他のコールバックが異なるスレッドから実行される可能性があるためです。

多くの/ほとんどのプラットフォームでは、別のスレッドは、がGLUTの入力に使用されていないため、理論的にそこで描画コマンドを発行できます。ただし、描画コマンドを発行できる場所とタイミングにはさまざまな役割があります。例えば、バッファリングされたバッファを非常に特殊な方法(X11の場合はEGLまたはGLXを使用する場合など)でフラッシュする必要がある環境では、ダブルバッファ出力を使用する必要がある場合などです。

要約:displayCallbackの外部に描画コマンドを発行しないでください。その存在理由は、GLUTにネイティブフレームバッファ管理に関連するプラットフォーム特有のものを処理させることができるようにするためであり、コードを適切な場所に置いて動作させることを期待しています。

代わりに、変更可能な変数を作成してください(ちょっと、OpenGLを使用しています;変更可能な状態は心配するべきではありません)。 (Data.IORefを使用する)ような何か:

main = do 
    -- ... 

    -- Create a mutable variable that stores a Bool and a pair of floats 
    mouseStateRef <- newIORef (False, (0, 0)) 

    -- Pass a reference to the mutable variable to the callbacks 
    keyboardMouseCallback $= Just (myKeyboardMouseCallback mouseStateRef) 
    displayCallback $= (display mouseStateRef) 

myKeyboardMouseCallback mouseStateRef key keyState modifiers (Position x y) = 
    case key of 
    MouseButton LeftButton -> do 
     -- Store the current mouse pressed state and coords in the reference 
     writeIORef mouseStateRef (keyState == Pressed, (x, y)) 
    _ -> return() 

display mouseStateRef = do 
    clear [ColorBuffer] 

    -- Read the state stored in the mutable reference 
    (pressed, (x, y)) <- readIORef mouseStateRef 

    -- Draw the quad if the mouse button is pressed 
    when pressed . renderPrimitive Quads $ do 
    color $ (Color3 (1.0::GLfloat) 0 0) 
    vertex $ (Vertex3 (x::GLfloat) y 0) 
    vertex $ (Vertex3 (x::GLfloat) (y+0.2) 0) 
    vertex $ (Vertex3 ((x+0.2)::GLfloat) (y+0.2) 0) 
    vertex $ (Vertex3 ((x+0.2)::GLfloat) y 0) 
    flush 
+0

一種の理にかなっているが、私はそれを試しに行ったとき、私は適用範囲外であることiorefsのためのエラーを持って、別のKEYSTATE上==すなわちプレスで、プレス。 – lewdsterthumbs

+0

私はコードをテストしていません。私はあなたに一般的な考えを伝えたいと思っていました。あなたは 'Data.IORef'と他のものをインポートしなければなりません。私はあなたのためにすべての*仕事をしません。 – dflemstr

+0

私は知っていますが、私はまだ同じ問題のいくつかを持っています。 MouseStateRefは実際にはintのペアを保持しています。私はフロートが必要です。 – lewdsterthumbs

関連する問題