module Main (main) where import Data.IORef import qualified Graphics.UI.Gtk as Gtk import Graphics.UI.Gtk (AttrOp((:=))) import qualified Graphics.UI.Gtk.OpenGL as GtkGL import Graphics.Rendering.OpenGL as GL main :: IO () main = do Gtk.initGUI -- Initialise the Gtk+ OpenGL extension -- (including reading various command line parameters) GtkGL.initGL -- We need a OpenGL frame buffer configuration to be able to create other -- OpenGL objects. glconfig <- GtkGL.glConfigNew [GtkGL.GLModeRGBA, GtkGL.GLModeDepth, GtkGL.GLModeDouble] -- Create an OpenGL drawing area widget canvas <- GtkGL.glDrawingAreaNew glconfig Gtk.widgetSetSizeRequest canvas 350 350 -- Initialise some GL setting just before the canvas first gets shown -- (We can't initialise these things earlier since the GL resources that -- we are using wouldn't heve been setup yet) Gtk.onRealize canvas $ GtkGL.withGLDrawingArea canvas $ \_ -> do clearColor $= (Color4 0.0 0.0 0.0 0.0) matrixMode $= Projection loadIdentity ortho 0.0 1.0 0.0 1.0 (-1.0) 1.0 depthFunc $= Just Less drawBuffer $= BackBuffers ref <- newIORef (0, 0, 0) -- Set the repaint handler Gtk.onExpose canvas $ \_ -> do GtkGL.withGLDrawingArea canvas $ \glwindow -> do (r_x, r_y, r_z) <- readIORef ref GL.clear [GL.DepthBuffer, GL.ColorBuffer] drawCube (r_x, r_y, r_z) GtkGL.glDrawableSwapBuffers glwindow return True -- Setup the animation Gtk.timeoutAddFull (do modifyIORef ref (\(r_x, r_y, r_z) -> (r_x + dx, r_y + dy, r_z + dz)) Gtk.widgetQueueDraw canvas return True) Gtk.priorityDefaultIdle animationWaitTime -------------------------------- -- Setup the rest of the GUI: -- window <- Gtk.windowNew Gtk.onDestroy window Gtk.mainQuit Gtk.set window [ Gtk.containerBorderWidth := 8, Gtk.windowTitle := "Gtk2Hs + HOpenGL demo" ] vbox <- Gtk.vBoxNew False 4 Gtk.set window [ Gtk.containerChild := vbox ] label <- Gtk.labelNew (Just "Gtk2Hs using OpenGL via HOpenGL!") button <- Gtk.buttonNewWithLabel "Close" Gtk.onClicked button (do Gtk.widgetDestroy window Gtk.mainQuit) Gtk.set vbox [ Gtk.containerChild := canvas, Gtk.containerChild := label, Gtk.containerChild := button ] Gtk.widgetShowAll window Gtk.mainGUI drawCube :: (GLfloat, GLfloat, GLfloat) -> IO () drawCube (r_x, r_y, r_z) = do loadIdentity rotate r_x (Vector3 1 0 0 :: Vector3 GLfloat) rotate r_y (Vector3 0 1 0 :: Vector3 GLfloat) rotate r_z (Vector3 0 0 1 :: Vector3 GLfloat) mapM_ drawFace (zip colours faces) where drawFace :: (Color3 GLfloat, IO ()) -> IO () drawFace (colour, face) = do color colour renderPrimitive Quads face faces = map (mapM_ vertex) faceVertices :: [IO ()] colours = [red, green, yellow, blue, purple, cyan] faceVertices = [ [Vertex3 to to to, Vertex3 from to to, Vertex3 from from to, Vertex3 to from to], [Vertex3 to to from, Vertex3 from to from, Vertex3 from from from, Vertex3 to from from], [Vertex3 to to to, Vertex3 from to to, Vertex3 from to from, Vertex3 to to from], [Vertex3 to from to, Vertex3 from from to, Vertex3 from from from, Vertex3 to from from], [Vertex3 to to to, Vertex3 to from to, Vertex3 to from from, Vertex3 to to from], [Vertex3 from to to, Vertex3 from from to, Vertex3 from from from, Vertex3 from to from]] to, from :: GLfloat to = 0.4 from = -0.4 animationWaitTime :: Int animationWaitTime = 3 dx, dy, dz :: GLfloat dx = 0.1 dy = 0.3 dz = 0.7 red, green, yellow, blue, purple, cyan :: Color3 GLfloat red = Color3 1 0 0 green = Color3 0 1 0 yellow = Color3 1 1 0 blue = Color3 0 0 1 purple = Color3 1 0 1 cyan = Color3 0 1 1