halive-0.1.5: demo/Window.hs
{-# LANGUAGE ViewPatterns #-}
module Window where
import Control.Monad
import SDL
import Control.Monad.Trans
import Control.Exception
import Linear
import Linear.Affine
import Data.Text (Text)
import Control.Lens
createGLWindow :: MonadIO m => Text -> m (Window, GLContext)
createGLWindow windowName = do
initialize
[ InitVideo
, InitEvents
-- , InitJoystick , InitGameController
]
window <- createWindow windowName defaultWindow
{ windowOpenGL = Just $ defaultOpenGL
{ glProfile = Core Normal 4 1
}
, windowHighDPI = True
, windowInitialSize = V2 640 480
--, windowPosition = Centered
, windowPosition = Absolute (P (V2 100 100))
, windowResizable = True
}
glContext <- glCreateContext window
glMakeCurrent window glContext
swapInterval $= ImmediateUpdates
return (window, glContext)
withWindow windowName = bracket (createGLWindow windowName)
(\(win, ctx) -> do
destroyWindow win
glDeleteContext ctx)
whileWindow :: MonadIO m => Window -> ([Event] -> m a) -> m ()
whileWindow window action = do
let loop = do
--liftIO (putStrLn "pollEvents")
events <- pollEvents
--liftIO (putStrLn "action")
_ <- action events
let shouldQuit = (QuitEvent `elem`) $ map eventPayload events
unless shouldQuit loop
loop
destroyWindow window
windowPosToWorldPos :: (Epsilon a, Real a, Floating a)
=> V2 a
-> M44 a
-> V2 a
-> a
-> V3 a
windowPosToWorldPos winSize viewProj coord depth = rayStart + rayDir * realToFrac depth
where
V2 xNDC yNDC = win2Ndc coord winSize
rayStart = ndc2Wld (V4 xNDC yNDC (-1.0) 1.0)
rayEnd = ndc2Wld (V4 xNDC yNDC 0.0 1.0)
rayDir = normalize (rayEnd ^-^ rayStart)
-- Converts from window coordinates (origin top-left) to normalized device coordinates
win2Ndc (V2 x y) (V2 w h) =
V2 ((x / w - 0.5) * 2)
((((h - y) / h) - 0.5) * 2)
-- Converts from normalized device coordinates to world coordinates
ndc2Wld i = hom2Euc (invViewProj !* i)
-- Converts from homogeneous coordinates to Euclidean coordinates
hom2Euc v = (v ^/ (v ^. _w)) ^. _xyz
invViewProj = inv44 viewProj