{-| Module : Main Copyright : (c) 2015 Brian W Bush License : MIT Maintainer : Brian W Bush Stability : Stable Portability : Portable Example application illustrating obtaining input from and tracking a SpaceNavigator \<\>, or a 3D mouse compatible with its protocols. -} module Main ( -- * Entry Point main ) where import Data.Default (def) import Data.IORef (IORef, newIORef) import Graphics.Rendering.OpenGL (ClearBuffer(..), Color3(..), ComparisonFunction(Less), GLfloat, MatrixMode(Modelview, Projection), Position(..), PrimitiveMode(..), SettableStateVar, Size(..), Vector3(..), Vertex3(..), ($=), ($=!), clear, color, depthFunc, flush, frustum, get, loadIdentity, matrixMode, preservingMatrix, renderPrimitive, rotate, translate, vertex, viewport) import Graphics.UI.GLUT (DisplayCallback, DisplayMode(..), ReshapeCallback, createWindow, displayCallback, getArgsAndInitialize, idleCallback, initialDisplayMode, mainLoop, postRedisplay, reshapeCallback, swapBuffers) import Graphics.UI.SpaceNavigator (SpaceNavigatorCallback, Track(..), defaultQuantization, defaultTracking, doTracking', quantize, spaceNavigatorCallback, track) -- | The main action. main :: IO () main = do (_, arguments) <- getArgsAndInitialize initialDisplayMode $= [WithDepthBuffer, DoubleBuffered] _ <- createWindow "SpaceNavigator " depthFunc $= Just Less reshapeCallback $= Just reshape dispatch arguments -- | Respond to the window being created or reshaped. reshape :: ReshapeCallback reshape (Size w h) = do viewport $= (Position 0 0, Size (minimum [w, h]) (minimum[w, h])) matrixMode $=! Projection loadIdentity frustum (-0.4) 0.4 (-0.4) 0.4 1 6 matrixMode $=! Modelview 0 -- | Respond to command-line arguments. dispatch :: [String] -> IO () dispatch ["raw"] = do (spaceNavigatorCallback :: SettableStateVar (Maybe (SpaceNavigatorCallback GLfloat))) $=! Just print displayCallback $=! display Nothing mainLoop dispatch ["quantized"] = let (pushThreshold, tiltThreshold) = defaultQuantization :: (GLfloat, GLfloat) in dispatch ["quantized", show pushThreshold, show tiltThreshold] dispatch ["quantized", pushThreshold, tiltThreshold] = do spaceNavigatorCallback $=! Just (quantize (read pushThreshold, read tiltThreshold :: GLfloat) print) displayCallback $=! display Nothing mainLoop dispatch ["track"] = let (pushThreshold, tiltThreshold) = defaultQuantization :: (GLfloat, GLfloat) in dispatch ["track", show pushThreshold, show tiltThreshold] dispatch ["track", pushThreshold, tiltThreshold] = do tracking <- newIORef $ def {trackPosition = Vector3 0 0 0} spaceNavigatorCallback $=! Just ( quantize (read pushThreshold, read tiltThreshold) $ \input -> do track defaultTracking tracking input tracking' <- get tracking print tracking' ) displayCallback $=! display (Just tracking) idleCallback $=! Just (postRedisplay Nothing) mainLoop dispatch _ = do putStrLn "Usage:" putStrLn " opengl-spacenavigator raw : prints raw data from SpaceNavigator" putStrLn " opengl-spacenavigator quantized [pushThreshold tiltThreshold] : prints quantized data from SpaceNavigator" putStrLn " opengl-spacenavigator track [pushThreshold tiltThreshold] : prints 6D tracking based on data from SpaceNavigator" -- | The display callback. display :: Maybe (IORef (Track GLfloat)) -> DisplayCallback display (Just tracking) = do let (u, v, w) = (0.03, 0.06, -0.18) :: (GLfloat, GLfloat, GLfloat) p0 = ( 0, 0, w) p1 = (-u, -u, 0) p2 = ( u, -u, 0) p3 = ( 0, v, 0) clear [ColorBuffer, DepthBuffer] loadIdentity rotate 10 $ Vector3 1 2 (0 :: GLfloat) translate $ Vector3 0.5 (-0.2) (-3.5 :: GLfloat) preservingMatrix $ do doTracking' tracking color $ Color3 1.0 0.4 (0.5 :: GLfloat) renderPrimitive Triangles $ mapM_ vertex3f [ p1, p2, p3 , p1, p2, p0 , p1, p0, p3 , p0, p2, p3 ] color $ Color3 1 1 (1 :: GLfloat) renderPrimitive Lines $ mapM_ vertex3f [ p1, p2 , p2, p3 , p3, p1 , p1, p0 , p2, p0 , p3, p0 ] color $ Color3 0.5 1.0 (0.4 :: GLfloat) preservingMatrix $ renderPrimitive Lines $ mapM_ vertex3f $ concat [ [ (2 * u' - 1, 2 * v' - 1, -0.8), (2 * u' - 1, 2 * v' - 1, 0.8) , (2 * u' - 1, -0.8, 2 * v' - 1), (2 * u' - 1, 0.8, 2 * v' - 1) , ( -0.8, 2 * u' - 1, 2 * v' - 1), ( 0.8, 2 * u' - 1, 2 * v' - 1) ] | u' <- [0.1,0.2..0.9] , v' <- [0.1,0.2..0.9] ] flush swapBuffers display Nothing = do clear [ColorBuffer, DepthBuffer] swapBuffers -- | Make coordinates into a vertex. vertex3f :: (GLfloat, GLfloat, GLfloat) -> IO () vertex3f (x, y, z) = vertex $ Vertex3 x y z