flaw-bullet/Flaw/Physics/Bullet.hs
{-|
Module: Flaw.Physics.Bullet
Description: Bullet Physics.
License: MIT
-}
{-# LANGUAGE TypeFamilies #-}
module Flaw.Physics.Bullet
( BulletWorld(..)
, initBulletWorld
) where
import Data.Coerce
import qualified Data.Vector.Generic as VG
import Foreign.C.Types
import Foreign.Marshal.Alloc
import Foreign.Marshal.Array
import Foreign.Marshal.Utils
import Foreign.Ptr
import Foreign.Storable
import Flaw.Math
import Flaw.Math.Transform
import Flaw.Physics
newtype BulletWorld = BulletWorld (Ptr C_BulletWorld)
instance World BulletWorld where
newtype Shape BulletWorld = BulletShape (Ptr C_btCollisionShape)
newtype Body BulletWorld = BulletBody (Ptr C_BulletRigidBody)
newtype Ghost BulletWorld = BulletGhost (Ptr C_BulletGhost)
newtype Character BulletWorld = BulletCharacter (Ptr C_BulletCharacter)
createBoxShape (BulletWorld pWorld) halfSize = do
pShape <- with halfSize $ \halfSizePtr -> flaw_bullet_newBoxShape pWorld (castPtr halfSizePtr)
return (BulletShape pShape, flaw_bullet_freeShape pShape)
createSphereShape (BulletWorld pWorld) radius = do
pShape <- flaw_bullet_newSphereShape pWorld (coerce radius)
return (BulletShape pShape, flaw_bullet_freeShape pShape)
createConvexHullShape (BulletWorld pWorld) points = do
pShape <- allocaArray (VG.length points) $ \pPoints -> do
VG.imapM_ (pokeElemOff pPoints) points
flaw_bullet_newConvexHullShape pWorld (castPtr pPoints) (fromIntegral $ VG.length points)
return (BulletShape pShape, flaw_bullet_freeShape pShape)
createBody (BulletWorld pWorld) (BulletShape pShape) motion (QuatOffset (FloatQ orientation) position) = do
let
mass = case motion of
MotionStatic -> 0
MotionDynamic m -> m
pBody <- with position $ \positionPtr -> with orientation $ \orientationPtr ->
flaw_bullet_newRigidBody pWorld pShape (castPtr positionPtr) (castPtr orientationPtr) (coerce mass)
return (BulletBody pBody, flaw_bullet_freeRigidBody pWorld pBody)
getBodyTransform _ (BulletBody pBody) = alloca $ \positionPtr -> alloca $ \orientationPtr -> do
flaw_bullet_getRigidBodyTransform pBody positionPtr orientationPtr
position <- peek $ castPtr positionPtr
orientation <- peek $ castPtr orientationPtr
return $ QuatOffset (FloatQ orientation) position
createGhost (BulletWorld pWorld) (BulletShape pShape) (QuatOffset (FloatQ orientation) position) = do
pGhost <- with position $ \positionPtr -> with orientation $ \orientationPtr -> flaw_bullet_newGhost pWorld pShape (castPtr positionPtr) (castPtr orientationPtr)
return (BulletGhost pGhost, flaw_bullet_freeGhost pWorld pGhost)
setGhostTransform (BulletWorld pWorld) (BulletGhost pGhost) (QuatOffset (FloatQ orientation) position) =
with position $ \positionPtr -> with orientation $ \orientationPtr -> flaw_bullet_setGhostTransform pWorld pGhost (castPtr positionPtr) (castPtr orientationPtr)
createCharacter (BulletWorld pWorld) (BulletShape pShape) maxStepHeight (QuatOffset (FloatQ orientation) position) = do
pCharacter <- with position $ \positionPtr -> with orientation $ \orientationPtr -> flaw_bullet_newCharacter pWorld pShape (coerce maxStepHeight) (castPtr positionPtr) (castPtr orientationPtr)
return (BulletCharacter pCharacter, flaw_bullet_freeCharacter pWorld pCharacter)
walkCharacter (BulletWorld pWorld) (BulletCharacter pCharacter) movement =
with movement $ \movementPtr -> flaw_bullet_walkCharacter pWorld pCharacter (castPtr movementPtr)
getCharacterTransform _ (BulletCharacter pCharacter) = alloca $ \positionPtr -> alloca $ \orientationPtr -> do
flaw_bullet_getCharacterTransform pCharacter positionPtr orientationPtr
position <- peek $ castPtr positionPtr
orientation <- peek $ castPtr orientationPtr
return $ QuatOffset (FloatQ orientation) position
simulateWorld (BulletWorld pWorld) stepTime substepTime = flaw_bullet_stepWorld pWorld (coerce stepTime) (coerce substepTime)
initBulletWorld :: IO (BulletWorld, IO ())
initBulletWorld = do
pWorld <- flaw_bullet_newWorld
return (BulletWorld pWorld, flaw_bullet_freeWorld pWorld)
data C_BulletWorld
data C_btCollisionShape
data C_BulletRigidBody
data C_BulletGhost
data C_BulletCharacter
foreign import ccall safe flaw_bullet_newWorld :: IO (Ptr C_BulletWorld)
foreign import ccall safe flaw_bullet_freeWorld :: Ptr C_BulletWorld -> IO ()
foreign import ccall safe flaw_bullet_newBoxShape :: Ptr C_BulletWorld -> Ptr CFloat -> IO (Ptr C_btCollisionShape)
foreign import ccall safe flaw_bullet_newSphereShape :: Ptr C_BulletWorld -> CFloat -> IO (Ptr C_btCollisionShape)
foreign import ccall safe flaw_bullet_newConvexHullShape :: Ptr C_BulletWorld -> Ptr CFloat -> CInt -> IO (Ptr C_btCollisionShape)
foreign import ccall safe flaw_bullet_freeShape :: Ptr C_btCollisionShape -> IO ()
foreign import ccall safe flaw_bullet_newRigidBody :: Ptr C_BulletWorld -> Ptr C_btCollisionShape -> Ptr CFloat -> Ptr CFloat -> CFloat -> IO (Ptr C_BulletRigidBody)
foreign import ccall safe flaw_bullet_freeRigidBody :: Ptr C_BulletWorld -> Ptr C_BulletRigidBody -> IO ()
foreign import ccall unsafe flaw_bullet_getRigidBodyTransform :: Ptr C_BulletRigidBody -> Ptr CFloat -> Ptr CFloat -> IO ()
foreign import ccall safe flaw_bullet_newGhost :: Ptr C_BulletWorld -> Ptr C_btCollisionShape -> Ptr CFloat -> Ptr CFloat -> IO (Ptr C_BulletGhost)
foreign import ccall safe flaw_bullet_freeGhost :: Ptr C_BulletWorld -> Ptr C_BulletGhost -> IO ()
foreign import ccall safe flaw_bullet_newCharacter :: Ptr C_BulletWorld -> Ptr C_btCollisionShape -> CFloat -> Ptr CFloat -> Ptr CFloat -> IO (Ptr C_BulletCharacter)
foreign import ccall safe flaw_bullet_freeCharacter :: Ptr C_BulletWorld -> Ptr C_BulletCharacter -> IO ()
foreign import ccall unsafe flaw_bullet_walkCharacter :: Ptr C_BulletWorld -> Ptr C_BulletCharacter -> Ptr CFloat -> IO ()
foreign import ccall unsafe flaw_bullet_getCharacterTransform :: Ptr C_BulletCharacter -> Ptr CFloat -> Ptr CFloat -> IO ()
foreign import ccall unsafe flaw_bullet_setGhostTransform :: Ptr C_BulletWorld -> Ptr C_BulletGhost -> Ptr CFloat -> Ptr CFloat -> IO ()
foreign import ccall safe flaw_bullet_stepWorld :: Ptr C_BulletWorld -> CFloat -> CFloat -> IO ()