diff --git a/Examples/BulletExample.hs b/Examples/BulletExample.hs
new file mode 100644
--- /dev/null
+++ b/Examples/BulletExample.hs
@@ -0,0 +1,338 @@
+import Control.Monad
+import Control.Concurrent.MVar
+import System.Exit
+import Graphics.UI.GLUT
+import Graphics.Rendering.OpenGL
+import Graphics.Rendering.OpenGL.GL.CoordTrans
+import Unsafe.Coerce -- because realToFrac just doesn't cut it...
+
+import Physics.Bullet
+import Foreign hiding (rotate)
+
+timerFrequencyMillis  ::  Timeout
+timerFrequencyMillis  =   1
+
+data BCube = BCube (GLfloat,GLfloat,GLfloat,PlRigidBodyHandle,(GLfloat,GLfloat,GLfloat,GLfloat))
+
+data State = State {
+      dworld     ::  PlDynamicsWorldHandle,
+      cubes      ::  [BCube],
+      viewAngle  ::  MVar GLfloat,
+      viewHeight ::  MVar GLfloat,
+      paused     ::  MVar Bool
+    }
+
+createBCube dw ((x,y,z), (w,h,d), m, col) = do
+  shape <- plNewBoxShape w h d
+  b <- plCreateRigidBody Foreign.nullPtr m shape
+  plAddRigidBody dw b
+  plSetPosition b (x,y,z)
+  return $ BCube (unsafeCoerce w,unsafeCoerce h,unsafeCoerce d,b,col)
+
+lightPosition = Vertex4 5 20 10 0
+
+lightPositionDeltas = map calcDelta [0..lightSteps-1]
+    where  Vertex4 lxo lyo lzo _ = lightPosition
+           calcDelta l = (lightSize*(lx1*sin ll+lx2*cos ll),
+                          lightSize*(ly1*sin ll+ly2*cos ll),
+                          lightSize*(lz1*sin ll+lz2*cos ll))
+               where  ll = 2*pi*l/lightSteps
+                      ll1 = sqrt (lxo*lxo+lzo*lzo)
+                      (lx1,ly1,lz1) = (lzo/ll1,0,-lxo/ll1)
+                      ll2 = sqrt (lxo*lxo*lyo*lyo+(lxo*lxo+lzo*lzo)*(lxo*lxo+lzo*lzo)+lzo*lzo*lyo*lyo)
+                      (lx2,ly2,lz2) = (-lxo*lyo/ll2,(lxo*lxo+lzo*lzo)/ll2,-lzo*lyo/ll2)
+
+lightSteps = 8
+lightSize = 0.3
+
+camDistance = 8
+
+makeState  ::  IO State
+makeState  =   do
+  sdk <- plNewBulletSdk
+  dw <- plCreateDynamicsWorld sdk
+  ang <- newMVar 0
+  h <- newMVar (-6)
+  p <- newMVar False
+
+  -- set up bullet scene
+  cs <- mapM (createBCube dw) $ [
+             ((0,-0.1,0), (50.0,0.1,50.0), 0, (0.9,0.9,0.9,1)),
+             ((4,15,-0.5), (1,1,1), 10, blue)
+             ]
+               ++ map (\x -> ((-5+x*0.5,0.5+10-abs(x-10),0), (0.5,0.5,0.5), 1, green)) [0..20]
+               ++ map (\x -> let h = min 4.5 (5-abs(x-5)) in ((-5+x,h,0), (0.1,h,0.1), 2, yellow)) [1..9]
+
+  return $ State {
+               dworld = dw,
+               cubes = cs,
+               viewAngle = ang,
+               viewHeight = h,
+               paused = p
+             }
+
+    where  green = (0,1,0,1)
+           yellow = (1,1,0,1)
+           blue = (0,0,1,1)
+
+display        ::  State -> DisplayCallback
+display state  =   do
+  loadIdentity
+  height <- readMVar $ viewHeight state
+  rotate (-atan ((height+3)/camDistance)*180/pi) (Vector3 1 0 (0 :: GLfloat))
+  translate (Vector3 0 height (-camDistance))
+  angle <- readMVar $ viewAngle state
+  rotate angle (Vector3 0 1 0)
+
+  scale (1 :: GLfloat) 1 1
+
+  position (Light 0) $= lightPosition
+
+  let cs = cubes state
+
+  -- draw fully lit scene
+  clear [ColorBuffer, DepthBuffer]
+  cullFace $= Just Back
+
+  forM_ cs $ \(BCube (w,h,d,body,(r,g,b,a))) -> do
+    materialDiffuse Front $= Color4 r g b a
+    preservingMatrix $ do
+      -- get position and orientation of body
+      (e0,e1,e2,e3,e4,e5,e6,e7,e8,e9,eA,eB,eC,eD,eE,eF) <- plGetOpenGLMatrix body
+      let f = unsafeCoerce
+      m <- newMatrix ColumnMajor $ [f e0,f e1,f e2,f e3,f e4,f e5,f e6,f e7,f e8,f e9,f eA,f eB,f eC,f eD,f eE,f eF]
+      -- set position and orientation of gl modelview matrix
+      multMatrix (m :: GLmatrix GLfloat)
+      drawCube w h d
+
+  -- settings needed for casting
+  depthMask $= Disabled
+  stencilTest $= Enabled
+
+  forM_ lightPositionDeltas $ \lpd -> do
+    -- generate shadow volumes (note that they are open-ended!)
+    svs <- forM (tail cs) $ \(BCube (w,h,d,body,_)) -> do
+      (px,py,pz) <- plGetPosition body
+      (ox,oy,oz,ow) <- plGetOrientation body
+      return $ (body, cubeShadow lpd (-unsafeCoerce px,-unsafeCoerce py,-unsafeCoerce pz) (unsafeCoerce ow,-unsafeCoerce ox,-unsafeCoerce oy,-unsafeCoerce oz) w h d)
+
+    renderShadows svs
+
+  -- restore settings
+  stencilTest $= Disabled
+  depthMask $= Enabled
+
+  flush
+  swapBuffers
+
+renderShadows svs = do
+  -- increment stencil for the front faces of shadow volumes
+  lighting $= Disabled
+  colorMask $= Color4 Disabled Disabled Disabled Disabled
+  stencilFunc $= (Always, 0, 0)
+  stencilOp $= (OpKeep, OpKeep, OpIncrWrap)
+  drawShadowVolumes svs
+
+  -- decrement stencil for the back faces of shadow volumes
+  cullFace $= Just Front
+  stencilOp $= (OpKeep, OpKeep, OpDecrWrap)
+  drawShadowVolumes svs
+
+  -- apply shadow using the stencil buffer
+  colorMask $= Color4 Enabled Enabled Enabled Enabled
+  depthFunc $= Just Less
+  stencilOp $= (OpZero, OpZero, OpZero)
+  stencilFunc $= (Less, 0, 0xffffffff)
+  lighting $= Enabled
+  cullFace $= Just Back
+  blend $= Enabled
+  blendFunc $= (SrcAlpha, OneMinusSrcAlpha)
+
+  materialDiffuse Front $= Color4 0 0 0 (0.4/lightSteps)
+  preservingMatrix $ do
+    loadIdentity
+    renderPrimitive TriangleStrip $ do
+      vertex $ Vertex3 (-10)   10  (-1 :: GLfloat)
+      vertex $ Vertex3 (-10) (-10) (-1 :: GLfloat)
+      vertex $ Vertex3   10    10  (-1 :: GLfloat)
+      vertex $ Vertex3   10  (-10) (-1 :: GLfloat)
+
+  blend $= Disabled
+
+drawShadowVolumes svs =
+  forM_ svs $ \(body,vs) -> do
+    preservingMatrix $ do
+      -- get position and orientation of body
+      (e0,e1,e2,e3,e4,e5,e6,e7,e8,e9,eA,eB,eC,eD,eE,eF) <- plGetOpenGLMatrix body
+      let f = unsafeCoerce
+      m <- newMatrix ColumnMajor $ [f e0,f e1,f e2,f e3,f e4,f e5,f e6,f e7,f e8,f e9,f eA,f eB,f eC,f eD,f eE,f eF]
+      -- set position and orientation of gl modelview matrix
+      multMatrix (m :: GLmatrix GLfloat)
+      renderPrimitive Quads $ forM_ vs $ \(p1,p2,p3,p4) -> do
+        vertex p1
+        vertex p2
+        vertex p3
+        vertex p4
+
+keyboard                            ::  State -> KeyboardMouseCallback
+keyboard state key keyState mods _  =   do
+  case (key, keyState) of
+    (Char 'q', Down) -> exitWith ExitSuccess
+    (Char '\27', Down) -> exitWith ExitSuccess
+    --(Char 't', Down) -> modelCycle state $~ tail
+    --(SpecialKey KeyHome, Down) -> resetState state
+    (SpecialKey KeyLeft, Down) -> do
+                       angle <- takeMVar $ viewAngle state
+                       putMVar (viewAngle state) (angle+2)
+    (SpecialKey KeyRight, Down) -> do
+                       angle <- takeMVar $ viewAngle state
+                       putMVar (viewAngle state) (angle-2)
+    (SpecialKey KeyUp, Down) -> do
+                       height <- takeMVar $ viewHeight state
+                       putMVar (viewHeight state) (height-0.2)
+    (SpecialKey KeyDown, Down) -> do
+                       height <- takeMVar $ viewHeight state
+                       putMVar (viewHeight state) (height+0.2)
+    (Char 'p', Down) -> do
+                       isPaused <- takeMVar $ paused state
+                       putMVar (paused state) (not isPaused)
+    (_, _) -> return ()
+
+reshape                  ::  ReshapeCallback
+reshape size@(Size w h)  =   do
+  let  vp = 0.8
+       aspect = fromIntegral w / fromIntegral h
+
+  viewport $= (Position 0 0, size)
+
+  matrixMode $= Projection
+  loadIdentity
+  frustum (-vp) vp (-vp / aspect) (vp / aspect) 1 1000
+
+  matrixMode $= Modelview 0
+  loadIdentity
+  translate (Vector3 0 0 (-5 :: GLfloat))
+
+timer        ::  State -> TimerCallback
+timer state  =   do
+  addTimerCallback timerFrequencyMillis (timer state)
+  isPaused <- readMVar $ paused state
+  when (not isPaused) $ plStepSimulation (dworld state) (fromIntegral(timerFrequencyMillis))
+  postRedisplay Nothing
+
+drawFace            ::  Normal3 GLfloat -> Vertex3 GLfloat -> Vertex3 GLfloat
+                        -> Vertex3 GLfloat -> Vertex3 GLfloat -> IO ()
+drawFace p q r s t  =   do
+  let texCoord2f = texCoord :: TexCoord2 GLfloat -> IO ()
+  normal p
+  texCoord2f (TexCoord2 1 1)
+  vertex q
+  texCoord2f (TexCoord2 0 1)
+  vertex r
+  texCoord2f (TexCoord2 0 0)
+  vertex s
+  texCoord2f (TexCoord2 1 0)
+  vertex t
+
+drawCube                    ::  GLfloat -> GLfloat -> GLfloat -> IO ()
+drawCube sx sy sz  =   do
+  let  a = Vertex3   sx    sy    sz
+       b = Vertex3   sx    sy  (-sz)
+       c = Vertex3   sx  (-sy) (-sz)
+       d = Vertex3   sx  (-sy)   sz
+       e = Vertex3 (-sx)   sy    sz
+       f = Vertex3 (-sx)   sy  (-sz)
+       g = Vertex3 (-sx) (-sy) (-sz)
+       h = Vertex3 (-sx) (-sy)   sz
+
+       i = Normal3   1    0    0
+       k = Normal3 (-1)   0    0
+       l = Normal3   0    0  (-1)
+       m = Normal3   0    0    1
+       n = Normal3   0    1    0
+       o = Normal3   0  (-1)   0
+
+  renderPrimitive Quads $ do
+    drawFace i d c b a
+    drawFace k g h e f
+    drawFace l c g f b
+    drawFace m h d a e
+    drawFace n e a b f
+    drawFace o g c d h
+
+cubeShadow (ldx,ldy,ldz) (x,y,z) (a,b,c,d) sx sy sz =
+    map shadowFace $ filter shouldCast edges
+    where  [oxx,oxy,oxz,oyx,oyy,oyz,ozx,ozy,ozz] =
+               [a*a+b*b-c*c-d*d, 2*(b*c-a*d), 2*(a*c+b*d),
+                2*(a*d+b*c), a*a-b*b+c*c-d*d, 2*(c*d-a*b),
+                2*(b*d-a*c), 2*(a*b+c*d), a*a-b*b-c*c+d*d]
+
+           Vertex4 lxo lyo lzo _ = lightPosition
+           (lxt,lyt,lzt) = (lxo+ldx+x,lyo+ldy+y,lzo+ldz+z)
+           (lx,ly,lz) = (lxt*oxx+lyt*oxy+lzt*oxz,
+                         lxt*oyx+lyt*oyy+lzt*oyz,
+                         lxt*ozx+lyt*ozy+lzt*ozz)
+
+           ni = lx > sx
+           nk = lx < (-sx)
+           nl = lz < (-sz)
+           nm = lz > sz
+           nn = ly > sy
+           no = ly < (-sy)
+
+           va = ( sx, sy, sz)
+           vb = ( sx, sy,-sz)
+           vc = ( sx,-sy,-sz)
+           vd = ( sx,-sy, sz)
+           ve = (-sx, sy, sz)
+           vf = (-sx, sy,-sz)
+           vg = (-sx,-sy,-sz)
+           vh = (-sx,-sy, sz)
+
+           edges = [(vd,vc,ni,no),(vc,vb,ni,nl),(vb,va,ni,nn),(va,vd,ni,nm),
+                    (vg,vh,nk,no),(vf,vg,nk,nl),(ve,vf,nk,nn),(vh,ve,nk,nm),
+                    (vc,vg,nl,no),(vf,vb,nl,nn),(vh,vd,nm,no),(va,ve,nm,nn)]
+
+           shouldCast (_,_,c1,c2) = (c1 && (not c2)) || (c2 && (not c1))
+
+           shadowFace ((v1x,v1y,v1z),(v2x,v2y,v2z),n1,n2) =
+               if n2 then
+                      (Vertex3 v1x v1y v1z, Vertex3 v2x v2y v2z,
+                       Vertex3 v3x v3y v3z, Vertex3 v4x v4y v4z)
+               else
+                      (Vertex3 v4x v4y v4z, Vertex3 v3x v3y v3z,
+                       Vertex3 v2x v2y v2z, Vertex3 v1x v1y v1z)
+               where  ss = 1000
+                      v3x = v2x+(v2x-lx)*ss
+                      v3y = v2y+(v2y-ly)*ss
+                      v3z = v2z+(v2z-lz)*ss
+                      v4x = v1x+(v1x-lx)*ss
+                      v4y = v1y+(v1y-ly)*ss
+                      v4z = v1z+(v1z-lz)*ss
+
+
+main = do
+  getArgsAndInitialize
+  initialDisplayMode $= [RGBMode, WithDepthBuffer, WithStencilBuffer, DoubleBuffered, Multisampling]
+  initialWindowSize $= Size 800 800
+  createWindow "Bullet Example"
+
+  state <- makeState
+  displayCallback $= display state
+  keyboardMouseCallback $= Just (keyboard state)
+  reshapeCallback $= Just reshape
+  addTimerCallback timerFrequencyMillis (timer state)
+
+  materialDiffuse Front $= Color4 1 0.3 0.2 1
+  materialSpecular Front $= Color4 0.3 0.3 0.3 1
+  materialShininess Front $= 16
+  lighting $= Enabled
+  light (Light 0) $= Enabled
+
+  depthFunc $= Just Less
+  clearColor $= Color4 0.0 0.0 0.0 1
+
+  clear [StencilBuffer]
+
+  mainLoop
+
diff --git a/Examples/bullet-example-1.png b/Examples/bullet-example-1.png
new file mode 100644
Binary files /dev/null and b/Examples/bullet-example-1.png differ
diff --git a/Examples/bullet-example-2.png b/Examples/bullet-example-2.png
new file mode 100644
Binary files /dev/null and b/Examples/bullet-example-2.png differ
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,28 @@
+Copyright (c) 2009, Csaba Hruska
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the author nor the names of its contributors may be
+   used to endorse or promote products derived from this software without
+   specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
diff --git a/Physics/Bullet.hs b/Physics/Bullet.hs
new file mode 100644
--- /dev/null
+++ b/Physics/Bullet.hs
@@ -0,0 +1,258 @@
+{-# CFILES cbits/bullet.c #-}  -- for Hugs (?)
+module Physics.Bullet (
+    PlQuaternion, PlVector3, PlRayCastResult, PlMatrix,
+    PlPhysicsSdkHandle, PlDynamicsWorldHandle, PlRigidBodyHandle, PlUserDataHandle, PlCollisionShapeHandle, PlMeshInterfaceHandle,
+    plNewBulletSdk, plDeletePhysicsSdk,
+--	plCreateSapBroadphase, plDestroyBroadphase,
+--	plCreateProxy, plDestroyProxy, plSetBoundingBox,
+--	plCreateCollisionWorld,
+    plCreateDynamicsWorld, plDeleteDynamicsWorld, plStepSimulation, plAddRigidBody, plRemoveRigidBody,
+    plCreateRigidBody, plDeleteRigidBody,
+    plNewSphereShape, plNewBoxShape, plNewCapsuleShape, plNewConeShape, plNewCylinderShape, plNewCompoundShape,
+
+    plAddChildShape, plDeleteShape, plNewConvexHullShape, plAddVertex, plNewMeshInterface,
+	plAddTriangle, plNewStaticTriangleMeshShape,plNewGimpactTriangleMeshShape,plNewConvexTriangleMeshShape,
+    plSetScaling, plGetOpenGLMatrix, plGetPosition, plGetOrientation, plSetPosition, plSetOrientation, plSetEuler
+--	plRayCast
+
+) where
+
+import Foreign
+import Foreign.C.Types
+import Foreign.Marshal.Array
+{-
+typedef float 	plVector3[3];
+typedef float 	plQuaternion[4];
+typedef float 	plVehicleTuning[5];
+
+typedef struct plRayCastResult {
+	plRigidBodyHandle		m_body;  
+	plCollisionShapeHandle	m_shape; 		
+	plVector3				m_positionWorld; 		
+	plVector3				m_normalWorld;
+} plRayCastResult;
+-}
+--plRayCastResult
+--type PlRayCastResult = Ptr ()
+data PlRayCastResult_ = PlRayCastResult_ PlRigidBodyHandle PlCollisionShapeHandle PlVector3 PlVector3
+type PlRayCastResult = Ptr PlRayCastResult_
+
+type PlQuaternion = Ptr CFloat
+
+type PlVector3 = Ptr CFloat
+
+type PlMatrix = Ptr CFloat
+
+type PlVehicleTuning = Ptr CFloat
+
+-----------------------------------------
+data PlPhysicsSdk = PlPhysicsSdk
+type PlPhysicsSdkHandle = Ptr PlPhysicsSdk
+
+data PlDynamicsWorld = PlDynamicsWorld
+type PlDynamicsWorldHandle = Ptr PlDynamicsWorld
+
+data PlRigidBody = PlRigidBody
+type PlRigidBodyHandle = Ptr PlRigidBody
+
+type PlUserDataHandle = Ptr ()
+
+data PlCollisionShape = PlCollisionShape
+type PlCollisionShapeHandle = Ptr PlCollisionShape
+
+data PlMeshInterface = PlMeshInterface
+type PlMeshInterfaceHandle = Ptr PlMeshInterface
+
+foreign import ccall unsafe "plNewBulletSdk"                plNewBulletSdk                  :: IO PlPhysicsSdkHandle
+foreign import ccall unsafe "plDeletePhysicsSdk"		    plDeletePhysicsSdk              :: PlPhysicsSdkHandle -> IO ()
+--foreign import ccall "plCreateSapBroadphase"              plCreateSapBroadphase           :: Ptr a -> Ptr a -> IO (Ptr a)
+--foreign import ccall "plDestroyBroadphase"                plDestroyBroadphase             :: Ptr a -> IO()
+--foreign import ccall "plCreateProxy"                      plCreateProxy                   :: Ptr a -> Ptr a -> CCFloat -> CCFloat -> CCFloat -> CCFloat -> CCFloat -> CCFloat -> IO( Ptr a )
+--foreign import ccall "plDestroyProxy"                     plDestroyProxy                  :: Ptr a -> Ptr a -> IO()
+--foreign import ccall "plSetBoundingBox"                   plSetBoundingBox                :: Ptr a -> CCFloat -> CCFloat -> CCFloat -> CCFloat -> CCFloat -> CCFloat -> IO()
+--foreign import ccall "plCreateCollisionWorld"             plCreateCollisionWorld          :: Ptr a -> IO( Ptr a )
+foreign import ccall unsafe "plCreateDynamicsWorld"         plCreateDynamicsWorld           :: PlPhysicsSdkHandle -> IO PlDynamicsWorldHandle
+foreign import ccall unsafe "plDeleteDynamicsWorld"         plDeleteDynamicsWorld           :: PlDynamicsWorldHandle -> IO ()
+foreign import ccall unsafe "plStepSimulation"              plStepSimulation                :: PlDynamicsWorldHandle -> CFloat -> IO ()
+foreign import ccall unsafe "plAddRigidBody"                plAddRigidBody                  :: PlDynamicsWorldHandle -> PlRigidBodyHandle -> IO ()
+foreign import ccall unsafe "plRemoveRigidBody"             plRemoveRigidBody               :: PlDynamicsWorldHandle -> PlRigidBodyHandle -> IO ()
+foreign import ccall unsafe "plCreateRigidBody"             plCreateRigidBody               :: PlUserDataHandle -> CFloat -> PlCollisionShapeHandle -> IO PlRigidBodyHandle
+foreign import ccall unsafe "plDeleteRigidBody"             plDeleteRigidBody               :: PlRigidBodyHandle -> IO ()
+foreign import ccall unsafe "plNewSphereShape"              plNewSphereShape                :: CFloat -> IO PlCollisionShapeHandle
+foreign import ccall unsafe "plNewBoxShape"                 plNewBoxShape                   :: CFloat -> CFloat -> CFloat -> IO PlCollisionShapeHandle
+foreign import ccall unsafe "plNewCapsuleShape"             plNewCapsuleShape               :: CFloat -> CFloat -> IO PlCollisionShapeHandle
+foreign import ccall unsafe "plNewConeShape"                plNewConeShape                  :: CFloat -> CFloat -> IO PlCollisionShapeHandle
+foreign import ccall unsafe "plNewCylinderShape"            plNewCylinderShape              :: CFloat -> CFloat -> IO PlCollisionShapeHandle
+foreign import ccall unsafe "plNewCompoundShape"            plNewCompoundShape              :: IO PlCollisionShapeHandle
+foreign import ccall unsafe "plAddChildShape"               plAddChildShape_                :: PlCollisionShapeHandle -> PlCollisionShapeHandle -> PlVector3 -> PlQuaternion -> IO ()
+foreign import ccall unsafe "plDeleteShape"                 plDeleteShape                   :: PlCollisionShapeHandle -> IO ()
+foreign import ccall unsafe "plNewConvexHullShape"          plNewConvexHullShape            :: Ptr CFloat -> Int -> Int -> IO PlCollisionShapeHandle
+
+foreign import ccall unsafe "plAddVertex"                   plAddVertex                     :: PlCollisionShapeHandle -> CFloat -> CFloat -> CFloat -> IO ()
+
+foreign import ccall unsafe "plNewMeshInterface"            plNewMeshInterface              :: IO PlMeshInterfaceHandle
+foreign import ccall unsafe "plAddTriangle"                 plAddTriangle_                  :: PlMeshInterfaceHandle -> PlVector3 -> PlVector3 -> PlVector3 -> Int -> IO ()
+foreign import ccall unsafe "plNewStaticTriangleMeshShape"  plNewStaticTriangleMeshShape    :: PlMeshInterfaceHandle -> IO PlCollisionShapeHandle
+foreign import ccall unsafe "plNewGimpactTriangleMeshShape" plNewGimpactTriangleMeshShape   :: PlMeshInterfaceHandle -> IO PlCollisionShapeHandle
+foreign import ccall unsafe "plNewConvexTriangleMeshShape"  plNewConvexTriangleMeshShape    :: PlMeshInterfaceHandle -> IO PlCollisionShapeHandle
+
+foreign import ccall unsafe "plSetScaling"                  plSetScaling_                   :: PlCollisionShapeHandle -> PlVector3 -> IO ()
+foreign import ccall unsafe "plGetOpenGLMatrix"             plGetOpenGLMatrix_              :: PlRigidBodyHandle -> PlMatrix -> IO ()
+foreign import ccall unsafe "plGetPosition"                 plGetPosition_                  :: PlRigidBodyHandle -> PlVector3 -> IO ()
+foreign import ccall unsafe "plGetOrientation"              plGetOrientation_               :: PlRigidBodyHandle -> PlQuaternion -> IO ()
+foreign import ccall unsafe "plSetPosition"                 plSetPosition_                  :: PlRigidBodyHandle -> PlVector3 -> IO ()
+foreign import ccall unsafe "plSetOrientation"              plSetOrientation_               :: PlRigidBodyHandle -> PlQuaternion -> IO ()
+foreign import ccall unsafe "plSetEuler"                    plSetEuler                      :: CFloat -> CFloat -> CFloat -> PlQuaternion -> IO ()
+foreign import ccall unsafe "plRayCast"                     plRayCast                       :: PlDynamicsWorldHandle -> PlVector3 -> PlVector3 -> PlRayCastResult -> IO Int
+
+-- TODO : new functions
+{-
+plCreateRaycastVehicle :: PlVehicleTuning -> PlRigidBodyHandle -> IO PlRaycastVehicleHandle
+plAddVehicle :: PlDynamicsWorldHandle -> PlRaycastVehicleHandle -> IO ()
+plSetCoordinateSystem :: PlRaycastVehicleHandle -> Int -> Int -> Int -> IO ()
+plAddWheel :: PlCFloat3 -> PlCFloat3 -> PlCFloat3 -> CFloat -> CFloat -> PlCFloat5 -> Bool -> IO (wheelinfo ????)
+
+
+	btRaycastVehicle::btVehicleTuning	m_tuning;
+	btVehicleRaycaster*	m_vehicleRayCaster;
+	btRaycastVehicle*	m_vehicle;
+	btCollisionShape*	m_wheelShape;
+
+	btWheelInfo&	addWheel( const btVector3& connectionPointCS0, const btVector3& wheelDirectionCS0,const btVector3& wheelAxleCS,btScalar suspensionRestLength,btScalar wheelRadius,const btVehicleTuning& tuning, bool isFrontWheel);
+
+	class btVehicleTuning
+		{
+			public:
+
+			btVehicleTuning()
+				:m_suspensionStiffness(btScalar(5.88)),
+				m_suspensionCompression(btScalar(0.83)),
+				m_suspensionDamping(btScalar(0.88)),
+				m_maxSuspensionTravelCm(btScalar(500.)),
+				m_frictionSlip(btScalar(10.5))
+			{
+			}
+			btScalar	m_suspensionStiffness;
+			btScalar	m_suspensionCompression;
+			btScalar	m_suspensionDamping;
+			btScalar	m_maxSuspensionTravelCm;
+			btScalar	m_frictionSlip;
+
+		};
+-}
+
+-- more nice wrappers
+plGetOpenGLMatrix body =
+    allocaArray 16 f
+  where
+    f p = do
+        plGetOpenGLMatrix_ body p
+        e0 <- peekElemOff p 0
+        e1 <- peekElemOff p 1
+        e2 <- peekElemOff p 2
+        e3 <- peekElemOff p 3
+        e4 <- peekElemOff p 4
+        e5 <- peekElemOff p 5
+        e6 <- peekElemOff p 6
+        e7 <- peekElemOff p 7
+        e8 <- peekElemOff p 8
+        e9 <- peekElemOff p 9
+        eA <- peekElemOff p 10
+        eB <- peekElemOff p 11
+        eC <- peekElemOff p 12
+        eD <- peekElemOff p 13
+        eE <- peekElemOff p 14
+        eF <- peekElemOff p 15
+        return (e0,e1,e2,e3,e4,e5,e6,e7,e8,e9,eA,eB,eC,eD,eE,eF)
+        --mapM (peekElemOff m) [0..15]
+
+packCFloat3 p (x,y,z) = do
+    pokeElemOff p 0  x 
+    pokeElemOff p 1  y
+    pokeElemOff p 2  z
+
+unpackCFloat3 p = do
+    x <- peekElemOff p 0
+    y <- peekElemOff p 1
+    z <- peekElemOff p 2
+    return (x,y,z)
+
+packCFloat4 p (x,y,z,w) = do
+    pokeElemOff p 0 x 
+    pokeElemOff p 1 y
+    pokeElemOff p 2 z
+    pokeElemOff p 3 w
+
+unpackCFloat4 p = do
+    x <- peekElemOff p 0
+    y <- peekElemOff p 1
+    z <- peekElemOff p 2
+    w <- peekElemOff p 3
+    return (x,y,z,w)
+
+packCFloat5 p (x,y,z,w,q) = do
+    pokeElemOff p 0 x 
+    pokeElemOff p 1 y
+    pokeElemOff p 2 z
+    pokeElemOff p 3 w
+    pokeElemOff p 4 q
+
+unpackCFloat5 p = do
+    x <- peekElemOff p 0
+    y <- peekElemOff p 1
+    z <- peekElemOff p 2
+    w <- peekElemOff p 3
+    q <- peekElemOff p 4
+    return (x,y,z,w,q)
+
+plGetPosition body =
+    allocaArray 3 f
+  where
+    f p = do
+        plGetPosition_ body p
+        unpackCFloat3 p
+
+plSetPosition b pos =
+    allocaArray 3 f
+  where
+    f p = do
+        packCFloat3 p pos
+        plSetPosition_ b p
+
+plGetOrientation body =
+    allocaArray 4 f
+  where
+    f p = do
+        plGetOrientation_ body p
+        unpackCFloat4 p
+
+plSetOrientation b o =
+    allocaArray 4 f
+  where
+    f p = do
+        packCFloat4 p o
+        plSetOrientation_ b p
+
+plAddChildShape compShape chShape chPos chOrig =
+    allocaArray 7 f
+  where
+    f p = do
+        packCFloat3 p chPos
+        packCFloat4 (advancePtr p 3) chOrig
+        plAddChildShape_ compShape chShape p (advancePtr p 3)
+
+plAddTriangle meshInterface v0 v1 v2 rmDup =
+    allocaArray 9 f
+  where
+    f p = do
+        packCFloat3 p v0
+        packCFloat3 (advancePtr p 3) v1
+        packCFloat3 (advancePtr p 6) v2
+        plAddTriangle_ meshInterface p (advancePtr p 3) (advancePtr p 6) $ if rmDup then 1 else 0
+
+plSetScaling shape v =
+    allocaArray 3 f
+  where
+    f p = do
+        packCFloat3 p v
+        plSetScaling_ shape p
diff --git a/README b/README
new file mode 100644
--- /dev/null
+++ b/README
@@ -0,0 +1,17 @@
+Compile:
+    - get bullet physics engine:
+        svn checkout http://bullet.googlecode.com/svn/trunk/ bullet-read-only
+
+    - compile and install the library:
+        cd bullet-read-only
+        cmake .
+        make
+        sudo make install
+
+    - compile and install the haskell bullet binding:
+        cabal install (run command in the bullet.cabal's directory)
+
+    - compile and run the example (needs OpenGL and GLUT):
+        cd Examples
+        ghc --make -O2 BulletExample
+        ./BulletExample
diff --git a/Setup.lhs b/Setup.lhs
new file mode 100644
--- /dev/null
+++ b/Setup.lhs
@@ -0,0 +1,4 @@
+#! /usr/bin/env runhaskell
+ 
+> import Distribution.Simple
+> main = defaultMain
diff --git a/bullet.cabal b/bullet.cabal
new file mode 100644
--- /dev/null
+++ b/bullet.cabal
@@ -0,0 +1,32 @@
+Name:                bullet
+Version:             0.1.1
+Synopsis:            A wrapper for the Bullet physics engine.
+Description:         A wrapper for the Bullet physics engine.
+License:             BSD3
+License-file:        LICENSE
+Author:              Csaba Hruska
+Maintainer:          csaba (dot) hruska (at) gmail (dot) com
+Homepage:            http://www.haskell.org/haskellwiki/Bullet
+Stability:           Experimental
+Category:            Physics
+Tested-With:         GHC == 6.10.1, GHC == 6.10.4
+Cabal-Version:       >= 1.2
+Build-Type:          Simple
+
+Extra-Source-Files:  cbits/bullet.h
+                     Examples/BulletExample.hs
+                     Examples/bullet-example-1.png
+                     Examples/bullet-example-2.png
+                     README
+
+Library
+  Build-Depends:       base >= 4 && < 5
+
+  Exposed-Modules:     Physics.Bullet
+
+  Hs-Source-Dirs:      .
+  Extensions:          ForeignFunctionInterface
+  Extra-Libraries:     BulletDynamics LinearMath BulletCollision
+
+  C-Sources:           cbits/bullet.cpp
+  Include-Dirs:        cbits
diff --git a/cbits/bullet.cpp b/cbits/bullet.cpp
new file mode 100644
--- /dev/null
+++ b/cbits/bullet.cpp
@@ -0,0 +1,436 @@
+/*
+Bullet Continuous Collision Detection and Physics Library C API modifications
+Copyright (c) 2009 Csaba Hruska
+
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "bullet.h"
+#include "btBulletDynamicsCommon.h"
+#include "LinearMath/btAlignedAllocator.h"
+
+
+
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btScalar.h"	
+#include "LinearMath/btMatrix3x3.h"
+#include "LinearMath/btTransform.h"
+#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
+#include "BulletCollision/CollisionShapes/btTriangleShape.h"
+
+#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h"
+#include "BulletCollision/NarrowPhaseCollision/btPointCollector.h"
+#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
+#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
+#include "BulletCollision/CollisionShapes/btMinkowskiSumShape.h"
+#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
+#include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h"
+#include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h"
+#include "LinearMath/btStackAlloc.h"
+
+#include "BulletCollision/Gimpact/btGImpactShape.h"
+#include "BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h"
+
+/*
+	Create and Delete a Physics SDK	
+*/
+
+struct	btPhysicsSdk
+{
+
+//	btDispatcher*				m_dispatcher;
+//	btOverlappingPairCache*		m_pairCache;
+//	btConstraintSolver*			m_constraintSolver
+
+	btVector3	m_worldAabbMin;
+	btVector3	m_worldAabbMax;
+
+
+	//todo: version, hardware/optimization settings etc?
+	btPhysicsSdk()
+		:m_worldAabbMin(-1000,-1000,-1000),
+		m_worldAabbMax(1000,1000,1000)
+	{
+
+	}
+
+	
+};
+
+plPhysicsSdkHandle	plNewBulletSdk()
+{
+	void* mem = btAlignedAlloc(sizeof(btPhysicsSdk),16);
+	return (plPhysicsSdkHandle)new (mem)btPhysicsSdk;
+}
+
+void		plDeletePhysicsSdk(plPhysicsSdkHandle	physicsSdk)
+{
+	btPhysicsSdk* phys = reinterpret_cast<btPhysicsSdk*>(physicsSdk);
+	btAlignedFree(phys);	
+}
+
+
+/* Dynamics World */
+plDynamicsWorldHandle plCreateDynamicsWorld(plPhysicsSdkHandle physicsSdkHandle)
+{
+	btPhysicsSdk* physicsSdk = reinterpret_cast<btPhysicsSdk*>(physicsSdkHandle);
+	void* mem = btAlignedAlloc(sizeof(btDefaultCollisionConfiguration),16);
+	btDefaultCollisionConfiguration* collisionConfiguration = new (mem)btDefaultCollisionConfiguration();
+	mem = btAlignedAlloc(sizeof(btCollisionDispatcher),16);
+	btCollisionDispatcher*      dispatcher = new (mem)btCollisionDispatcher(collisionConfiguration);
+	mem = btAlignedAlloc(sizeof(btAxisSweep3),16);
+	btBroadphaseInterface*		pairCache = new (mem)btAxisSweep3(physicsSdk->m_worldAabbMin,physicsSdk->m_worldAabbMax);
+	mem = btAlignedAlloc(sizeof(btSequentialImpulseConstraintSolver),16);
+	btConstraintSolver*			constraintSolver = new(mem) btSequentialImpulseConstraintSolver();
+
+    //register algorithm
+	btGImpactCollisionAlgorithm::registerAlgorithm(dispatcher);
+
+	mem = btAlignedAlloc(sizeof(btDiscreteDynamicsWorld),16);
+	return (plDynamicsWorldHandle) new (mem)btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver,collisionConfiguration);
+}
+void           plDeleteDynamicsWorld(plDynamicsWorldHandle world)
+{
+	//todo: also clean up the other allocations, axisSweep, pairCache,dispatcher,constraintSolver,collisionConfiguration
+	btDynamicsWorld* dynamicsWorld = reinterpret_cast< btDynamicsWorld* >(world);
+	btAlignedFree(dynamicsWorld);
+}
+
+void	plStepSimulation(plDynamicsWorldHandle world,	plReal	timeStep)
+{
+	btDynamicsWorld* dynamicsWorld = reinterpret_cast< btDynamicsWorld* >(world);
+	btAssert(dynamicsWorld);
+	dynamicsWorld->stepSimulation(timeStep);
+}
+
+void plAddRigidBody(plDynamicsWorldHandle world, plRigidBodyHandle object)
+{
+	btDynamicsWorld* dynamicsWorld = reinterpret_cast< btDynamicsWorld* >(world);
+	btAssert(dynamicsWorld);
+	btRigidBody* body = reinterpret_cast< btRigidBody* >(object);
+	btAssert(body);
+
+	dynamicsWorld->addRigidBody(body);
+}
+
+void plRemoveRigidBody(plDynamicsWorldHandle world, plRigidBodyHandle object)
+{
+	btDynamicsWorld* dynamicsWorld = reinterpret_cast< btDynamicsWorld* >(world);
+	btAssert(dynamicsWorld);
+	btRigidBody* body = reinterpret_cast< btRigidBody* >(object);
+	btAssert(body);
+
+	dynamicsWorld->removeRigidBody(body);
+}
+
+/* Rigid Body  */
+
+plRigidBodyHandle plCreateRigidBody(	void* user_data,  float mass, plCollisionShapeHandle cshape )
+{
+	btTransform trans;
+	trans.setIdentity();
+	btVector3 localInertia(0,0,0);
+	btCollisionShape* shape = reinterpret_cast<btCollisionShape*>( cshape);
+	btAssert(shape);
+	if (mass)
+	{
+		shape->calculateLocalInertia(mass,localInertia);
+	}
+	void* mem = btAlignedAlloc(sizeof(btRigidBody),16);
+	btRigidBody::btRigidBodyConstructionInfo rbci(mass, 0,shape,localInertia);
+	btRigidBody* body = new (mem)btRigidBody(rbci);
+	body->setWorldTransform(trans);
+	body->setUserPointer(user_data);
+	return (plRigidBodyHandle) body;
+}
+
+void plDeleteRigidBody(plRigidBodyHandle cbody)
+{
+	btRigidBody* body = reinterpret_cast< btRigidBody* >(cbody);
+	btAssert(body);
+	btAlignedFree( body);
+}
+
+
+/* Collision Shape definition */
+
+plCollisionShapeHandle plNewSphereShape(plReal radius)
+{
+	void* mem = btAlignedAlloc(sizeof(btSphereShape),16);
+	return (plCollisionShapeHandle) new (mem)btSphereShape(radius);
+	
+}
+	
+plCollisionShapeHandle plNewBoxShape(plReal x, plReal y, plReal z)
+{
+	void* mem = btAlignedAlloc(sizeof(btBoxShape),16);
+	return (plCollisionShapeHandle) new (mem)btBoxShape(btVector3(x,y,z));
+}
+
+plCollisionShapeHandle plNewCapsuleShape(plReal radius, plReal height)
+{
+	//capsule is convex hull of 2 spheres, so use btMultiSphereShape
+	
+	const int numSpheres = 2;
+	btVector3 positions[numSpheres] = {btVector3(0,height,0),btVector3(0,-height,0)};
+	btScalar radi[numSpheres] = {radius,radius};
+	void* mem = btAlignedAlloc(sizeof(btMultiSphereShape),16);
+	return (plCollisionShapeHandle) new (mem)btMultiSphereShape(positions,radi,numSpheres);
+}
+plCollisionShapeHandle plNewConeShape(plReal radius, plReal height)
+{
+	void* mem = btAlignedAlloc(sizeof(btConeShape),16);
+	return (plCollisionShapeHandle) new (mem)btConeShape(radius,height);
+}
+
+plCollisionShapeHandle plNewCylinderShape(plReal radius, plReal height)
+{
+	void* mem = btAlignedAlloc(sizeof(btCylinderShape),16);
+	return (plCollisionShapeHandle) new (mem)btCylinderShape(btVector3(radius,height,radius));
+}
+
+/* Convex Meshes */
+plCollisionShapeHandle plNewConvexHullShape()
+{
+	void* mem = btAlignedAlloc(sizeof(btConvexHullShape),16);
+	return (plCollisionShapeHandle) new (mem)btConvexHullShape();
+}
+
+
+/* Concave static triangle meshes */
+plMeshInterfaceHandle plNewMeshInterface()
+{
+	void* mem = btAlignedAlloc(sizeof(btTriangleMesh),16);
+	return (plMeshInterfaceHandle) new (mem)btTriangleMesh();
+}
+
+void plAddTriangle(plMeshInterfaceHandle meshHandle, plVector3 v0,plVector3 v1,plVector3 v2, int rmDup)
+{
+	btTriangleMesh* triangleMesh = reinterpret_cast<btTriangleMesh*>(meshHandle);
+    triangleMesh->addTriangle(btVector3(v0[0],v0[1],v0[2]),btVector3(v1[0],v1[1],v1[2]),btVector3(v2[0],v2[1],v2[2]),rmDup != 0);
+}
+
+plCollisionShapeHandle plNewStaticTriangleMeshShape(plMeshInterfaceHandle meshHandle)
+{
+	btTriangleMesh* triangleMesh = reinterpret_cast<btTriangleMesh*>(meshHandle);
+	void* mem = btAlignedAlloc(sizeof(btBvhTriangleMeshShape),16);
+	return (plCollisionShapeHandle) new (mem)btBvhTriangleMeshShape(triangleMesh,true);
+}
+
+plCollisionShapeHandle plNewGimpactTriangleMeshShape(plMeshInterfaceHandle meshHandle)
+{
+	btTriangleMesh* triangleMesh = reinterpret_cast<btTriangleMesh*>(meshHandle);
+	void* mem = btAlignedAlloc(sizeof(btGImpactMeshShape),16);
+    btGImpactMeshShape* trimesh = new (mem)btGImpactMeshShape(triangleMesh);
+	trimesh->updateBound();
+	return (plCollisionShapeHandle) mem;
+}
+
+plCollisionShapeHandle plNewConvexTriangleMeshShape(plMeshInterfaceHandle meshHandle)
+{
+	btTriangleMesh* triangleMesh = reinterpret_cast<btTriangleMesh*>(meshHandle);
+	void* mem = btAlignedAlloc(sizeof(btConvexTriangleMeshShape),16);
+	return (plCollisionShapeHandle) new (mem)btConvexTriangleMeshShape(triangleMesh);
+}
+
+plCollisionShapeHandle plNewCompoundShape()
+{
+	void* mem = btAlignedAlloc(sizeof(btCompoundShape),16);
+	return (plCollisionShapeHandle) new (mem)btCompoundShape();
+}
+
+void	plAddChildShape(plCollisionShapeHandle compoundShapeHandle,plCollisionShapeHandle childShapeHandle, plVector3 childPos,plQuaternion childOrn)
+{
+	btCollisionShape* colShape = reinterpret_cast<btCollisionShape*>(compoundShapeHandle);
+	btAssert(colShape->getShapeType() == COMPOUND_SHAPE_PROXYTYPE);
+	btCompoundShape* compoundShape = reinterpret_cast<btCompoundShape*>(colShape);
+	btCollisionShape* childShape = reinterpret_cast<btCollisionShape*>(childShapeHandle);
+	btTransform	localTrans;
+	localTrans.setIdentity();
+	localTrans.setOrigin(btVector3(childPos[0],childPos[1],childPos[2]));
+	localTrans.setRotation(btQuaternion(childOrn[0],childOrn[1],childOrn[2],childOrn[3]));
+	compoundShape->addChildShape(localTrans,childShape);
+}
+
+void plSetEuler(plReal yaw,plReal pitch,plReal roll, plQuaternion orient)
+{
+	btQuaternion orn;
+	orn.setEuler(yaw,pitch,roll);
+	orient[0] = orn.getX();
+	orient[1] = orn.getY();
+	orient[2] = orn.getZ();
+	orient[3] = orn.getW();
+
+}
+
+
+
+
+void		plAddVertex(plCollisionShapeHandle cshape, plReal x,plReal y,plReal z)
+{
+	btCollisionShape* colShape = reinterpret_cast<btCollisionShape*>( cshape);
+	(void)colShape;
+	btAssert(colShape->getShapeType()==CONVEX_HULL_SHAPE_PROXYTYPE);
+	btConvexHullShape* convexHullShape = reinterpret_cast<btConvexHullShape*>( cshape);
+	convexHullShape->addPoint(btVector3(x,y,z));
+
+}
+
+void plDeleteShape(plCollisionShapeHandle cshape)
+{
+	btCollisionShape* shape = reinterpret_cast<btCollisionShape*>( cshape);
+	btAssert(shape);
+	btAlignedFree(shape);
+}
+void plSetScaling(plCollisionShapeHandle cshape, plVector3 cscaling)
+{
+	btCollisionShape* shape = reinterpret_cast<btCollisionShape*>( cshape);
+	btAssert(shape);
+	btVector3 scaling(cscaling[0],cscaling[1],cscaling[2]);
+	shape->setLocalScaling(scaling);	
+}
+
+void plSetPosition(plRigidBodyHandle object, const plVector3 position)
+{
+	btRigidBody* body = reinterpret_cast< btRigidBody* >(object);
+	btAssert(body);
+	btVector3 pos(position[0],position[1],position[2]);
+	btTransform worldTrans = body->getWorldTransform();
+	worldTrans.setOrigin(pos);
+	body->setWorldTransform(worldTrans);
+}
+
+void plSetOrientation(plRigidBodyHandle object, const plQuaternion orientation)
+{
+	btRigidBody* body = reinterpret_cast< btRigidBody* >(object);
+	btAssert(body);
+	btQuaternion orn(orientation[0],orientation[1],orientation[2],orientation[3]);
+	btTransform worldTrans = body->getWorldTransform();
+	worldTrans.setRotation(orn);
+	body->setWorldTransform(worldTrans);
+}
+
+void	plSetOpenGLMatrix(plRigidBodyHandle object, plReal* matrix)
+{
+	btRigidBody* body = reinterpret_cast< btRigidBody* >(object);
+	btAssert(body);
+	btTransform& worldTrans = body->getWorldTransform();
+	worldTrans.setFromOpenGLMatrix(matrix);
+}
+
+void	plGetOpenGLMatrix(plRigidBodyHandle object, plReal* matrix)
+{
+	btRigidBody* body = reinterpret_cast< btRigidBody* >(object);
+	btAssert(body);
+	body->getWorldTransform().getOpenGLMatrix(matrix);
+
+}
+
+void	plGetPosition(plRigidBodyHandle object,plVector3 position)
+{
+	btRigidBody* body = reinterpret_cast< btRigidBody* >(object);
+	btAssert(body);
+	const btVector3& pos = body->getWorldTransform().getOrigin();
+	position[0] = pos.getX();
+	position[1] = pos.getY();
+	position[2] = pos.getZ();
+}
+
+void plGetOrientation(plRigidBodyHandle object,plQuaternion orientation)
+{
+	btRigidBody* body = reinterpret_cast< btRigidBody* >(object);
+	btAssert(body);
+	const btQuaternion& orn = body->getWorldTransform().getRotation();
+	orientation[0] = orn.getX();
+	orientation[1] = orn.getY();
+	orientation[2] = orn.getZ();
+	orientation[3] = orn.getW();
+}
+
+
+
+//plRigidBodyHandle plRayCast(plDynamicsWorldHandle world, const plVector3 rayStart, const plVector3 rayEnd, plVector3 hitpoint, plVector3 normal);
+
+//	extern  plRigidBodyHandle plObjectCast(plDynamicsWorldHandle world, const plVector3 rayStart, const plVector3 rayEnd, plVector3 hitpoint, plVector3 normal);
+
+double plNearestPoints(float p1[3], float p2[3], float p3[3], float q1[3], float q2[3], float q3[3], float *pa, float *pb, float normal[3])
+{
+	btVector3 vp(p1[0], p1[1], p1[2]);
+	btTriangleShape trishapeA(vp, 
+				  btVector3(p2[0], p2[1], p2[2]), 
+				  btVector3(p3[0], p3[1], p3[2]));
+	trishapeA.setMargin(0.000001f);
+	btVector3 vq(q1[0], q1[1], q1[2]);
+	btTriangleShape trishapeB(vq, 
+				  btVector3(q2[0], q2[1], q2[2]), 
+				  btVector3(q3[0], q3[1], q3[2]));
+	trishapeB.setMargin(0.000001f);
+	
+	// btVoronoiSimplexSolver sGjkSimplexSolver;
+	// btGjkEpaPenetrationDepthSolver penSolverPtr;	
+	
+	static btSimplexSolverInterface sGjkSimplexSolver;
+	sGjkSimplexSolver.reset();
+	
+	static btGjkEpaPenetrationDepthSolver Solver0;
+	static btMinkowskiPenetrationDepthSolver Solver1;
+		
+	btConvexPenetrationDepthSolver* Solver = NULL;
+	
+	Solver = &Solver1;	
+		
+	btGjkPairDetector convexConvex(&trishapeA ,&trishapeB,&sGjkSimplexSolver,Solver);
+	
+	convexConvex.m_catchDegeneracies = 1;
+	
+	// btGjkPairDetector convexConvex(&trishapeA ,&trishapeB,&sGjkSimplexSolver,0);
+	
+	btPointCollector gjkOutput;
+	btGjkPairDetector::ClosestPointInput input;
+	
+	btStackAlloc gStackAlloc(1024*1024*2);
+ 
+	input.m_stackAlloc = &gStackAlloc;
+	
+	btTransform tr;
+	tr.setIdentity();
+	
+	input.m_transformA = tr;
+	input.m_transformB = tr;
+	
+	convexConvex.getClosestPoints(input, gjkOutput, 0);
+	
+	
+	if (gjkOutput.m_hasResult)
+	{
+		
+		pb[0] = pa[0] = gjkOutput.m_pointInWorld[0];
+		pb[1] = pa[1] = gjkOutput.m_pointInWorld[1];
+		pb[2] = pa[2] = gjkOutput.m_pointInWorld[2];
+
+		pb[0]+= gjkOutput.m_normalOnBInWorld[0] * gjkOutput.m_distance;
+		pb[1]+= gjkOutput.m_normalOnBInWorld[1] * gjkOutput.m_distance;
+		pb[2]+= gjkOutput.m_normalOnBInWorld[2] * gjkOutput.m_distance;
+		
+		normal[0] = gjkOutput.m_normalOnBInWorld[0];
+		normal[1] = gjkOutput.m_normalOnBInWorld[1];
+		normal[2] = gjkOutput.m_normalOnBInWorld[2];
+
+		return gjkOutput.m_distance;
+	}
+	return -1.0f;	
+}
+
diff --git a/cbits/bullet.h b/cbits/bullet.h
new file mode 100644
--- /dev/null
+++ b/cbits/bullet.h
@@ -0,0 +1,174 @@
+/*
+Bullet Continuous Collision Detection and Physics Library C API modifications
+Copyright (c) 2009 Csaba Hruska
+
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BULLET_C_API_H
+#define BULLET_C_API_H
+
+#define PL_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name
+
+#ifdef BT_USE_DOUBLE_PRECISION
+typedef double	plReal;
+#else
+typedef float	plReal;
+#endif
+
+typedef plReal	plVector3[3];
+typedef plReal	plQuaternion[4];
+
+#ifdef __cplusplus
+extern "C" { 
+#endif
+
+/**	Particular physics SDK (C-API) */
+	PL_DECLARE_HANDLE(plPhysicsSdkHandle);
+
+/** 	Dynamics world, belonging to some physics SDK (C-API)*/
+	PL_DECLARE_HANDLE(plDynamicsWorldHandle);
+
+/** Rigid Body that can be part of a Dynamics World (C-API)*/	
+	PL_DECLARE_HANDLE(plRigidBodyHandle);
+
+/** 	Collision Shape/Geometry, property of a Rigid Body (C-API)*/
+	PL_DECLARE_HANDLE(plCollisionShapeHandle);
+
+/** Constraint for Rigid Bodies (C-API)*/
+	PL_DECLARE_HANDLE(plConstraintHandle);
+
+/** Triangle Mesh interface (C-API)*/
+	PL_DECLARE_HANDLE(plMeshInterfaceHandle);
+
+/** Broadphase Scene/Proxy Handles (C-API)*/
+	PL_DECLARE_HANDLE(plCollisionBroadphaseHandle);
+	PL_DECLARE_HANDLE(plBroadphaseProxyHandle);
+	PL_DECLARE_HANDLE(plCollisionWorldHandle);
+
+/**
+	Create and Delete a Physics SDK	
+*/
+
+	extern	plPhysicsSdkHandle	plNewBulletSdk(); //this could be also another sdk, like ODE, PhysX etc.
+	extern	void		plDeletePhysicsSdk(plPhysicsSdkHandle	physicsSdk);
+
+/** Collision World, not strictly necessary, you can also just create a Dynamics World with Rigid Bodies which internally manages the Collision World with Collision Objects */
+
+	typedef void(*btBroadphaseCallback)(void* clientData, void* object1,void* object2);
+
+	extern plCollisionBroadphaseHandle	plCreateSapBroadphase(btBroadphaseCallback beginCallback,btBroadphaseCallback endCallback);
+
+	extern void	plDestroyBroadphase(plCollisionBroadphaseHandle bp);
+
+	extern 	plBroadphaseProxyHandle plCreateProxy(plCollisionBroadphaseHandle bp, void* clientData, plReal minX,plReal minY,plReal minZ, plReal maxX,plReal maxY, plReal maxZ);
+
+	extern void plDestroyProxy(plCollisionBroadphaseHandle bp, plBroadphaseProxyHandle proxyHandle);
+
+	extern void plSetBoundingBox(plBroadphaseProxyHandle proxyHandle, plReal minX,plReal minY,plReal minZ, plReal maxX,plReal maxY, plReal maxZ);
+
+/* todo: add pair cache support with queries like add/remove/find pair */
+	
+	extern plCollisionWorldHandle plCreateCollisionWorld(plPhysicsSdkHandle physicsSdk);
+
+/* todo: add/remove objects */
+	
+
+/* Dynamics World */
+
+	extern  plDynamicsWorldHandle plCreateDynamicsWorld(plPhysicsSdkHandle physicsSdk);
+
+	extern  void           plDeleteDynamicsWorld(plDynamicsWorldHandle world);
+
+	extern	void	plStepSimulation(plDynamicsWorldHandle,	plReal	timeStep);
+
+	extern  void plAddRigidBody(plDynamicsWorldHandle world, plRigidBodyHandle object);
+
+	extern  void plRemoveRigidBody(plDynamicsWorldHandle world, plRigidBodyHandle object);
+
+
+/* Rigid Body  */
+
+	extern  plRigidBodyHandle plCreateRigidBody(	void* user_data,  float mass, plCollisionShapeHandle cshape );
+
+	extern  void plDeleteRigidBody(plRigidBodyHandle body);
+
+
+/* Collision Shape definition */
+
+	extern  plCollisionShapeHandle plNewSphereShape(plReal radius);
+	extern  plCollisionShapeHandle plNewBoxShape(plReal x, plReal y, plReal z);
+	extern  plCollisionShapeHandle plNewCapsuleShape(plReal radius, plReal height);	
+	extern  plCollisionShapeHandle plNewConeShape(plReal radius, plReal height);
+	extern  plCollisionShapeHandle plNewCylinderShape(plReal radius, plReal height);
+	extern	plCollisionShapeHandle plNewCompoundShape();
+	extern	void	plAddChildShape(plCollisionShapeHandle compoundShape,plCollisionShapeHandle childShape, plVector3 childPos,plQuaternion childOrn);
+
+	extern  void plDeleteShape(plCollisionShapeHandle shape);
+
+	/* Convex Meshes */
+    extern  plCollisionShapeHandle          plNewConvexHullShape();
+    extern  void                            plAddVertex(plCollisionShapeHandle convexHull, plReal x,plReal y,plReal z);
+    /* Concave static triangle meshes */
+    extern  plMeshInterfaceHandle           plNewMeshInterface();
+    extern  void                            plAddTriangle(plMeshInterfaceHandle meshHandle, plVector3 v0,plVector3 v1,plVector3 v2, int rmDup);
+    extern  plCollisionShapeHandle          plNewStaticTriangleMeshShape(plMeshInterfaceHandle);
+    extern  plCollisionShapeHandle          plNewGimpactTriangleMeshShape(plMeshInterfaceHandle);
+    extern  plCollisionShapeHandle          plNewConvexTriangleMeshShape(plMeshInterfaceHandle);
+
+	extern  void plSetScaling(plCollisionShapeHandle shape, plVector3 scaling);
+
+/* SOLID has Response Callback/Table/Management */
+/* PhysX has Triggers, User Callbacks and filtering */
+/* ODE has the typedef void dNearCallback (void *data, dGeomID o1, dGeomID o2); */
+
+/*	typedef void plUpdatedPositionCallback(void* userData, plRigidBodyHandle	rbHandle, plVector3 pos); */
+/*	typedef void plUpdatedOrientationCallback(void* userData, plRigidBodyHandle	rbHandle, plQuaternion orientation); */
+
+	/* get world transform */
+	extern void	plGetOpenGLMatrix(plRigidBodyHandle object, plReal* matrix);
+	extern void	plGetPosition(plRigidBodyHandle object,plVector3 position);
+	extern void plGetOrientation(plRigidBodyHandle object,plQuaternion orientation);
+
+	/* set world transform (position/orientation) */
+	extern  void plSetPosition(plRigidBodyHandle object, const plVector3 position);
+	extern  void plSetOrientation(plRigidBodyHandle object, const plQuaternion orientation);
+	extern	void plSetEuler(plReal yaw,plReal pitch,plReal roll, plQuaternion orient);
+	extern	void plSetOpenGLMatrix(plRigidBodyHandle object, plReal* matrix);
+
+	typedef struct plRayCastResult {
+		plRigidBodyHandle		m_body;  
+		plCollisionShapeHandle	m_shape; 		
+		plVector3				m_positionWorld; 		
+		plVector3				m_normalWorld;
+	} plRayCastResult;
+
+	extern  int plRayCast(plDynamicsWorldHandle world, const plVector3 rayStart, const plVector3 rayEnd, plRayCastResult res);
+
+	/* Sweep API */
+
+	/* extern  plRigidBodyHandle plObjectCast(plDynamicsWorldHandle world, const plVector3 rayStart, const plVector3 rayEnd, plVector3 hitpoint, plVector3 normal); */
+
+	/* Continuous Collision Detection API */
+	
+	// needed for source/blender/blenkernel/intern/collision.c
+	double plNearestPoints(float p1[3], float p2[3], float p3[3], float q1[3], float q2[3], float q3[3], float *pa, float *pb, float normal[3]);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif //BULLET_C_API_H
+
