1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
|
{-# 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
|