summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoe Crayne <joe@jerkface.net>2019-07-23 23:21:57 -0400
committerJoe Crayne <joe@jerkface.net>2019-07-23 23:21:57 -0400
commite52cbba217272384df4285c45beb73c90ad67c09 (patch)
tree3a33a50d5bf10817976192f3f8a4682578187002
parente2a39102145e8cb145c690f9b56d4c63126fe106 (diff)
Support NURBS surface.HEADmaster
-rw-r--r--src/Wavefront.hs51
-rw-r--r--src/Wavefront/Types.hs13
2 files changed, 58 insertions, 6 deletions
diff --git a/src/Wavefront.hs b/src/Wavefront.hs
index 3c4eff0..e6b31ec 100644
--- a/src/Wavefront.hs
+++ b/src/Wavefront.hs
@@ -2,8 +2,8 @@
2{-# LANGUAGE RankNTypes #-} 2{-# LANGUAGE RankNTypes #-}
3module Wavefront where 3module Wavefront where
4 4
5import Wavefront.Types 5import Wavefront.Types as Types
6import Wavefront.Lex 6import Wavefront.Lex as Lex
7 7
8import Control.Arrow 8import Control.Arrow
9import Control.Monad.State 9import Control.Monad.State
@@ -75,10 +75,17 @@ mkn cs = Normal x y z where (x:y:z:_) = map realToFrac cs ++ repeat 0
75mkl :: RefTriple -> RefTriple -> Line 75mkl :: RefTriple -> RefTriple -> Line
76mkl (RefTriple a at _) (RefTriple b bt _) = Line (LineIndex a at) (LineIndex b bt) 76mkl (RefTriple a at _) (RefTriple b bt _) = Line (LineIndex a at) (LineIndex b bt)
77 77
78-- I'd have thought these would be Coercible, but I guess not.
79mkF :: RefTriple -> FaceIndex 78mkF :: RefTriple -> FaceIndex
80mkF (RefTriple a at an) = FaceIndex a at an 79mkF (RefTriple a at an) = FaceIndex a at an
81 80
81-- 'mkF' and 'mkTyp' are a little awkward, but it increases modularity.
82mkTyp :: Lex.CSType -> Types.CSType
83mkTyp Lex.Bmatrix = Types.Bmatrix
84mkTyp Lex.Bezier = Types.Bezier
85mkTyp Lex.Bspline = Types.Bspline
86mkTyp Lex.Cardinal = Types.Cardinal
87mkTyp Lex.Taylor = Types.Taylor
88
82elemental :: Element () -> x -> Element x 89elemental :: Element () -> x -> Element x
83elemental element x = fmap (const x) element 90elemental element x = fmap (const x) element
84 91
@@ -88,26 +95,33 @@ modifyFirst = modify' . (\f s -> s { pstObj = f (pstObj s) })
88modifySecond :: MonadState ParserState m => (Element () -> Element ()) -> m () 95modifySecond :: MonadState ParserState m => (Element () -> Element ()) -> m ()
89modifySecond = modify' . (\f s -> s { pstElm = f (pstElm s) }) 96modifySecond = modify' . (\f s -> s { pstElm = f (pstElm s) })
90 97
98modifyFF :: MonadState ParserState m => (FreeForm -> FreeForm) -> m ()
99modifyFF = modify' . (\f s -> s { pstFF = f (pstFF s) })
100
91(*.*) :: (OBJ DList -> a) -> (Element () -> b) -> ParserState -> (a, b) 101(*.*) :: (OBJ DList -> a) -> (Element () -> b) -> ParserState -> (a, b)
92fld *.* elm = \s -> (fld (pstObj s), elm (pstElm s)) 102fld *.* elm = \s -> (fld (pstObj s), elm (pstElm s))
93 103
94data FFPts = Curv Float Float [Int] 104data FFPts = Curv Float Float [Int]
95 | Curv2 [Int] 105 | Curv2 [Int]
96 | Surf Float Float Float Float [RefTriple] 106 | Surf Float Float Float Float [FaceIndex]
97 107
98data FreeForm = FreeForm 108data FreeForm = FreeForm
99 { ffRat :: Bool 109 { ffRat :: Bool
100 , ffTyp :: CSType 110 , ffTyp :: Types.CSType
101 , ffDeg :: (Int,Int) 111 , ffDeg :: (Int,Int)
102 , ffPts :: FFPts 112 , ffPts :: FFPts
113 , ffParamU :: [Float]
114 , ffParamV :: [Float]
103 } 115 }
104 116
105initFF :: FreeForm 117initFF :: FreeForm
106initFF = FreeForm 118initFF = FreeForm
107 { ffRat = False 119 { ffRat = False
108 , ffTyp = Bspline 120 , ffTyp = Types.Bspline
109 , ffDeg = (1,1) 121 , ffDeg = (1,1)
110 , ffPts = Curv2 [] 122 , ffPts = Curv2 []
123 , ffParamU = []
124 , ffParamV = []
111 } 125 }
112 126
113mkcurv2 :: FreeForm -> EmbeddedCurve 127mkcurv2 :: FreeForm -> EmbeddedCurve
@@ -118,6 +132,21 @@ mkcurv ff = Curve
118 132
119mksurf :: FreeForm -> Surface 133mksurf :: FreeForm -> Surface
120mksurf ff = Surface 134mksurf ff = Surface
135 { surfIsRational = ffRat ff
136 , surfDegree = ffDeg ff
137 , surfType = ffTyp ff
138 , surfRangeU = case ffPts ff of
139 Surf minu maxu _ _ _ -> (minu,maxu)
140 _ -> (0,1)
141 , surfRangeV = case ffPts ff of
142 Surf _ _ minv maxv _ -> (minv,maxv)
143 _ -> (0,1)
144 , surfPoints = case ffPts ff of
145 Surf _ _ _ _ pts -> pts
146 _ -> []
147 , surfKnotsU = ffParamU ff
148 , surfKnotsV = ffParamV ff
149 }
121 150
122addFreeForm :: (forall x. x -> Element x) -> FreeForm -> OBJ DList -> OBJ DList 151addFreeForm :: (forall x. x -> Element x) -> FreeForm -> OBJ DList -> OBJ DList
123addFreeForm elm ff o = case ffPts ff of 152addFreeForm elm ff o = case ffPts ff of
@@ -167,6 +196,16 @@ buildOBJ = nullBuilder
167 modifySecond $ \e -> e { elMtl = Just (length libs,mtl) } 196 modifySecond $ \e -> e { elMtl = Just (length libs,mtl) }
168 , smoothingGroup = \x -> when (x > 0) $ do 197 , smoothingGroup = \x -> when (x > 0) $ do
169 modifySecond $ \e -> e { elSmoothingGroup = fromIntegral x } 198 modifySecond $ \e -> e { elSmoothingGroup = fromIntegral x }
199
200 -- Free-form support
201 , cstype = \israt typ -> modifyFF $ \s -> s { ffRat = israt, ffTyp = mkTyp typ }
202 , deg = \ds -> modifyFF $ \s -> s { ffDeg = ((!! 0) &&& (!! 1)) (ds ++ [3,3]) }
203 , surf = \u0 u1 v0 v1 ts -> do
204 let [uA,uB,vA,vB] = map realToFrac [u0,u1,v0,v1]
205 modifyFF $ \s -> s { ffPts = Surf uA uB vA vB (map mkF ts) }
206 , parm = \uv ks -> case uv of
207 ParamU -> modifyFF $ \s -> s { ffParamU = map realToFrac ks }
208 ParamV -> modifyFF $ \s -> s { ffParamV = map realToFrac ks }
170 , endFreeForm = 209 , endFreeForm =
171 modify' $ \s -> s { pstObj = addFreeForm (elemental $ pstElm s) (pstFF s) (pstObj s) 210 modify' $ \s -> s { pstObj = addFreeForm (elemental $ pstElm s) (pstFF s) (pstObj s)
172 , pstFF = initFF } 211 , pstFF = initFF }
diff --git a/src/Wavefront/Types.hs b/src/Wavefront/Types.hs
index 2ab48ba..fe49a57 100644
--- a/src/Wavefront/Types.hs
+++ b/src/Wavefront/Types.hs
@@ -132,7 +132,20 @@ data EmbeddedCurve = EmbeddedCurve
132data Curve = Curve 132data Curve = Curve
133 deriving (Eq,Ord,Show) 133 deriving (Eq,Ord,Show)
134 134
135data CSType = Bmatrix | Bezier | Bspline | Cardinal | Taylor
136 deriving (Eq,Ord,Show,Enum)
137
135data Surface = Surface 138data Surface = Surface
139 { surfIsRational :: !Bool
140 , surfDegree :: !(Int,Int)
141 , surfType :: !CSType
142 , surfPoints :: [FaceIndex]
143 , surfRangeU :: !(Float,Float)
144 , surfRangeV :: !(Float,Float)
145 , surfKnotsU :: ![Float]
146 , surfKnotsV :: ![Float]
147 -- TODO: trim/hole/special
148 }
136 deriving (Eq,Ord,Show) 149 deriving (Eq,Ord,Show)
137 150
138-- | A point is a single index that references the locations. It’s a canonical 151-- | A point is a single index that references the locations. It’s a canonical