module Gamgine.Math.Matrix (
module Data.Vec,
Matrix,
Window,
Frustum(..),
mkOrtho,
mkScale,
mkTranslate,
mkWindowMatrix,
mkWorldToWinMatrix,
mkWinToWorldMatrix,
winToWorld,
inverseOrIdentity) where
import Data.Vec
import Gamgine.Math.Vect
type Matrix = Mat44 Double
type Width = Int
type Height = Int
type Window = (Width, Height)
type X = Int
type Y = Int
type WinCoord = (X, Y)
data Frustum = Frustum {
left :: Double,
right :: Double,
bottom :: Double,
top :: Double,
near :: Double,
far :: Double
} deriving (Show, Eq)
mkOrtho :: Frustum -> Matrix
mkOrtho Frustum {left = l, right = r, bottom = b, top = t, near = n, far = f} =
matFromList [2 / rml, 0, 0, (rpl / rml),
0 , 2 / tmb, 0, (tpb / tmb),
0 , 0, 2 / fmn, (fpn / fmn),
0 , 0, 0, 1]
where
rml = r l
rpl = r + l
tmb = t b
tpb = t + b
fmn = f n
fpn = f + n
mkScale :: Vect -> Matrix
mkScale v = scale (snoc v 1) identity
mkTranslate :: Vect -> Matrix
mkTranslate v = translate v identity
mkWindowMatrix :: Window -> Matrix
mkWindowMatrix (width, height) = toGLFW dHeight `multmm` unitCubeToWin dWidth dHeight
where
unitCubeToWin :: Double -> Double -> Matrix
unitCubeToWin width height =
mkScale (v3 (width*0.5) (height*0.5) 0.5) `multmm` mkTranslate (v3 1 1 1)
toGLFW :: Double -> Matrix
toGLFW height = mkTranslate (v3 0 height 0) `multmm` mkScale (v3 1 (1) 1)
dWidth = fromIntegral width
dHeight = fromIntegral height
mkWorldToWinMatrix :: Window -> Frustum -> Matrix
mkWorldToWinMatrix win frust = mkWindowMatrix win `multmm` mkOrtho frust
mkWinToWorldMatrix :: Window -> Frustum -> Matrix
mkWinToWorldMatrix win frust = inverseOrIdentity $ mkWorldToWinMatrix win frust
inverseOrIdentity :: Matrix -> Matrix
inverseOrIdentity m =
case invert m of
Nothing -> identity
Just m -> m
winToWorld :: Matrix -> WinCoord -> Vect
winToWorld winToWorldMatrix (x, y) = fromVect4 $ winToWorldMatrix `multmv` posVec
where
posVec = v4 (fromIntegral x) (fromIntegral y) 0 1