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 -- row major matrix 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