{-| Module : Graphics.Rendering.Handa.Shape Copyright : (c) 2015 Brian W Bush License : MIT Maintainer : Brian W Bush Stability : Stable Portability : Portable Functions and types for managing shapes represented as vertex buffer objects (VBOs). -} {-# LANGUAGE RecordWildCards #-} module Graphics.Rendering.Handa.Shape ( -- * Types Shape -- * Functions , makeShape , remakeShape , drawShape ) where import Data.Array.Storable (newListArray, withStorableArray) import Foreign.Ptr (nullPtr) import Foreign.Storable (Storable, sizeOf) import Graphics.Rendering.OpenGL (DataType, BufferObject, BufferTarget(ArrayBuffer), BufferUsage(StaticDraw), Capability(..), ClientArrayType(VertexArray), NumArrayIndices, NumComponents, PrimitiveMode, Stride, VertexArrayDescriptor(..), ($=), arrayPointer, bindBuffer, bufferData, drawArrays, clientState, genObjectNames) -- | A shape stored as a vertex buffer object (VBO). data Shape = Shape { vbo :: BufferObject -- ^ The handle to the vertex buffer object. , components :: NumComponents -- ^ The number of components for the shape's vertices. , dataType :: DataType -- ^ The data type of the shape's vertices. , stride :: Stride -- ^ The stride, the number of components between consecutive vertices. , size :: NumArrayIndices -- ^ The number of vertices. , mode :: PrimitiveMode -- ^ The type of primitive. , priorAction :: IO () -- ^ The display action to be executed prior to rendering the shape. } -- | Construct a shape. makeShape :: Storable a => NumComponents -- ^ The number of components per vertex. -> DataType -- ^ The data type for the vertices' components. -> PrimitiveMode -- ^ The type of primitive. -> [a] -- ^ The vertices. -> IO () -- ^ The display action to be executed prior to rendering the shape. -> IO Shape -- ^ An action for the shape. makeShape components dataType mode vertices priorAction = let stride = undefined size = undefined in do vbo <- head <$> genObjectNames 1 remakeShape Shape{..} vertices -- | Reconstruct a shape by replacing its vertices. remakeShape :: Storable a => Shape -- ^ The shape. -> [a] -- ^ The replacement vertices. -> IO Shape -- ^ An action for the updated shape. remakeShape shape@Shape{..} vertices = let n = length vertices m = if null vertices then 0 else sizeOf $ head vertices ptrSize = toEnum $ n * m in do bindBuffer ArrayBuffer $= Just vbo vertices' <- newListArray (0, n - 1) vertices withStorableArray vertices' $ \ptr -> bufferData ArrayBuffer $= (ptrSize, ptr, StaticDraw) bindBuffer ArrayBuffer $= Nothing return $ shape {size = toEnum n, stride = toEnum m} -- | Render a shape. drawShape :: Shape -- ^ The shape. -> IO () -- ^ An action to render the shape, also executing its prior actions before rendering it. drawShape Shape{..} = do clientState VertexArray $= Enabled bindBuffer ArrayBuffer $= Just vbo arrayPointer VertexArray $= VertexArrayDescriptor components dataType stride nullPtr priorAction drawArrays mode 0 size bindBuffer ArrayBuffer $= Nothing clientState VertexArray $= Disabled