summaryrefslogtreecommitdiff
path: root/src/Wavefront.hs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Wavefront.hs')
-rw-r--r--src/Wavefront.hs84
1 files changed, 71 insertions, 13 deletions
diff --git a/src/Wavefront.hs b/src/Wavefront.hs
index cae6508..3c4eff0 100644
--- a/src/Wavefront.hs
+++ b/src/Wavefront.hs
@@ -1,4 +1,5 @@
1{-# LANGUAGE FlexibleContexts #-} 1{-# LANGUAGE FlexibleContexts #-}
2{-# LANGUAGE RankNTypes #-}
2module Wavefront where 3module Wavefront where
3 4
4import Wavefront.Types 5import Wavefront.Types
@@ -60,7 +61,9 @@ objBookKeeping builder = (lift Rank2.<$> builder)
60 incrementCount objFaces $ \x o -> o { objFaces = x } 61 incrementCount objFaces $ \x o -> o { objFaces = x }
61 } 62 }
62 63
64-- TODO: meshlab vertex colors extension
63mkv :: [Double] -> Location 65mkv :: [Double] -> Location
66mkv [x,y,z,r,g,b] = Location x' y' z' 1 where (x':y':z':_) = map realToFrac [x,y,z]
64mkv cs = Location x y z w where (x:y:z:w:_) = map realToFrac cs ++ repeat 1 67mkv cs = Location x y z w where (x:y:z:w:_) = map realToFrac cs ++ repeat 1
65 68
66mkt :: [Double] -> TexCoord 69mkt :: [Double] -> TexCoord
@@ -79,45 +82,94 @@ mkF (RefTriple a at an) = FaceIndex a at an
79elemental :: Element () -> x -> Element x 82elemental :: Element () -> x -> Element x
80elemental element x = fmap (const x) element 83elemental element x = fmap (const x) element
81 84
82modifyFirst :: MonadState (c, d) m => (c -> c) -> m () 85modifyFirst :: MonadState ParserState m => (OBJ DList -> OBJ DList) -> m ()
83modifyFirst = modify' . first 86modifyFirst = modify' . (\f s -> s { pstObj = f (pstObj s) })
84 87
85buildOBJ :: ObjBuilder (State (OBJ DList,Element ())) 88modifySecond :: MonadState ParserState m => (Element () -> Element ()) -> m ()
89modifySecond = modify' . (\f s -> s { pstElm = f (pstElm s) })
90
91(*.*) :: (OBJ DList -> a) -> (Element () -> b) -> ParserState -> (a, b)
92fld *.* elm = \s -> (fld (pstObj s), elm (pstElm s))
93
94data FFPts = Curv Float Float [Int]
95 | Curv2 [Int]
96 | Surf Float Float Float Float [RefTriple]
97
98data FreeForm = FreeForm
99 { ffRat :: Bool
100 , ffTyp :: CSType
101 , ffDeg :: (Int,Int)
102 , ffPts :: FFPts
103 }
104
105initFF :: FreeForm
106initFF = FreeForm
107 { ffRat = False
108 , ffTyp = Bspline
109 , ffDeg = (1,1)
110 , ffPts = Curv2 []
111 }
112
113mkcurv2 :: FreeForm -> EmbeddedCurve
114mkcurv2 ff = EmbeddedCurve
115
116mkcurv :: FreeForm -> Curve
117mkcurv ff = Curve
118
119mksurf :: FreeForm -> Surface
120mksurf ff = Surface
121
122addFreeForm :: (forall x. x -> Element x) -> FreeForm -> OBJ DList -> OBJ DList
123addFreeForm elm ff o = case ffPts ff of
124 Curv2 {} -> o { objEmbeddedCurves = objEmbeddedCurves o `DList.snoc` mkcurv2 ff }
125 Curv {} -> o { objCurves = objCurves o `DList.snoc` elm (mkcurv ff) }
126 Surf {} -> o { objSurfaces = objSurfaces o `DList.snoc` elm (mksurf ff) }
127
128data ParserState = ParserState
129 { pstObj :: OBJ DList
130 , pstElm :: Element ()
131 , pstFF :: FreeForm
132 }
133
134buildOBJ :: ObjBuilder (State ParserState)
86buildOBJ = nullBuilder 135buildOBJ = nullBuilder
87 { vertex = \xs -> modifyFirst $ \o -> o { objLocations = objLocations o `DList.snoc` mkv xs } 136 { vertex = \xs -> modifyFirst $ \o -> o { objLocations = objLocations o `DList.snoc` mkv xs }
88 , vertexT = \xs -> modifyFirst $ \o -> o { objTexCoords = objTexCoords o `DList.snoc` mkt xs } 137 , vertexT = \xs -> modifyFirst $ \o -> o { objTexCoords = objTexCoords o `DList.snoc` mkt xs }
89 , vertexN = \xs -> modifyFirst $ \o -> o { objNormals = objNormals o `DList.snoc` mkn xs } 138 , vertexN = \xs -> modifyFirst $ \o -> o { objNormals = objNormals o `DList.snoc` mkn xs }
90 , points = \xs -> do 139 , points = \xs -> do
91 let p = map Point xs :: [Point] 140 let p = map Point xs :: [Point]
92 (pts,element) <- gets (objPoints *** elemental) 141 (pts,element) <- gets (objPoints *.* elemental)
93 modifyFirst $ \o -> o { objPoints = pts `DList.append` fmap element (DList.fromList p) } 142 modifyFirst $ \o -> o { objPoints = pts `DList.append` fmap element (DList.fromList p) }
94 , line = \xs -> do 143 , line = \xs -> do
95 (lns,element) <- gets (objLines *** elemental) 144 (lns,element) <- gets (objLines *.* elemental)
96 let l = zipWith mkl xs (tail xs) 145 let l = zipWith mkl xs (tail xs)
97 -- Line requires at least two points. We'll ignore it otherwise. 146 -- Line requires at least two points. We'll ignore it otherwise.
98 when (not $ null l) $ 147 when (not $ null l) $
99 modifyFirst $ \o -> o { objLines = lns `DList.append` fmap element (DList.fromList l) } 148 modifyFirst $ \o -> o { objLines = lns `DList.append` fmap element (DList.fromList l) }
100 , face = \xs -> do 149 , face = \xs -> do
101 (fcs,element) <- gets (objFaces *** elemental) 150 (fcs,element) <- gets (objFaces *.* elemental)
102 case map mkF xs of 151 case map mkF xs of
103 a:b:c:ds -> modifyFirst $ \o -> o { objFaces = fcs `DList.snoc` element (Face a b c ds) } 152 a:b:c:ds -> modifyFirst $ \o -> o { objFaces = fcs `DList.snoc` element (Face a b c ds) }
104 _ -> return () -- Ignore faces with less than 3 indices. 153 _ -> return () -- Ignore faces with less than 3 indices.
105 , mtllib = \xs -> do 154 , mtllib = \xs -> do
106 let l = map decodeUtf8 xs 155 let l = map decodeUtf8 xs
107 libs <- gets (objMtlLibs . fst) 156 libs <- gets (objMtlLibs . pstObj)
108 modifyFirst $ \o -> o { objMtlLibs = DList.fromList l `DList.append` libs } 157 modifyFirst $ \o -> o { objMtlLibs = DList.fromList l `DList.append` libs }
109 , groups = \xs -> do 158 , groups = \xs -> do
110 let g = map decodeUtf8 xs 159 let g = map decodeUtf8 xs
111 modify' $ second $ \e -> e { elGroups = g } 160 modifySecond $ \e -> e { elGroups = g }
112 , objectName = \x -> do 161 , objectName = \x -> do
113 let o = decodeUtf8 x 162 let o = decodeUtf8 x
114 modify' $ second $ \e -> e { elObject = Just o } 163 modifySecond $ \e -> e { elObject = Just o }
115 , usemtl = \x -> do 164 , usemtl = \x -> do
116 let mtl = decodeUtf8 x 165 let mtl = decodeUtf8 x
117 libs <- DList.toList <$> gets (objMtlLibs . fst) 166 libs <- DList.toList <$> gets (objMtlLibs . pstObj)
118 modify' $ second $ \e -> e { elMtl = Just (length libs,mtl) } 167 modifySecond $ \e -> e { elMtl = Just (length libs,mtl) }
119 , smoothingGroup = \x -> when (x > 0) $ do 168 , smoothingGroup = \x -> when (x > 0) $ do
120 modify $ second $ \e -> e { elSmoothingGroup = fromIntegral x } 169 modifySecond $ \e -> e { elSmoothingGroup = fromIntegral x }
170 , endFreeForm =
171 modify' $ \s -> s { pstObj = addFreeForm (elemental $ pstElm s) (pstFF s) (pstObj s)
172 , pstFF = initFF }
121 } 173 }
122 174
123blankElement :: Element () 175blankElement :: Element ()
@@ -134,9 +186,12 @@ emptyCounts = OBJ
134 { objLocations = Count 0 186 { objLocations = Count 0
135 , objTexCoords = Count 0 187 , objTexCoords = Count 0
136 , objNormals = Count 0 188 , objNormals = Count 0
189 , objEmbeddedCurves = Count 0
137 , objPoints = Count 0 190 , objPoints = Count 0
138 , objLines = Count 0 191 , objLines = Count 0
139 , objFaces = Count 0 192 , objFaces = Count 0
193 , objCurves = Count 0
194 , objSurfaces = Count 0
140 , objMtlLibs = Count 0 195 , objMtlLibs = Count 0
141 } 196 }
142 197
@@ -145,9 +200,12 @@ mzeroOBJ = OBJ
145 { objLocations = mzero 200 { objLocations = mzero
146 , objTexCoords = mzero 201 , objTexCoords = mzero
147 , objNormals = mzero 202 , objNormals = mzero
203 , objEmbeddedCurves = mzero
148 , objPoints = mzero 204 , objPoints = mzero
149 , objLines = mzero 205 , objLines = mzero
150 , objFaces = mzero 206 , objFaces = mzero
207 , objCurves = mzero
208 , objSurfaces = mzero
151 , objMtlLibs = mzero 209 , objMtlLibs = mzero
152 } 210 }
153 211
@@ -155,7 +213,7 @@ parse :: L.ByteString -> OBJ Vector
155parse bs = Rank2.fmap (Vector.fromList . DList.toList) obj 213parse bs = Rank2.fmap (Vector.fromList . DList.toList) obj
156 where 214 where
157 go = parseCustom buildOBJ (const $ return ()) bs 215 go = parseCustom buildOBJ (const $ return ()) bs
158 (obj,_) = execState go (mzeroOBJ,blankElement) 216 ParserState { pstObj = obj } = execState go (ParserState mzeroOBJ blankElement initFF)
159 217
160parseCustom :: Monad m => ObjBuilder m -> (OBJ Count -> m b) -> L.ByteString -> m b 218parseCustom :: Monad m => ObjBuilder m -> (OBJ Count -> m b) -> L.ByteString -> m b
161parseCustom builder finish bs = do 219parseCustom builder finish bs = do