diff options
author | Joe Crayne <joe@jerkface.net> | 2019-04-22 03:13:44 -0400 |
---|---|---|
committer | Joe Crayne <joe@jerkface.net> | 2019-04-22 03:36:23 -0400 |
commit | ac89ee199abfe893b03cdbb89a426cd0594e06c9 (patch) | |
tree | c3542c880eb610e9a2d5d863ec9ba518a32a0b02 | |
parent | 36bd8e7133eca5d4e04252c555ee0cc2cc78106e (diff) |
objdemo: pass view matrix from haskell.
-rw-r--r-- | GLWidget.hs | 5 | ||||
-rw-r--r-- | LambdaCube/GL/HMatrix.hs | 49 | ||||
-rw-r--r-- | Matrix.hs | 230 | ||||
-rw-r--r-- | TimeKeeper.hs | 3 | ||||
-rw-r--r-- | hello_obj2.lc | 16 | ||||
-rw-r--r-- | lambda-gtk.cabal | 8 | ||||
-rw-r--r-- | mainObj.hs | 35 |
7 files changed, 323 insertions, 23 deletions
diff --git a/GLWidget.hs b/GLWidget.hs index 19ef129..8620c1a 100644 --- a/GLWidget.hs +++ b/GLWidget.hs | |||
@@ -82,7 +82,10 @@ oopsG e = do | |||
82 | oops :: String -> IO () | 82 | oops :: String -> IO () |
83 | oops s = hPutStrLn stderr s | 83 | oops s = hPutStrLn stderr s |
84 | 84 | ||
85 | runGLApp :: IsWidget b => (GLArea -> IO b) -> WidgetMethods b -> IO () | 85 | runGLApp :: IsWidget b => (GLArea -> IO b) -- ^ Initialize a state object that will be passed |
86 | -- to all the event handlers. | ||
87 | -> WidgetMethods b | ||
88 | -> IO () | ||
86 | runGLApp mk methods = do | 89 | runGLApp mk methods = do |
87 | _ <- Gtk.init Nothing | 90 | _ <- Gtk.init Nothing |
88 | 91 | ||
diff --git a/LambdaCube/GL/HMatrix.hs b/LambdaCube/GL/HMatrix.hs new file mode 100644 index 0000000..ff5e7a7 --- /dev/null +++ b/LambdaCube/GL/HMatrix.hs | |||
@@ -0,0 +1,49 @@ | |||
1 | {-# LANGUAGE PatternSynonyms #-} | ||
2 | {-# LANGUAGE FlexibleInstances #-} | ||
3 | {-# LANGUAGE MultiParamTypeClasses #-} | ||
4 | module LambdaCube.GL.HMatrix where | ||
5 | |||
6 | import GHC.TypeLits | ||
7 | |||
8 | import LambdaCube.GL.Uniform | ||
9 | import Numeric.LinearAlgebra | ||
10 | import Numeric.LinearAlgebra.Devel | ||
11 | |||
12 | import Graphics.Rendering.OpenGL.GL (GLboolean) | ||
13 | |||
14 | instance Uniformable (Matrix Float) where | ||
15 | uniformContexts _ = contexts floatMatrices | ||
16 | |||
17 | instance (KnownNat r, KnownNat c) => IsUniform (Matrix Float) (UMatrix r c Float) where | ||
18 | marshalUniform abi mat = case matrixDimensions abi of | ||
19 | (r,c) | fromIntegral (natVal r) /= rows mat -> Nothing | ||
20 | | fromIntegral (natVal c) /= cols mat -> Nothing | ||
21 | _ -> let isRowOrder = case orderOf mat of | ||
22 | RowMajor -> 1 :: GLboolean | ||
23 | ColumnMajor -> 0 :: GLboolean | ||
24 | in Just $ MarshalUMatrix | ||
25 | $ \f -> apply mat (\ptr -> f 1 isRowOrder ptr) (\r c sr sc ptr -> ptr) | ||
26 | |||
27 | {- | ||
28 | |||
29 | -- apply :: Storable a => Matrix a -> (f -> IO r) -> (CInt -> CInt -> CInt -> CInt -> Ptr a -> f) -> IO r | ||
30 | {-# INLINE amat #-} | ||
31 | amat :: Storable a => Matrix a -> (f -> IO r) -> (CInt -> CInt -> CInt -> CInt -> Ptr a -> f) -> IO r | ||
32 | amat x f g = unsafeWith (xdat x) (f . g r c sr sc) | ||
33 | where | ||
34 | r = fi (rows x) | ||
35 | c = fi (cols x) | ||
36 | sr = fi (xRow x) | ||
37 | sc = fi (xCol x) | ||
38 | |||
39 | |||
40 | apply (0 :: Matrix Float) | ||
41 | :: (b -> IO r) | ||
42 | -> (Foreign.C.Types.CInt | ||
43 | -> Foreign.C.Types.CInt | ||
44 | -> Foreign.C.Types.CInt | ||
45 | -> Foreign.C.Types.CInt | ||
46 | -> GHC.Ptr.Ptr Float | ||
47 | -> b) | ||
48 | -> IO r | ||
49 | -} | ||
diff --git a/Matrix.hs b/Matrix.hs new file mode 100644 index 0000000..b47e223 --- /dev/null +++ b/Matrix.hs | |||
@@ -0,0 +1,230 @@ | |||
1 | {-# LANGUAGE BangPatterns, FlexibleContexts #-} | ||
2 | module Matrix where | ||
3 | |||
4 | import Numeric.LinearAlgebra | ||
5 | import Foreign.Storable | ||
6 | import Data.Vector.Generic as V (snoc,init) | ||
7 | import Prelude hiding ((<>)) | ||
8 | |||
9 | rotMatrixX :: (Storable a, Floating a) => a -> Matrix a | ||
10 | rotMatrixX a = (4><4) | ||
11 | [ 1 , 0 , 0 , 0 | ||
12 | , 0 , c , -s , 0 | ||
13 | , 0 , s , c , 0 | ||
14 | , 0 , 0 , 0 , 1 ] where (c,s) = (cos a, sin a) | ||
15 | |||
16 | |||
17 | rotMatrixY :: (Storable a, Floating a) => a -> Matrix a | ||
18 | rotMatrixY a = (4><4) | ||
19 | [ c , 0 , s , 0 | ||
20 | , 0 , 1 , 0 , 0 | ||
21 | , -s , 0 , c , 0 | ||
22 | , 0 , 0 , 0 , 1 ] where (c,s) = (cos a, sin a) | ||
23 | |||
24 | rotMatrixZ :: (Storable a, Floating a) => a -> Matrix a | ||
25 | rotMatrixZ a = (4><4) | ||
26 | [ c , -s , 0 , 0 | ||
27 | , s , c , 0 , 0 | ||
28 | , 0 , 0 , 1 , 0 | ||
29 | , 0 , 0 , 0 , 1 ] where (c,s) = (cos a, sin a) | ||
30 | |||
31 | |||
32 | -- | Equivalent to | ||
33 | -- | ||
34 | -- > translateBefore3to4 v m = translation v <> homoMatrix m | ||
35 | -- | ||
36 | -- where translation and homoMatrix are taken as the usual transformations into | ||
37 | -- the 4-dimensional homogeneous coordinate space. | ||
38 | translateBefore3to4 :: Numeric t => | ||
39 | Vector t -- 3 vector (translation) | ||
40 | -> Matrix t -- 3><3 matrix (projection) | ||
41 | -> Matrix t -- 4><4 matrix (projection) | ||
42 | translateBefore3to4 v p3 = fromRows $ rs ++ [u] | ||
43 | where | ||
44 | !u = snoc (v <# p3) 1 | ||
45 | rs = map (`snoc` 0) $ toRows p3 | ||
46 | {-# SPECIALIZE translateBefore3to4 :: Vector R -> Matrix R -> Matrix R #-} | ||
47 | |||
48 | {- | ||
49 | lookat pos target up = translateBefore3to4 (negate pos) r | ||
50 | where | ||
51 | backward = normalize $ pos - target | ||
52 | rightward = normalize $ up `cross` backward | ||
53 | upward = backward `cross` rightward | ||
54 | r = fromColumns [rightward,upward,backward] | ||
55 | |||
56 | -- Rebind 'normalize' in order to support Float which has no Field | ||
57 | -- instance. | ||
58 | normalize :: (Linear t c, Fractional t, Normed (c t)) => c t -> c t | ||
59 | normalize v = scale (1 / realToFrac (norm_2 v)) v | ||
60 | -} | ||
61 | |||
62 | -- | Camera transformation matrix (4x4). | ||
63 | lookat :: (Numeric t, Num (Vector t), Fractional t, Normed (Vector t)) => | ||
64 | Vector t -- ^ Camera position 3-vector. | ||
65 | -> Vector t -- ^ Target position 3-vector. | ||
66 | -> Vector t -- ^ Upward direction 3-vector. | ||
67 | -> Matrix t | ||
68 | lookat pos target up = fromRows | ||
69 | [ snoc rightward (- dot rightward pos) | ||
70 | , snoc upward (- dot upward pos) | ||
71 | , snoc backward (- dot backward pos) | ||
72 | , snoc (fromList[0,0,0]) 1 | ||
73 | ] | ||
74 | where | ||
75 | backward = normalize $ pos - target | ||
76 | rightward = normalize $ up `cross` backward | ||
77 | upward = backward `cross` rightward | ||
78 | |||
79 | -- Rebind 'normalize' in order to support Float which has no Field | ||
80 | -- instance. | ||
81 | normalize :: (Linear t c, Fractional t, Normed (c t)) => c t -> c t | ||
82 | normalize v = scale (1 / realToFrac (norm_2 v)) v | ||
83 | |||
84 | {-# SPECIALIZE lookat :: Vector R -> Vector R -> Vector R -> Matrix R #-} | ||
85 | |||
86 | |||
87 | |||
88 | |||
89 | |||
90 | -- lookat pos target up <> rot t | ||
91 | -- == lookat ((((pos - target) <# rot (-t))) + target) | ||
92 | -- target | ||
93 | -- | ||
94 | -- | Perspective transformation 4x4 matrix. | ||
95 | perspective :: (Storable a, Floating a) => | ||
96 | a -- ^ Near plane clipping distance (always positive). | ||
97 | -> a -- ^ Far plane clipping distance (always positive). | ||
98 | -> a -- ^ Field of view of the y axis, in radians. | ||
99 | -> a -- ^ Aspect ratio, i.e. screen's width\/height. | ||
100 | -> Matrix a | ||
101 | perspective n f fovy aspect = (4><4) | ||
102 | [ (2*n/(r-l)) , 0 , 0 , 0 | ||
103 | , 0 , (2*n/(t-b)) , 0 , 0 | ||
104 | , (-(r+l)/(r-l)) , ((t+b)/(t-b)) , (-(f+n)/(f-n)) , (-1) | ||
105 | , 0 , 0 , (-2*f*n/(f-n)) , 0 ] | ||
106 | where | ||
107 | t = n*tan(fovy/2) | ||
108 | b = -t | ||
109 | r = aspect*t | ||
110 | l = -r | ||
111 | |||
112 | |||
113 | |||
114 | -- | Build a look at view matrix | ||
115 | {- | ||
116 | lookat2 | ||
117 | :: (Epsilon a, Floating a) | ||
118 | => V3 a -- ^ Eye | ||
119 | -> V3 a -- ^ Center | ||
120 | -> V3 a -- ^ Up | ||
121 | -> M44 a | ||
122 | -} | ||
123 | lookat2 :: (Normed (Vector a), Field a, Num (Vector a)) => | ||
124 | Vector a -> Vector a -> Vector a -> Matrix a | ||
125 | lookat2 eye center up = fromColumns | ||
126 | [ snoc xa xd | ||
127 | , snoc ya yd | ||
128 | , snoc (-za) zd | ||
129 | , fromList [ 0 , 0 , 0 , 1 ] ] | ||
130 | where za = normalize $ center - eye | ||
131 | xa = normalize $ cross za up | ||
132 | ya = cross xa za | ||
133 | xd = -dot xa eye | ||
134 | yd = -dot ya eye | ||
135 | zd = dot za eye | ||
136 | |||
137 | {- | ||
138 | |||
139 | -- | Build a look at view matrix | ||
140 | lookAt | ||
141 | :: (Epsilon a, Floating a) | ||
142 | => V3 a -- ^ Eye | ||
143 | -> V3 a -- ^ Center | ||
144 | -> V3 a -- ^ Up | ||
145 | -> M44 a | ||
146 | lookAt eye center up = | ||
147 | V4 (V4 (xa^._x) (xa^._y) (xa^._z) xd) | ||
148 | (V4 (ya^._x) (ya^._y) (ya^._z) yd) | ||
149 | (V4 (-za^._x) (-za^._y) (-za^._z) zd) | ||
150 | (V4 0 0 0 1) | ||
151 | where za = normalize $ center - eye | ||
152 | xa = normalize $ cross za up | ||
153 | ya = cross xa za | ||
154 | xd = -dot xa eye | ||
155 | yd = -dot ya eye | ||
156 | zd = dot za eye | ||
157 | |||
158 | -- | Build a matrix for a symmetric perspective-view frustum | ||
159 | perspective | ||
160 | :: Floating a | ||
161 | => a -- ^ FOV (y direction, in radians) | ||
162 | -> a -- ^ Aspect ratio | ||
163 | -> a -- ^ Near plane | ||
164 | -> a -- ^ Far plane | ||
165 | -> M44 a | ||
166 | perspective fovy aspect near far = | ||
167 | V4 (V4 x 0 0 0) | ||
168 | (V4 0 y 0 0) | ||
169 | (V4 0 0 z w) | ||
170 | (V4 0 0 (-1) 0) | ||
171 | where tanHalfFovy = tan $ fovy / 2 | ||
172 | x = 1 / (aspect * tanHalfFovy) | ||
173 | y = 1 / tanHalfFovy | ||
174 | fpn = far + near | ||
175 | fmn = far - near | ||
176 | oon = 0.5/near | ||
177 | oof = 0.5/far | ||
178 | -- z = 1 / (near/fpn - far/fpn) -- would be better by .5 bits | ||
179 | z = -fpn/fmn | ||
180 | w = 1/(oof-oon) -- 13 bits error reduced to 0.17 | ||
181 | -- w = -(2 * far * near) / fmn | ||
182 | |||
183 | |||
184 | -- | Perspective transformation matrix in row major order. | ||
185 | perspective :: Float -- ^ Near plane clipping distance (always positive). | ||
186 | -> Float -- ^ Far plane clipping distance (always positive). | ||
187 | -> Float -- ^ Field of view of the y axis, in radians. | ||
188 | -> Float -- ^ Aspect ratio, i.e. screen's width\/height. | ||
189 | -> Mat4 | ||
190 | perspective n f fovy aspect = transpose $ | ||
191 | Mat4 (Vec4 (2*n/(r-l)) 0 (-(r+l)/(r-l)) 0) | ||
192 | (Vec4 0 (2*n/(t-b)) ((t+b)/(t-b)) 0) | ||
193 | (Vec4 0 0 (-(f+n)/(f-n)) (-2*f*n/(f-n))) | ||
194 | (Vec4 0 0 (-1) 0) | ||
195 | where | ||
196 | t = n*tan(fovy/2) | ||
197 | b = -t | ||
198 | r = aspect*t | ||
199 | l = -r | ||
200 | |||
201 | -} | ||
202 | |||
203 | lookAtRotate :: (Normed (Vector t), Num (Vector t), Numeric t, | ||
204 | Floating t) => | ||
205 | Vector t -> Vector t -> Vector t -> t -> Matrix t | ||
206 | lookAtRotate pos target up t = lookat pos target up <> m | ||
207 | where | ||
208 | m = rotMatrixX t {- <> rotMatrixZ t -} | ||
209 | |||
210 | rotateLookAt :: (Normed (Vector t), Floating t, Num (Vector t), | ||
211 | Numeric t) => | ||
212 | Vector t -> Vector t -> Vector t -> t -> Matrix t | ||
213 | rotateLookAt pos target up t = lookat pos' target up' | ||
214 | where | ||
215 | m = rotMatrixX (-t) | ||
216 | pos' = V.init $ (m #> snoc pos 0) | ||
217 | up' = V.init (m #> snoc up 0) | ||
218 | |||
219 | |||
220 | {- | ||
221 | void UniformMatrix{234}{fd}v( int location, sizei count, boolean transpose, const float *value ); | ||
222 | void UniformMatrix{2x3,3x2,2x4,4x2,3x4,4x3}{fd}v( int location, sizei count, boolean transpose, const float *value ); | ||
223 | |||
224 | The UniformMatrix{234}fv and UniformMatrix{234}dv commands will load count 2 × | ||
225 | 2, 3 × 3, or 4 × 4 matrices (corresponding to 2, 3, or 4 in the command name) | ||
226 | of single- or double-precision floating-point values, respectively, into a | ||
227 | uniform defined as a matrix or an array of matrices. If transpose is FALSE , | ||
228 | the matrix is specified in column major order, otherwise in row major order. | ||
229 | |||
230 | -} | ||
diff --git a/TimeKeeper.hs b/TimeKeeper.hs index d85f61f..36e7e8a 100644 --- a/TimeKeeper.hs +++ b/TimeKeeper.hs | |||
@@ -24,6 +24,9 @@ newTimeKeeper = do | |||
24 | ff <- newMVar 0 | 24 | ff <- newMVar 0 |
25 | return $ TimeKeeper s ff | 25 | return $ TimeKeeper s ff |
26 | 26 | ||
27 | getSeconds :: TimeKeeper -> IO Double | ||
28 | getSeconds tk = readMVar (tmSeconds tk) | ||
29 | |||
27 | tick :: TimeKeeper -> Widget -> FrameClock -> IO Bool | 30 | tick :: TimeKeeper -> Widget -> FrameClock -> IO Bool |
28 | tick tm widget clock = widgetGetWindow widget >>= \case | 31 | tick tm widget clock = widgetGetWindow widget >>= \case |
29 | Nothing -> return SOURCE_REMOVE | 32 | Nothing -> return SOURCE_REMOVE |
diff --git a/hello_obj2.lc b/hello_obj2.lc index ebee807..7adf8b1 100644 --- a/hello_obj2.lc +++ b/hello_obj2.lc | |||
@@ -1,15 +1,11 @@ | |||
1 | deg30 = 0.5235987755982988 -- pi/6 | 1 | deg30 = 0.5235987755982988 -- pi/6 |
2 | 2 | ||
3 | coordmap (time::Float) (p::Vec 4 Float) | 3 | coordmap (cam::Mat 4 4 Float) (p::Vec 4 Float) |
4 | = perspective 0.1 -- near plane | 4 | = perspective 0.1 -- near plane |
5 | 100 -- far plane | 5 | 100 -- far plane |
6 | deg30 -- y fov radians | 6 | deg30 -- y fov radians |
7 | 1 -- aspect ratio w/h | 7 | 1 -- aspect ratio w/h |
8 | *. lookat (V3 0 0 10) -- camera position | 8 | *. cam |
9 | (V3 0 0 0) -- target position | ||
10 | (V3 0 1 0) -- upward direction | ||
11 | *. rotMatrixX time -- time = radians | ||
12 | *. rotMatrixZ time -- time = radians | ||
13 | *. p | 9 | *. p |
14 | 10 | ||
15 | blendplane = -- NoBlending -- BlendLogicOp Xor | 11 | blendplane = -- NoBlending -- BlendLogicOp Xor |
@@ -17,7 +13,7 @@ blendplane = -- NoBlending -- BlendLogicOp Xor | |||
17 | ((OneBF,SrcAlpha),(DstAlpha,DstAlpha)) | 13 | ((OneBF,SrcAlpha),(DstAlpha,DstAlpha)) |
18 | (V4 0 0 0 0) | 14 | (V4 0 0 0 0) |
19 | 15 | ||
20 | makeFrame (time :: Float) | 16 | makeFrame (cam :: Mat 4 4 Float) |
21 | (color :: Vec 4 Float) | 17 | (color :: Vec 4 Float) |
22 | (texture :: Texture) | 18 | (texture :: Texture) |
23 | (prims :: PrimitiveStream Triangle (Vec 4 Float, Vec 3 Float, Vec 3 Float)) | 19 | (prims :: PrimitiveStream Triangle (Vec 4 Float, Vec 3 Float, Vec 3 Float)) |
@@ -26,13 +22,13 @@ makeFrame (time :: Float) | |||
26 | = imageFrame (emptyDepthImage 1, emptyColorImage (V4 0 0 0.4 1)) | 22 | = imageFrame (emptyDepthImage 1, emptyColorImage (V4 0 0 0.4 1)) |
27 | `overlay` | 23 | `overlay` |
28 | prims | 24 | prims |
29 | & mapPrimitives (\(p,n,uvw) -> ( coordmap time p, V2 uvw%x (1 - uvw%y) )) | 25 | & mapPrimitives (\(p,n,uvw) -> ( coordmap cam p, V2 uvw%x (1 - uvw%y) )) |
30 | & rasterizePrimitives (TriangleCtx CullBack PolygonFill NoOffset LastVertex) ((Smooth)) | 26 | & rasterizePrimitives (TriangleCtx CullBack PolygonFill NoOffset LastVertex) ((Smooth)) |
31 | & mapFragments (\((uv)) -> ((color * texture2D (Sampler PointFilter MirroredRepeat texture) uv ))) | 27 | & mapFragments (\((uv)) -> ((color * texture2D (Sampler PointFilter MirroredRepeat texture) uv ))) |
32 | & accumulateWith (DepthOp Less True, ColorOp NoBlending (V4 True True True True)) | 28 | & accumulateWith (DepthOp Less True, ColorOp NoBlending (V4 True True True True)) |
33 | `overlay` | 29 | `overlay` |
34 | plane | 30 | plane |
35 | & mapPrimitives (\((p)) -> (coordmap time p, p%xy )) | 31 | & mapPrimitives (\((p)) -> (coordmap cam p, p%xy )) |
36 | & rasterizePrimitives (TriangleCtx CullNone PolygonFill NoOffset LastVertex) ((Smooth)) | 32 | & rasterizePrimitives (TriangleCtx CullNone PolygonFill NoOffset LastVertex) ((Smooth)) |
37 | -- & mapFragments (\((uv)) -> ((texture2D (Sampler PointFilter MirroredRepeat texture) uv ))) | 33 | -- & mapFragments (\((uv)) -> ((texture2D (Sampler PointFilter MirroredRepeat texture) uv ))) |
38 | -- & mapFragments (\((uv)) -> ((V4 uv%x uv%y 0 1))) -- ((rgb 1 0 0))) | 34 | -- & mapFragments (\((uv)) -> ((V4 uv%x uv%y 0 1))) -- ((rgb 1 0 0))) |
@@ -46,7 +42,7 @@ makeFrame (time :: Float) | |||
46 | 42 | ||
47 | 43 | ||
48 | main = renderFrame $ | 44 | main = renderFrame $ |
49 | makeFrame (Uniform "time") | 45 | makeFrame (Uniform "cam") |
50 | (Uniform "diffuseColor") | 46 | (Uniform "diffuseColor") |
51 | (Texture2DSlot "diffuseTexture") | 47 | (Texture2DSlot "diffuseTexture") |
52 | (fetch "objects" (Attribute "position", Attribute "normal", Attribute "uvw")) | 48 | (fetch "objects" (Attribute "position", Attribute "normal", Attribute "uvw")) |
diff --git a/lambda-gtk.cabal b/lambda-gtk.cabal index bc86d57..83eb922 100644 --- a/lambda-gtk.cabal +++ b/lambda-gtk.cabal | |||
@@ -25,7 +25,7 @@ executable lambda-gtk | |||
25 | -- GUI | 25 | -- GUI |
26 | gi-gdk , gi-glib , gi-gobject , gi-gtk , haskell-gi-base | 26 | gi-gdk , gi-glib , gi-gobject , gi-gtk , haskell-gi-base |
27 | -- , gi-gtk-declarative, gi-gtk-declarative-app-simple, | 27 | -- , gi-gtk-declarative, gi-gtk-declarative-app-simple, |
28 | 28 | default-language: Haskell2010 | |
29 | -- hs-source-dirs: | 29 | -- hs-source-dirs: |
30 | 30 | ||
31 | 31 | ||
@@ -48,15 +48,15 @@ executable gldemo | |||
48 | executable objdemo | 48 | executable objdemo |
49 | main-is: mainObj.hs | 49 | main-is: mainObj.hs |
50 | other-modules: InfinitePlane LambdaCubeWidget GLWidget LambdaCube.Gtk TimeKeeper | 50 | other-modules: InfinitePlane LambdaCubeWidget GLWidget LambdaCube.Gtk TimeKeeper |
51 | LoadMesh MtlParser | 51 | LoadMesh MtlParser Matrix LambdaCube.GL.HMatrix |
52 | extensions: NondecreasingIndentation | 52 | extensions: NondecreasingIndentation |
53 | other-extensions: OverloadedLabels, OverloadedLists, OverloadedStrings | 53 | other-extensions: OverloadedLabels, OverloadedLists, OverloadedStrings |
54 | build-depends: base, containers >=0.5 && <0.6, bytestring >=0.10 && <0.11, | 54 | build-depends: base, containers >=0.5 && <0.6, bytestring >=0.10 && <0.11, |
55 | vector, aeson, JuicyPixels, text, contravariant, | 55 | vector, aeson, JuicyPixels, text, contravariant, hmatrix, |
56 | -- writer monad | 56 | -- writer monad |
57 | mtl, | 57 | mtl, |
58 | -- rendering | 58 | -- rendering |
59 | lambdacube-ir, lambdacube-gl, OpenGL, wavefront, | 59 | lambdacube-ir, lambdacube-gl >=0.5.4, OpenGL, wavefront, |
60 | -- GUI | 60 | -- GUI |
61 | gi-gdk , gi-glib , gi-gobject , gi-gtk , haskell-gi-base | 61 | gi-gdk , gi-glib , gi-gobject , gi-gtk , haskell-gi-base |
62 | 62 | ||
@@ -13,23 +13,31 @@ import Data.Text (Text) | |||
13 | import Data.Map.Strict (Map) | 13 | import Data.Map.Strict (Map) |
14 | import qualified Data.Map.Strict as Map | 14 | import qualified Data.Map.Strict as Map |
15 | import qualified Data.Vector as V | 15 | import qualified Data.Vector as V |
16 | import Data.Vector.Generic as VG (init,snoc) | ||
16 | import GI.Gdk.Objects | 17 | import GI.Gdk.Objects |
17 | import GI.GLib.Constants | 18 | import GI.GLib.Constants |
18 | import GI.Gtk as Gtk hiding (main) | 19 | import GI.Gtk as Gtk hiding (main) |
19 | import LambdaCube.GL as LC | 20 | import LambdaCube.GL as LC |
20 | import LambdaCube.GL.Mesh as LC | 21 | import LambdaCube.GL.Mesh as LC |
22 | import Numeric.LinearAlgebra hiding ((<>)) | ||
21 | import System.Environment | 23 | import System.Environment |
22 | import System.IO | 24 | import System.IO |
23 | import System.IO.Error | 25 | import System.IO.Error |
24 | 26 | ||
25 | import GLWidget | 27 | import GLWidget |
28 | import LambdaCube.GL.HMatrix | ||
26 | import LambdaCubeWidget | 29 | import LambdaCubeWidget |
27 | import TimeKeeper | 30 | import TimeKeeper |
28 | import LoadMesh | 31 | import LoadMesh |
29 | import InfinitePlane | 32 | import InfinitePlane |
30 | import MtlParser (ObjMaterial(..)) | 33 | import MtlParser (ObjMaterial(..)) |
34 | import Matrix | ||
31 | 35 | ||
32 | type State = (TimeKeeper, TickCallbackHandle) | 36 | -- State created by uploadState. |
37 | data State = State | ||
38 | { stTimeKeeper :: TimeKeeper | ||
39 | , stTickCallback :: TickCallbackHandle | ||
40 | } | ||
33 | 41 | ||
34 | addOBJToObjectArray :: GLStorage -> String -> [(GPUMesh, Maybe Text)] -> Map Text (ObjMaterial,TextureData) -> IO [LC.Object] | 42 | addOBJToObjectArray :: GLStorage -> String -> [(GPUMesh, Maybe Text)] -> Map Text (ObjMaterial,TextureData) -> IO [LC.Object] |
35 | addOBJToObjectArray storage slotName objMesh mtlLib = forM objMesh $ \(mesh,mat) -> do | 43 | addOBJToObjectArray storage slotName objMesh mtlLib = forM objMesh $ \(mesh,mat) -> do |
@@ -57,17 +65,28 @@ uploadState obj glarea storage = do | |||
57 | -- setup FrameClock | 65 | -- setup FrameClock |
58 | tm <- newTimeKeeper | 66 | tm <- newTimeKeeper |
59 | tickcb <- widgetAddTickCallback glarea (tick tm) | 67 | tickcb <- widgetAddTickCallback glarea (tick tm) |
60 | return (tm,tickcb) | 68 | |
69 | return State | ||
70 | { stTimeKeeper = tm | ||
71 | , stTickCallback = tickcb | ||
72 | } | ||
61 | 73 | ||
62 | destroyState :: GLArea -> State -> IO () | 74 | destroyState :: GLArea -> State -> IO () |
63 | destroyState glarea (tm,tickcb) = do | 75 | destroyState glarea st = do |
64 | widgetRemoveTickCallback glarea tickcb | 76 | widgetRemoveTickCallback glarea (stTickCallback st) |
65 | 77 | ||
66 | setUniforms :: glctx -> GLStorage -> State -> IO () | 78 | setUniforms :: glctx -> GLStorage -> State -> IO () |
67 | setUniforms gl storage (tm,_) = do | 79 | setUniforms gl storage st = do |
68 | t <- withMVar (tmSeconds tm) return | 80 | t <- getSeconds $ stTimeKeeper st |
81 | let tf = realToFrac t :: Float | ||
82 | roZ = rotMatrixZ (-tf) | ||
83 | roX = rotMatrixX (-tf) | ||
84 | ro = roZ <> roX | ||
85 | pos = VG.init (ro #> fromList [0,0,10,0]) | ||
86 | up = VG.init (ro #> fromList [0,1,0,0]) | ||
87 | cam = lookat pos 0 up | ||
69 | LC.updateUniforms storage $ do | 88 | LC.updateUniforms storage $ do |
70 | "time" @= return (realToFrac t :: Float) | 89 | "cam" @= return (cam :: Matrix Float) |
71 | 90 | ||
72 | main :: IO () | 91 | main :: IO () |
73 | main = do | 92 | main = do |
@@ -82,7 +101,7 @@ main = do | |||
82 | defObjectArray "plane" Triangles $ do | 101 | defObjectArray "plane" Triangles $ do |
83 | "position" @: Attribute_V4F | 102 | "position" @: Attribute_V4F |
84 | defUniforms $ do | 103 | defUniforms $ do |
85 | "time" @: Float | 104 | "cam" @: M44F |
86 | "diffuseTexture" @: FTexture2D | 105 | "diffuseTexture" @: FTexture2D |
87 | "diffuseColor" @: V4F | 106 | "diffuseColor" @: V4F |
88 | return $ (,) <$> mobj <*> mpipeline | 107 | return $ (,) <$> mobj <*> mpipeline |