3

私はOpenGlと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

いずれかの方法でプログラムが早期に終了する原因は何かありますか、それともこれはコンピューターがこれを実行できないことを私に伝える方法ですか?

4

1 に答える 1

5

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

ただし、次のように言うかもしれません。多くの/ほとんどのプラットフォームでは、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
于 2012-04-17T00:51:24.347 に答える