module Shader.Poke ( pokeVerxs -- , pokeSPics , pokeLayVerxs , pokeArrayOff -- , pokePoint33s , pokeShape , pokeShape' , pokeWallsWindowsFloor ) where import Shader.Data import Shader.Parameters import Picture.Data import Shape.Data import Geometry.Data --import ShapePicture import Graphics.Rendering.OpenGL hiding (color,scale,translate,rotate) import Foreign import qualified Data.Vector as V import qualified Data.Vector.Unboxed as UV import qualified Data.Vector.Unboxed.Mutable as UMV import qualified Data.Vector.Mutable as MV --import Data.Vector.Fusion.Util import Control.Monad.Primitive --import qualified Control.Monad.Parallel as MP import qualified Streaming.Prelude as S import Streaming pokeVerxs :: MV.MVector (PrimState IO) FullShader -> UMV.MVector (PrimState IO) Int -> Picture -> IO () pokeVerxs vbos count = S.mapM_ (pokeVerx vbos count) . S.each pokeVerx :: MV.MVector (PrimState IO) FullShader -> UMV.MVector (PrimState IO) Int -> Verx -> IO () pokeVerx vbos offsets Verx{_vxPos=thePos,_vxCol=theCol,_vxExt=ext,_vxShadNum=theShadNum} = do typeOff <- UMV.unsafeRead offsets sn basePtr <- _vboPtr . _vaoVBO . _shadVAO <$> MV.unsafeRead vbos sn let thePtr = plusPtr basePtr (typeOff * pokeStride sn * floatSize) poke34 thePtr thePos theCol pokeArrayOff thePtr 7 ext UMV.unsafeModify offsets (+1) sn where sn = _unShadNum theShadNum pokeWallsWindowsFloor :: Ptr Float -> Ptr Float -> Ptr Float -> [ ( (Point2,Point2) , Point4 ) ] -> [ ( (Point2,Point2) , Point4 ) ] -> [ ( Point3 , Point3 ) ] -> IO (Int,Int,Int) pokeWallsWindowsFloor wlptr wiptr flptr wls wis fls = do wlcounts1 <- S.foldM_ (pokeW wlptr) (return 0) return (S.each wls) wlcounts2 <- S.foldM_ (pokeW wiptr) (return 0) return (S.each wis) flcounts <- S.foldM_ (pokeF flptr) (return 0) return (S.each fls) return (wlcounts1,wlcounts2,flcounts) pokeF :: Ptr Float -> Int -> (Point3,Point3) -> IO Int pokeF ptr i' (V3 a b c,V3 d e f) = do let i = i' * 6 pokeElemOff ptr (i + 0) a pokeElemOff ptr (i + 1) b pokeElemOff ptr (i + 2) c pokeElemOff ptr (i + 3) d pokeElemOff ptr (i + 4) e pokeElemOff ptr (i + 5) f return $ i' + 1 pokeW :: Ptr Float -> Int -> ((Point2,Point2),Point4) -> IO Int pokeW ptr i' ((V2 a b,V2 c d),V4 e f g h) = do let i = i' * 8 pokeElemOff ptr (i + 0) a pokeElemOff ptr (i + 1) b pokeElemOff ptr (i + 2) c pokeElemOff ptr (i + 3) d pokeElemOff ptr (i + 4) e pokeElemOff ptr (i + 5) f pokeElemOff ptr (i + 6) g pokeElemOff ptr (i + 7) h return $ i' + 1 --pokeSPics -- :: MV.MVector (PrimState IO) FullShader -- -> UMV.MVector (PrimState IO) Int -- -> Ptr Float -> Ptr GLushort -> Ptr GLushort -- -> Stream (Of SPic) IO () -- -> IO (Int,Int,Int) --pokeSPics vbos counts ptr iptr ieptr = -- S.foldM_ (\is (sh,pic) -> pokeLayVerxs vbos counts pic >> pokeShape' ptr iptr ieptr is sh) -- (return (0,0,0)) return pokeShape :: Ptr Float -> Ptr GLushort -> Ptr GLushort -> Stream (Of ShapeObj) IO () -> IO (Int,Int,Int) pokeShape ptr iptr ieptr = S.foldM_ (pokeShapeObj ptr iptr ieptr) (return (0,0,0)) return --pokeShape' :: Ptr Float -> Ptr GLushort -> Ptr GLushort -- -> (Int,Int,Int) -- -> Stream (Of ShapeObj) IO () -- -> IO (Int,Int,Int) --pokeShape' ptr iptr ieptr is = S.foldM_ (pokeShapeObj ptr iptr ieptr) (return is) return -- pokeShape' :: Ptr Float -> Ptr GLushort -> Ptr GLushort -> (Int,Int,Int) -> [ShapeObj] -> IO (Int,Int,Int) pokeShape' ptr iptr ieptr is = S.foldM_ (pokeShapeObj ptr iptr ieptr) (return is) return . S.each pokeShapeObj :: Ptr Float -> Ptr GLushort -> Ptr GLushort -> (Int,Int,Int) -> ShapeObj -> IO (Int,Int,Int) {-# INLINE pokeShapeObj #-} pokeShapeObj ptr iptr ieptr counts (ShapeObj shtype shVerts) = case shtype of TopPrism size -> pokeTopPrism (size - 2) ptr iptr ieptr counts (S.each shVerts) pokeTopPrism :: Int -> Ptr Float -> Ptr GLushort -> Ptr GLushort -> (Int,Int,Int) -> Stream (Of ShapeV) IO () -> IO (Int,Int,Int) {-# INLINE pokeTopPrism #-} pokeTopPrism size ptr iptr ieptr (nv,nshapeindices,nedgeindices) svs = do nv' <- S.foldM_ (pokeJustV ptr) (return nv) return svs nshapeindices' <- UV.foldM' (pokeTopPrismIndex nv iptr) nshapeindices (memoTopPrismIndices V.! size) nedgeindices' <- UV.foldM' (pokeTopPrismEdgeIndex nv ieptr) nedgeindices (memoTopPrismEdgeIndices V.! size) return (nv', nshapeindices', nedgeindices') pokeTopPrismEdgeIndex :: Int -> Ptr GLushort -> Int -> Int -> IO Int --{-# INLINE pokeTopPrismEdgeIndex #-} pokeTopPrismEdgeIndex nv eiptr nedgeindices ioff = do pokeElemOff eiptr nedgeindices (fromIntegral $ nv + ioff) return $ nedgeindices + 1 pokeTopPrismIndex :: Int -> Ptr GLushort -> Int -> Int -> IO Int --{-# INLINE pokeTopPrismIndex #-} pokeTopPrismIndex nv iptr nshapeindices ioff = do pokeElemOff iptr nshapeindices (fromIntegral $ nv + ioff) return $ nshapeindices + 1 memoTopPrismEdgeIndices :: V.Vector (UV.Vector Int) memoTopPrismEdgeIndices = V.generate 10 $ UV.fromList . topPrismEdgeIndices . (+ 2) memoTopPrismIndices :: V.Vector (UV.Vector Int) memoTopPrismIndices = V.generate 10 $ UV.fromList . topPrismIndices . (+ 2) topPrismEdgeIndices :: Int -> [Int] topPrismEdgeIndices n = concatMap f [0..n-1] where f i = map g [ 0 , 2 , 1 , 4 , 0 , 1 ,-2 , 3 , 1 , 3 ,-1 , 2 ] where g j = (2 * i + j) `mod` (2*n) topPrismIndices :: Int -> [Int] topPrismIndices n = concatMap f [1..n-2] -- triangles on top face ++ concatMap f' [1..n-2] -- triangles on bottom face -- these should be checked ++ [2*n-2,2*n-1,1 ,2*n-2,1,0] -- last side triangle (applies mod 2n) ++ concatMap g [0..n-2] -- other triangles on sides where f x = [0,2*x,2*x+2] f' x = [1,2*x+3,2*x+1] g x = [2*x,2*x+1,2*x+3 ,2*x,2*x+3,2*x+2] pokeJustV :: Ptr Float -> Int -> ShapeV -> IO Int --{-# INLINE pokeJustV #-} pokeJustV ptr nv sh = do -- pokeArray (advancePtr ptr (off 0)) [a,b,c,d,e,f,g] pokeElemOff ptr (off 0) a pokeElemOff ptr (off 1) b pokeElemOff ptr (off 2) c pokeElemOff ptr (off 3) d pokeElemOff ptr (off 4) e pokeElemOff ptr (off 5) f pokeElemOff ptr (off 6) g return (nv + 1) where off i = nv*7 + i V3 a b c = _svPos sh V4 d e f g = _svCol sh pokeLayVerxs :: MV.MVector (PrimState IO) FullShader -> UMV.MVector (PrimState IO) Int -> Picture -> IO () pokeLayVerxs vbos counts = S.mapM_ (pokeLayVerx vbos counts) . S.each pokeLayVerx :: MV.MVector (PrimState IO) FullShader -> UMV.MVector (PrimState IO) Int -> Verx -> IO () --{-# INLINE pokeLayVerx #-} pokeLayVerx vbos counts vx = do theOff <- UMV.unsafeRead counts vecPos basePtr <- _vboPtr . _vaoVBO . _shadVAO <$> MV.unsafeRead vbos sn let thePtr = plusPtr basePtr ((theOff + layOff) * theStride * floatSize) poke34 thePtr thePos theCol pokeArrayOff thePtr 7 (_vxExt vx) UMV.unsafeModify counts (+ 1) vecPos where sn = _unShadNum (_vxShadNum vx) vecPos = theLayer * numLayers + sn theLayer = layerNum $ _vxLayer vx thePos = _vxPos vx theCol = _vxCol vx layOff = theLayer * numSubElements theStride = pokeStride sn pokeStride :: Int -> Int {-# INLINE pokeStride #-} pokeStride 0 = 7 pokeStride 1 = 8 pokeStride 2 = 11 pokeStride 3 = 9 pokeStride 4 = 10 pokeStride 5 = 7 pokeStride _ = undefined poke34 :: Ptr Float -> Point3 -> Point4 -> IO () {-# INLINE poke34 #-} poke34 ptr (V3 a b c) (V4 d e f g) = do pokeElemOff ptr 0 a pokeElemOff ptr 1 b pokeElemOff ptr 2 c pokeElemOff ptr 3 d pokeElemOff ptr 4 e pokeElemOff ptr 5 f pokeElemOff ptr 6 g pokeArrayOff :: Ptr Float -> Int -> [Float] -> IO () {-# INLINE pokeArrayOff #-} pokeArrayOff ptr i = pokeArray (plusPtr ptr (floatSize * i)) --pokePoint33s :: Ptr Float -> [(Point3,Point3)] -> IO Int --pokePoint33s ptr = S.foldM_ (pokePoint33 ptr) (return 0) return . S.each --pokePoint33 :: Ptr Float -> Int -> (Point3,Point3) -> IO Int --pokePoint33 ptr n (V3 a b c,V3 d e f) = do -- pokeElemOff ptr (off 0) a -- pokeElemOff ptr (off 1) b -- pokeElemOff ptr (off 2) c -- pokeElemOff ptr (off 3) d -- pokeElemOff ptr (off 4) e -- pokeElemOff ptr (off 5) f -- return (n+1) -- where -- off i = n*6 + i