summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoe Crayne <joe@jerkface.net>2019-06-17 17:33:18 -0400
committerJoe Crayne <joe@jerkface.net>2019-06-17 17:33:18 -0400
commit40b339a401a82610d16601e9a1ce34af9b159d56 (patch)
tree61fb201151db692e9fc50c9b369f251fd27a53d0
parentde867b10f2a3645fd7f42efc6389013fa8ad62f5 (diff)
Maskable materials.
-rw-r--r--Mask.hs63
-rw-r--r--MeshSketch.hs64
-rw-r--r--lambda-gtk.cabal2
3 files changed, 111 insertions, 18 deletions
diff --git a/Mask.hs b/Mask.hs
new file mode 100644
index 0000000..0b91e42
--- /dev/null
+++ b/Mask.hs
@@ -0,0 +1,63 @@
1module Mask where
2
3import Data.Int
4
5newtype Mask = Mask [(Int32,Int32)]
6 deriving (Eq,Ord,Show)
7
8{-
9merge ((x0,x):xs) ((y0,y):ys) =
10 if x0 <= y0
11 then case compare x y0 of
12 LT -> (x0 x) (y0 y)
13 EQ -> (x0 x=y0 y)
14 GT -> if x <= y then -> (x0 y0 x y)
15 else -> (x0 y0 y x)
16 else case compare x0 y of
17 LT -> if x <= y then (y0 x0 x y)
18 else (y0 x0 y x)
19 EQ -> (y0 y=x0 x)
20 GT -> (y0 y) (x0 x)
21-}
22
23subtr [] ys = []
24subtr xs [] = xs
25subtr ((x0,x):xs) ((y0,y):ys) =
26 if x0 <= y0
27 then case compare x y0 of
28 LT -> subtr ((x0,x):xs) ys
29 EQ -> (x0,x) : subtr xs ((y0,y):ys)
30 GT -> if x <= y then (if x0<y0 then ((x0,y0) :) else id) $ subtr xs ((y0,y):ys)
31 else (if x0<y0 then ((x0,y0) :) else id) $ subtr ((y,x):xs) ys
32 else case compare x0 y of
33 LT -> if x <= y then subtr xs ((y0,y):ys)
34 else subtr ((y,x):xs) ys
35 EQ -> subtr ((x0,x):xs) ys
36 GT -> subtr ((x0,x):xs) ys
37
38union [] ys = ys
39union xs [] = xs
40union ((x0,x):xs) ((y0,y):ys) =
41 if x0 <= y0
42 then case compare x y0 of
43 LT -> (x0,x) : union xs ((y0,y):ys)
44 EQ -> (x0,y) : union xs ys
45 GT -> if x <= y then union xs ((x0,y):ys)
46 else union ((x0,x):xs) ys
47 else case compare x0 y of
48 LT -> if x <= y then union xs ((y0,y):ys)
49 else union ((y0,x):xs) ys
50 EQ -> (y0,x) : union xs ys
51 GT -> (y0,y) : union ((x0,x):xs) ys
52
53endpts :: (Int32,Int32) -> (Int32,Int32)
54endpts (x0,sz) = (x0,x0 + sz)
55
56sized :: (Int32,Int32) -> (Int32,Int32)
57sized (x0,x) = (x0, x - x0)
58
59maskPlus :: Mask -> Mask -> Mask
60maskPlus (Mask xs) (Mask ys) = Mask $ sized <$> union (endpts <$> xs) (endpts <$> ys)
61
62maskSubtract :: Mask -> Mask -> Mask
63maskSubtract (Mask xs) (Mask ys) = Mask $ sized <$> subtr (endpts <$> xs) (endpts <$> ys)
diff --git a/MeshSketch.hs b/MeshSketch.hs
index 7ab0d7a..f31c7cf 100644
--- a/MeshSketch.hs
+++ b/MeshSketch.hs
@@ -66,11 +66,12 @@ import Matrix
66import qualified GPURing as GPU 66import qualified GPURing as GPU
67import qualified VectorRing as Vector 67import qualified VectorRing as Vector
68import RingBuffer 68import RingBuffer
69import MaskableStream (AttributeKey,(@<-)) 69import MaskableStream (AttributeKey,(@<-),updateCommands)
70import SmallRing 70import SmallRing
71import Camera 71import Camera
72import FitCurves 72import FitCurves
73import Bezier 73import Bezier
74import Mask
74 75
75prettyDebug :: GL.DebugMessage -> String 76prettyDebug :: GL.DebugMessage -> String
76prettyDebug (GL.DebugMessage src typ (GL.DebugMessageID mid) severity msg) = unwords ws 77prettyDebug (GL.DebugMessage src typ (GL.DebugMessageID mid) severity msg) = unwords ws
@@ -113,6 +114,8 @@ data State = State
113 , stDragPlane :: IORef (Maybe (Vector Float,Plane)) 114 , stDragPlane :: IORef (Maybe (Vector Float,Plane))
114 , stRecentPts :: IORef (Giver (Vector Double)) 115 , stRecentPts :: IORef (Giver (Vector Double))
115 , stAngle :: IORef Int 116 , stAngle :: IORef Int
117 , stObjects :: IORef [MaskableObject]
118 , stMasks :: IORef [Mask]
116 } 119 }
117 120
118initCamera :: Camera 121initCamera :: Camera
@@ -138,9 +141,14 @@ realToFracVector v = Math.fromList $ map realToFrac $ Math.toList v
138 141
139data MaskableObject = MaskableObject 142data MaskableObject = MaskableObject
140 { maskableObject :: LC.Object 143 { maskableObject :: LC.Object
141 , groupMasks :: Map Text [(Int32,Int32)] 144 , groupMasks :: Map Text Mask
142 } 145 }
143 146
147objSpan :: LC.Object -> Mask
148objSpan obj = case Map.elems (objAttributes obj) of
149 Stream { streamLength = x }:_ -> Mask [(0,fromIntegral x)]
150 _ -> Mask [(0,1)]
151
144addOBJToObjectArray :: GLStorage -> String -> [(GPUMesh, Maybe Text)] -> Map Text (ObjMaterial,TextureData) 152addOBJToObjectArray :: GLStorage -> String -> [(GPUMesh, Maybe Text)] -> Map Text (ObjMaterial,TextureData)
145 -> IO [MaskableObject] 153 -> IO [MaskableObject]
146addOBJToObjectArray storage slotName objMesh mtlLib = forM objMesh $ \(mesh,mat) -> do 154addOBJToObjectArray storage slotName objMesh mtlLib = forM objMesh $ \(mesh,mat) -> do
@@ -151,10 +159,7 @@ addOBJToObjectArray storage slotName objMesh mtlLib = forM objMesh $ \(mesh,mat)
151 Just (ObjMaterial{..},t) -> LC.updateObjectUniforms obj $ do 159 Just (ObjMaterial{..},t) -> LC.updateObjectUniforms obj $ do
152 "diffuseTexture" @= return t -- set model's diffuse texture 160 "diffuseTexture" @= return t -- set model's diffuse texture
153 "diffuseColor" @= let (r,g,b) = mtl_Kd in return (V4 r g b mtl_Tr) 161 "diffuseColor" @= let (r,g,b) = mtl_Kd in return (V4 r g b mtl_Tr)
154 let len = case Map.elems (objAttributes obj) of 162 return $ MaskableObject obj $ maybe Map.empty (`Map.singleton` objSpan obj) mat
155 Stream { streamLength = x }:_ -> x
156 _ -> 1
157 return $ MaskableObject obj $ maybe Map.empty (`Map.singleton` [(0,1)]) mat
158 163
159mkFullscreenToggle :: IsWindow a => a -> IO (IO ()) 164mkFullscreenToggle :: IsWindow a => a -> IO (IO ())
160mkFullscreenToggle w = do 165mkFullscreenToggle w = do
@@ -182,6 +187,8 @@ uploadState obj mm storage = do
182 let gs = Map.keys $ foldr (\a ms -> Map.union (groupMasks a) ms) Map.empty bufs 187 let gs = Map.keys $ foldr (\a ms -> Map.union (groupMasks a) ms) Map.empty bufs
183 forM_ gs $ \groupname -> do 188 forM_ gs $ \groupname -> do
184 addToGroupsPane (mmListStore mm) True groupname 189 addToGroupsPane (mmListStore mm) True groupname
190 objsRef <- newIORef bufs
191 masksRef <- newIORef $ map (objSpan . maskableObject) bufs
185 192
186 -- grid plane 193 -- grid plane
187 uploadMeshToGPU xzplane >>= addMeshToObjectArray storage "plane" [] 194 uploadMeshToGPU xzplane >>= addMeshToObjectArray storage "plane" []
@@ -239,6 +246,8 @@ uploadState obj mm storage = do
239 , stDragPlane = dragPlane 246 , stDragPlane = dragPlane
240 , stRecentPts = recentPts 247 , stRecentPts = recentPts
241 , stAngle = angle 248 , stAngle = angle
249 , stObjects = objsRef
250 , stMasks = masksRef
242 } 251 }
243 -- _ <- addAnimation tm (whirlingCamera st) 252 -- _ <- addAnimation tm (whirlingCamera st)
244 253
@@ -336,17 +345,15 @@ new = do
336 either (\e _ -> hPutStrLn stderr e >> throwIO (userError e)) (&) m $ \(obj,pipeline) -> do 345 either (\e _ -> hPutStrLn stderr e >> throwIO (userError e)) (&) m $ \(obj,pipeline) -> do
337 mapM_ (putStrLn . ppShow) (targets $ dynamicPipeline pipeline) 346 mapM_ (putStrLn . ppShow) (targets $ dynamicPipeline pipeline)
338 ref <- newIORef Nothing 347 ref <- newIORef Nothing
339 (groups,liststore) <- newGroupsListWidget 348 g <- gLAreaNew
349 (groups,liststore) <- newGroupsListWidget (\store itr b -> onMaskedGroup g ref store itr b)
340 panes <- panedNew OrientationHorizontal 350 panes <- panedNew OrientationHorizontal
341 g <- do 351 let mm = MeshSketch g panes groups liststore ref
342 g <- gLAreaNew 352 gLAreaSetHasDepthBuffer g True
343 let mm = MeshSketch g panes groups liststore ref 353 st <- return g
344 gLAreaSetHasDepthBuffer g True 354 _ <- on g #realize $ withCurrentGL g (onRealize obj (dynamicPipeline pipeline) (dynamicSchema pipeline) mm)
345 st <- return g 355 _ <- on g #unrealize $ onUnrealize mm
346 _ <- on g #realize $ withCurrentGL g (onRealize obj (dynamicPipeline pipeline) (dynamicSchema pipeline) mm) 356 _ <- on g #createContext $ nullableContext (onCreateContext g)
347 _ <- on g #unrealize $ onUnrealize mm
348 _ <- on g #createContext $ nullableContext (onCreateContext g)
349 return g
350 panedPack1 panes g True True 357 panedPack1 panes g True True
351 return panes 358 return panes
352 359
@@ -357,7 +364,7 @@ addToGroupsPane liststore isEnabled groupName = do
357 iter <- listStoreAppend liststore 364 iter <- listStoreAppend liststore
358 listStoreSet liststore iter [0,1] [gtrue,gvalue] 365 listStoreSet liststore iter [0,1] [gtrue,gvalue]
359 366
360newGroupsListWidget = do 367newGroupsListWidget changedListStore = do
361 liststore <- listStoreNew [gtypeBoolean,gtypeString] 368 liststore <- listStoreNew [gtypeBoolean,gtypeString]
362 treeView <- treeViewNewWithModel liststore 369 treeView <- treeViewNewWithModel liststore
363 treeViewSetHeadersVisible treeView False 370 treeViewSetHeadersVisible treeView False
@@ -379,6 +386,7 @@ newGroupsListWidget = do
379 b <- fromGValue gval 386 b <- fromGValue gval
380 notb <- toGValue (not b) 387 notb <- toGValue (not b)
381 listStoreSetValue liststore itr 0 notb 388 listStoreSetValue liststore itr 0 notb
389 changedListStore liststore itr (not b)
382 return togc 390 return togc
383 groupc <- do 391 groupc <- do
384 groupr <- cellRendererTextNew 392 groupr <- cellRendererTextNew
@@ -876,3 +884,25 @@ onCreateContext w = do
876 putStrLn "onCreateContext!" 884 putStrLn "onCreateContext!"
877 mwin <- widgetGetWindow w 885 mwin <- widgetGetWindow w
878 forM mwin $ \win -> windowCreateGlContext win 886 forM mwin $ \win -> windowCreateGlContext win
887
888onMaskedGroup g ref store itr b = do
889 gval <- treeModelGetValue store itr 1
890 mtxt <- fromGValue gval
891 let _ = mtxt :: Maybe Text
892 putStrLn $ "Mask changed " ++ show (mtxt,b)
893 mr <- readIORef ref
894 forM_ ((,) <$> mr <*> mtxt) $ \(r,txt) -> do
895 let st = stState r
896 os <- readIORef (stObjects st) -- stObjects :: IORef [MaskableObject]
897 ms <- readIORef (stMasks st) -- stMasks :: IORef [Mask]
898 ms' <- forM (zip os ms) $ \(o,m) -> do
899 let mmask = Map.lookup txt (groupMasks o)
900 op = maybe id (flip $ bool maskSubtract maskPlus b) mmask
901 m' = op m
902 unmask (Mask is) = is
903 updateCommands (stStorage r) (maskableObject o) (const $ unmask m')
904 return m'
905 writeIORef (stMasks st) ms'
906 mwin <- widgetGetWindow g
907 forM_ mwin $ \win -> windowInvalidateRect win Nothing False
908 return ()
diff --git a/lambda-gtk.cabal b/lambda-gtk.cabal
index 75bcdfc..08e9ff2 100644
--- a/lambda-gtk.cabal
+++ b/lambda-gtk.cabal
@@ -50,7 +50,7 @@ executable meshsketch
50 other-modules: InfinitePlane LambdaCubeWidget GLWidget LambdaCube.Gtk TimeKeeper 50 other-modules: InfinitePlane LambdaCubeWidget GLWidget LambdaCube.Gtk TimeKeeper
51 LoadMesh MtlParser Matrix LambdaCube.GL.HMatrix 51 LoadMesh MtlParser Matrix LambdaCube.GL.HMatrix
52 Animator MeshSketch CubeMap AttributeData GPURing MaskableStream 52 Animator MeshSketch CubeMap AttributeData GPURing MaskableStream
53 RingBuffer SmallRing VectorRing Camera Bezier FitCurves 53 RingBuffer SmallRing VectorRing Camera Bezier FitCurves Mask
54 extensions: NondecreasingIndentation 54 extensions: NondecreasingIndentation
55 other-extensions: OverloadedLabels, OverloadedLists, OverloadedStrings 55 other-extensions: OverloadedLabels, OverloadedLists, OverloadedStrings
56 build-depends: base, containers >=0.5 && <0.6, bytestring >=0.10 && <0.11, 56 build-depends: base, containers >=0.5 && <0.6, bytestring >=0.10 && <0.11,