{-# LANGUAGE CPP #-}
{-# LANGUAGE TypeSynonymInstances, FlexibleInstances, ScopedTypeVariables, EmptyDataDecls, TypeFamilies, GADTs #-}
module Graphics.GPipe.Internal.PrimitiveArray where
import Graphics.GPipe.Internal.Buffer
import Graphics.GPipe.Internal.Shader
#if __GLASGOW_HASKELL__ < 804
import Data.Semigroup
#endif
import Data.Monoid hiding ((<>))
import Data.IORef
import Data.Word
import Graphics.GL.Core33
import Graphics.GL.Types
data VertexArray t a = VertexArray {
vertexArrayLength :: Int,
vertexArraySkip :: Int,
bArrBFunc:: BInput -> a
}
data Instances
newVertexArray :: Buffer os a -> Render os (VertexArray t a)
newVertexArray buffer = Render $ return $ VertexArray (bufferLength buffer) 0 $ bufBElement buffer
instance Functor (VertexArray t) where
fmap f (VertexArray n s g) = VertexArray n s (f . g)
zipVertices :: (a -> b -> c) -> VertexArray t a -> VertexArray t' b -> VertexArray (Combine t t') c
zipVertices h (VertexArray n s f) (VertexArray m t g) = VertexArray (min n m) totSkip newArrFun
where totSkip = min s t
newArrFun x = let baseSkip = bInSkipElems x - totSkip in h (f x { bInSkipElems = baseSkip + s}) (g x { bInSkipElems = baseSkip + t})
type family Combine t t' where
Combine () Instances = Instances
Combine Instances () = Instances
Combine Instances Instances = Instances
Combine () () = ()
takeVertices :: Int -> VertexArray t a -> VertexArray t a
takeVertices n (VertexArray l s f) = VertexArray (min (max n 0) l) s f
dropVertices :: Int -> VertexArray () a -> VertexArray t a
dropVertices n (VertexArray l s f) = VertexArray (l - n') (s+n') f
where
n' = min (max n 0) l
replicateEach :: Int -> VertexArray t a -> VertexArray Instances a
replicateEach n (VertexArray m s f) = VertexArray (n*m) s (\x -> f $ x {bInInstanceDiv = bInInstanceDiv x * n})
type family IndexFormat a where
IndexFormat (B Word32) = Word32
IndexFormat (BPacked Word16) = Word16
IndexFormat (BPacked Word8) = Word8
data IndexArray = IndexArray {
iArrName :: IORef GLuint,
indexArrayLength:: Int,
offset:: Int,
restart:: Maybe Int,
indexType :: GLuint
}
newIndexArray :: forall os f b a. (BufferFormat b, Integral a, IndexFormat b ~ a) => Buffer os b -> Maybe a -> Render os IndexArray
newIndexArray buf r = let a = undefined :: b in Render $ return $ IndexArray (bufName buf) (bufferLength buf) 0 (fmap fromIntegral r) (getGlType a)
takeIndices :: Int -> IndexArray -> IndexArray
takeIndices n i = i { indexArrayLength = min (max n 0) (indexArrayLength i) }
dropIndices :: Int -> IndexArray -> IndexArray
dropIndices n i = i { indexArrayLength = l - n', offset = offset i + n' }
where
l = indexArrayLength i
n' = min (max n 0) l
data Triangles
data Lines
data Points
data PrimitiveTopology p where
TriangleList :: PrimitiveTopology Triangles
TriangleStrip :: PrimitiveTopology Triangles
TriangleFan :: PrimitiveTopology Triangles
LineList :: PrimitiveTopology Lines
LineStrip :: PrimitiveTopology Lines
LineLoop :: PrimitiveTopology Lines
PointList :: PrimitiveTopology Points
toGLtopology :: PrimitiveTopology p -> GLuint
toGLtopology TriangleList = GL_TRIANGLES
toGLtopology TriangleStrip = GL_TRIANGLE_STRIP
toGLtopology TriangleFan = GL_TRIANGLE_FAN
toGLtopology LineList = GL_LINES
toGLtopology LineStrip = GL_LINE_STRIP
toGLtopology LineLoop = GL_LINE_LOOP
toGLtopology PointList = GL_POINTS
type InstanceCount = Int
type BaseVertex = Int
data PrimitiveArrayInt p a = PrimitiveArraySimple (PrimitiveTopology p) Int BaseVertex a
| PrimitiveArrayIndexed (PrimitiveTopology p) IndexArray BaseVertex a
| PrimitiveArrayInstanced (PrimitiveTopology p) InstanceCount Int BaseVertex a
| PrimitiveArrayIndexedInstanced (PrimitiveTopology p) IndexArray InstanceCount BaseVertex a
newtype PrimitiveArray p a = PrimitiveArray {getPrimitiveArray :: [PrimitiveArrayInt p a]}
instance Semigroup (PrimitiveArray p a) where
PrimitiveArray a <> PrimitiveArray b = PrimitiveArray (a ++ b)
instance Monoid (PrimitiveArray p a) where
mempty = PrimitiveArray []
#if __GLASGOW_HASKELL__ < 804
mappend = (<>)
#endif
instance Functor (PrimitiveArray p) where
fmap f (PrimitiveArray xs) = PrimitiveArray $ fmap g xs
where g (PrimitiveArraySimple p l s a) = PrimitiveArraySimple p l s (f a)
g (PrimitiveArrayIndexed p i s a) = PrimitiveArrayIndexed p i s (f a)
g (PrimitiveArrayInstanced p il l s a) = PrimitiveArrayInstanced p il l s (f a)
g (PrimitiveArrayIndexedInstanced p i il s a) = PrimitiveArrayIndexedInstanced p i il s (f a)
toPrimitiveArray :: PrimitiveTopology p -> VertexArray () a -> PrimitiveArray p a
toPrimitiveArray p va = PrimitiveArray [PrimitiveArraySimple p (vertexArrayLength va) (vertexArraySkip va) (bArrBFunc va (BInput 0 0))]
toPrimitiveArrayIndexed :: PrimitiveTopology p -> IndexArray -> VertexArray () a -> PrimitiveArray p a
toPrimitiveArrayIndexed p ia va = PrimitiveArray [PrimitiveArrayIndexed p ia (vertexArraySkip va) (bArrBFunc va (BInput 0 0))]
toPrimitiveArrayInstanced :: PrimitiveTopology p -> (a -> b -> c) -> VertexArray () a -> VertexArray t b -> PrimitiveArray p c
toPrimitiveArrayInstanced p f va ina = PrimitiveArray [PrimitiveArrayInstanced p (vertexArrayLength ina) (vertexArrayLength va) (vertexArraySkip va) (f (bArrBFunc va $ BInput 0 0) (bArrBFunc ina $ BInput (vertexArraySkip ina) 1))]
toPrimitiveArrayIndexedInstanced :: PrimitiveTopology p -> IndexArray -> (a -> b -> c) -> VertexArray () a -> VertexArray t b -> PrimitiveArray p c
toPrimitiveArrayIndexedInstanced p ia f va ina = PrimitiveArray [PrimitiveArrayIndexedInstanced p ia (vertexArrayLength ina) (vertexArraySkip va) (f (bArrBFunc va $ BInput 0 0) (bArrBFunc ina $ BInput (vertexArraySkip ina) 1))]