diff options
Diffstat (limited to 'LoadMesh.hs')
-rw-r--r-- | LoadMesh.hs | 60 |
1 files changed, 50 insertions, 10 deletions
diff --git a/LoadMesh.hs b/LoadMesh.hs index aaf0e06..cd7a8ad 100644 --- a/LoadMesh.hs +++ b/LoadMesh.hs | |||
@@ -18,6 +18,7 @@ import Data.Maybe | |||
18 | import Data.Map (Map) | 18 | import Data.Map (Map) |
19 | import qualified Data.Map as Map | 19 | import qualified Data.Map as Map |
20 | import qualified Data.Vector as V | 20 | import qualified Data.Vector as V |
21 | import qualified Data.Vector.Storable as StorableV | ||
21 | import qualified Data.ByteString as SB | 22 | import qualified Data.ByteString as SB |
22 | import qualified Data.ByteString.Lazy.Char8 as L | 23 | import qualified Data.ByteString.Lazy.Char8 as L |
23 | import Data.Text (unpack,Text,pack) | 24 | import Data.Text (unpack,Text,pack) |
@@ -37,10 +38,19 @@ data MaterialMesh m = MaterialMesh | |||
37 | , materialMasks :: Map Text Mask | 38 | , materialMasks :: Map Text Mask |
38 | } | 39 | } |
39 | 40 | ||
40 | type MeshData = ( [MaterialMesh Mesh] -- List of uniform-material meshes (and the name of the material). | 41 | data CurveData = CurveData |
41 | , ( V.Vector MtlLib -- Material definitions. | 42 | { curves :: [Curve] |
42 | , FilePath ) -- Path to wavefront obj file. | 43 | , curvePt :: Int -> Location |
43 | ) | 44 | , curveMax :: Int |
45 | } | ||
46 | |||
47 | |||
48 | data MeshData = MeshData | ||
49 | { matMeshes :: [MaterialMesh Mesh] -- List of uniform-material meshes (and the name of the material). | ||
50 | , matLib :: ( V.Vector MtlLib -- Material definitions. | ||
51 | , FilePath ) -- Path to wavefront obj file. | ||
52 | , matCurves :: CurveData | ||
53 | } | ||
44 | 54 | ||
45 | relativeFrom :: FilePath -> FilePath -> FilePath | 55 | relativeFrom :: FilePath -> FilePath -> FilePath |
46 | relativeFrom path file | isAbsolute file = file | 56 | relativeFrom path file | isAbsolute file = file |
@@ -51,7 +61,12 @@ loadOBJ fname = L.readFile fname >>= \bs -> do | |||
51 | let obj@OBJ{..} = Wavefront.parse bs | 61 | let obj@OBJ{..} = Wavefront.parse bs |
52 | -- load materials | 62 | -- load materials |
53 | mtlLib <- mapM (readMtlWithFallback . relativeFrom fname . unpack) objMtlLibs | 63 | mtlLib <- mapM (readMtlWithFallback . relativeFrom fname . unpack) objMtlLibs |
54 | return $ Right (objToMesh obj,(mtlLib,fname)) | 64 | return $ Right MeshData |
65 | { matMeshes = objToMesh obj | ||
66 | , matLib = (mtlLib,fname) | ||
67 | , matCurves = objToCurveData obj | ||
68 | } | ||
69 | |||
55 | 70 | ||
56 | 71 | ||
57 | data BoundingBox = BoundingBox | 72 | data BoundingBox = BoundingBox |
@@ -122,22 +137,37 @@ transformMesh t m = m | |||
122 | { mAttributes = Map.adjust (tranformAttribute t) "position" (mAttributes m) | 137 | { mAttributes = Map.adjust (tranformAttribute t) "position" (mAttributes m) |
123 | } | 138 | } |
124 | 139 | ||
125 | uploadOBJToGPU :: Maybe BoundingBox -> MeshData -> IO ([MaterialMesh GPUMesh],Matrix Float) | 140 | transformLocation :: Matrix Float -> Location -> Location |
126 | uploadOBJToGPU scalebb (subModels,(mtlLib,objpath)) = do | 141 | transformLocation t (Location x y z w) = Location xx yy zz ww |
127 | let meshbb = foldMap (attribBoundingBox . mAttributes . materialMesh) subModels :: BoundingBox | 142 | where |
143 | [xx,yy,zz,ww] = toList $ t #> fromList [x,y,z,w] | ||
144 | |||
145 | locationBoundingBox :: Location -> BoundingBox | ||
146 | locationBoundingBox (Location x y z w) = BoundingBox x x y y z z | ||
147 | |||
148 | uploadOBJToGPU :: Maybe BoundingBox -> MeshData -> IO (([MaterialMesh GPUMesh],CurveData),Matrix Float) | ||
149 | uploadOBJToGPU scalebb (MeshData subModels (mtlLib,objpath) curveData) = do | ||
150 | let meshbb = foldMap (attribBoundingBox . mAttributes . materialMesh) subModels | ||
151 | <> foldMap (foldMap (locationBoundingBox . curvePt curveData) . curvePoints) | ||
152 | (curves curveData) | ||
128 | m = maybe (ident 4) (scaleWithin meshbb) scalebb | 153 | m = maybe (ident 4) (scaleWithin meshbb) scalebb |
154 | curveData' = case scalebb of | ||
155 | Just _ -> curveData { curvePt = transformLocation m . curvePt curveData } | ||
156 | Nothing -> curveData | ||
129 | putStrLn $ show meshbb | 157 | putStrLn $ show meshbb |
130 | gpuSubModels <- forM subModels $ \matmesh -> do | 158 | gpuSubModels <- forM subModels $ \matmesh -> do |
131 | a <- LambdaCubeGL.uploadMeshToGPU (transformMesh m (materialMesh matmesh)) | 159 | a <- LambdaCubeGL.uploadMeshToGPU (transformMesh m (materialMesh matmesh)) |
132 | return matmesh { materialMesh = a } | 160 | return matmesh { materialMesh = a } |
133 | return (gpuSubModels,m) | 161 | return ((gpuSubModels,curveData'),m) |
134 | 162 | ||
135 | uploadMtlLib :: (V.Vector MtlLib,FilePath) -> IO (V.Vector (Map Text (ObjMaterial,TextureData))) | 163 | uploadMtlLib :: (V.Vector MtlLib,FilePath) -> IO (V.Vector (Map Text (ObjMaterial,TextureData))) |
136 | uploadMtlLib (mtlLib,objpath) = do | 164 | uploadMtlLib (mtlLib,objpath) = do |
137 | -- collect used textures | 165 | -- collect used textures |
138 | let usedTextures = nub . concatMap (maybeToList . mtl_map_Kd) $ concatMap Map.elems $ V.toList mtlLib | 166 | let usedTextures = nub . concatMap (maybeToList . mtl_map_Kd) $ concatMap Map.elems $ V.toList mtlLib |
139 | whiteImage = Juicy.ImageRGB8 $ Juicy.generateImage (\_ _ -> Juicy.PixelRGB8 255 255 255) 1 1 | 167 | whiteImage = Juicy.ImageRGB8 $ Juicy.generateImage (\_ _ -> Juicy.PixelRGB8 255 255 255) 1 1 |
140 | 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 | 168 | checkerImage = Juicy.ImageRGB8 $ Juicy.generateImage mkchecker 2 2 |
169 | where mkchecker x y = if mod (x + y) 2 == 0 then Juicy.PixelRGB8 0 0 0 | ||
170 | else Juicy.PixelRGB8 255 255 0 | ||
141 | checkerTex <- LC.uploadTexture2DToGPU checkerImage | 171 | checkerTex <- LC.uploadTexture2DToGPU checkerImage |
142 | -- load images and upload to gpu | 172 | -- load images and upload to gpu |
143 | textureLib <- forM (Map.fromList $ zip usedTextures usedTextures) $ \fname -> Juicy.readImage (relativeFrom objpath fname) >>= \case | 173 | textureLib <- forM (Map.fromList $ zip usedTextures usedTextures) $ \fname -> Juicy.readImage (relativeFrom objpath fname) >>= \case |
@@ -147,6 +177,16 @@ uploadMtlLib (mtlLib,objpath) = do | |||
147 | -- pair textures and materials | 177 | -- pair textures and materials |
148 | return $ fmap (\a -> (a, maybe whiteTex (fromMaybe checkerTex . flip Map.lookup textureLib) . mtl_map_Kd $ a)) <$> mtlLib | 178 | return $ fmap (\a -> (a, maybe whiteTex (fromMaybe checkerTex . flip Map.lookup textureLib) . mtl_map_Kd $ a)) <$> mtlLib |
149 | 179 | ||
180 | vecLocation :: Location -> StorableV.Vector Float | ||
181 | vecLocation (Location x y z w) = StorableV.fromList [x,y,z,w] | ||
182 | |||
183 | objToCurveData :: WavefrontOBJ -> CurveData | ||
184 | objToCurveData OBJ{..} = CurveData | ||
185 | { curves = map elValue $ V.toList $ objCurves | ||
186 | , curvePt = (objLocations V.!) | ||
187 | , curveMax = V.length objLocations | ||
188 | } | ||
189 | |||
150 | objToMesh :: WavefrontOBJ -> [MaterialMesh Mesh] | 190 | objToMesh :: WavefrontOBJ -> [MaterialMesh Mesh] |
151 | objToMesh OBJ{..} = [ toMesh faceGroup | faceGroup <- faces ] | 191 | objToMesh OBJ{..} = [ toMesh faceGroup | faceGroup <- faces ] |
152 | where | 192 | where |