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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
|
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}
module Graphics.Glyph.GLMath where
import Graphics.Glyph.Mat4
import qualified Graphics.Rendering.OpenGL as GL
import Graphics.Rendering.OpenGL (GLfloat,Uniform,Vertex3(..),uniform,UniformComponent)
import Data.Angle
import Data.Maybe
import Debug.Trace
data Vec2 a = Vec2 (a,a) deriving Show
data Vec3 a = Vec3 (a,a,a) deriving Show
data Vec4 a = Vec4 (a,a,a,a) deriving Show
instance UniformComponent a => Uniform (Vec3 a) where
uniform loc = GL.makeStateVar
(do
(Vertex3 x y z) <-
GL.get (uniform loc)
return (Vec3 (x,y,z)) )
(\(Vec3 (x,y,z)) -> uniform loc GL.$= Vertex3 x y z)
uniformv _ = undefined
instance UniformComponent a => Uniform (Vec4 a) where
uniform loc = GL.makeStateVar
(do
(GL.Vertex4 x y z w) <-
GL.get (uniform loc)
return (Vec4 (x,y,z,w)) )
(\(Vec4 (x,y,z,w)) -> uniform loc GL.$= GL.Vertex4 x y z w)
uniformv _ = undefined
class (Floating flT) => Vector flT b where
(<+>) :: b flT -> b flT -> b flT
(<->) :: b flT -> b flT -> b flT
norm :: b flT -> flT
normalize :: b flT -> b flT
vDot :: b flT -> b flT -> flT
vScale :: flT -> b flT -> b flT
vNegate :: b flT -> b flT
(<.>) :: (Vector a b) => b a -> b a -> a
(<.>) = vDot
(|||) :: (Vector a b) => b a -> a
(|||) = norm
instance (Floating flT) => Vector flT Vec2 where
(<+>) (Vec2 (a,b)) (Vec2 (c,d)) = Vec2 (a+c,b+d)
(<->) (Vec2 (a,b)) (Vec2 (c,d)) = Vec2 (a-c,b-d)
vDot (Vec2 (a,b)) (Vec2 (c,d)) = a * c + b * d
vScale c (Vec2 (a,b)) = Vec2 (a*c,b*c)
norm (Vec2 (a,b)) = sqrt (a*a + b*b)
normalize vec@(Vec2 (a,b)) =
let n = norm vec in Vec2 (a/n,b/n)
vNegate (Vec2 (a,b)) = Vec2 (-a,-b)
instance (Floating flT) => Vector flT Vec3 where
(<+>) (Vec3 (a,b,c)) (Vec3 (d,e,f)) = Vec3 (a+d,b+e,c+f)
(<->) (Vec3 (a,b,c)) (Vec3 (d,e,f)) = Vec3 (a-d,b-e,c-f)
vDot (Vec3 (a,b,c)) (Vec3 (d,e,f)) = a * d + b * e + c * f
vScale x (Vec3 (a,b,c)) = Vec3 (a*x,b*x,c*x)
norm (Vec3 (a,b,c)) = sqrt (a*a + b*b + c*c)
normalize vec@(Vec3 (a,b,c)) =
let n = norm vec in Vec3 (a/n,b/n,c/n)
vNegate (Vec3 (a,b,c)) = Vec3 (-a,-b,-c)
instance (Floating flT) => Vector flT Vec4 where
(<+>) (Vec4 (a,b,c,g)) (Vec4 (d,e,f,h)) = Vec4 (a+d,b+e,c+f,g+h)
(<->) (Vec4 (a,b,c,g)) (Vec4 (d,e,f,h)) = Vec4 (a-d,b-e,c-f,g-h)
vDot (Vec4 (a,b,c,g)) (Vec4 (d,e,f,h)) = a * d + b * e + c * f + g * h
vScale x (Vec4 (a,b,c,d)) = Vec4 (a*x,b*x,c*x,d*x)
norm (Vec4 (a,b,c,d)) = sqrt (a*a + b*b + c*c + d*d)
normalize vec@(Vec4 (a,b,c,d)) =
let n = norm vec in Vec4 (a/n,b/n,c/n,d/n)
vNegate (Vec4 (a,b,c,d)) = Vec4 (-a,-b,-c,-d)
cross :: (Num a) => Vec3 a -> Vec3 a -> Vec3 a
cross (Vec3 (u1,u2,u3)) (Vec3 (v1,v2,v3)) =
Vec3 ( u2*v3 - u3*v2,
u3*v1 - u1*v3,
u1*v2 - u2*v1 )
(×) :: (Num a) => Vec3 a -> Vec3 a -> Vec3 a
(×) = cross
lookAtMatrix :: Vec3 GLfloat -> Vec3 GLfloat -> Vec3 GLfloat -> Mat4 GLfloat
lookAtMatrix e c u =
let f@(Vec3 (fx,fy,fz)) = normalize (c <-> e)
s@(Vec3 (sx,sy,sz)) = normalize (f × u)
u'@(Vec3 (ux,uy,uz)) = s × f in
Matrix4 (sx, ux, -fx, 0,
sy, uy, -fy, 0,
sz, uz, -fz, 0,
-(s<.>e) , -(u'<.>e), f<.>e, 1 )
orthoMatrix :: GLfloat -> GLfloat -> GLfloat -> GLfloat -> GLfloat -> GLfloat -> Mat4 GLfloat
orthoMatrix top bot right left near far =
Matrix4 (2 / (right-left), 0, 0, - (right + left) / (right - left),
0, 2 / (top-bot), 0, - (top+bot) / (top-bot),
0, 0, -2 / (far-near), - (far+near) / (far - near),
0, 0, 0, 1)
perspectiveMatrix :: GLfloat -> GLfloat -> GLfloat -> GLfloat -> Mat4 GLfloat
{- as close to copied from glm as possible -}
perspectiveMatrix fov asp zn zf =
let tanHalfFovy = tangent (Degrees fov/2)
res00 = 1 / (asp * tanHalfFovy)
res11 = 1 / tanHalfFovy
res22 = - (zf + zn) / (zf - zn)
res23 = - 1
res32 = - (2 * zf * zn) / (zf - zn) in
trace ("res22=" ++ show res22) $
Matrix4 (res00, 0, 0, 0,
0, res11, 0, 0,
0, 0, res22, res23,
0, 0, res32, 0)
class VectorMatrix vecT matT where
vTranslate :: matT -> vecT -> matT
(-*|) :: matT -> vecT -> vecT
instance (Num a) => VectorMatrix (Vec3 a) (Mat3 a) where
vTranslate (Matrix3 (a00,a01,a02,
a10,a11,a12,
a20,a21,a22)) (Vec3 (a,b,c)) =
Matrix3 (a00,a01,a02+a,
a10,a11,a12+b,
a20,a21,a22+c)
(Matrix3 (a00,a01,a02,
a10,a11,a12,
a20,a21,a22)) -*| (Vec3 (a,b,c)) =
Vec3 (a00 * a + a01 * b + a02 * c,
a10 * a + a11 * b + a12 * c,
a20 * a + a21 * b + a22 * c )
instance (Num a) => VectorMatrix (Vec4 a) (Mat4 a) where
vTranslate mat (Vec4 tmp) = translateMat4 mat tmp
mat -*| tmp = glslMatMul mat tmp
glslMatMul :: (Num a) => Mat4 a -> Vec4 a -> Vec4 a
glslMatMul (Matrix4 (m00,m01,m02,m03,
m10,m11,m12,m13,
m20,m21,m22,m23,
m30,m31,m32,m33)) (Vec4 (v0,v1,v2,v3)) =
Vec4 ( v0 * m00 + v1 * m10 + v2 * m20 + v3 * m30,
v0 * m01 + v1 * m11 + v2 * m21 + v3 * m31,
v0 * m02 + v1 * m12 + v2 * m22 + v3 * m32,
v0 * m03 + v1 * m13 + v2 * m23 + v3 * m33 )
glslModelViewToNormalMatrix :: Mat4 GLfloat -> Mat3 GLfloat
glslModelViewToNormalMatrix = fromJust.inverse.transpose.trunc4
(==>) :: (Num a) => Mat4 a -> Vec4 a -> Mat4 a
(==>) = glslMatTranslate
glslMatTranslate :: (Num a) => Mat4 a -> Vec4 a -> Mat4 a
glslMatTranslate
mat@(Matrix4 (m00,m01,m02,m03,
m10,m11,m12,m13,
m20,m21,m22,m23,
m30,m31,m32,m33)) vec =
let (Vec4 (v0,v1,v2,v3)) = mat -*| vec in
Matrix4 (m00,m01,m02,m03,
m10,m11,m12,m13,
m20,m21,m22,m23,
m30+v0,m31+v1,m32+v2,m33+v3)
|