diff options
Diffstat (limited to 'Backend/GL/Mesh.hs')
-rw-r--r-- | Backend/GL/Mesh.hs | 238 |
1 files changed, 0 insertions, 238 deletions
diff --git a/Backend/GL/Mesh.hs b/Backend/GL/Mesh.hs deleted file mode 100644 index 4539622..0000000 --- a/Backend/GL/Mesh.hs +++ /dev/null | |||
@@ -1,238 +0,0 @@ | |||
1 | {-# LANGUAGE TupleSections #-} | ||
2 | module Backend.GL.Mesh ( | ||
3 | loadMesh', | ||
4 | loadMesh, | ||
5 | saveMesh, | ||
6 | addMesh, | ||
7 | compileMesh, | ||
8 | updateMesh, | ||
9 | Mesh(..), | ||
10 | MeshPrimitive(..), | ||
11 | MeshAttribute(..), | ||
12 | GPUData | ||
13 | ) where | ||
14 | |||
15 | import Control.Applicative | ||
16 | import Control.Monad | ||
17 | import Data.Binary | ||
18 | import Data.ByteString.Char8 (ByteString) | ||
19 | import Foreign.Ptr | ||
20 | import Data.Int | ||
21 | import Foreign.Storable | ||
22 | import Foreign.Marshal.Utils | ||
23 | import System.IO.Unsafe | ||
24 | import qualified Data.ByteString.Char8 as SB | ||
25 | import qualified Data.ByteString.Lazy as LB | ||
26 | import qualified Data.Trie as T | ||
27 | import qualified Data.Vector.Storable as V | ||
28 | import qualified Data.Vector.Storable.Mutable as MV | ||
29 | |||
30 | import Backend.GL | ||
31 | import Backend.GL.Type as T | ||
32 | import IR as IR | ||
33 | import Linear as IR | ||
34 | |||
35 | fileVersion :: Int32 | ||
36 | fileVersion = 1 | ||
37 | |||
38 | data MeshAttribute | ||
39 | = A_Float (V.Vector Float) | ||
40 | | A_V2F (V.Vector V2F) | ||
41 | | A_V3F (V.Vector V3F) | ||
42 | | A_V4F (V.Vector V4F) | ||
43 | | A_M22F (V.Vector M22F) | ||
44 | | A_M33F (V.Vector M33F) | ||
45 | | A_M44F (V.Vector M44F) | ||
46 | | A_Int (V.Vector Int32) | ||
47 | | A_Word (V.Vector Word32) | ||
48 | |||
49 | data MeshPrimitive | ||
50 | = P_Points | ||
51 | | P_TriangleStrip | ||
52 | | P_Triangles | ||
53 | | P_TriangleStripI (V.Vector Int32) | ||
54 | | P_TrianglesI (V.Vector Int32) | ||
55 | |||
56 | data Mesh | ||
57 | = Mesh | ||
58 | { mAttributes :: T.Trie MeshAttribute | ||
59 | , mPrimitive :: MeshPrimitive | ||
60 | , mGPUData :: Maybe GPUData | ||
61 | } | ||
62 | |||
63 | data GPUData | ||
64 | = GPUData | ||
65 | { dPrimitive :: Primitive | ||
66 | , dStreams :: T.Trie (Stream Buffer) | ||
67 | , dIndices :: Maybe (IndexStream Buffer) | ||
68 | } | ||
69 | |||
70 | loadMesh' :: String -> IO Mesh | ||
71 | loadMesh' n = decode <$> LB.readFile n | ||
72 | |||
73 | loadMesh :: String -> IO Mesh | ||
74 | loadMesh n = compileMesh =<< loadMesh' n | ||
75 | |||
76 | saveMesh :: String -> Mesh -> IO () | ||
77 | saveMesh n m = LB.writeFile n (encode m) | ||
78 | |||
79 | addMesh :: GLPipelineInput -> ByteString -> Mesh -> [ByteString] -> IO Object | ||
80 | addMesh input slotName (Mesh _ _ (Just (GPUData prim streams indices))) objUniNames = do | ||
81 | -- select proper attributes | ||
82 | let Just (SlotSchema slotPrim slotStreams) = T.lookup slotName $! T.slots $! T.schema input | ||
83 | filterStream n s | ||
84 | | T.member n slotStreams = Just s | ||
85 | | otherwise = Nothing | ||
86 | addObject input slotName prim indices (T.mapBy filterStream streams) objUniNames | ||
87 | addMesh _ _ _ _ = fail "addMesh: only compiled mesh with GPUData is supported" | ||
88 | |||
89 | withV w a f = w a (\p -> f $ castPtr p) | ||
90 | |||
91 | meshAttrToArray :: MeshAttribute -> Array | ||
92 | meshAttrToArray (A_Float v) = Array ArrFloat (1 * V.length v) $ withV V.unsafeWith v | ||
93 | meshAttrToArray (A_V2F v) = Array ArrFloat (2 * V.length v) $ withV V.unsafeWith v | ||
94 | meshAttrToArray (A_V3F v) = Array ArrFloat (3 * V.length v) $ withV V.unsafeWith v | ||
95 | meshAttrToArray (A_V4F v) = Array ArrFloat (4 * V.length v) $ withV V.unsafeWith v | ||
96 | meshAttrToArray (A_M22F v) = Array ArrFloat (4 * V.length v) $ withV V.unsafeWith v | ||
97 | meshAttrToArray (A_M33F v) = Array ArrFloat (9 * V.length v) $ withV V.unsafeWith v | ||
98 | meshAttrToArray (A_M44F v) = Array ArrFloat (16 * V.length v) $ withV V.unsafeWith v | ||
99 | meshAttrToArray (A_Int v) = Array ArrInt32 (1 * V.length v) $ withV V.unsafeWith v | ||
100 | meshAttrToArray (A_Word v) = Array ArrWord32 (1 * V.length v) $ withV V.unsafeWith v | ||
101 | |||
102 | meshAttrToStream :: Buffer -> Int -> MeshAttribute -> Stream Buffer | ||
103 | meshAttrToStream b i (A_Float v) = Stream TFloat b i 0 (V.length v) | ||
104 | meshAttrToStream b i (A_V2F v) = Stream TV2F b i 0 (V.length v) | ||
105 | meshAttrToStream b i (A_V3F v) = Stream TV3F b i 0 (V.length v) | ||
106 | meshAttrToStream b i (A_V4F v) = Stream TV4F b i 0 (V.length v) | ||
107 | meshAttrToStream b i (A_M22F v) = Stream TM22F b i 0 (V.length v) | ||
108 | meshAttrToStream b i (A_M33F v) = Stream TM33F b i 0 (V.length v) | ||
109 | meshAttrToStream b i (A_M44F v) = Stream TM44F b i 0 (V.length v) | ||
110 | meshAttrToStream b i (A_Int v) = Stream TInt b i 0 (V.length v) | ||
111 | meshAttrToStream b i (A_Word v) = Stream TWord b i 0 (V.length v) | ||
112 | |||
113 | {- | ||
114 | updateBuffer :: Buffer -> [(Int,Array)] -> IO () | ||
115 | |||
116 | | Stream | ||
117 | { streamType :: StreamType | ||
118 | , streamBuffer :: b | ||
119 | , streamArrIdx :: Int | ||
120 | , streamStart :: Int | ||
121 | , streamLength :: Int | ||
122 | } | ||
123 | |||
124 | -- stream of index values (for index buffer) | ||
125 | data IndexStream b | ||
126 | = IndexStream | ||
127 | { indexBuffer :: b | ||
128 | , indexArrIdx :: Int | ||
129 | , indexStart :: Int | ||
130 | , indexLength :: Int | ||
131 | } | ||
132 | -} | ||
133 | updateMesh :: Mesh -> [(ByteString,MeshAttribute)] -> Maybe MeshPrimitive -> IO () | ||
134 | updateMesh (Mesh dMA dMP (Just (GPUData _ dS dI))) al mp = do | ||
135 | -- check type match | ||
136 | let arrayChk (Array t1 s1 _) (Array t2 s2 _) = t1 == t2 && s1 == s2 | ||
137 | ok = and [T.member n dMA && arrayChk (meshAttrToArray a1) (meshAttrToArray a2) | (n,a1) <- al, let Just a2 = T.lookup n dMA] | ||
138 | if not ok then putStrLn "updateMesh: attribute mismatch!" | ||
139 | else do | ||
140 | forM_ al $ \(n,a) -> do | ||
141 | case T.lookup n dS of | ||
142 | Just (Stream _ b i _ _) -> updateBuffer b [(i,meshAttrToArray a)] | ||
143 | _ -> return () | ||
144 | {- | ||
145 | case mp of | ||
146 | Nothing -> return () | ||
147 | Just p -> do | ||
148 | let ok2 = case (dMP,p) of | ||
149 | (Just (P_TriangleStripI v1, P_TriangleStripI v2) -> V.length v1 == V.length v2 | ||
150 | (P_TrianglesI v1, P_TrianglesI v2) -> V.length v1 == V.length v2 | ||
151 | (a,b) -> a == b | ||
152 | -} | ||
153 | |||
154 | compileMesh :: Mesh -> IO Mesh | ||
155 | compileMesh (Mesh attrs mPrim Nothing) = do | ||
156 | let mkIndexBuf v = do | ||
157 | iBuf <- compileBuffer [Array ArrWord32 (V.length v) $ withV V.unsafeWith v] | ||
158 | return $! Just $! IndexStream iBuf 0 0 (V.length v) | ||
159 | vBuf <- compileBuffer [meshAttrToArray a | a <- T.elems attrs] | ||
160 | (indices,prim) <- case mPrim of | ||
161 | P_Points -> return (Nothing,PointList) | ||
162 | P_TriangleStrip -> return (Nothing,TriangleStrip) | ||
163 | P_Triangles -> return (Nothing,TriangleList) | ||
164 | P_TriangleStripI v -> (,TriangleStrip) <$> mkIndexBuf v | ||
165 | P_TrianglesI v -> (,TriangleList) <$> mkIndexBuf v | ||
166 | let streams = T.fromList $! zipWith (\i (n,a) -> (n,meshAttrToStream vBuf i a)) [0..] (T.toList attrs) | ||
167 | gpuData = GPUData prim streams indices | ||
168 | return $! Mesh attrs mPrim (Just gpuData) | ||
169 | |||
170 | compileMesh mesh = return mesh | ||
171 | |||
172 | sblToV :: Storable a => [SB.ByteString] -> V.Vector a | ||
173 | sblToV ls = v | ||
174 | where | ||
175 | offs o (s:xs) = (o,s):offs (o + SB.length s) xs | ||
176 | offs _ [] = [] | ||
177 | cnt = sum (map SB.length ls) `div` (sizeOf $ V.head v) | ||
178 | v = unsafePerformIO $ do | ||
179 | mv <- MV.new cnt | ||
180 | MV.unsafeWith mv $ \dst -> forM_ (offs 0 ls) $ \(o,s) -> | ||
181 | SB.useAsCStringLen s $ \(src,len) -> moveBytes (plusPtr dst o) src len | ||
182 | V.unsafeFreeze mv | ||
183 | |||
184 | vToSB :: Storable a => V.Vector a -> SB.ByteString | ||
185 | vToSB v = unsafePerformIO $ do | ||
186 | let len = V.length v * sizeOf (V.head v) | ||
187 | V.unsafeWith v $ \p -> SB.packCStringLen (castPtr p,len) | ||
188 | |||
189 | instance Storable a => Binary (V.Vector a) where | ||
190 | put v = put $ vToSB v | ||
191 | get = do s <- get ; return $ sblToV [s] | ||
192 | |||
193 | instance Binary MeshAttribute where | ||
194 | put (A_Float a) = putWord8 0 >> put a | ||
195 | put (A_V2F a) = putWord8 1 >> put a | ||
196 | put (A_V3F a) = putWord8 2 >> put a | ||
197 | put (A_V4F a) = putWord8 3 >> put a | ||
198 | put (A_M22F a) = putWord8 4 >> put a | ||
199 | put (A_M33F a) = putWord8 5 >> put a | ||
200 | put (A_M44F a) = putWord8 6 >> put a | ||
201 | put (A_Int a) = putWord8 7 >> put a | ||
202 | put (A_Word a) = putWord8 8 >> put a | ||
203 | get = do | ||
204 | tag_ <- getWord8 | ||
205 | case tag_ of | ||
206 | 0 -> A_Float <$> get | ||
207 | 1 -> A_V2F <$> get | ||
208 | 2 -> A_V3F <$> get | ||
209 | 3 -> A_V4F <$> get | ||
210 | 4 -> A_M22F <$> get | ||
211 | 5 -> A_M33F <$> get | ||
212 | 6 -> A_M44F <$> get | ||
213 | 7 -> A_Int <$> get | ||
214 | 8 -> A_Word <$> get | ||
215 | _ -> fail "no parse" | ||
216 | |||
217 | instance Binary MeshPrimitive where | ||
218 | put P_Points = putWord8 0 | ||
219 | put P_TriangleStrip = putWord8 1 | ||
220 | put P_Triangles = putWord8 2 | ||
221 | put (P_TriangleStripI a) = putWord8 3 >> put a | ||
222 | put (P_TrianglesI a) = putWord8 4 >> put a | ||
223 | get = do | ||
224 | tag_ <- getWord8 | ||
225 | case tag_ of | ||
226 | 0 -> return P_Points | ||
227 | 1 -> return P_TriangleStrip | ||
228 | 2 -> return P_Triangles | ||
229 | 3 -> P_TriangleStripI <$> get | ||
230 | 4 -> P_TrianglesI <$> get | ||
231 | _ -> fail "no parse" | ||
232 | |||
233 | instance Binary Mesh where | ||
234 | put (Mesh a b _) = put (T.toList a) >> put b | ||
235 | get = do | ||
236 | a <- get | ||
237 | b <- get | ||
238 | return $! Mesh (T.fromList a) b Nothing | ||