packages feed

Box3D-0.1.0.0: src/Box3D/Mesh.hsc

{-# LANGUAGE ForeignFunctionInterface #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}

-- Produced by boxnd-gen; edit the generator, not this file.

module Box3D.Mesh
  ( Mesh (..)
  , MeshData (..)
  , MeshTriangle (..)
  , MeshEdgeFlags (..)
  , pattern ConcaveEdge1
  , pattern ConcaveEdge2
  , pattern ConcaveEdge3
  , pattern InverseConcaveEdge1
  , pattern InverseConcaveEdge2
  , pattern InverseConcaveEdge3
  , pattern AllConcaveEdges
  , pattern FlatEdge1
  , pattern FlatEdge2
  , pattern FlatEdge3
  , pattern AllFlatEdges
  , MeshDef (..)
  , create
  , destroy
  )
  where

import Foreign
import Foreign.C.Types (CBool (..), CInt (..))
import Box3D.MathTypes (AABB, Vec3)

#include "box3d/box3d.h"


-- | This allows mesh data to be re-used with different scales.
data Mesh = Mesh
  { data_ :: Ptr MeshData
  -- ^ Immutable pointer to the mesh data.
  , scale :: Vec3
  -- ^ This scale may be non-uniform and have negative components. However,
  -- no component may be very small in magnitude.
  }
  deriving (Eq, Show)

instance Storable Mesh where
  sizeOf _ = #{size b3Mesh}
  alignment _ = #{alignment b3Mesh}
  peek p =
    Mesh
      <$> #{peek b3Mesh, data} p
      <*> #{peek b3Mesh, scale} p
  poke p (Mesh f1 f2) = do
    #{poke b3Mesh, data} p f1
    #{poke b3Mesh, scale} p f2

{- | This is a sorted triangle collision bounding volume hierarchy.

__Note:__ This struct has data hanging off the end and cannot be directly copied.
-}
data MeshData = MeshData
  { version :: Word64
  -- ^ Version must be first.
  , hash :: Word64
  -- ^ Hash of this mesh (this field is zero when the hash is computed)
  , byteCount :: Int32
  -- ^ The total number of bytes for this mesh.
  , bounds :: AABB
  -- ^ Local axis-aligned box.
  , surfaceArea :: Float
  -- ^ Combined surface area of all triangles. Single-sided.
  , treeHeight :: Int32
  -- ^ The height of the bounding volume hierarchy.
  , degenerateCount :: Int32
  -- ^ The number of degenerate triangles. Diagnostic.
  , nodeOffset :: Int32
  -- ^ Offset of the node array in bytes from the struct address.
  , nodeCount :: Int32
  -- ^ The number of BVH nodes.
  , vertexOffset :: Int32
  -- ^ Offset of the vertex array in bytes from the struct address.
  , vertexCount :: Int32
  -- ^ The number of vertices.
  , triangleOffset :: Int32
  -- ^ Offset of the triangle array in bytes from the struct address.
  , triangleCount :: Int32
  -- ^ The number of triangles.
  , materialOffset :: Int32
  -- ^ Offset of the material array in bytes from the struct address.
  , materialCount :: Int32
  -- ^ The number of materials.
  , flagsOffset :: Int32
  -- ^ Offset of the triangle flag array in bytes from the struct address.
  , padding :: Int32
  -- ^ Explicit padding.
  }
  deriving (Eq, Show)

instance Storable MeshData where
  sizeOf _ = #{size b3MeshData}
  alignment _ = #{alignment b3MeshData}
  peek p =
    MeshData
      <$> #{peek b3MeshData, version} p
      <*> #{peek b3MeshData, hash} p
      <*> #{peek b3MeshData, byteCount} p
      <*> #{peek b3MeshData, bounds} p
      <*> #{peek b3MeshData, surfaceArea} p
      <*> #{peek b3MeshData, treeHeight} p
      <*> #{peek b3MeshData, degenerateCount} p
      <*> #{peek b3MeshData, nodeOffset} p
      <*> #{peek b3MeshData, nodeCount} p
      <*> #{peek b3MeshData, vertexOffset} p
      <*> #{peek b3MeshData, vertexCount} p
      <*> #{peek b3MeshData, triangleOffset} p
      <*> #{peek b3MeshData, triangleCount} p
      <*> #{peek b3MeshData, materialOffset} p
      <*> #{peek b3MeshData, materialCount} p
      <*> #{peek b3MeshData, flagsOffset} p
      <*> #{peek b3MeshData, padding} p
  poke p (MeshData f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12 f13 f14 f15 f16 f17) = do
    #{poke b3MeshData, version} p f1
    #{poke b3MeshData, hash} p f2
    #{poke b3MeshData, byteCount} p f3
    #{poke b3MeshData, bounds} p f4
    #{poke b3MeshData, surfaceArea} p f5
    #{poke b3MeshData, treeHeight} p f6
    #{poke b3MeshData, degenerateCount} p f7
    #{poke b3MeshData, nodeOffset} p f8
    #{poke b3MeshData, nodeCount} p f9
    #{poke b3MeshData, vertexOffset} p f10
    #{poke b3MeshData, vertexCount} p f11
    #{poke b3MeshData, triangleOffset} p f12
    #{poke b3MeshData, triangleCount} p f13
    #{poke b3MeshData, materialOffset} p f14
    #{poke b3MeshData, materialCount} p f15
    #{poke b3MeshData, flagsOffset} p f16
    #{poke b3MeshData, padding} p f17

-- | A mesh triangle.
data MeshTriangle = MeshTriangle
  { index1 :: Int32
  -- ^ Index of vertex 1.
  , index2 :: Int32
  -- ^ Index of vertex 2.
  , index3 :: Int32
  -- ^ Index of vertex 3.
  }
  deriving (Eq, Show)

instance Storable MeshTriangle where
  sizeOf _ = #{size b3MeshTriangle}
  alignment _ = #{alignment b3MeshTriangle}
  peek p =
    MeshTriangle
      <$> #{peek b3MeshTriangle, index1} p
      <*> #{peek b3MeshTriangle, index2} p
      <*> #{peek b3MeshTriangle, index3} p
  poke p (MeshTriangle f1 f2 f3) = do
    #{poke b3MeshTriangle, index1} p f1
    #{poke b3MeshTriangle, index2} p f2
    #{poke b3MeshTriangle, index3} p f3

-- | Triangle mesh edge flags.
newtype MeshEdgeFlags = MeshEdgeFlags CInt
  deriving (Eq, Show, Storable)

pattern ConcaveEdge1 :: MeshEdgeFlags
pattern ConcaveEdge2 :: MeshEdgeFlags
pattern ConcaveEdge3 :: MeshEdgeFlags
pattern InverseConcaveEdge1 :: MeshEdgeFlags
pattern InverseConcaveEdge2 :: MeshEdgeFlags
pattern InverseConcaveEdge3 :: MeshEdgeFlags
pattern AllConcaveEdges :: MeshEdgeFlags
pattern FlatEdge1 :: MeshEdgeFlags
pattern FlatEdge2 :: MeshEdgeFlags
pattern FlatEdge3 :: MeshEdgeFlags
pattern AllFlatEdges :: MeshEdgeFlags
pattern ConcaveEdge1 = MeshEdgeFlags #{const b3_concaveEdge1}
pattern ConcaveEdge2 = MeshEdgeFlags #{const b3_concaveEdge2}
pattern ConcaveEdge3 = MeshEdgeFlags #{const b3_concaveEdge3}
pattern InverseConcaveEdge1 = MeshEdgeFlags #{const b3_inverseConcaveEdge1}
pattern InverseConcaveEdge2 = MeshEdgeFlags #{const b3_inverseConcaveEdge2}
pattern InverseConcaveEdge3 = MeshEdgeFlags #{const b3_inverseConcaveEdge3}
pattern AllConcaveEdges = MeshEdgeFlags #{const b3_allConcaveEdges}
pattern FlatEdge1 = MeshEdgeFlags #{const b3_flatEdge1}
pattern FlatEdge2 = MeshEdgeFlags #{const b3_flatEdge2}
pattern FlatEdge3 = MeshEdgeFlags #{const b3_flatEdge3}
pattern AllFlatEdges = MeshEdgeFlags #{const b3_allFlatEdges}

{- | This is used to create a re-usable collision mesh. No pointers
are held to this data in @b3MeshData@. So all this data can be temporary.
-}
data MeshDef = MeshDef
  { vertices :: Ptr Vec3
  -- ^ Triangle vertices.
  , indices :: Ptr ()
  -- ^ Triangle vertex indices. 3 for each triangle. CCW winding.
  , materialIndices :: Ptr ()
  -- ^ Triangle material index. 1 per triangle. Indexes into @b3ShapeDef::materials@.
  -- This allows different run-time material data to be associated with different
  -- instances of this mesh.
  , weldTolerance :: Float
  -- ^ Tolerance for vertex welding in length units.
  , vertexCount :: CInt
  -- ^ The vertex count. Must be 3 or more.
  , triangleCount :: CInt
  -- ^ The triangle count. Must be 1 or more.
  , weldVertices :: CBool
  -- ^ Optionally weld nearby vertices.
  , useMedianSplit :: CBool
  -- ^ Use the median split instead of SAH to speed up mesh creation. Good
  -- for meshes that are structured like a grid.
  , identifyEdges :: CBool
  -- ^ Compute triangle adjacency information using shared edges
  }
  deriving (Eq, Show)

instance Storable MeshDef where
  sizeOf _ = #{size b3MeshDef}
  alignment _ = #{alignment b3MeshDef}
  peek p =
    MeshDef
      <$> #{peek b3MeshDef, vertices} p
      <*> #{peek b3MeshDef, indices} p
      <*> #{peek b3MeshDef, materialIndices} p
      <*> #{peek b3MeshDef, weldTolerance} p
      <*> #{peek b3MeshDef, vertexCount} p
      <*> #{peek b3MeshDef, triangleCount} p
      <*> #{peek b3MeshDef, weldVertices} p
      <*> #{peek b3MeshDef, useMedianSplit} p
      <*> #{peek b3MeshDef, identifyEdges} p
  poke p (MeshDef f1 f2 f3 f4 f5 f6 f7 f8 f9) = do
    #{poke b3MeshDef, vertices} p f1
    #{poke b3MeshDef, indices} p f2
    #{poke b3MeshDef, materialIndices} p f3
    #{poke b3MeshDef, weldTolerance} p f4
    #{poke b3MeshDef, vertexCount} p f5
    #{poke b3MeshDef, triangleCount} p f6
    #{poke b3MeshDef, weldVertices} p f7
    #{poke b3MeshDef, useMedianSplit} p f8
    #{poke b3MeshDef, identifyEdges} p f9


foreign import ccall unsafe "b3CreateMesh"
  c_b3CreateMesh :: Ptr MeshDef -> Ptr CInt -> CInt -> IO (Ptr MeshData)

foreign import ccall unsafe "b3DestroyMesh"
  c_b3DestroyMesh :: Ptr MeshData -> IO ()

{- | Create a generic mesh.

Binds @b3CreateMesh@.
-}
create
  :: Ptr MeshDef
  -> Ptr CInt
  -- ^ @degenerateTriangleIndices@
  -> Int
  -- ^ @degenerateCapacity@
  -> IO (Ptr MeshData)
create a0 a1 a2 =
  c_b3CreateMesh a0 a1 (fromIntegral a2)

{- | Destroy a mesh.

Binds @b3DestroyMesh@.
-}
destroy
  :: Ptr MeshData
  -> IO ()
destroy a0 =
  c_b3DestroyMesh a0