diff options
Diffstat (limited to 'LoadMesh.hs')
-rw-r--r-- | LoadMesh.hs | 36 |
1 files changed, 21 insertions, 15 deletions
diff --git a/LoadMesh.hs b/LoadMesh.hs index 9eaa047..ee93344 100644 --- a/LoadMesh.hs +++ b/LoadMesh.hs | |||
@@ -3,11 +3,12 @@ | |||
3 | {-# LANGUAGE FlexibleContexts #-} | 3 | {-# LANGUAGE FlexibleContexts #-} |
4 | module LoadMesh where | 4 | module LoadMesh where |
5 | 5 | ||
6 | import LambdaCube.GL as LambdaCubeGL -- renderer | 6 | import LambdaCube.GL as LC -- renderer |
7 | import LambdaCube.GL.Mesh as LambdaCubeGL | 7 | import LambdaCube.GL.Mesh as LambdaCubeGL |
8 | import MtlParser | 8 | import MtlParser |
9 | 9 | ||
10 | import Control.Monad | 10 | import Control.Monad |
11 | import Data.Int | ||
11 | import Data.Maybe | 12 | import Data.Maybe |
12 | import Data.Map (Map) | 13 | import Data.Map (Map) |
13 | import qualified Data.Map as Map | 14 | import qualified Data.Map as Map |
@@ -16,7 +17,8 @@ import qualified Data.ByteString as SB | |||
16 | import qualified Data.ByteString.Lazy.Char8 as L | 17 | import qualified Data.ByteString.Lazy.Char8 as L |
17 | import Data.Text (unpack,Text) | 18 | import Data.Text (unpack,Text) |
18 | import Data.List (groupBy,nub) | 19 | import Data.List (groupBy,nub) |
19 | import Numeric.LinearAlgebra hiding ((<>)) | 20 | import Numeric.LinearAlgebra hiding ((<>),Element) |
21 | import System.FilePath | ||
20 | 22 | ||
21 | import Codec.Picture as Juicy | 23 | import Codec.Picture as Juicy |
22 | import Wavefront | 24 | import Wavefront |
@@ -24,15 +26,20 @@ import Wavefront.Types | |||
24 | import Data.Aeson | 26 | import Data.Aeson |
25 | 27 | ||
26 | type MeshData = ( [(Mesh,Maybe Text)] -- List of uniform-material meshes (and the name of the material). | 28 | type MeshData = ( [(Mesh,Maybe Text)] -- List of uniform-material meshes (and the name of the material). |
27 | , MtlLib -- Material definitions. | 29 | , ( MtlLib -- Material definitions. |
30 | , FilePath ) -- Path to wavefront obj file. | ||
28 | ) | 31 | ) |
29 | 32 | ||
33 | relativeFrom :: FilePath -> FilePath -> FilePath | ||
34 | relativeFrom path file | isAbsolute file = file | ||
35 | relativeFrom path file = takeDirectory path </> file | ||
36 | |||
30 | loadOBJ :: String -> IO (Either String MeshData) | 37 | loadOBJ :: String -> IO (Either String MeshData) |
31 | loadOBJ fname = L.readFile fname >>= \bs -> do | 38 | loadOBJ fname = L.readFile fname >>= \bs -> do |
32 | let obj@OBJ{..} = parse bs | 39 | let obj@OBJ{..} = parse bs |
33 | -- load materials | 40 | -- load materials |
34 | mtlLib <- mconcat . V.toList <$> mapM (readMtl . unpack) objMtlLibs | 41 | mtlLib <- mconcat . V.toList <$> mapM (readMtlWithFallback . relativeFrom fname . unpack) objMtlLibs |
35 | return $ Right (objToMesh obj,mtlLib) | 42 | return $ Right (objToMesh obj,(mtlLib,fname)) |
36 | 43 | ||
37 | 44 | ||
38 | data BoundingBox = BoundingBox | 45 | data BoundingBox = BoundingBox |
@@ -99,25 +106,25 @@ transformMesh t m = m | |||
99 | { mAttributes = Map.adjust (tranformAttribute t) "position" (mAttributes m) | 106 | { mAttributes = Map.adjust (tranformAttribute t) "position" (mAttributes m) |
100 | } | 107 | } |
101 | 108 | ||
102 | uploadOBJToGPU :: Maybe BoundingBox -> MeshData -> IO (([(GPUMesh, Maybe Text)], MtlLib),Matrix Float) | 109 | uploadOBJToGPU :: Maybe BoundingBox -> MeshData -> IO ([(GPUMesh, Maybe Text)],Matrix Float) |
103 | uploadOBJToGPU scalebb (subModels,mtlLib) = do | 110 | uploadOBJToGPU scalebb (subModels,(mtlLib,objpath)) = do |
104 | let meshbb = foldMap (attribBoundingBox . mAttributes . fst) subModels :: BoundingBox | 111 | let meshbb = foldMap (attribBoundingBox . mAttributes . fst) subModels :: BoundingBox |
105 | m = maybe (ident 4) (scaleWithin meshbb) scalebb | 112 | m = maybe (ident 4) (scaleWithin meshbb) scalebb |
106 | gpuSubModels <- forM subModels $ \(mesh,mat) -> LambdaCubeGL.uploadMeshToGPU (transformMesh m mesh) >>= \a -> return (a,mat) | 113 | gpuSubModels <- forM subModels $ \(mesh,mat) -> LambdaCubeGL.uploadMeshToGPU (transformMesh m mesh) >>= \a -> return (a,mat) |
107 | return ((gpuSubModels,mtlLib),m) | 114 | return (gpuSubModels,m) |
108 | 115 | ||
109 | uploadMtlLib :: MtlLib -> IO (Map Text (ObjMaterial,TextureData)) | 116 | uploadMtlLib :: (MtlLib,FilePath) -> IO (Map Text (ObjMaterial,TextureData)) |
110 | uploadMtlLib mtlLib = do | 117 | uploadMtlLib (mtlLib,objpath) = do |
111 | -- collect used textures | 118 | -- collect used textures |
112 | let usedTextures = nub . concatMap (maybeToList . mtl_map_Kd) $ Map.elems mtlLib | 119 | let usedTextures = nub . concatMap (maybeToList . mtl_map_Kd) $ Map.elems mtlLib |
113 | whiteImage = Juicy.ImageRGB8 $ Juicy.generateImage (\_ _ -> Juicy.PixelRGB8 255 255 255) 1 1 | 120 | whiteImage = Juicy.ImageRGB8 $ Juicy.generateImage (\_ _ -> Juicy.PixelRGB8 255 255 255) 1 1 |
114 | 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 | 121 | 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 |
115 | checkerTex <- LambdaCubeGL.uploadTexture2DToGPU checkerImage | 122 | checkerTex <- LC.uploadTexture2DToGPU checkerImage |
116 | -- load images and upload to gpu | 123 | -- load images and upload to gpu |
117 | textureLib <- forM (Map.fromList $ zip usedTextures usedTextures) $ \fname -> Juicy.readImage fname >>= \case | 124 | textureLib <- forM (Map.fromList $ zip usedTextures usedTextures) $ \fname -> Juicy.readImage (relativeFrom objpath fname) >>= \case |
118 | Left err -> putStrLn (fname ++": "++err) >> return checkerTex | 125 | Left err -> putStrLn (fname ++": "++err) >> return checkerTex |
119 | Right img -> LambdaCubeGL.uploadTexture2DToGPU img | 126 | Right img -> LC.uploadTexture2DToGPU img |
120 | whiteTex <- LambdaCubeGL.uploadTexture2DToGPU whiteImage | 127 | whiteTex <- LC.uploadTexture2DToGPU whiteImage |
121 | -- pair textures and materials | 128 | -- pair textures and materials |
122 | return $ (\a -> (a, maybe whiteTex (fromMaybe checkerTex . flip Map.lookup textureLib) . mtl_map_Kd $ a)) <$> mtlLib | 129 | return $ (\a -> (a, maybe whiteTex (fromMaybe checkerTex . flip Map.lookup textureLib) . mtl_map_Kd $ a)) <$> mtlLib |
123 | 130 | ||
@@ -144,4 +151,3 @@ objToMesh OBJ{..} = [(toMesh faceGroup, elMtl . head $ faceGroup) | faceGroup <- | |||
144 | , let TexCoord x y z = fromMaybe defaultTexCoord ((objTexCoords !-) =<< faceTexCoordIndex) in V3 x y z | 151 | , let TexCoord x y z = fromMaybe defaultTexCoord ((objTexCoords !-) =<< faceTexCoordIndex) in V3 x y z |
145 | ) | 152 | ) |
146 | (position,normal,texcoord) = V.unzip3 . V.concat . map (V.fromList . map toVertex . triangulate . elValue) $ l | 153 | (position,normal,texcoord) = V.unzip3 . V.concat . map (V.fromList . map toVertex . triangulate . elValue) $ l |
147 | |||