{-# LANGUAGE BangPatterns, FlexibleContexts #-} module Matrix where import Numeric.LinearAlgebra import Foreign.Storable import Data.Vector.Generic as V (snoc,init) import Prelude hiding ((<>)) -- | 3×3 rotation matrix about the x axis. rotMatrixX :: (Storable a, Floating a) => a -> Matrix a rotMatrixX a = (3><3) [ 1 , 0 , 0 , 0 , c , -s , 0 , s , c ] where (c,s) = (cos a, sin a) -- | 3×3 rotation matrix about the y axis. rotMatrixY :: (Storable a, Floating a) => a -> Matrix a rotMatrixY a = (3><3) [ c , 0 , s , 0 , 1 , 0 , -s , 0 , c ] where (c,s) = (cos a, sin a) -- | 3×3 rotation matrix about the z axis. rotMatrixZ :: (Storable a, Floating a) => a -> Matrix a rotMatrixZ a = (3><3) [ c , -s , 0 , s , c , 0 , 0 , 0 , 1 ] where (c,s) = (cos a, sin a) -- | Camera transformation matrix (4×4). lookat :: (Numeric t, Num (Vector t), Fractional t, Normed (Vector t)) => Vector t -- ^ Camera position 3-vector. -> Vector t -- ^ Target position 3-vector. -> Vector t -- ^ Upward direction 3-vector. -> Matrix t lookat pos target up = fromRows [ snoc rightward (- dot rightward pos) , snoc upward (- dot upward pos) , snoc backward (- dot backward pos) , snoc (fromList[0,0,0]) 1 ] where backward = normalize $ pos - target rightward = normalize $ up `cross` backward upward = backward `cross` rightward -- Rebind 'normalize' in order to support Float which has no Field -- instance. normalize :: (Linear t c, Fractional t, Normed (c t)) => c t -> c t normalize v = scale (1 / realToFrac (norm_2 v)) v {-# SPECIALIZE lookat :: Vector R -> Vector R -> Vector R -> Matrix R #-} -- | Perspective transformation 4×4 matrix. perspective :: (Storable a, Floating a) => a -- ^ Near plane clipping distance (always positive). -> a -- ^ Far plane clipping distance (always positive). -> a -- ^ Field of view of the y axis, in radians. -> a -- ^ Aspect ratio, i.e. screen's width\/height. -> Matrix a perspective n f fovy aspect = (4><4) [ (2*n/(r-l)) , 0 , (-(r+l)/(r-l)) , 0 , 0 , (2*n/(t-b)) , ((t+b)/(t-b)) , 0 , 0 , 0 , (-(f+n)/(f-n)) , (-2*f*n/(f-n)) , 0 , 0 , (-1) , 0 ] where t = n*tan(fovy/2) b = -t r = aspect*t l = -r