summaryrefslogtreecommitdiff
path: root/src/Codec
diff options
context:
space:
mode:
authorJoe Crayne <joe@jerkface.net>2019-06-11 05:11:54 -0400
committerJoe Crayne <joe@jerkface.net>2019-06-11 05:16:39 -0400
commit083779f1bdf92aed9519c9d1f1e6c4042f574a82 (patch)
treec4d414c756622a20cc6a92bbdf1f68ab62ae0d70 /src/Codec
parent952f0b322459a9ae5635f1420c14dffc1561cf44 (diff)
Sabadie parser: relative vertex references in faces.
Diffstat (limited to 'src/Codec')
-rw-r--r--src/Codec/Wavefront/Lexer.hs54
-rw-r--r--src/Codec/Wavefront/Object.hs8
-rw-r--r--src/Codec/Wavefront/Token.hs6
3 files changed, 39 insertions, 29 deletions
diff --git a/src/Codec/Wavefront/Lexer.hs b/src/Codec/Wavefront/Lexer.hs
index 712cabf..77ecb35 100644
--- a/src/Codec/Wavefront/Lexer.hs
+++ b/src/Codec/Wavefront/Lexer.hs
@@ -29,13 +29,13 @@ import Numeric.Natural ( Natural )
29-- |The lexer context. The result of lexing a stream of tokens is this exact type. 29-- |The lexer context. The result of lexing a stream of tokens is this exact type.
30data Ctxt = Ctxt { 30data Ctxt = Ctxt {
31 -- |Locations. 31 -- |Locations.
32 ctxtLocations :: DList Location 32 ctxtLocations :: (Int, DList Location)
33 -- |Texture coordinates. 33 -- |Texture coordinates.
34 , ctxtTexCoords :: DList TexCoord 34 , ctxtTexCoords :: (Int, DList TexCoord)
35 -- |Texture coordinates. 35 -- |Texture coordinates.
36 , ctxtParamCoords :: DList ParamCoord 36 , ctxtParamCoords :: (Int, DList ParamCoord)
37 -- |Normals. 37 -- |Normals.
38 , ctxtNormals :: DList Normal 38 , ctxtNormals :: (Int, DList Normal)
39 -- |Points. 39 -- |Points.
40 , ctxtPoints :: DList (Element Point) 40 , ctxtPoints :: DList (Element Point)
41 -- |Lines. 41 -- |Lines.
@@ -56,12 +56,12 @@ data Ctxt = Ctxt {
56 56
57-- |The empty 'Ctxt'. Such a context exists at the beginning of the token stream and gets altered 57-- |The empty 'Ctxt'. Such a context exists at the beginning of the token stream and gets altered
58-- as we consume tokens. 58-- as we consume tokens.
59emptyCtxt :: Ctxt 59emptyCtxt :: Ctxt
60emptyCtxt = Ctxt { 60emptyCtxt = Ctxt {
61 ctxtLocations = empty 61 ctxtLocations = (0,empty)
62 , ctxtTexCoords = empty 62 , ctxtTexCoords = (0,empty)
63 , ctxtParamCoords = empty 63 , ctxtParamCoords = (0,empty)
64 , ctxtNormals = empty 64 , ctxtNormals = (0,empty)
65 , ctxtPoints = empty 65 , ctxtPoints = empty
66 , ctxtLines = empty 66 , ctxtLines = empty
67 , ctxtFaces = empty 67 , ctxtFaces = empty
@@ -72,30 +72,40 @@ emptyCtxt = Ctxt {
72 , ctxtCurrentSmoothingGroup = 0 72 , ctxtCurrentSmoothingGroup = 0
73 } 73 }
74 74
75updateList v field setField = do
76 (c0,vs) <- gets field
77 let c = succ c0
78 c `seq` modify $ setField (c, vs `snoc` v)
79
80derel c x | x > 0 = x
81 | otherwise = c + x + 1
82
83derelF cv ct cn (FaceIndex v mt mn) = FaceIndex (derel cv v) (derel ct <$> mt) (derel cn <$> mn)
84
85derelativizeFace cv ct cn (Face a b c ds) = Face a' b' c' ds'
86 where
87 a':b':c':ds' = map (derelF cv ct cn) $ a:b:c:ds
88
75-- |The lexer function, consuming tokens and yielding a 'Ctxt'. 89-- |The lexer function, consuming tokens and yielding a 'Ctxt'.
76lexer :: TokenStream -> Ctxt 90lexer :: TokenStream -> Ctxt
77lexer stream = execState (traverse_ consume stream) emptyCtxt 91lexer stream = execState (traverse_ consume stream) emptyCtxt
78 where 92 where
79 consume tk = case tk of 93 consume tk = case tk of
80 TknV v -> do 94 TknV v -> updateList v ctxtLocations $ \x ctxt -> ctxt { ctxtLocations = x }
81 locations <- gets ctxtLocations 95 TknVN vn -> updateList vn ctxtNormals $ \x ctxt -> ctxt { ctxtNormals = x }
82 modify $ \ctxt -> ctxt { ctxtLocations = locations `snoc` v } 96 TknVT vt -> updateList vt ctxtTexCoords $ \x ctxt -> ctxt { ctxtTexCoords = x }
83 TknVN vn -> do 97 TknVP vp -> updateList vp ctxtParamCoords $ \x ctxt -> ctxt { ctxtParamCoords = x }
84 normals <- gets ctxtNormals
85 modify $ \ctxt -> ctxt { ctxtNormals = normals `snoc` vn }
86 TknVT vt -> do
87 texCoords <- gets ctxtTexCoords
88 modify $ \ctxt -> ctxt { ctxtTexCoords = texCoords `snoc` vt }
89 TknVP vp -> do
90 pCoords <- gets ctxtParamCoords
91 modify $ \ctxt -> ctxt { ctxtParamCoords = pCoords `snoc` vp }
92 TknP p -> do 98 TknP p -> do
93 (pts,element) <- prepareElement ctxtPoints 99 (pts,element) <- prepareElement ctxtPoints
94 modify $ \ctxt -> ctxt { ctxtPoints = pts `append` fmap element (fromList p) } 100 modify $ \ctxt -> ctxt { ctxtPoints = pts `append` fmap element (fromList p) }
95 TknL l -> do 101 TknL l -> do
96 (lns,element) <- prepareElement ctxtLines 102 (lns,element) <- prepareElement ctxtLines
97 modify $ \ctxt -> ctxt { ctxtLines = lns `append` fmap element (fromList l) } 103 modify $ \ctxt -> ctxt { ctxtLines = lns `append` fmap element (fromList l) }
98 TknF f -> do 104 TknF f0 -> do
105 vgcnt <- gets (fst . ctxtLocations)
106 vtcnt <- gets (fst . ctxtTexCoords)
107 vncnt <- gets (fst . ctxtNormals)
108 let f = derelativizeFace vgcnt vtcnt vncnt f0
99 (fcs,element) <- prepareElement ctxtFaces 109 (fcs,element) <- prepareElement ctxtFaces
100 modify $ \ctxt -> ctxt { ctxtFaces = fcs `snoc` element f } 110 modify $ \ctxt -> ctxt { ctxtFaces = fcs `snoc` element f }
101 TknG g -> modify $ \ctxt -> ctxt { ctxtCurrentGroups = g } 111 TknG g -> modify $ \ctxt -> ctxt { ctxtCurrentGroups = g }
diff --git a/src/Codec/Wavefront/Object.hs b/src/Codec/Wavefront/Object.hs
index bdd756f..26d85c2 100644
--- a/src/Codec/Wavefront/Object.hs
+++ b/src/Codec/Wavefront/Object.hs
@@ -44,10 +44,10 @@ data WavefrontOBJ = WavefrontOBJ {
44 44
45ctxtToWavefrontOBJ :: Ctxt -> WavefrontOBJ 45ctxtToWavefrontOBJ :: Ctxt -> WavefrontOBJ
46ctxtToWavefrontOBJ ctxt = WavefrontOBJ { 46ctxtToWavefrontOBJ ctxt = WavefrontOBJ {
47 objLocations = fromDList (ctxtLocations ctxt) 47 objLocations = fromDList (snd $ ctxtLocations ctxt)
48 , objTexCoords = fromDList (ctxtTexCoords ctxt) 48 , objTexCoords = fromDList (snd $ ctxtTexCoords ctxt)
49 , objNormals = fromDList (ctxtNormals ctxt) 49 , objNormals = fromDList (snd $ ctxtNormals ctxt)
50 , objParamCoords = fromDList (ctxtParamCoords ctxt) 50 , objParamCoords = fromDList (snd $ ctxtParamCoords ctxt)
51 , objPoints = fromDList (ctxtPoints ctxt) 51 , objPoints = fromDList (ctxtPoints ctxt)
52 , objLines = fromDList (ctxtLines ctxt) 52 , objLines = fromDList (ctxtLines ctxt)
53 , objFaces = fromDList (ctxtFaces ctxt) 53 , objFaces = fromDList (ctxtFaces ctxt)
diff --git a/src/Codec/Wavefront/Token.hs b/src/Codec/Wavefront/Token.hs
index 01acd5c..70b3437 100644
--- a/src/Codec/Wavefront/Token.hs
+++ b/src/Codec/Wavefront/Token.hs
@@ -169,13 +169,13 @@ face = do
169 where 169 where
170 parseFaceIndices = fmap (\(i,k,j) -> FaceIndex i k j) parseFaceTriple `sepBy1` skipHSpace 170 parseFaceIndices = fmap (\(i,k,j) -> FaceIndex i k j) parseFaceTriple `sepBy1` skipHSpace
171 parseFaceTriple = do 171 parseFaceTriple = do
172 v <- decimal 172 v <- signed decimal
173 slashThenElse (parseVT v) (pure (v,Nothing,Nothing)) 173 slashThenElse (parseVT v) (pure (v,Nothing,Nothing))
174 parseVT v = slashThenElse (parseVN v Nothing) $ do 174 parseVT v = slashThenElse (parseVN v Nothing) $ do
175 vt <- decimal 175 vt <- signed decimal
176 slashThenElse (parseVN v $ Just vt) (pure (v,Just vt,Nothing)) 176 slashThenElse (parseVN v $ Just vt) (pure (v,Just vt,Nothing))
177 parseVN v vt = do 177 parseVN v vt = do
178 vn <- decimal 178 vn <- signed decimal
179 pure (v,vt,Just vn) 179 pure (v,vt,Just vn)
180 180
181---------------------------------------------------------------------------------------------------- 181----------------------------------------------------------------------------------------------------