summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoe Crayne <joe@jerkface.net>2019-07-28 00:16:13 -0400
committerJoe Crayne <joe@jerkface.net>2019-07-28 00:17:11 -0400
commit5aba33b6f801910a8f5e1587c13678e237e31782 (patch)
tree67e71c9161dc23e1fe120e2e51074cd9f69b96f5
parent175e4a0ee82e4db1fade4fbd8b5e55e88c21a826 (diff)
Render curve from obj file.
-rw-r--r--Bezier.hs2
-rw-r--r--LoadMesh.hs60
-rw-r--r--MeshSketch.hs40
3 files changed, 89 insertions, 13 deletions
diff --git a/Bezier.hs b/Bezier.hs
index e526608..b93196d 100644
--- a/Bezier.hs
+++ b/Bezier.hs
@@ -32,6 +32,8 @@ data Curve = Curve
32 , curveSegments :: Maybe Polygonization 32 , curveSegments :: Maybe Polygonization
33 } 33 }
34 34
35-- Although this function accepts an index, 'subdivideCurve' increases the
36-- index by one after each call, so it is safe to ignore the index passed.
35type StorePoint m = BufferID -> Int -> Vector Float {- 3d -} -> m () 37type StorePoint m = BufferID -> Int -> Vector Float {- 3d -} -> m ()
36 38
37xz :: Vector Float -> (Float,Float) 39xz :: Vector Float -> (Float,Float)
diff --git a/LoadMesh.hs b/LoadMesh.hs
index aaf0e06..cd7a8ad 100644
--- a/LoadMesh.hs
+++ b/LoadMesh.hs
@@ -18,6 +18,7 @@ import Data.Maybe
18import Data.Map (Map) 18import Data.Map (Map)
19import qualified Data.Map as Map 19import qualified Data.Map as Map
20import qualified Data.Vector as V 20import qualified Data.Vector as V
21import qualified Data.Vector.Storable as StorableV
21import qualified Data.ByteString as SB 22import qualified Data.ByteString as SB
22import qualified Data.ByteString.Lazy.Char8 as L 23import qualified Data.ByteString.Lazy.Char8 as L
23import Data.Text (unpack,Text,pack) 24import Data.Text (unpack,Text,pack)
@@ -37,10 +38,19 @@ data MaterialMesh m = MaterialMesh
37 , materialMasks :: Map Text Mask 38 , materialMasks :: Map Text Mask
38 } 39 }
39 40
40type MeshData = ( [MaterialMesh Mesh] -- List of uniform-material meshes (and the name of the material). 41data CurveData = CurveData
41 , ( V.Vector MtlLib -- Material definitions. 42 { curves :: [Curve]
42 , FilePath ) -- Path to wavefront obj file. 43 , curvePt :: Int -> Location
43 ) 44 , curveMax :: Int
45 }
46
47
48data MeshData = MeshData
49 { matMeshes :: [MaterialMesh Mesh] -- List of uniform-material meshes (and the name of the material).
50 , matLib :: ( V.Vector MtlLib -- Material definitions.
51 , FilePath ) -- Path to wavefront obj file.
52 , matCurves :: CurveData
53 }
44 54
45relativeFrom :: FilePath -> FilePath -> FilePath 55relativeFrom :: FilePath -> FilePath -> FilePath
46relativeFrom path file | isAbsolute file = file 56relativeFrom path file | isAbsolute file = file
@@ -51,7 +61,12 @@ loadOBJ fname = L.readFile fname >>= \bs -> do
51 let obj@OBJ{..} = Wavefront.parse bs 61 let obj@OBJ{..} = Wavefront.parse bs
52 -- load materials 62 -- load materials
53 mtlLib <- mapM (readMtlWithFallback . relativeFrom fname . unpack) objMtlLibs 63 mtlLib <- mapM (readMtlWithFallback . relativeFrom fname . unpack) objMtlLibs
54 return $ Right (objToMesh obj,(mtlLib,fname)) 64 return $ Right MeshData
65 { matMeshes = objToMesh obj
66 , matLib = (mtlLib,fname)
67 , matCurves = objToCurveData obj
68 }
69
55 70
56 71
57data BoundingBox = BoundingBox 72data BoundingBox = BoundingBox
@@ -122,22 +137,37 @@ transformMesh t m = m
122 { mAttributes = Map.adjust (tranformAttribute t) "position" (mAttributes m) 137 { mAttributes = Map.adjust (tranformAttribute t) "position" (mAttributes m)
123 } 138 }
124 139
125uploadOBJToGPU :: Maybe BoundingBox -> MeshData -> IO ([MaterialMesh GPUMesh],Matrix Float) 140transformLocation :: Matrix Float -> Location -> Location
126uploadOBJToGPU scalebb (subModels,(mtlLib,objpath)) = do 141transformLocation t (Location x y z w) = Location xx yy zz ww
127 let meshbb = foldMap (attribBoundingBox . mAttributes . materialMesh) subModels :: BoundingBox 142 where
143 [xx,yy,zz,ww] = toList $ t #> fromList [x,y,z,w]
144
145locationBoundingBox :: Location -> BoundingBox
146locationBoundingBox (Location x y z w) = BoundingBox x x y y z z
147
148uploadOBJToGPU :: Maybe BoundingBox -> MeshData -> IO (([MaterialMesh GPUMesh],CurveData),Matrix Float)
149uploadOBJToGPU scalebb (MeshData subModels (mtlLib,objpath) curveData) = do
150 let meshbb = foldMap (attribBoundingBox . mAttributes . materialMesh) subModels
151 <> foldMap (foldMap (locationBoundingBox . curvePt curveData) . curvePoints)
152 (curves curveData)
128 m = maybe (ident 4) (scaleWithin meshbb) scalebb 153 m = maybe (ident 4) (scaleWithin meshbb) scalebb
154 curveData' = case scalebb of
155 Just _ -> curveData { curvePt = transformLocation m . curvePt curveData }
156 Nothing -> curveData
129 putStrLn $ show meshbb 157 putStrLn $ show meshbb
130 gpuSubModels <- forM subModels $ \matmesh -> do 158 gpuSubModels <- forM subModels $ \matmesh -> do
131 a <- LambdaCubeGL.uploadMeshToGPU (transformMesh m (materialMesh matmesh)) 159 a <- LambdaCubeGL.uploadMeshToGPU (transformMesh m (materialMesh matmesh))
132 return matmesh { materialMesh = a } 160 return matmesh { materialMesh = a }
133 return (gpuSubModels,m) 161 return ((gpuSubModels,curveData'),m)
134 162
135uploadMtlLib :: (V.Vector MtlLib,FilePath) -> IO (V.Vector (Map Text (ObjMaterial,TextureData))) 163uploadMtlLib :: (V.Vector MtlLib,FilePath) -> IO (V.Vector (Map Text (ObjMaterial,TextureData)))
136uploadMtlLib (mtlLib,objpath) = do 164uploadMtlLib (mtlLib,objpath) = do
137 -- collect used textures 165 -- collect used textures
138 let usedTextures = nub . concatMap (maybeToList . mtl_map_Kd) $ concatMap Map.elems $ V.toList mtlLib 166 let usedTextures = nub . concatMap (maybeToList . mtl_map_Kd) $ concatMap Map.elems $ V.toList mtlLib
139 whiteImage = Juicy.ImageRGB8 $ Juicy.generateImage (\_ _ -> Juicy.PixelRGB8 255 255 255) 1 1 167 whiteImage = Juicy.ImageRGB8 $ Juicy.generateImage (\_ _ -> Juicy.PixelRGB8 255 255 255) 1 1
140 checkerImage = Juicy.ImageRGB8 $ Juicy.generateImage (\x y -> if mod (x + y) 2 == 0 then Juicy.PixelRGB8 0 0 0 else Juicy.PixelRGB8 255 255 0) 2 2 168 checkerImage = Juicy.ImageRGB8 $ Juicy.generateImage mkchecker 2 2
169 where mkchecker x y = if mod (x + y) 2 == 0 then Juicy.PixelRGB8 0 0 0
170 else Juicy.PixelRGB8 255 255 0
141 checkerTex <- LC.uploadTexture2DToGPU checkerImage 171 checkerTex <- LC.uploadTexture2DToGPU checkerImage
142 -- load images and upload to gpu 172 -- load images and upload to gpu
143 textureLib <- forM (Map.fromList $ zip usedTextures usedTextures) $ \fname -> Juicy.readImage (relativeFrom objpath fname) >>= \case 173 textureLib <- forM (Map.fromList $ zip usedTextures usedTextures) $ \fname -> Juicy.readImage (relativeFrom objpath fname) >>= \case
@@ -147,6 +177,16 @@ uploadMtlLib (mtlLib,objpath) = do
147 -- pair textures and materials 177 -- pair textures and materials
148 return $ fmap (\a -> (a, maybe whiteTex (fromMaybe checkerTex . flip Map.lookup textureLib) . mtl_map_Kd $ a)) <$> mtlLib 178 return $ fmap (\a -> (a, maybe whiteTex (fromMaybe checkerTex . flip Map.lookup textureLib) . mtl_map_Kd $ a)) <$> mtlLib
149 179
180vecLocation :: Location -> StorableV.Vector Float
181vecLocation (Location x y z w) = StorableV.fromList [x,y,z,w]
182
183objToCurveData :: WavefrontOBJ -> CurveData
184objToCurveData OBJ{..} = CurveData
185 { curves = map elValue $ V.toList $ objCurves
186 , curvePt = (objLocations V.!)
187 , curveMax = V.length objLocations
188 }
189
150objToMesh :: WavefrontOBJ -> [MaterialMesh Mesh] 190objToMesh :: WavefrontOBJ -> [MaterialMesh Mesh]
151objToMesh OBJ{..} = [ toMesh faceGroup | faceGroup <- faces ] 191objToMesh OBJ{..} = [ toMesh faceGroup | faceGroup <- faces ]
152 where 192 where
diff --git a/MeshSketch.hs b/MeshSketch.hs
index a51cd3d..a2e4cbe 100644
--- a/MeshSketch.hs
+++ b/MeshSketch.hs
@@ -54,6 +54,10 @@ import Text.Printf
54import qualified Foreign.C.Types 54import qualified Foreign.C.Types
55import System.FilePath 55import System.FilePath
56import System.Directory 56import System.Directory
57import Wavefront.Types
58import Wavefront.Util
59
60
57 61
58import CubeMap 62import CubeMap
59import GLWidget (nullableContext, withCurrentGL) 63import GLWidget (nullableContext, withCurrentGL)
@@ -160,8 +164,8 @@ stateChangeMesh obj mm storage st = do
160 let glarea = mmWidget mm 164 let glarea = mmWidget mm
161 -- load OBJ geometry and material descriptions 165 -- load OBJ geometry and material descriptions
162 let workarea = BoundingBox (-2.5) (2.5) (-2.5) 2.5 (-2.5) (2.5) 166 let workarea = BoundingBox (-2.5) (2.5) (-2.5) 2.5 (-2.5) (2.5)
163 mtlLib = snd obj 167 mtlLib = matLib obj
164 (objMesh,objscale) <- uploadOBJToGPU (Just workarea) obj 168 ((objMesh,curveData),objscale) <- uploadOBJToGPU (Just workarea) obj
165 putStrLn $ "Using object scale:\n" ++ show objscale 169 putStrLn $ "Using object scale:\n" ++ show objscale
166 -- load materials textures 170 -- load materials textures
167 gpuMtlLib <- uploadMtlLib mtlLib 171 gpuMtlLib <- uploadMtlLib mtlLib
@@ -172,6 +176,36 @@ stateChangeMesh obj mm storage st = do
172 addToGroupsPane (mmListStore mm) True groupname 176 addToGroupsPane (mmListStore mm) True groupname
173 writeIORef (stObjects st) bufs 177 writeIORef (stObjects st) bufs
174 writeIORef (stMasks st) $ map (objSpan . maskableObject) bufs 178 writeIORef (stMasks st) $ map (objSpan . maskableObject) bufs
179 forM_ (take 1 $ curves curveData) $ \c -> do
180 let mn = minimum $ curvePoints c
181 mx = maximum $ curvePoints c
182 bs = decomposeCurve (curvePt curveData) c
183 mapM_ (putStrLn . show) bs
184 clearRing (stRingBuffer st)
185 forM_ bs $ \(BezierSegment [a,b,c,d]) -> do
186 let cv = Bezier.Curve Nothing (vecLocation a)
187 (vecLocation b)
188 (vecLocation c)
189 (vecLocation d)
190 Nothing
191 δ = 0.005 -- TODO
192 range = Polygonization
193 { curveBufferID = error "curveBufferID"
194 , curveStartIndex = 0
195 , curveSegmentCount = ringCapacity (stRingBuffer st)
196 }
197 r <- subdivideCurve δ cv range $ \_ _ v -> do
198 RingBuffer.pushBack (stRingBuffer st) $ \RingPoint{..} -> do
199 rpPosition @<- v
200 rpColor @<- yellow
201 putStrLn $ "Subdivided "++show (curveSegmentCount r)++" poly-lines."
202 return ()
203 {-
204 RingBuffer.pushBack (stRingBuffer st) $ \RingPoint{..} -> do
205 rpPosition @<- V3 0 0 (0::Float)
206 rpColor @<- red -}
207 return ()
208 putStrLn $ "Returning from stateChangeMesh."
175 return st 209 return st
176 210
177initializeState :: MeshSketch -> GLStorage -> IO State 211initializeState :: MeshSketch -> GLStorage -> IO State
@@ -321,7 +355,7 @@ loadInitialMesh kont = do
321 objName <- head . (++ ["cube.obj"]) <$> getArgs 355 objName <- head . (++ ["cube.obj"]) <$> getArgs
322 putStrLn $ "Loading object "++objName++"..." 356 putStrLn $ "Loading object "++objName++"..."
323 mobj <- loadOBJ objName 357 mobj <- loadOBJ objName
324 putStrLn $ "Finisehd loading object "++objName++"." 358 putStrLn $ "Finished loading object "++objName++"."
325 kont mobj 359 kont mobj
326 360
327new :: IO Gtk.Paned 361new :: IO Gtk.Paned