reactive-glut-0.0.1: src/FRP/Reactive/GLUT/SimpleGfx.hs
{-# OPTIONS_GHC -Wall #-}
module FRP.Reactive.GLUT.SimpleGfx
( initGfx, glwrap, windowPoint
-- remove later
, drawBox
) where
import Graphics.UI.GLUT
-- import Graphics.Rendering.OpenGL as GL
windowWidth, windowHeight :: GLint
windowWidth = 800 -- physical pixels
windowHeight = 600 -- physical pixels
canvasMinX, canvasMaxX, canvasMinY, canvasMaxY :: Double
canvasMaxX = 400 -- logical units
canvasMinX = -400 -- logical units
canvasMaxY = 300 -- logical units
canvasMinY = -300 -- logical units
canvasFarZ, canvasNearZ :: GLclampd
canvasFarZ = 4000
canvasNearZ = -4000
-- Initialize GL graphics
initGfx :: String -> IO ()
initGfx title = do
-- Glut Part
getArgsAndInitialize
initialWindowSize $= (Size windowWidth windowHeight)
initialDisplayMode $= [DoubleBuffered, RGBAMode]
createWindow title
-- OpenGL Part
shadeModel $= Smooth
lineSmooth $= Enabled
lighting $= Enabled
-- Needs to be disabled for fieldtrip
-- colorMaterial $= Just (Front,AmbientAndDiffuse)
light (Light 0) $= Enabled
-- Enable the following if non-uniform scaling will occur
normalize $= Enabled
-- Enable the following if only uniform scaling will occur
-- rescaleNormal $= Enabled
-- Set the light up at an infinite distance behind the camera
position (Light 0) $= (Vertex4 0.0 0.0 1.0 0.0)
ambient (Light 0) $= (Color4 0.0 0.0 0.0 1.0)
diffuse (Light 0) $= (Color4 1.0 1.0 1.0 1.0)
specular (Light 0) $= (Color4 1.0 1.0 1.0 1.0)
-- Some simple defaults here.
materialSpecular (Front) $= (Color4 1.0 1.0 1.0 1.0)
materialEmission (Front) $= (Color4 0.0 0.0 0.0 1.0)
materialShininess (Front) $= 70.0
blend $= Enabled
blendFunc $= (SrcAlpha, OneMinusSrcAlpha)
lineWidth $= 1.5
clearColor $= Color4 0 0 0 0
pointSmooth $= Enabled
-- pointSize $= 5.0
clearDepth $= canvasFarZ
depthRange $= (canvasNearZ, canvasFarZ)
depthFunc $= Just Lequal
matrixMode $= Projection
loadIdentity
ortho canvasMinX canvasMaxX canvasMinY canvasMaxY canvasNearZ canvasFarZ
matrixMode $= Modelview 0
loadIdentity
-- | Convert a window position to a logical X,Y. Logical zero is at the
-- origin, and [size??].
--
-- TODO: fix to work with variable window size.
windowPoint :: Position -> IO (Double, Double)
windowPoint (Position x y) = return $
let pixToLog p minP maxP l u =
let p0to1 = (realToFrac $ p-minP)/(realToFrac $ maxP-minP)
in (p0to1 * (u-l)) + l
in (pixToLog x 0 (windowWidth-1) canvasMinX canvasMaxX,
-(pixToLog y 0 (windowHeight-1) canvasMinY canvasMaxY))
-- | Wrap an OpenGL rendering action, to clear the frame-buffer before
-- swap buffers afterward.
glwrap :: IO () -> IO ()
glwrap act = do clearScreen (0.0,0.0,0.0)
-- putStrLn "glwrap"
act
swapBuffers
clearScreen :: (GLdouble, GLdouble, GLdouble) -> IO()
clearScreen (r,g,b) = do
clearColor $= Color4 (realToFrac r) (realToFrac g) (realToFrac b) 0
clear [ColorBuffer, DepthBuffer]
vertexPF :: VertexComponent a => (a,a) -> IO ()
vertexPF = vertex . (uncurry Vertex2)
drawBox :: (MatrixComponent c, Fractional c) => (c, c) -> IO ()
drawBox (centerX,centerY) = preservingMatrix $ do
translate $ Vector3 centerX centerY 0.0
renderPrimitive Polygon (mapM_ vertexPF [
(-10.0::GLdouble ,-10.0),
(-10.0,10.0),
(10.0,10.0),
(10.0,-10.0) ] )