summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoe Crayne <joe@jerkface.net>2019-07-18 17:19:18 -0400
committerJoe Crayne <joe@jerkface.net>2019-07-18 17:19:26 -0400
commit8d6b40691b6b40687c2a461baa0c22d14e125224 (patch)
tree9e1e33531b1910fe263231d425ea6b43473825b0
parentbf3001c4c4577cf5c65e05a21a3e9502dbe0b834 (diff)
LoadMesh: support multiple mtllib files.
-rw-r--r--LoadMesh.hs36
1 files changed, 26 insertions, 10 deletions
diff --git a/LoadMesh.hs b/LoadMesh.hs
index b970f3e..cda6349 100644
--- a/LoadMesh.hs
+++ b/LoadMesh.hs
@@ -20,7 +20,7 @@ import qualified Data.Map as Map
20import qualified Data.Vector as V 20import qualified Data.Vector as V
21import qualified Data.ByteString as SB 21import qualified Data.ByteString as SB
22import qualified Data.ByteString.Lazy.Char8 as L 22import qualified Data.ByteString.Lazy.Char8 as L
23import Data.Text (unpack,Text) 23import Data.Text (unpack,Text,pack)
24import Data.List (groupBy,nub) 24import Data.List (groupBy,nub)
25import Numeric.LinearAlgebra hiding ((<>),Element) 25import Numeric.LinearAlgebra hiding ((<>),Element)
26import System.FilePath 26import System.FilePath
@@ -33,12 +33,12 @@ import Mask
33 33
34data MaterialMesh m = MaterialMesh 34data MaterialMesh m = MaterialMesh
35 { materialMesh :: m 35 { materialMesh :: m
36 , materialName :: Maybe Text 36 , materialName :: Maybe (Int,Text)
37 , materialMasks :: Map Text Mask 37 , materialMasks :: Map Text Mask
38 } 38 }
39 39
40type MeshData = ( [MaterialMesh Mesh] -- List of uniform-material meshes (and the name of the material). 40type MeshData = ( [MaterialMesh Mesh] -- List of uniform-material meshes (and the name of the material).
41 , ( MtlLib -- Material definitions. 41 , ( V.Vector MtlLib -- Material definitions.
42 , FilePath ) -- Path to wavefront obj file. 42 , FilePath ) -- Path to wavefront obj file.
43 ) 43 )
44 44
@@ -50,7 +50,7 @@ loadOBJ :: String -> IO (Either String MeshData)
50loadOBJ fname = L.readFile fname >>= \bs -> do 50loadOBJ fname = L.readFile fname >>= \bs -> do
51 let obj@OBJ{..} = parse bs 51 let obj@OBJ{..} = parse bs
52 -- load materials 52 -- load materials
53 mtlLib <- mconcat . V.toList <$> mapM (readMtlWithFallback . relativeFrom fname . unpack) objMtlLibs 53 mtlLib <- mapM (readMtlWithFallback . relativeFrom fname . unpack) objMtlLibs
54 return $ Right (objToMesh obj,(mtlLib,fname)) 54 return $ Right (objToMesh obj,(mtlLib,fname))
55 55
56 56
@@ -107,9 +107,13 @@ scaleWithin meshbb scalebb =
107 in tr1 <> sc <> tr0 107 in tr1 <> sc <> tr0
108 else ident 4 108 else ident 4
109 109
110transV3 :: Matrix Float -> V3 Float -> V3 Float
110transV3 t (V3 x y z) = let v = t #> fromList [x,y,z,1] in V3 (v!0/v!3) (v!1/v!3) (v!2/v!3) 111transV3 t (V3 x y z) = let v = t #> fromList [x,y,z,1] in V3 (v!0/v!3) (v!1/v!3) (v!2/v!3)
112
113transV4 :: Matrix Float -> V4 Float -> V4 Float
111transV4 t (V4 x y z w) = let v = t #> fromList [x,y,z,w] in V4 (v!0) (v!1) (v!2) (v!3) 114transV4 t (V4 x y z w) = let v = t #> fromList [x,y,z,w] in V4 (v!0) (v!1) (v!2) (v!3)
112 115
116tranformAttribute :: Matrix Float -> MeshAttribute -> MeshAttribute
113tranformAttribute t (A_V3F v) = A_V3F $ transV3 t <$> v 117tranformAttribute t (A_V3F v) = A_V3F $ transV3 t <$> v
114tranformAttribute t (A_V4F v) = A_V4F $ transV4 t <$> v 118tranformAttribute t (A_V4F v) = A_V4F $ transV4 t <$> v
115 119
@@ -122,15 +126,18 @@ uploadOBJToGPU :: Maybe BoundingBox -> MeshData -> IO ([MaterialMesh GPUMesh],Ma
122uploadOBJToGPU scalebb (subModels,(mtlLib,objpath)) = do 126uploadOBJToGPU scalebb (subModels,(mtlLib,objpath)) = do
123 let meshbb = foldMap (attribBoundingBox . mAttributes . materialMesh) subModels :: BoundingBox 127 let meshbb = foldMap (attribBoundingBox . mAttributes . materialMesh) subModels :: BoundingBox
124 m = maybe (ident 4) (scaleWithin meshbb) scalebb 128 m = maybe (ident 4) (scaleWithin meshbb) scalebb
129 -- BoundingBox {minX = -6.44698, maxX = 6.44698, minY = 0.0, maxY = 1.0e9, minZ = -0.768655, maxZ = 1.0e8}
130 -- BoundingBox {minX = -6.44698, maxX = 6.44698, minY = 0.0, maxY = 18.2027, minZ = -0.768655, maxZ = 2.238049}
131 putStrLn $ show meshbb
125 gpuSubModels <- forM subModels $ \matmesh -> do 132 gpuSubModels <- forM subModels $ \matmesh -> do
126 a <- LambdaCubeGL.uploadMeshToGPU (transformMesh m (materialMesh matmesh)) 133 a <- LambdaCubeGL.uploadMeshToGPU (transformMesh m (materialMesh matmesh))
127 return matmesh { materialMesh = a } 134 return matmesh { materialMesh = a }
128 return (gpuSubModels,m) 135 return (gpuSubModels,m)
129 136
130uploadMtlLib :: (MtlLib,FilePath) -> IO (Map Text (ObjMaterial,TextureData)) 137uploadMtlLib :: (V.Vector MtlLib,FilePath) -> IO (V.Vector (Map Text (ObjMaterial,TextureData)))
131uploadMtlLib (mtlLib,objpath) = do 138uploadMtlLib (mtlLib,objpath) = do
132 -- collect used textures 139 -- collect used textures
133 let usedTextures = nub . concatMap (maybeToList . mtl_map_Kd) $ Map.elems mtlLib 140 let usedTextures = nub . concatMap (maybeToList . mtl_map_Kd) $ concatMap Map.elems $ V.toList mtlLib
134 whiteImage = Juicy.ImageRGB8 $ Juicy.generateImage (\_ _ -> Juicy.PixelRGB8 255 255 255) 1 1 141 whiteImage = Juicy.ImageRGB8 $ Juicy.generateImage (\_ _ -> Juicy.PixelRGB8 255 255 255) 1 1
135 checkerImage = Juicy.ImageRGB8 $ Juicy.generateImage (\x y -> if mod (x + y) 2 == 0 then Juicy.PixelRGB8 0 0 0 else Juicy.PixelRGB8 255 255 0) 2 2 142 checkerImage = Juicy.ImageRGB8 $ Juicy.generateImage (\x y -> if mod (x + y) 2 == 0 then Juicy.PixelRGB8 0 0 0 else Juicy.PixelRGB8 255 255 0) 2 2
136 checkerTex <- LC.uploadTexture2DToGPU checkerImage 143 checkerTex <- LC.uploadTexture2DToGPU checkerImage
@@ -140,7 +147,7 @@ uploadMtlLib (mtlLib,objpath) = do
140 Right img -> LC.uploadTexture2DToGPU img 147 Right img -> LC.uploadTexture2DToGPU img
141 whiteTex <- LC.uploadTexture2DToGPU whiteImage 148 whiteTex <- LC.uploadTexture2DToGPU whiteImage
142 -- pair textures and materials 149 -- pair textures and materials
143 return $ (\a -> (a, maybe whiteTex (fromMaybe checkerTex . flip Map.lookup textureLib) . mtl_map_Kd $ a)) <$> mtlLib 150 return $ fmap (\a -> (a, maybe whiteTex (fromMaybe checkerTex . flip Map.lookup textureLib) . mtl_map_Kd $ a)) <$> mtlLib
144 151
145objToMesh :: WavefrontOBJ -> [MaterialMesh Mesh] 152objToMesh :: WavefrontOBJ -> [MaterialMesh Mesh]
146objToMesh OBJ{..} = [ toMesh faceGroup | faceGroup <- faces ] 153objToMesh OBJ{..} = [ toMesh faceGroup | faceGroup <- faces ]
@@ -197,16 +204,25 @@ objSpan obj = case Map.elems (objAttributes obj) of
197 _ -> Mask [(0,1)] 204 _ -> Mask [(0,1)]
198 205
199 206
207searchMaterial :: V.Vector (Map Text (ObjMaterial, TextureData))
208 -> (Int, Text)
209 -> Maybe (ObjMaterial, TextureData)
210searchMaterial mtlLib (count,name) = foldr go id (V.drop (V.length mtlLib - count) mtlLib) Nothing
211 where
212 go m f r = case Map.lookup name m of
213 Nothing -> f r
214 x -> x :: Maybe (ObjMaterial,TextureData)
200 215
201addOBJToObjectArray :: GLStorage -> String -> [MaterialMesh GPUMesh] -> Map Text (ObjMaterial,TextureData) 216addOBJToObjectArray :: GLStorage -> String -> [MaterialMesh GPUMesh] -> V.Vector (Map Text (ObjMaterial,TextureData))
202 -> IO [MaskableObject] 217 -> IO [MaskableObject]
203addOBJToObjectArray storage slotName objMesh mtlLib = forM objMesh $ \matmesh -> do 218addOBJToObjectArray storage slotName objMesh mtlLib = forM objMesh $ \matmesh -> do
204 obj <- LambdaCubeGL.addMeshToObjectArray storage slotName ["diffuseTexture","diffuseColor"] (materialMesh matmesh) 219 obj <- LambdaCubeGL.addMeshToObjectArray storage slotName ["diffuseTexture","diffuseColor"] (materialMesh matmesh)
205 -- diffuseTexture and diffuseColor values can change on each model 220 -- diffuseTexture and diffuseColor values can change on each model
206 case (materialName matmesh) >>= flip Map.lookup mtlLib of 221 case materialName matmesh >>= searchMaterial mtlLib of
207 Nothing -> return () 222 Nothing -> return ()
208 Just (ObjMaterial{..},t) -> LC.updateObjectUniforms obj $ do 223 Just (ObjMaterial{..},t) -> LC.updateObjectUniforms obj $ do
209 "diffuseTexture" @= return t -- set model's diffuse texture 224 "diffuseTexture" @= return t -- set model's diffuse texture
210 "diffuseColor" @= let (r,g,b) = mtl_Kd in return (V4 r g b mtl_Tr) 225 "diffuseColor" @= let (r,g,b) = mtl_Kd in return (V4 r g b mtl_Tr)
211 let matmask = maybe Map.empty (`Map.singleton` objSpan obj) (fmap ("m:" <>) $ materialName matmesh) 226 let matmask = maybe Map.empty (`Map.singleton` objSpan obj)
227 (fmap (\(c,n) -> "m:" <> pack (show c) <> ":" <> n) $ materialName matmesh)
212 return $ MaskableObject obj (matmask `Map.union` materialMasks matmesh) 228 return $ MaskableObject obj (matmask `Map.union` materialMasks matmesh)