diff options
Diffstat (limited to 'src/Wavefront/Lex.hs')
-rw-r--r-- | src/Wavefront/Lex.hs | 101 |
1 files changed, 95 insertions, 6 deletions
diff --git a/src/Wavefront/Lex.hs b/src/Wavefront/Lex.hs index 05a6595..f4cb54a 100644 --- a/src/Wavefront/Lex.hs +++ b/src/Wavefront/Lex.hs | |||
@@ -2,15 +2,21 @@ | |||
2 | {-# LANGUAGE OverloadedStrings #-} | 2 | {-# LANGUAGE OverloadedStrings #-} |
3 | module Wavefront.Lex where | 3 | module Wavefront.Lex where |
4 | 4 | ||
5 | import Data.Bool | ||
5 | import qualified Data.ByteString.Lazy.Char8 as L | 6 | import qualified Data.ByteString.Lazy.Char8 as L |
6 | import qualified Data.ByteString.Char8 as S | 7 | import qualified Data.ByteString.Char8 as S |
7 | import Data.ByteString.Internal as BS | 8 | import Data.ByteString.Internal as BS |
9 | import Data.ByteString.Lex.Fractional as F | ||
10 | import Data.ByteString.Lex.Integral as I | ||
8 | import Data.Char | 11 | import Data.Char |
9 | import Data.IntMap (IntMap) | 12 | import Data.IntMap (IntMap) |
10 | import qualified Data.IntMap as IntMap | 13 | import qualified Data.IntMap as IntMap |
11 | import Data.ByteString.Lex.Fractional as F | 14 | import Data.List |
12 | import Data.ByteString.Lex.Integral as I | 15 | import Data.Maybe |
13 | import qualified Rank2 | 16 | import qualified Rank2 |
17 | import Control.Monad.Writer.Lazy | ||
18 | |||
19 | import Text.UTF8 | ||
14 | 20 | ||
15 | data ObjBuilder m = ObjBuilder | 21 | data ObjBuilder m = ObjBuilder |
16 | { vertex :: [Double] -> m () | 22 | { vertex :: [Double] -> m () |
@@ -18,7 +24,7 @@ data ObjBuilder m = ObjBuilder | |||
18 | , vertexN :: [Double] -> m () | 24 | , vertexN :: [Double] -> m () |
19 | , vertexP :: [Double] -> m () | 25 | , vertexP :: [Double] -> m () |
20 | , face :: [RefTriple] -> m () | 26 | , face :: [RefTriple] -> m () |
21 | , line :: [RefTriple] -> m () | 27 | , line :: [RefTriple] -> m () |
22 | , cstype :: Bool -> CSType -> m () | 28 | , cstype :: Bool -> CSType -> m () |
23 | , curv2 :: [Int] -> m () | 29 | , curv2 :: [Int] -> m () |
24 | , curv :: Double -> Double -> [Int] -> m () | 30 | , curv :: Double -> Double -> [Int] -> m () |
@@ -67,7 +73,7 @@ instance Rank2.Functor ObjBuilder where | |||
67 | , vertexN = \vs -> f $ vertexN b vs | 73 | , vertexN = \vs -> f $ vertexN b vs |
68 | , vertexP = \vs -> f $ vertexP b vs | 74 | , vertexP = \vs -> f $ vertexP b vs |
69 | , face = \is -> f $ face b is | 75 | , face = \is -> f $ face b is |
70 | , line = \is -> f $ line b is | 76 | , line = \is -> f $ line b is |
71 | , cstype = \isRat typ -> f $ cstype b isRat typ | 77 | , cstype = \isRat typ -> f $ cstype b isRat typ |
72 | , curv2 = \is -> f $ curv2 b is | 78 | , curv2 = \is -> f $ curv2 b is |
73 | , curv = \u0 v0 is -> f $ curv b u0 v0 is | 79 | , curv = \u0 v0 is -> f $ curv b u0 v0 is |
@@ -159,6 +165,59 @@ nullBuilder = ObjBuilder | |||
159 | , badToken = \bs -> pure () | 165 | , badToken = \bs -> pure () |
160 | } | 166 | } |
161 | 167 | ||
168 | echoBuilder :: (MonadWriter (f String) m, Applicative f) => ObjBuilder m | ||
169 | echoBuilder = ObjBuilder | ||
170 | { vertex = \vs -> echo $ unwords ("v": map show vs) | ||
171 | , vertexT = \vs -> echo $ unwords ("vt": map show vs) | ||
172 | , vertexN = \vs -> echo $ unwords ("vn": map show vs) | ||
173 | , vertexP = \vs -> echo $ unwords ("vp": map show vs) | ||
174 | , face = \ts -> echo $ unwords ("f":map showRefTriple ts) | ||
175 | , line = \ts -> echo $ unwords ("l":map showRefTriple ts) | ||
176 | , cstype = \isRat typ -> echo $ unwords [ if isRat then "cstype rat" else "cstype" | ||
177 | , map toLower (show typ) ] | ||
178 | , curv2 = \is -> echo $ unwords ("curv2":map show is) | ||
179 | , curv = \u0 v0 is -> echo $ unwords ("curv":show u0:show v0:map show is) | ||
180 | , parm = \isU ds -> echo $ unwords ("parm":showParamSpec isU:map show ds) | ||
181 | , specialPoints = \is -> echo $ unwords ("sp":map show is) | ||
182 | , endFreeForm = echo "end" | ||
183 | , ctech = \approx -> echo $ "ctech " ++ showCurveSamplingSpec approx | ||
184 | , stech = \approx -> echo $ "stech " ++ showSurfaceSamplingSpec approx | ||
185 | , deg = \is -> echo $ unwords ("deg":map show is) | ||
186 | , surf = \u0 u1 v0 v1 ts -> echo $ unwords $ "surf " : map show [u0,u1,v0,v1] | ||
187 | ++ map showRefTriple ts | ||
188 | , trim = \ss -> echo $ unwords ("trim":concatMap (\(CurveSpec s e r) -> [show s,show e,show r]) ss) | ||
189 | , hole = \ss -> echo $ unwords ("hole":concatMap (\(CurveSpec s e r) -> [show s,show e,show r]) ss) | ||
190 | , specialCurves = \ss -> echo $ unwords ("scrv":concatMap (\(CurveSpec s e r) -> [show s,show e,show r]) ss) | ||
191 | , equivalentCurves = \ccs -> echo $ unwords ("con":map showEmbeddedCurve ccs) | ||
192 | , groups = \gs -> echo $ unwords $ "g":map unpackUtf8 gs | ||
193 | , smoothingGroup = \sg -> echo ("s " ++ show sg) | ||
194 | , mergingGroup = \mg δ -> echo $ unwords ["mg",show mg,show δ] | ||
195 | , usemtl = \mtl -> echo ("usemtl " ++ unpackUtf8 mtl) | ||
196 | , deprecated_cdc = \is -> echo $ unwords ("cdc":map show is) | ||
197 | , deprecated_bzp = \is -> echo $ unwords ("bzp":map show is) | ||
198 | , mtllib = \fns -> echo $ unwords $ "mtllib " : map unpackUtf8 fns | ||
199 | , objectName = \obn -> echo ("o " ++ unpackUtf8 obn) | ||
200 | , bmat = \isU is -> echo $ unwords ("bmat":showParamSpec isU:map show is) | ||
201 | , step = \is -> echo $ unwords ("step":map show is) | ||
202 | , points = \is -> echo $ unwords ("p":map show is) | ||
203 | , usemap = \mp -> echo $ "usemap " ++ maybe "off" unpackUtf8 mp | ||
204 | , maplib = \fns -> echo ("maplib " ++ show fns) | ||
205 | , c_interp = \flag -> echo $ "c_interp " ++ bool "off" "on" flag | ||
206 | , d_interp = \flag -> echo $ "d_interp " ++ bool "off" "on" flag | ||
207 | , deprecated_cdp = \x -> echo $ "cdp " ++ show x | ||
208 | , deprecated_bsp = \x -> echo $ "bsp " ++ show x | ||
209 | , trace_obj = \x -> echo $ "trace_obj " ++ unpackUtf8 x | ||
210 | , shadow_obj = \x -> echo $ "shadow_obj " ++ unpackUtf8 x | ||
211 | , deprecated_res = \x -> echo $ "res " ++ show x | ||
212 | , bevel = \x -> echo $ "bevel " ++ show x | ||
213 | , lod = \x -> echo $ "lod " ++ show x | ||
214 | , call = \fn as -> echo $ unwords ("call":map unpackUtf8 (fn:as)) | ||
215 | , command = \e cmd -> do echo $ "csh " ++ (bool ('-':) id e $ unpackUtf8 $ L.toStrict cmd) | ||
216 | return L.empty | ||
217 | , badToken = \bs -> echo $ "bad token: " ++ show (L.take 20 bs) | ||
218 | } | ||
219 | where | ||
220 | echo = tell . pure | ||
162 | 221 | ||
163 | data CurveSamplingSpec | 222 | data CurveSamplingSpec |
164 | -- ctech cparm | 223 | -- ctech cparm |
@@ -175,6 +234,11 @@ data CurveSamplingSpec | |||
175 | | CurvatureBasedPolygon { maxDistanceToCurve :: Double, maximumDegreesPerSample :: Double } | 234 | | CurvatureBasedPolygon { maxDistanceToCurve :: Double, maximumDegreesPerSample :: Double } |
176 | deriving (Eq,Show) | 235 | deriving (Eq,Show) |
177 | 236 | ||
237 | showCurveSamplingSpec :: CurveSamplingSpec -> String | ||
238 | showCurveSamplingSpec (UniformSubdivision d) = "cparm " ++ show d | ||
239 | showCurveSamplingSpec (MaxLengthPolygonal d) = "cspace " ++ show d | ||
240 | showCurveSamplingSpec (CurvatureBasedPolygon d a) = unwords ["curv",show d,show a] | ||
241 | |||
178 | data SurfaceSamplingSpec | 242 | data SurfaceSamplingSpec |
179 | -- stech cparma ures vres | 243 | -- stech cparma ures vres |
180 | = UniformIsoparametric { uDivisionsPerDegree :: Double, vDivisionsPerDegree :: Double } | 244 | = UniformIsoparametric { uDivisionsPerDegree :: Double, vDivisionsPerDegree :: Double } |
@@ -186,6 +250,11 @@ data SurfaceSamplingSpec | |||
186 | | CurvatureBasedPolytope { maxDistanceToSurface :: Double, maxDegreesPerCorner :: Double } | 250 | | CurvatureBasedPolytope { maxDistanceToSurface :: Double, maxDegreesPerCorner :: Double } |
187 | deriving (Eq,Show) | 251 | deriving (Eq,Show) |
188 | 252 | ||
253 | showSurfaceSamplingSpec :: SurfaceSamplingSpec -> String | ||
254 | showSurfaceSamplingSpec (UniformIsoparametric ures vres) = unwords ["cparma",show ures,show vres] | ||
255 | showSurfaceSamplingSpec (UniformAfterTrimming uvres) = "cparmb " ++ show uvres | ||
256 | showSurfaceSamplingSpec (MaxLengthPolytopal maxlength) = "cspace " ++ show maxlength | ||
257 | showSurfaceSamplingSpec (CurvatureBasedPolytope maxd maxa) = unwords ["curv",show maxd,show maxa] | ||
189 | 258 | ||
190 | data ObjState = ObjState | 259 | data ObjState = ObjState |
191 | { | 260 | { |
@@ -291,13 +360,13 @@ findNewLine ps o@(ObjConfig args) bs = case L.break (\c -> c=='\n' || c=='\\' || | |||
291 | nextToken :: (L.ByteString -> L.ByteString) -> L.ByteString -> L.ByteString | 360 | nextToken :: (L.ByteString -> L.ByteString) -> L.ByteString -> L.ByteString |
292 | nextToken tok bs = tok $ L.dropWhile (not . isSpace) bs | 361 | nextToken tok bs = tok $ L.dropWhile (not . isSpace) bs |
293 | 362 | ||
294 | parseFloats tok bs cont = case L.splitAt 10 (tok bs) of | 363 | parseFloats tok bs cont = case L.splitAt 22 (tok bs) of |
295 | (ds,bs') -> case F.readSigned F.readExponential (L.toStrict ds) of | 364 | (ds,bs') -> case F.readSigned F.readExponential (L.toStrict ds) of |
296 | Just (x,b) -> parseFloats tok (reconsChunk b bs') (cont . (x :)) | 365 | Just (x,b) -> parseFloats tok (reconsChunk b bs') (cont . (x :)) |
297 | Nothing -> cont [] bs | 366 | Nothing -> cont [] bs |
298 | 367 | ||
299 | parseFloatsN 0 _ bs cont = cont [] bs | 368 | parseFloatsN 0 _ bs cont = cont [] bs |
300 | parseFloatsN n tok bs cont = case L.splitAt 10 (tok bs) of | 369 | parseFloatsN n tok bs cont = case L.splitAt 22 (tok bs) of |
301 | (ds,bs') -> case F.readSigned F.readExponential (L.toStrict ds) of | 370 | (ds,bs') -> case F.readSigned F.readExponential (L.toStrict ds) of |
302 | Just (x,b) -> parseFloatsN (n-1) tok (reconsChunk b bs') (cont . (x :)) | 371 | Just (x,b) -> parseFloatsN (n-1) tok (reconsChunk b bs') (cont . (x :)) |
303 | Nothing -> cont [] bs | 372 | Nothing -> cont [] bs |
@@ -376,6 +445,10 @@ data CSType = Bmatrix | Bezier | Bspline | Cardinal | Taylor | |||
376 | data ParamSpec = ParamU | ParamV | 445 | data ParamSpec = ParamU | ParamV |
377 | deriving (Eq,Ord,Show,Enum) | 446 | deriving (Eq,Ord,Show,Enum) |
378 | 447 | ||
448 | showParamSpec :: ParamSpec -> String | ||
449 | showParamSpec ParamU = "u" | ||
450 | showParamSpec ParamV = "v" | ||
451 | |||
379 | data RefTriple = RefTriple | 452 | data RefTriple = RefTriple |
380 | { refV :: {-# UNPACK #-} !Int | 453 | { refV :: {-# UNPACK #-} !Int |
381 | , refT :: !(Maybe Int) | 454 | , refT :: !(Maybe Int) |
@@ -384,6 +457,14 @@ data RefTriple = RefTriple | |||
384 | -- data RefTriple = RefTriple Int (Maybe Int) (Maybe Int) | 457 | -- data RefTriple = RefTriple Int (Maybe Int) (Maybe Int) |
385 | deriving (Eq,Ord,Show) | 458 | deriving (Eq,Ord,Show) |
386 | 459 | ||
460 | showRefTriple :: RefTriple -> String | ||
461 | showRefTriple (RefTriple v Nothing (Just n)) = show v ++ "//" ++ show n | ||
462 | showRefTriple (RefTriple v mt mn) = intercalate "/" $ map show | ||
463 | $ mappend [v] | ||
464 | $ maybe id (mappend . pure) mt | ||
465 | $ maybe id (mappend . pure) mn | ||
466 | $ [] | ||
467 | |||
387 | data CurveSpec = CurveSpec | 468 | data CurveSpec = CurveSpec |
388 | { curveStart :: Double | 469 | { curveStart :: Double |
389 | , curveEnd :: Double | 470 | , curveEnd :: Double |
@@ -397,6 +478,14 @@ data EmbeddedCurve = EmbeddedCurve | |||
397 | } | 478 | } |
398 | deriving (Eq,Ord,Show) | 479 | deriving (Eq,Ord,Show) |
399 | 480 | ||
481 | showEmbeddedCurve :: EmbeddedCurve -> String | ||
482 | showEmbeddedCurve (EmbeddedCurve s c) = unwords | ||
483 | [ show s | ||
484 | , show (curveStart c) | ||
485 | , show (curveEnd c) | ||
486 | , show (curveRef c) | ||
487 | ] | ||
488 | |||
400 | lengthLessThan :: Int -> L.ByteString -> Bool | 489 | lengthLessThan :: Int -> L.ByteString -> Bool |
401 | lengthLessThan n bs = | 490 | lengthLessThan n bs = |
402 | foldr (\c ret ac -> let m = S.length c in if ac <= m then False else ret $! ac - m) | 491 | foldr (\c ret ac -> let m = S.length c in if ac <= m then False else ret $! ac - m) |