summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoe Crayne <joe@jerkface.net>2019-06-19 02:28:58 -0400
committerJoe Crayne <joe@jerkface.net>2019-06-19 02:28:58 -0400
commit5024860293943ad598d4d89331bdc1615a862d25 (patch)
treedef28134dd1b9e20d2189d6a6f71067d43df9bbc
parent4e615656484dfe4347b0a2ccbdf38c2e609162df (diff)
Load mesh in background.
-rw-r--r--GPURing.hs3
-rw-r--r--MeshSketch.hs79
-rw-r--r--lambda-gtk.cabal1
3 files changed, 58 insertions, 25 deletions
diff --git a/GPURing.hs b/GPURing.hs
index 904c551..a315349 100644
--- a/GPURing.hs
+++ b/GPURing.hs
@@ -20,9 +20,6 @@ import LambdaCube.GL.Input.Type
20import LambdaCube.GL.Input hiding (createObjectCommands) 20import LambdaCube.GL.Input hiding (createObjectCommands)
21 21
22 22
23-- | Typical usage:
24--
25-- > ringBuffer <- newRing capacity (VectorRing.new capacity)
26type Update keys = (keys -> Writer [DSum AttributeKey GLUniformValue] ()) 23type Update keys = (keys -> Writer [DSum AttributeKey GLUniformValue] ())
27 24
28new :: Data keys => Primitive -> String -> GLStorage -> (String -> String) -> Int -> IO (TargetBuffer (Update keys)) 25new :: Data keys => Primitive -> String -> GLStorage -> (String -> String) -> Int -> IO (TargetBuffer (Update keys))
diff --git a/MeshSketch.hs b/MeshSketch.hs
index 8c18b67..87d9763 100644
--- a/MeshSketch.hs
+++ b/MeshSketch.hs
@@ -176,8 +176,8 @@ xzPlaneVector :: Vector Float
176xzPlaneVector = fromList [ 0,1,0 -- unit normal 176xzPlaneVector = fromList [ 0,1,0 -- unit normal
177 , 0 ] -- distance from origin 177 , 0 ] -- distance from origin
178 178
179uploadState :: MeshData -> MeshSketch -> GLStorage -> IO State 179stateChangeMesh :: MeshData -> MeshSketch -> GLStorage -> State -> IO State
180uploadState obj mm storage = do 180stateChangeMesh obj mm storage st = do
181 let glarea = mmWidget mm 181 let glarea = mmWidget mm
182 -- load OBJ geometry and material descriptions 182 -- load OBJ geometry and material descriptions
183 let workarea = BoundingBox (-2.5) (2.5) (-2.5) 2.5 (-2.5) (2.5) 183 let workarea = BoundingBox (-2.5) (2.5) (-2.5) 2.5 (-2.5) (2.5)
@@ -191,23 +191,26 @@ uploadState obj mm storage = do
191 let gs = Map.keys $ foldr (\a ms -> Map.union (groupMasks a) ms) Map.empty bufs 191 let gs = Map.keys $ foldr (\a ms -> Map.union (groupMasks a) ms) Map.empty bufs
192 forM_ gs $ \groupname -> do 192 forM_ gs $ \groupname -> do
193 addToGroupsPane (mmListStore mm) True groupname 193 addToGroupsPane (mmListStore mm) True groupname
194 objsRef <- newIORef bufs 194 writeIORef (stObjects st) bufs
195 masksRef <- newIORef $ map (objSpan . maskableObject) bufs 195 writeIORef (stMasks st) $ map (objSpan . maskableObject) bufs
196 return st
196 197
198initializeState :: MeshSketch -> GLStorage -> IO State
199initializeState mm storage = do
200 let glarea = mmWidget mm
201 objsRef <- newIORef []
202 masksRef <- newIORef []
197 -- grid plane 203 -- grid plane
198 uploadMeshToGPU xzplane >>= addMeshToObjectArray storage "plane" [] 204 uploadMeshToGPU xzplane >>= addMeshToObjectArray storage "plane" []
199
200 let bufsize = 1000 205 let bufsize = 1000
201 v <- MV.unsafeNew bufsize 206 v <- MV.unsafeNew bufsize
202 pts <- newRing bufsize (Vector.new v) 207 pts <- newRing bufsize (Vector.new v)
203 ring <- newRing bufsize (GPU.new LineStrip "Curve" storage ringPointAttr bufsize) 208 ring <- newRing bufsize (GPU.new LineStrip "Curve" storage ringPointAttr bufsize)
204 cpts <- newRing 100 (GPU.new PointList "Points" storage ringPointAttr 100) 209 cpts <- newRing 100 (GPU.new PointList "Points" storage ringPointAttr 100)
205
206 -- setup FrameClock 210 -- setup FrameClock
207 w <- toWidget glarea 211 w <- toWidget glarea
208 tm <- newAnimator w 212 tm <- newAnimator w
209 cam <- newIORef initCamera 213 cam <- newIORef initCamera
210
211 Just pwidget <- get w #parent 214 Just pwidget <- get w #parent
212 Just parent <- get pwidget #window 215 Just parent <- get pwidget #window
213 toggle <- mkFullscreenToggle parent 216 toggle <- mkFullscreenToggle parent
@@ -225,14 +228,12 @@ uploadState obj mm storage = do
225 skytex <- newIORef skybox_id 228 skytex <- newIORef skybox_id
226 mi <- LC.uploadMeshToGPU cubeMesh 229 mi <- LC.uploadMeshToGPU cubeMesh
227 LC.addMeshToObjectArray storage "SkyCube" [] mi 230 LC.addMeshToObjectArray storage "SkyCube" [] mi
228
229 drag <- newIORef Nothing 231 drag <- newIORef Nothing
230 dragPlane <- newIORef Nothing 232 dragPlane <- newIORef Nothing
231 pendown <- newIORef False 233 pendown <- newIORef False
232 plane <- newIORef $ Just (xzPlaneVector G.// [(3,-1)]) 234 plane <- newIORef $ Just (xzPlaneVector G.// [(3,-1)])
233 recentPts <- newIORef Give0 235 recentPts <- newIORef Give0
234 angle <- newIORef 0 236 angle <- newIORef 0
235
236 let st = State 237 let st = State
237 { stAnimator = tm 238 { stAnimator = tm
238 , stCamera = cam 239 , stCamera = cam
@@ -254,10 +255,8 @@ uploadState obj mm storage = do
254 , stMasks = masksRef 255 , stMasks = masksRef
255 } 256 }
256 -- _ <- addAnimation tm (whirlingCamera st) 257 -- _ <- addAnimation tm (whirlingCamera st)
257
258 return st 258 return st
259 259
260
261destroyState :: GLArea -> State -> IO () 260destroyState :: GLArea -> State -> IO ()
262destroyState glarea st = do 261destroyState glarea st = do
263 -- widgetRemoveTickCallback glarea (stTickCallback st) 262 -- widgetRemoveTickCallback glarea (stTickCallback st)
@@ -313,6 +312,21 @@ data Realized = Realized
313 , stSigs :: [SignalHandlerId] -- Signals attached by onRealize. 312 , stSigs :: [SignalHandlerId] -- Signals attached by onRealize.
314 } 313 }
315 314
315-- | Assumes the executable is nested somewhere in the source tree like so:
316--
317-- <src-tree>/<dist>/build/.../<executable>
318--
319-- If a "build" directory was not found, an empty string is returned.
320findSrcTree :: IO FilePath
321findSrcTree = do
322 exe <- getExecutablePath
323 let ps = reverse . drop 2
324 . dropWhile (/="build")
325 . reverse
326 . splitDirectories
327 . takeDirectory $ exe
328 return $ foldr (</>) "" ps
329
316findModule :: FilePath -> IO FilePath 330findModule :: FilePath -> IO FilePath
317findModule fn = do 331findModule fn = do
318 let checkPath action next = do 332 let checkPath action next = do
@@ -321,16 +335,19 @@ findModule fn = do
321 found <- doesFileExist f 335 found <- doesFileExist f
322 if found then return f 336 if found then return f
323 else next 337 else next
324 foldr checkPath (return fn) [getExecutablePath,getCurrentDirectory] 338 foldr checkPath (return fn) [getExecutablePath,findSrcTree,getCurrentDirectory]
339
340loadInitialMesh kont = do
341 objName <- head . (++ ["cube.obj"]) <$> getArgs
342 putStrLn $ "Loading object "++objName++"..."
343 mobj <- loadOBJ objName
344 putStrLn $ "Finisehd loading object "++objName++"."
345 kont mobj
325 346
326new :: IO Gtk.Paned 347new :: IO Gtk.Paned
327new = do 348new = do
328 putStrLn "new!" 349 putStrLn "new!"
329 m <- do 350 m <- do
330 objName <- head . (++ ["cube.obj"]) <$> getArgs
331 putStrLn $ "Loading object "++objName++"..."
332 mobj <- loadOBJ objName
333 putStrLn $ "Finisehd loading object "++objName++"."
334 -- mpipeline <- (\s -> return (Right (DynamicPipeline savedPipeline (makeSchema s)))) $ do 351 -- mpipeline <- (\s -> return (Right (DynamicPipeline savedPipeline (makeSchema s)))) $ do
335 ppath <- findModule "hello_obj2.json" 352 ppath <- findModule "hello_obj2.json"
336 mpipeline <- loadPipeline ppath $ do 353 mpipeline <- loadPipeline ppath $ do
@@ -358,8 +375,8 @@ new = do
358 "PointsStart" @: Int 375 "PointsStart" @: Int
359 "diffuseTexture" @: FTexture2D 376 "diffuseTexture" @: FTexture2D
360 "diffuseColor" @: V4F 377 "diffuseColor" @: V4F
361 return $ (,) <$> mobj <*> mpipeline 378 return mpipeline
362 either (\e _ -> hPutStrLn stderr e >> throwIO (userError e)) (&) m $ \(obj,pipeline) -> do 379 either (\e _ -> hPutStrLn stderr e >> throwIO (userError e)) (&) m $ \pipeline -> do
363 mapM_ (putStrLn . ppShow) (targets $ dynamicPipeline pipeline) 380 mapM_ (putStrLn . ppShow) (targets $ dynamicPipeline pipeline)
364 ref <- newIORef Nothing 381 ref <- newIORef Nothing
365 g <- gLAreaNew 382 g <- gLAreaNew
@@ -368,7 +385,7 @@ new = do
368 let mm = MeshSketch g panes groups liststore ref 385 let mm = MeshSketch g panes groups liststore ref
369 gLAreaSetHasDepthBuffer g True 386 gLAreaSetHasDepthBuffer g True
370 st <- return g 387 st <- return g
371 _ <- on g #realize $ withCurrentGL g (onRealize obj (dynamicPipeline pipeline) (dynamicSchema pipeline) mm) 388 _ <- on g #realize $ withCurrentGL g (onRealize (dynamicPipeline pipeline) (dynamicSchema pipeline) mm)
372 _ <- on g #unrealize $ onUnrealize mm 389 _ <- on g #unrealize $ onUnrealize mm
373 _ <- on g #createContext $ nullableContext (onCreateContext g) 390 _ <- on g #createContext $ nullableContext (onCreateContext g)
374 panedPack1 panes g True True 391 panedPack1 panes g True True
@@ -441,8 +458,22 @@ onUnrealize mm = do
441 -- lcDestroyState lc x 458 -- lcDestroyState lc x
442 writeIORef (mmRealized mm) Nothing 459 writeIORef (mmRealized mm) Nothing
443 460
444onRealize :: MeshData -> Pipeline -> PipelineSchema -> MeshSketch -> IO () 461onLoadedMesh :: MeshSketch -> Either String MeshData -> IO Bool
445onRealize mesh pipeline schema mm = do 462onLoadedMesh mm mmesh = do
463 case mmesh of
464 Left e -> putStrLn e
465 Right mesh -> do
466 mr <- readIORef (mmRealized mm)
467 forM_ mr $ \r -> do
468 x <- stateChangeMesh mesh mm (stStorage r) (stState r)
469 writeIORef (mmRealized mm) $ Just r { stState = x }
470 mwin <- widgetGetWindow (mmWidget mm)
471 forM_ mwin $ \win ->
472 windowInvalidateRect win Nothing False
473 return False
474
475onRealize :: Pipeline -> PipelineSchema -> MeshSketch -> IO ()
476onRealize pipeline schema mm = do
446 putStrLn "onRealize!" 477 putStrLn "onRealize!"
447 onUnrealize mm 478 onUnrealize mm
448 setupGLDebugging 479 setupGLDebugging
@@ -452,7 +483,7 @@ onRealize mesh pipeline schema mm = do
452 renderer <- LC.allocRenderer pipeline 483 renderer <- LC.allocRenderer pipeline
453 compat <- LC.setStorage renderer storage -- check schema compatibility 484 compat <- LC.setStorage renderer storage -- check schema compatibility
454 -- putStrLn $ "setStorage compat = " ++ show compat 485 -- putStrLn $ "setStorage compat = " ++ show compat
455 x <- uploadState mesh mm storage 486 x <- initializeState mm storage
456 let r = Realized 487 let r = Realized
457 { stStorage = storage 488 { stStorage = storage
458 , stRenderer = renderer 489 , stRenderer = renderer
@@ -484,6 +515,10 @@ onRealize mesh pipeline schema mm = do
484 panedSetPosition (mmPaned mm) (panedW * 8 `div` 10) 515 panedSetPosition (mmPaned mm) (panedW * 8 `div` 10)
485 -- widgetQueueAllocate (mmPaned mm) 516 -- widgetQueueAllocate (mmPaned mm)
486 writeIORef (mmRealized mm) $ Just r { stSigs = [sige,sigr,sigs] } 517 writeIORef (mmRealized mm) $ Just r { stSigs = [sige,sigr,sigs] }
518 forkOS $ loadInitialMesh $ \mmesh -> do
519 sid <- threadsAddIdle PRIORITY_DEFAULT_IDLE $ onLoadedMesh mm mmesh
520 return ()
521 return ()
487 522
488onRender :: w -> Realized -> GLContext -> IO Bool 523onRender :: w -> Realized -> GLContext -> IO Bool
489onRender w realized gl = do 524onRender w realized gl = do
diff --git a/lambda-gtk.cabal b/lambda-gtk.cabal
index 24340d8..02dbc85 100644
--- a/lambda-gtk.cabal
+++ b/lambda-gtk.cabal
@@ -66,3 +66,4 @@ executable meshsketch
66 gi-gdk , gi-glib , gi-gobject , gi-gtk , haskell-gi-base 66 gi-gdk , gi-glib , gi-gobject , gi-gtk , haskell-gi-base
67 67
68 default-language: Haskell2010 68 default-language: Haskell2010
69 ghc-options: -threaded