summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoe Crayne <joe@jerkface.net>2019-05-14 17:52:40 -0400
committerJoe Crayne <joe@jerkface.net>2019-05-14 17:52:40 -0400
commitf5d4a74e9a4b23917b97f48bde529cb21e3ec152 (patch)
treee46037115608c455b738b864ab2f70cc4162f14c
parentb24d6672ff055208f6c0a85a01c43d17d8de9226 (diff)
Factor TEXTURE_BUFFER-based ring buffer into module.
-rw-r--r--MeshSketch.hs46
-rw-r--r--TextureBufferRing.hs61
2 files changed, 63 insertions, 44 deletions
diff --git a/MeshSketch.hs b/MeshSketch.hs
index 9425890..16c8284 100644
--- a/MeshSketch.hs
+++ b/MeshSketch.hs
@@ -48,6 +48,7 @@ import LoadMesh
48import InfinitePlane 48import InfinitePlane
49import MtlParser (ObjMaterial(..)) 49import MtlParser (ObjMaterial(..))
50import Matrix 50import Matrix
51import TextureBufferRing
51 52
52 53
53prettyDebug :: GL.DebugMessage -> String 54prettyDebug :: GL.DebugMessage -> String
@@ -139,48 +140,6 @@ mkFullscreenToggle w = do
139 if b then windowFullscreen w 140 if b then windowFullscreen w
140 else windowUnfullscreen w 141 else windowUnfullscreen w
141 142
142data Ring = Ring
143 { ringMax :: Int
144 , ringTexture :: TextureBufferData
145 , ringStart :: IO Int
146 , ringSize :: IO Int
147 , pushBack :: Float -> Float -> Float -> IO ()
148 , popFront :: IO ()
149 }
150
151newRing :: GLStorage -> Int -> IO Ring
152newRing storage cnt = do
153 let ringCapacity = cnt * 3
154 tbo <- uploadTextureBufferToGPU ringCapacity
155 p <- uploadMeshToGPU Mesh
156 { mAttributes = Map.singleton "position" $ A_Float $ V.fromList
157 $ replicate ringCapacity 0.0
158 , mPrimitive = P_Points
159 }
160 obj <- addMeshToObjectArray storage "Points" [] p
161 LC.updateUniforms storage $ do
162 "PointBuffer" @= return tbo
163 rstart <- newIORef 0
164 rsize <- newIORef 0
165 return Ring
166 { ringMax = cnt * 3
167 , ringTexture = tbo
168 , ringStart = readIORef rstart
169 , ringSize = readIORef rsize
170 , pushBack = \x y z -> do
171 start <- readIORef rstart
172 allocaArray 3 $ \ptr -> do
173 pokeElemOff ptr 0 x
174 pokeElemOff ptr 1 y
175 pokeElemOff ptr 2 z
176 updateTextureBuffer tbo start 3 ptr
177 writeIORef rstart (mod (start + 3) ringCapacity)
178 sz <- readIORef rsize
179 putStrLn $ "pushBack "++show (sz,start,(x,y,z))
180 when (sz < ringCapacity) $ do
181 writeIORef rsize (sz + 3)
182 , popFront = modifyIORef' rsize $ \s -> if s > 3 then s - 3 else 0
183 }
184 143
185uploadState :: IsWidget glarea => MeshData -> glarea -> GLStorage -> IO State 144uploadState :: IsWidget glarea => MeshData -> glarea -> GLStorage -> IO State
186uploadState obj glarea storage = do 145uploadState obj glarea storage = do
@@ -263,8 +222,7 @@ setUniforms gl storage st = do
263 LC.updateUniforms storage $ do 222 LC.updateUniforms storage $ do
264 "CameraPosition" @= return (pos :: Vector Float) 223 "CameraPosition" @= return (pos :: Vector Float)
265 "ViewProjection" @= return (mvp :: Matrix Float) 224 "ViewProjection" @= return (mvp :: Matrix Float)
266 "PointsStart" @= fmap (fromIntegral :: Int -> Int32) (ringStart $ stRingBuffer st) 225 updateRingUniforms storage (stRingBuffer st)
267 "PointsMax" @= return (fromIntegral (ringMax $ stRingBuffer st) :: Int32)
268 226
269data MeshSketch = MeshSketch 227data MeshSketch = MeshSketch
270 { mmWidget :: GLArea 228 { mmWidget :: GLArea
diff --git a/TextureBufferRing.hs b/TextureBufferRing.hs
new file mode 100644
index 0000000..2edf86f
--- /dev/null
+++ b/TextureBufferRing.hs
@@ -0,0 +1,61 @@
1module TextureBufferRing where
2
3import Control.Monad
4import Data.Int
5import Data.IORef
6import qualified Data.Map.Strict as Map
7import qualified Data.Vector as V
8import Foreign.Marshal.Array
9import Foreign.Storable
10
11import LambdaCube.GL as LC
12import LambdaCube.GL.Data (uploadCubeMapToGPU,uploadTextureBufferToGPU,updateTextureBuffer)
13import LambdaCube.GL.Mesh as LC
14import LambdaCube.IR as LC
15
16data Ring = Ring
17 { ringMax :: Int
18 , ringTexture :: TextureBufferData
19 , ringStart :: IO Int
20 , ringSize :: IO Int
21 , pushBack :: Float -> Float -> Float -> IO ()
22 , popFront :: IO ()
23 }
24
25newRing :: GLStorage -> Int -> IO Ring
26newRing storage cnt = do
27 let ringCapacity = cnt * 3
28 tbo <- uploadTextureBufferToGPU ringCapacity
29 p <- uploadMeshToGPU Mesh
30 { mAttributes = Map.singleton "position" $ A_Float $ V.fromList
31 $ replicate ringCapacity 0.0
32 , mPrimitive = P_Points
33 }
34 obj <- addMeshToObjectArray storage "Points" [] p
35 LC.updateUniforms storage $ do
36 "PointBuffer" @= return tbo
37 rstart <- newIORef 0
38 rsize <- newIORef 0
39 return Ring
40 { ringMax = cnt * 3
41 , ringTexture = tbo
42 , ringStart = readIORef rstart
43 , ringSize = readIORef rsize
44 , pushBack = \x y z -> do
45 start <- readIORef rstart
46 allocaArray 3 $ \ptr -> do
47 pokeElemOff ptr 0 x
48 pokeElemOff ptr 1 y
49 pokeElemOff ptr 2 z
50 updateTextureBuffer tbo start 3 ptr
51 writeIORef rstart (mod (start + 3) ringCapacity)
52 sz <- readIORef rsize
53 putStrLn $ "pushBack "++show (sz,start,(x,y,z))
54 when (sz < ringCapacity) $ do
55 writeIORef rsize (sz + 3)
56 , popFront = modifyIORef' rsize $ \s -> if s > 3 then s - 3 else 0
57 }
58
59updateRingUniforms storage ring = LC.updateUniforms storage $ do
60 "PointsStart" @= fmap (fromIntegral :: Int -> Int32) (ringStart ring)
61 "PointsMax" @= return (fromIntegral (ringMax ring) :: Int32)