summaryrefslogtreecommitdiff
path: root/examples/MtlParser.hs
diff options
context:
space:
mode:
Diffstat (limited to 'examples/MtlParser.hs')
-rw-r--r--examples/MtlParser.hs74
1 files changed, 74 insertions, 0 deletions
diff --git a/examples/MtlParser.hs b/examples/MtlParser.hs
new file mode 100644
index 0000000..b57a7f0
--- /dev/null
+++ b/examples/MtlParser.hs
@@ -0,0 +1,74 @@
1module MtlParser
2 ( ObjMaterial (..)
3 , MtlLib
4 , parseMtl
5 , readMtl
6 ) where
7
8import Data.Map (Map)
9import qualified Data.Map as Map
10import Data.Maybe
11import Control.Monad.State.Strict
12import Control.Monad.Writer
13import Data.Text (pack,Text)
14
15type Vec3 = (Float,Float,Float)
16
17type MtlLib = Map Text ObjMaterial
18
19data ObjMaterial
20 = ObjMaterial
21 { mtl_Name :: Text
22 , mtl_Ka :: Vec3 -- ambient color
23 , mtl_Kd :: Vec3 -- diffuse color
24 , mtl_Ks :: Vec3 -- specular color
25 , mtl_illum :: Int
26 , mtl_Tr :: Float -- transparency
27 , mtl_Ns :: Float -- specular exponent
28 , mtl_map_Kd :: Maybe String -- diffuse texture file name
29 }
30 deriving (Eq,Show)
31
32newMaterial name = ObjMaterial
33 { mtl_Name = name
34 , mtl_Ka = (1, 1, 1)
35 , mtl_Kd = (1, 1, 1)
36 , mtl_Ks = (0, 0, 0)
37 , mtl_illum = 1
38 , mtl_Tr = 1
39 , mtl_Ns = 0
40 , mtl_map_Kd = Nothing
41 }
42
43type Mtl = WriterT [ObjMaterial] (State (Maybe ObjMaterial))
44
45readMaybe :: Read a => String -> Maybe a
46readMaybe s = case reads s of
47 [(val, "")] -> Just val
48 _ -> Nothing
49
50readVec3 :: String -> String -> String -> Maybe Vec3
51readVec3 r g b = (,,) <$> readMaybe r <*> readMaybe g <*> readMaybe b
52
53setAttr = modify' . fmap
54addMaterial = gets maybeToList >>= tell
55
56parseLine :: String -> Mtl ()
57parseLine s = case words $ takeWhile (/='#') s of
58 ["newmtl",name] -> do
59 addMaterial
60 put $ Just $ newMaterial $ pack name
61 ["map_Kd",textureName] -> setAttr (\s -> s {mtl_map_Kd = Just textureName})
62 ["Ka",r,g,b] | Just rgb <- readVec3 r g b -> setAttr (\s -> s {mtl_Ka = rgb})
63 ["Kd",r,g,b] | Just rgb <- readVec3 r g b -> setAttr (\s -> s {mtl_Kd = rgb})
64 ["Ks",r,g,b] | Just rgb <- readVec3 r g b -> setAttr (\s -> s {mtl_Ks = rgb})
65 ["illum",a] | Just v <- readMaybe a -> setAttr (\s -> s {mtl_illum = v})
66 ["Tr",a] | Just v <- readMaybe a -> setAttr (\s -> s {mtl_Tr = v})
67 ["Ns",a] | Just v <- readMaybe a -> setAttr (\s -> s {mtl_Ns = v})
68 _ -> return ()
69
70parseMtl :: String -> MtlLib
71parseMtl src = Map.fromList [(mtl_Name m,m) | m <- evalState (execWriterT (mapM_ parseLine (lines src) >> addMaterial)) Nothing]
72
73readMtl :: String -> IO MtlLib
74readMtl fname = parseMtl <$> readFile fname