diff options
author | Joe Crayne <joe@jerkface.net> | 2019-06-19 23:10:17 -0400 |
---|---|---|
committer | Joe Crayne <joe@jerkface.net> | 2019-06-19 23:10:17 -0400 |
commit | bf3001c4c4577cf5c65e05a21a3e9502dbe0b834 (patch) | |
tree | da07a05559203ecb5f4723f536e3e131f35fd669 | |
parent | 018f8847fe987abe3f036ff8739468f164429e7d (diff) |
Maskable groups.
-rw-r--r-- | LoadMesh.hs | 63 |
1 files changed, 42 insertions, 21 deletions
diff --git a/LoadMesh.hs b/LoadMesh.hs index bfc5070..b970f3e 100644 --- a/LoadMesh.hs +++ b/LoadMesh.hs | |||
@@ -1,6 +1,8 @@ | |||
1 | {-# LANGUAGE LambdaCase #-} | 1 | {-# LANGUAGE FlexibleContexts #-} |
2 | {-# LANGUAGE RecordWildCards #-} | 2 | {-# LANGUAGE LambdaCase #-} |
3 | {-# LANGUAGE FlexibleContexts #-} | 3 | {-# LANGUAGE OverloadedStrings #-} |
4 | {-# LANGUAGE RecordWildCards #-} | ||
5 | {-# LANGUAGE TupleSections #-} | ||
4 | module LoadMesh where | 6 | module LoadMesh where |
5 | 7 | ||
6 | import LambdaCube.GL as LC -- renderer | 8 | import LambdaCube.GL as LC -- renderer |
@@ -8,8 +10,10 @@ import LambdaCube.GL.Mesh as LambdaCubeGL | |||
8 | import LambdaCube.GL.Type as LC | 10 | import LambdaCube.GL.Type as LC |
9 | import MtlParser | 11 | import MtlParser |
10 | 12 | ||
13 | import Control.Arrow | ||
11 | import Control.Monad | 14 | import Control.Monad |
12 | import Data.Int | 15 | import Data.Int |
16 | import Data.List as List | ||
13 | import Data.Maybe | 17 | import Data.Maybe |
14 | import Data.Map (Map) | 18 | import Data.Map (Map) |
15 | import qualified Data.Map as Map | 19 | import qualified Data.Map as Map |
@@ -139,32 +143,48 @@ uploadMtlLib (mtlLib,objpath) = do | |||
139 | return $ (\a -> (a, maybe whiteTex (fromMaybe checkerTex . flip Map.lookup textureLib) . mtl_map_Kd $ a)) <$> mtlLib | 143 | return $ (\a -> (a, maybe whiteTex (fromMaybe checkerTex . flip Map.lookup textureLib) . mtl_map_Kd $ a)) <$> mtlLib |
140 | 144 | ||
141 | objToMesh :: WavefrontOBJ -> [MaterialMesh Mesh] | 145 | objToMesh :: WavefrontOBJ -> [MaterialMesh Mesh] |
142 | objToMesh OBJ{..} = [ MaterialMesh (toMesh faceGroup) | 146 | objToMesh OBJ{..} = [ toMesh faceGroup | faceGroup <- faces ] |
143 | (elMtl . head $ faceGroup) | ||
144 | Map.empty {- TODO -} | ||
145 | | faceGroup <- faces ] | ||
146 | where | 147 | where |
147 | faces = groupBy (\a b -> elMtl a == elMtl b) (V.toList objFaces) | 148 | faces = groupBy (\a b -> elMtl a == elMtl b) (V.toList objFaces) |
148 | toMesh l = Mesh | 149 | toMesh l = MaterialMesh mesh mtl gs |
149 | { mAttributes = Map.fromList | 150 | where |
150 | [ ("position", A_V4F position) | 151 | mtl = elMtl $ head l |
151 | , ("normal", A_V3F normal) | 152 | mesh = Mesh { mAttributes = Map.fromList |
152 | , ("uvw", A_V3F texcoord) | 153 | [ ("position", A_V4F position) |
153 | ] | 154 | , ("normal", A_V3F normal) |
154 | , mPrimitive = P_Triangles | 155 | , ("uvw", A_V3F texcoord) |
155 | } where | 156 | ] |
156 | triangulate (Triangle a b c) = [a,b,c] | 157 | , mPrimitive = P_Triangles |
157 | triangulate (Quad a b c d) = [a,b,c, c,d,a] | 158 | } |
158 | triangulate (Face a b c l) = a : b : c : concatMap (\(x,y) -> [a,x,y]) (zip (c:l) l) -- should work for convex polygons without holes | ||
159 | defaultPosition = Location 0 0 0 0 | 159 | defaultPosition = Location 0 0 0 0 |
160 | defaultNormal = Normal 0 0 0 | 160 | defaultNormal = Normal 0 1 0 |
161 | defaultTexCoord = TexCoord 0 0 0 | 161 | defaultTexCoord = TexCoord 0 0 0 |
162 | v !- i = v V.!? i | 162 | v !- i = v V.!? i |
163 | toVertex FaceIndex{..} = ( let Location x y z w = fromMaybe defaultPosition (objLocations !- faceLocIndex) in V4 x y z w | 163 | toVertex FaceIndex{..} = ( let Location x y z w = fromMaybe defaultPosition (objLocations !- faceLocIndex) in V4 x y z w |
164 | , let Normal x y z = fromMaybe defaultNormal ((objNormals !-) =<< faceNorIndex) in V3 x y z | 164 | , let Normal x y z = fromMaybe defaultNormal ((objNormals !-) =<< faceNorIndex) in V3 x y z |
165 | , let TexCoord x y z = fromMaybe defaultTexCoord ((objTexCoords !-) =<< faceTexCoordIndex) in V3 x y z | 165 | , let TexCoord x y z = fromMaybe defaultTexCoord ((objTexCoords !-) =<< faceTexCoordIndex) in V3 x y z |
166 | ) | 166 | ) |
167 | (position,normal,texcoord) = V.unzip3 . V.concat . map (V.fromList . map toVertex . triangulate . elValue) $ l | 167 | (gs,fs) = elementIndices l |
168 | (positions,normals,texcoords) = unzip3 $ map toVertex fs | ||
169 | position = V.fromList positions | ||
170 | normal = V.fromList normals | ||
171 | texcoord = V.fromList texcoords | ||
172 | |||
173 | triangulate :: Face -> [FaceIndex] | ||
174 | triangulate (Triangle a b c) = [a,b,c] | ||
175 | triangulate (Quad a b c d) = [a,b,c, c,d,a] | ||
176 | triangulate (Face a b c l) = a : b : c : concatMap (\(x,y) -> [a,x,y]) (zip (c:l) l) -- should work for convex polygons without holes | ||
177 | |||
178 | elementIndices :: [Element Face] -> (Map Text Mask, [FaceIndex]) | ||
179 | elementIndices els = (spans,concatMap snd ts) | ||
180 | where | ||
181 | ts = map ((elGroups &&& elValue) . fmap triangulate) els | ||
182 | rs = List.scanl' go ((0,0),[]) ts -- scanl :: (b -> a -> b) -> b -> [a] -> [b] | ||
183 | go ((start,len),_) (gs,vs) = ((start+len,length vs),gs) | ||
184 | spans = fmap (Mask . map (fromIntegral***fromIntegral)) | ||
185 | $ foldr (Map.unionWith (++)) Map.empty $ map singletonSpan rs | ||
186 | singletonSpan (span,gnames) = Map.fromList $ map (, [span]) gnames | ||
187 | |||
168 | 188 | ||
169 | data MaskableObject = MaskableObject | 189 | data MaskableObject = MaskableObject |
170 | { maskableObject :: LC.Object | 190 | { maskableObject :: LC.Object |
@@ -188,4 +208,5 @@ addOBJToObjectArray storage slotName objMesh mtlLib = forM objMesh $ \matmesh -> | |||
188 | Just (ObjMaterial{..},t) -> LC.updateObjectUniforms obj $ do | 208 | Just (ObjMaterial{..},t) -> LC.updateObjectUniforms obj $ do |
189 | "diffuseTexture" @= return t -- set model's diffuse texture | 209 | "diffuseTexture" @= return t -- set model's diffuse texture |
190 | "diffuseColor" @= let (r,g,b) = mtl_Kd in return (V4 r g b mtl_Tr) | 210 | "diffuseColor" @= let (r,g,b) = mtl_Kd in return (V4 r g b mtl_Tr) |
191 | return $ MaskableObject obj $ maybe Map.empty (`Map.singleton` objSpan obj) (materialName matmesh) | 211 | let matmask = maybe Map.empty (`Map.singleton` objSpan obj) (fmap ("m:" <>) $ materialName matmesh) |
212 | return $ MaskableObject obj (matmask `Map.union` materialMasks matmesh) | ||