packages feed

Hipmunk 5.0.1.1 → 5.1.0

raw patch · 114 files changed

+7903/−6432 lines, 114 filesdep +transformersPVP ok

version bump matches the API change (PVP)

Dependencies added: transformers

API changes (from Hackage documentation)

- Physics.Hipmunk.Space: Basic :: (Shape -> Shape -> IO Bool) -> Callback
- Physics.Hipmunk.Space: Constant :: !Bool -> Callback
- Physics.Hipmunk.Space: Contact :: Position -> Vector -> CpFloat -> CpFloat -> CpFloat -> Contact
- Physics.Hipmunk.Space: Full :: (Shape -> Shape -> StorableArray Int Contact -> CpFloat -> IO Bool) -> Callback
- Physics.Hipmunk.Space: addCallback :: Space -> (CollisionType, CollisionType) -> Callback -> IO ()
- Physics.Hipmunk.Space: ctDist :: Contact -> CpFloat
- Physics.Hipmunk.Space: ctJnAcc :: Contact -> CpFloat
- Physics.Hipmunk.Space: ctJtAcc :: Contact -> CpFloat
- Physics.Hipmunk.Space: ctNormal :: Contact -> Vector
- Physics.Hipmunk.Space: ctPos :: Contact -> Position
- Physics.Hipmunk.Space: data Callback
- Physics.Hipmunk.Space: data Contact
- Physics.Hipmunk.Space: removeCallback :: Space -> (CollisionType, CollisionType) -> IO ()
- Physics.Hipmunk.Space: setDefaultCallback :: Space -> Callback -> IO ()
- Physics.Hipmunk.Space: sumImpulses :: StorableArray Int Contact -> IO Vector
- Physics.Hipmunk.Space: sumImpulsesWithFriction :: StorableArray Int Contact -> IO Vector
+ Physics.Hipmunk.Body: getMaxAngVel :: Body -> IO CpFloat
+ Physics.Hipmunk.Body: getMaxVelocity :: Body -> IO CpFloat
+ Physics.Hipmunk.Body: setMaxAngVel :: Body -> CpFloat -> IO ()
+ Physics.Hipmunk.Body: setMaxVelocity :: Body -> CpFloat -> IO ()
+ Physics.Hipmunk.Callbacks: Handler :: Maybe (Callback Begin Bool) -> Maybe (Callback PreSolve Bool) -> Maybe (Callback PostSolve ()) -> Maybe (Callback Separate ()) -> CollisionHandler
+ Physics.Hipmunk.Callbacks: addCollisionHandler :: Space -> CollisionType -> CollisionType -> CollisionHandler -> IO ()
+ Physics.Hipmunk.Callbacks: beginHandler :: CollisionHandler -> Maybe (Callback Begin Bool)
+ Physics.Hipmunk.Callbacks: class NotPostStep t
+ Physics.Hipmunk.Callbacks: class NotSeparate t
+ Physics.Hipmunk.Callbacks: currentSpaceAdd :: (Entity a) => a -> Callback (PostStep t) ()
+ Physics.Hipmunk.Callbacks: currentSpaceRemove :: (Entity a) => a -> Callback (PostStep t) ()
+ Physics.Hipmunk.Callbacks: data Begin
+ Physics.Hipmunk.Callbacks: data Callback t a
+ Physics.Hipmunk.Callbacks: data CollisionHandler
+ Physics.Hipmunk.Callbacks: data PostSolve
+ Physics.Hipmunk.Callbacks: data PostStep t
+ Physics.Hipmunk.Callbacks: data PreSolve
+ Physics.Hipmunk.Callbacks: data Separate
+ Physics.Hipmunk.Callbacks: instance (NotSeparate t) => NotSeparate (PostStep t)
+ Physics.Hipmunk.Callbacks: instance Applicative (Callback t)
+ Physics.Hipmunk.Callbacks: instance Functor (Callback t)
+ Physics.Hipmunk.Callbacks: instance MakeChipmunkCB ()
+ Physics.Hipmunk.Callbacks: instance MakeChipmunkCB CInt
+ Physics.Hipmunk.Callbacks: instance Monad (Callback t)
+ Physics.Hipmunk.Callbacks: instance MonadIO (Callback t)
+ Physics.Hipmunk.Callbacks: instance NotPostStep Begin
+ Physics.Hipmunk.Callbacks: instance NotPostStep PostSolve
+ Physics.Hipmunk.Callbacks: instance NotPostStep PreSolve
+ Physics.Hipmunk.Callbacks: instance NotPostStep Separate
+ Physics.Hipmunk.Callbacks: instance NotSeparate Begin
+ Physics.Hipmunk.Callbacks: instance NotSeparate PostSolve
+ Physics.Hipmunk.Callbacks: instance NotSeparate PreSolve
+ Physics.Hipmunk.Callbacks: isFirstContact :: Callback t Bool
+ Physics.Hipmunk.Callbacks: normal :: (NotSeparate t) => Callback t Vector
+ Physics.Hipmunk.Callbacks: points :: (NotSeparate t) => Callback t [Position]
+ Physics.Hipmunk.Callbacks: postSolveHandler :: CollisionHandler -> Maybe (Callback PostSolve ())
+ Physics.Hipmunk.Callbacks: postStep :: (Entity a, NotPostStep t) => a -> Callback (PostStep t) () -> Callback t ()
+ Physics.Hipmunk.Callbacks: preSolveHandler :: CollisionHandler -> Maybe (Callback PreSolve Bool)
+ Physics.Hipmunk.Callbacks: removeCollisionHandler :: Space -> CollisionType -> CollisionType -> IO ()
+ Physics.Hipmunk.Callbacks: separateHandler :: CollisionHandler -> Maybe (Callback Separate ())
+ Physics.Hipmunk.Callbacks: setDefaultCollisionHandler :: Space -> CollisionHandler -> IO ()
+ Physics.Hipmunk.Callbacks: shapes :: Callback t (Shape, Shape)
+ Physics.Hipmunk.Callbacks: totalImpulse :: (NotSeparate t) => Callback (PostStep t) Vector
+ Physics.Hipmunk.Callbacks: totalImpulseWithFriction :: (NotSeparate t) => Callback (PostStep t) Vector
+ Physics.Hipmunk.Callbacks: unsafePostStep :: (Entity a) => Space -> a -> IO () -> IO ()
+ Physics.Hipmunk.Constraint: Ratchet :: !CpFloat -> !CpFloat -> Ratchet
+ Physics.Hipmunk.Constraint: data Ratchet
+ Physics.Hipmunk.Constraint: instance ConstraintType Ratchet
+ Physics.Hipmunk.Constraint: instance Eq Ratchet
+ Physics.Hipmunk.Constraint: instance Ord Ratchet
+ Physics.Hipmunk.Constraint: instance Show Ratchet
+ Physics.Hipmunk.Constraint: ratchet :: Ratchet -> !CpFloat
+ Physics.Hipmunk.Constraint: ratchetPhase :: Ratchet -> !CpFloat
- Physics.Hipmunk.Shape: shapePointQuery :: Shape -> Position -> Layers -> Group -> IO Bool
+ Physics.Hipmunk.Shape: shapePointQuery :: Shape -> Position -> IO Bool
- Physics.Hipmunk.Shape: shapeSegmentQuery :: Shape -> Position -> Position -> Layers -> Group -> IO (Maybe (CpFloat, Vector))
+ Physics.Hipmunk.Shape: shapeSegmentQuery :: Shape -> Position -> Position -> IO (Maybe (CpFloat, Vector))

Files

Hipmunk.cabal view
@@ -3,65 +3,96 @@ Tested-With:   GHC Category:      Physics, Game Name:          Hipmunk-Version:       5.0.1.1+Version:       5.1.0 Stability:     provisional License:       OtherLicense License-File:  LICENSE-Copyright:     (c) 2008-2009 Felipe A. Lessa+Copyright:     (c) 2008-2010 Felipe A. Lessa Author:        Felipe A. Lessa <felipe.lessa@gmail.com> Maintainer:    Felipe A. Lessa <felipe.lessa@gmail.com> Synopsis:      A Haskell binding for Chipmunk. Description:       Chipmunk is a fast, simple, portable, 2D physics engine-      (<http://wiki.slembcke.net/main/published/Chipmunk>).  This-      package contains a prerelease Chipmunk 5.0 source-      and Haskell bindings to all of its functions. It is+      (<http://code.google.com/p/chipmunk-physics/> and+      <http://wiki.slembcke.net/main/published/Chipmunk>).  This+      package contains a prerelease Chipmunk 5.0 source and+      Haskell bindings to all of its functions. It is       completely self-contained.  Please see       <http://hackage.haskell.org/package/HipmunkPlayground>       for a demonstration of this library.       .-      New in version 5.0.1:+      New in version 5.1.0:       .-      * Updated dependencies for GHC 6.12.  Thanks, dons.+      * Updated to Chipmunk 5.0 revision 402.+        'setElasticIterations' is now deprecated.       .-      New in version 5.0.0:+      * New, revamped callback system.  See module+        "Physics.Hipmunk.Callbacks".       .-      * Updated for a prerelease of Chipmunk 5.0 from subversion-        revision 192.  Besides bugfixes this new version brings-        the long awaited new constraints type, doubling the-        number of different joints from four to nine.+      * Support for the new ratchet joint.  Thanks, Owen+        Anderson.       .-      * Tighter dependencies following the versioning policies.+      * Support for limits on linear and angular velocities.       .+      * @shapePointQuery@ and @shapeSegmentQuery@ don't filter+        groups and layers anymore.+      .       Licensed under the MIT license (like Chipmunk itself). Extra-Source-Files:       NEWS,-      chipmunk-5.0/chipmunk.h,-      chipmunk-5.0/chipmunk_types.h,-      chipmunk-5.0/chipmunk_unsafe.h,-      chipmunk-5.0/cpArbiter.h,-      chipmunk-5.0/cpArray.h,-      chipmunk-5.0/cpBB.h,-      chipmunk-5.0/cpBody.h,-      chipmunk-5.0/cpCollision.h,-      chipmunk-5.0/cpHashSet.h,-      chipmunk-5.0/cpPolyShape.h,-      chipmunk-5.0/cpShape.h,-      chipmunk-5.0/cpSpace.h,-      chipmunk-5.0/cpSpaceHash.h,-      chipmunk-5.0/cpVect.h,-      chipmunk-5.0/prime.h,-      chipmunk-5.0/constraints/cpConstraint.h,-      chipmunk-5.0/constraints/cpDampedRotarySpring.h,-      chipmunk-5.0/constraints/cpDampedSpring.h,-      chipmunk-5.0/constraints/cpGearJoint.h,-      chipmunk-5.0/constraints/cpGrooveJoint.h,-      chipmunk-5.0/constraints/cpPinJoint.h,-      chipmunk-5.0/constraints/cpPivotJoint.h,-      chipmunk-5.0/constraints/cpRotaryLimitJoint.h,-      chipmunk-5.0/constraints/cpSimpleMotor.h,-      chipmunk-5.0/constraints/cpSlideJoint.h,-      chipmunk-5.0/constraints/util.h,+      chipmunk-r402/include/chipmunk/chipmunk_ffi.h,+      chipmunk-r402/include/chipmunk/chipmunk.h,+      chipmunk-r402/include/chipmunk/chipmunk_types.h,+      chipmunk-r402/include/chipmunk/chipmunk_unsafe.h,+      chipmunk-r402/include/chipmunk/constraints/cpConstraint.h,+      chipmunk-r402/include/chipmunk/constraints/cpDampedRotarySpring.h,+      chipmunk-r402/include/chipmunk/constraints/cpDampedSpring.h,+      chipmunk-r402/include/chipmunk/constraints/cpGearJoint.h,+      chipmunk-r402/include/chipmunk/constraints/cpGrooveJoint.h,+      chipmunk-r402/include/chipmunk/constraints/cpPinJoint.h,+      chipmunk-r402/include/chipmunk/constraints/cpPivotJoint.h,+      chipmunk-r402/include/chipmunk/constraints/cpRatchetJoint.h,+      chipmunk-r402/include/chipmunk/constraints/cpRotaryLimitJoint.h,+      chipmunk-r402/include/chipmunk/constraints/cpSimpleMotor.h,+      chipmunk-r402/include/chipmunk/constraints/cpSlideJoint.h,+      chipmunk-r402/include/chipmunk/constraints/util.h,+      chipmunk-r402/include/chipmunk/cpArbiter.h,+      chipmunk-r402/include/chipmunk/cpArray.h,+      chipmunk-r402/include/chipmunk/cpBB.h,+      chipmunk-r402/include/chipmunk/cpBody.h,+      chipmunk-r402/include/chipmunk/cpCollision.h,+      chipmunk-r402/include/chipmunk/cpHashSet.h,+      chipmunk-r402/include/chipmunk/cpPolyShape.h,+      chipmunk-r402/include/chipmunk/cpShape.h,+      chipmunk-r402/include/chipmunk/cpSpace.h,+      chipmunk-r402/include/chipmunk/cpSpaceHash.h,+      chipmunk-r402/include/chipmunk/cpVect.h,+      chipmunk-r402/LICENSE.txt,+      chipmunk-r402/README.txt,+      chipmunk-r402/src/chipmunk.c,+      chipmunk-r402/src/constraints/cpConstraint.c,+      chipmunk-r402/src/constraints/cpDampedRotarySpring.c,+      chipmunk-r402/src/constraints/cpDampedSpring.c,+      chipmunk-r402/src/constraints/cpGearJoint.c,+      chipmunk-r402/src/constraints/cpGrooveJoint.c,+      chipmunk-r402/src/constraints/cpPinJoint.c,+      chipmunk-r402/src/constraints/cpPivotJoint.c,+      chipmunk-r402/src/constraints/cpRatchetJoint.c,+      chipmunk-r402/src/constraints/cpRotaryLimitJoint.c,+      chipmunk-r402/src/constraints/cpSimpleMotor.c,+      chipmunk-r402/src/constraints/cpSlideJoint.c,+      chipmunk-r402/src/cpArbiter.c,+      chipmunk-r402/src/cpArray.c,+      chipmunk-r402/src/cpBB.c,+      chipmunk-r402/src/cpBody.c,+      chipmunk-r402/src/cpCollision.c,+      chipmunk-r402/src/cpHashSet.c,+      chipmunk-r402/src/cpPolyShape.c,+      chipmunk-r402/src/cpShape.c,+      chipmunk-r402/src/cpSpace.c,+      chipmunk-r402/src/cpSpaceHash.c,+      chipmunk-r402/src/cpVect.c,+      chipmunk-r402/src/prime.h,       Physics/Hipmunk/wrapper.h  Flag small_base@@ -71,6 +102,7 @@ Library   Exposed-Modules:       Physics.Hipmunk,+      Physics.Hipmunk.Callbacks,       Physics.Hipmunk.Common,       Physics.Hipmunk.Body,       Physics.Hipmunk.Shape,@@ -81,41 +113,44 @@       Physics.Hipmunk.Internal   Include-Dirs:       Physics/Hipmunk,-      chipmunk-5.0+      chipmunk-r402/include/chipmunk   Includes:       wrapper.h   C-Sources:-      chipmunk-5.0/chipmunk.c,-      chipmunk-5.0/cpArbiter.c,-      chipmunk-5.0/cpArray.c,-      chipmunk-5.0/cpBB.c,-      chipmunk-5.0/cpBody.c,-      chipmunk-5.0/cpCollision.c,-      chipmunk-5.0/cpHashSet.c,-      chipmunk-5.0/cpPolyShape.c,-      chipmunk-5.0/cpShape.c,-      chipmunk-5.0/cpSpace.c,-      chipmunk-5.0/cpSpaceHash.c,-      chipmunk-5.0/cpVect.c,-      chipmunk-5.0/constraints/cpConstraint.c,-      chipmunk-5.0/constraints/cpDampedRotarySpring.c,-      chipmunk-5.0/constraints/cpDampedSpring.c,-      chipmunk-5.0/constraints/cpGearJoint.c,-      chipmunk-5.0/constraints/cpGrooveJoint.c,-      chipmunk-5.0/constraints/cpPinJoint.c,-      chipmunk-5.0/constraints/cpPivotJoint.c,-      chipmunk-5.0/constraints/cpRotaryLimitJoint.c,-      chipmunk-5.0/constraints/cpSimpleMotor.c,-      chipmunk-5.0/constraints/cpSlideJoint.c,+      chipmunk-r402/src/chipmunk.c,+      chipmunk-r402/src/constraints/cpConstraint.c,+      chipmunk-r402/src/constraints/cpDampedRotarySpring.c,+      chipmunk-r402/src/constraints/cpDampedSpring.c,+      chipmunk-r402/src/constraints/cpGearJoint.c,+      chipmunk-r402/src/constraints/cpGrooveJoint.c,+      chipmunk-r402/src/constraints/cpPinJoint.c,+      chipmunk-r402/src/constraints/cpPivotJoint.c,+      chipmunk-r402/src/constraints/cpRatchetJoint.c,+      chipmunk-r402/src/constraints/cpRotaryLimitJoint.c,+      chipmunk-r402/src/constraints/cpSimpleMotor.c,+      chipmunk-r402/src/constraints/cpSlideJoint.c,+      chipmunk-r402/src/cpArbiter.c,+      chipmunk-r402/src/cpArray.c,+      chipmunk-r402/src/cpBB.c,+      chipmunk-r402/src/cpBody.c,+      chipmunk-r402/src/cpCollision.c,+      chipmunk-r402/src/cpHashSet.c,+      chipmunk-r402/src/cpPolyShape.c,+      chipmunk-r402/src/cpShape.c,+      chipmunk-r402/src/cpSpace.c,+      chipmunk-r402/src/cpSpaceHash.c,+      chipmunk-r402/src/cpVect.c,       Physics/Hipmunk/wrapper.c   if flag(small_base)     Build-Depends: base >= 3 && < 5,                    array >= 0.1 && < 0.4,-                   containers >= 0.1 && < 0.4+                   containers >= 0.1 && < 0.4,+                   transformers >= 0.2 && < 0.3   else-    Build-Depends: base >= 2 && < 3+    Build-Depends: base >= 2 && < 3,+                   transformers >= 0.2 && < 0.3   Extensions:    CPP, ForeignFunctionInterface   Build-Tools:   hsc2hs   GHC-Options:   -Wall-  CC-Options:    -O3 -ffast-math -std=gnu99+  CC-Options:    -ffast-math -std=gnu99   Extra-Libraries: m
NEWS view
@@ -1,3 +1,14 @@+Version 5.1.0+=============+ - Updated to Chipmunk 5.0 revision 402.  'setElasticIterations'+   is now deprecated.+ - New, revamped callback system.  See module+   "Physics.Hipmunk.Callbacks".+ - Support for the new ratchet joint.  Thanks, Owen Anderson.+ - Support for limits on linear and angular velocities.+ - @shapePointQuery@ and @shapeSegmentQuery@ don't filter groups+   and layers anymore.+ Version 5.0.1 =============  - Updated dependencies for GHC 6.12.  Thanks, dons.
Physics/Hipmunk.hs view
@@ -1,7 +1,7 @@ ----------------------------------------------------------------------------- -- | -- Module      :  Physics/Hipmunk/Hipmunk.hs--- Copyright   :  (c) Felipe A. Lessa 2008-2009+-- Copyright   :  (c) Felipe A. Lessa 2008-2010 -- License     :  MIT (see LICENSE) -- -- Maintainer  :  felipe.lessa@gmail.com@@ -20,15 +20,18 @@ -----------------------------------------------------------------------------  module Physics.Hipmunk-    (module Physics.Hipmunk.Common,+    (-- * Modules re-exported+     module Physics.Hipmunk.Common,      module Physics.Hipmunk.Body,      module Physics.Hipmunk.Shape,      module Physics.Hipmunk.Constraint,-     module Physics.Hipmunk.Space+     module Physics.Hipmunk.Space,+     module Physics.Hipmunk.Callbacks     )     where  import Physics.Hipmunk.Common+import Physics.Hipmunk.Callbacks import Physics.Hipmunk.Body import Physics.Hipmunk.Shape import Physics.Hipmunk.Constraint
Physics/Hipmunk/Body.hsc view
@@ -1,7 +1,7 @@ ----------------------------------------------------------------------------- -- | -- Module      :  Physics/Hipmunk/Body.hsc--- Copyright   :  (c) 2008-2009 Felipe A. Lessa+-- Copyright   :  (c) 2008-2010 Felipe A. Lessa -- License     :  MIT (see LICENSE) -- -- Maintainer  :  felipe.lessa@gmail.com@@ -36,6 +36,8 @@      Velocity,      getVelocity,      setVelocity,+     getMaxVelocity,+     setMaxVelocity,      -- *** Force      Force,      getForce,@@ -49,6 +51,8 @@      AngVel,      getAngVel,      setAngVel,+     getMaxAngVel,+     setMaxAngVel,      -- *** Torque      Torque,      getTorque,@@ -166,8 +170,19 @@   withForeignPtr b $ \ptr -> do     #{poke cpBody, v} ptr v +-- | Maximum linear velocity after integrating, defaults to infinity.+getMaxVelocity :: Body -> IO CpFloat+getMaxVelocity (B b) = do+  withForeignPtr b $ \ptr -> do+    #{peek cpBody, v_limit} ptr +setMaxVelocity :: Body -> CpFloat -> IO ()+setMaxVelocity (B b) v_limit = do+  withForeignPtr b $ \ptr -> do+    #{poke cpBody, v_limit} ptr v_limit ++ type Force = Vector  getForce :: Body -> IO Force@@ -192,6 +207,18 @@ setAngVel (B b) w = do   withForeignPtr b $ \ptr -> do     #{poke cpBody, w} ptr w++-- | Maximum angular velocity after integrating, defaults to infinity.+getMaxAngVel :: Body -> IO CpFloat+getMaxAngVel (B b) = do+  withForeignPtr b $ \ptr -> do+    #{peek cpBody, w_limit} ptr++setMaxAngVel :: Body -> CpFloat -> IO ()+setMaxAngVel (B b) w_limit = do+  withForeignPtr b $ \ptr -> do+    #{poke cpBody, w_limit} ptr w_limit+   type Torque = CpFloat
+ Physics/Hipmunk/Callbacks.hsc view
@@ -0,0 +1,544 @@+-----------------------------------------------------------------------------+-- |+-- Module      :  Physics/Hipmunk/Callbacks.hsc+-- Copyright   :  (c) 2008-2010 Felipe A. Lessa+-- License     :  MIT (see LICENSE)+--+-- Maintainer  :  felipe.lessa@gmail.com+-- Stability   :  provisional+-- Portability :  portable (needs FFI)+--+-- Callbacks are functions that are called whenever certain+-- events happen.  For example, you may use a callback to know+-- when a player bumps into an enemy.  Or when a bullet hits its+-- target.  Or how strong was a collision.+-----------------------------------------------------------------------------++module Physics.Hipmunk.Callbacks+    (-- * Collision handlers++     -- $collisionHandlers++     -- * Callback types+     Begin,+     PreSolve,+     PostSolve,+     Separate,+     PostStep,+     NotSeparate,+     NotPostStep,++     -- * Callback monad+     Callback,++     -- * Callback functions+     -- | Functions that may be called within a callback.  We+     -- divide them in groups according to the kinds of callbacks+     -- allowed to use them.++     -- ** General+     -- | These functions can be used in any kind of callback.+     shapes,+     isFirstContact,++     -- ** Only when colliding+     -- | These functions make sense only if the shapes @a@ and+     -- @b@ are colliding, i.e., outside a @Separate@ event.+     normal,+     points,++     -- ** Only in @PostStep@+     -- | These functions can be used only in @PostStep@+     -- events.  Use the 'postStep' function to add a+     -- @PostStep@ callback.+     totalImpulse,+     totalImpulseWithFriction,+     currentSpaceAdd,+     currentSpaceRemove,++     -- * Adding post-step callbacks+     postStep,+     unsafePostStep,++     -- * Adding collision handlers+     CollisionHandler(..),+     setDefaultCollisionHandler,+     addCollisionHandler,+     removeCollisionHandler+    )+    where++import Control.Applicative+import Control.Monad.IO.Class+import Control.Monad.Trans.Reader+import Data.IORef+import qualified Data.Map as M+import Foreign hiding (new)+import Foreign.C.Types (CInt)+#include "wrapper.h"++import Physics.Hipmunk.Common+import Physics.Hipmunk.Internal+import Physics.Hipmunk.Shape+++-- $collisionHandlers+--   Collision handlers ('CollisionHandler') are tuples of 4+--   callback functions.  Each function is called when a+--   different kind of collision events happens.  Most of the+--   time they are triggered inside a+--   'Physics.Hipmunk.Space.step' function call, however they can+--   also be called when a shape is removed.+--+--   Collision events always happen between two shapes, say @a@+--   and @b@.  Possible events are:+--+--     ['Begin'] Shapes @a@ and @b@ started touching for the+--     first time on this step (that is, they were not touching+--     on the last step).  May return @False@ to ignore the+--     collision entirely or @True@ to process it normally.  If+--     the collision is ignored, then you /will not/ receive+--     @PreSolve@ or @PostSolve@ events, however you /will/+--     receive a @Separate@ event when they stop overlapping.+--+--     ['PreSolve'] Shapes @a@ and @b@ are touching during this+--     step.  May return @False@ to ignore the collision for this+--     step or @True@ to process it normally.  You may also use+--     this step to give custom friction or elasticity values.+--+--     ['PostSolve'] Shapes @a@ and @b@ are touching and their+--     collision response has been processed.  You can retrive+--     the collision force (e.g. to calculate sound volumes or+--     damage amounts).+--+--     ['Separate'] Shapes @a@ and @b@ stopped touching (or+--     overlapping, if the collision was ignored on @Begin@)+--     for the first time on this step (that is, on the last step+--     they were touching or overlapping).+--+--   You may have many different kinds of collision handlers.+--   Each collision handler is associated with two+--   'CollisionType's.  Whenever shapes @a@ and @b@ collide, if+--   there was a callback associated with @a@'s and @b@'s+--   collision types, then it is called.  Otherwise the default+--   callback is called.  The default callback is also+--   overrideable.+--+--   The callbacks themselves may execute arbitrary operations+--   with a simple exception: /callbacks cannot add or remove/+--   /entities from the space/.  To that end, there exist another+--   kind of callback:+--+--     ['PostStep'] Called on the end of the 'step' function.+--     This is the only callback where you may remove entities+--     from the space, using 'currentSpaceAdd' or+--     'currentSpaceRemove'.+--+--   Post-step callbacks are not collision handlers, because they+--   aren't called for each collision.  Instead, inside a+--   collision handler you may use 'postStep' to add a post-step+--   callback that will be called when the 'step' ends.  Each+--   post-step callback is associated with an entity, and there+--   can be only one post-step callback per entity.+++-- | Phantom type used in @Begin@ collision events.+data Begin      = Begin++-- | Phantom type used in @PreSolve@ collision events.+data PreSolve   = PreSolve++-- | Phantom type used in @PostSolve@ collision events.+data PostSolve  = PostSolve++-- | Phantom type used in @Separate@ collision events.+data Separate   = Separate++-- | Phantom type used in @PostStep@ callbacks.+--+--  The phantom type @t@ inside this @PostStep@ phantom type is+--  the collision event that originated this @PostStep@ callback.+--  For example, if you add a @PostStep@ from a @Begin@ handler,+--  then it will have type @PostStep Begin@.  It is used by the+--  @PostStep@'s instance of 'NotSeparate'.+data PostStep t = PostStep++-- | Class of collision events other than @Separate@.  That is,+-- collision events where the shapes are touching or overlapping.+class NotSeparate t where+instance NotSeparate Begin where+instance NotSeparate PreSolve where+instance NotSeparate PostSolve where+instance NotSeparate t => NotSeparate (PostStep t) where++-- | Class of callbacks called from collision events. That is,+-- everything other than 'PostStep'.+class NotPostStep t where+instance NotPostStep Begin where+instance NotPostStep PreSolve where+instance NotPostStep PostSolve where+instance NotPostStep Separate where++-- | Monad where callbacks are run.  Within this monad you have+-- access to functions describing the collision.  You can also+-- run any IO actions using 'liftIO' from @transformers@ package.+-- However, remember not to call 'spaceAdd' or 'spaceRemove'+-- outside a @PostStep@ callback -- use 'postStep' instead, for example:+--+-- @+-- postStep entity (currentSpaceRemove entity)+-- @+--+-- The phantom type @t@ describes the type of callback, which can be+--+--   ['Begin'] When the collision first occurs.+--+--   ['PreSolve'] Before the collision is processed.+--+--   ['PostSolve'] After the collision is processed.+--+--   ['Separate'] When the collision ends.+--+--   ['PostStep'] After the 'step' finishes.+--+-- This phantom type is used to disallow invalid operations.  For+-- example, you can't calculate the normal of a collision if you+-- are in a @Separate@ event, as there is no collision inside+-- this event.  And you can't add a new post-step callback inside+-- a post-step callback.+newtype Callback t a = CB {unCB :: ReaderT CallbackEnv IO a}+data CallbackEnv = CE {ceSpace   :: !Space,+                       ceArbiter :: {-# UNPACK #-} !ArbiterPtr}++instance Functor (Callback t) where+    fmap f (CB m) = CB (fmap f m)++instance Monad (Callback t) where+    return       = CB . return+    (CB m) >>= n = CB (m >>= unCB . n)+    (CB m) >>  n = CB (m >>  unCB   n)+    fail         = CB . fail++instance Applicative (Callback t) where+    pure              = CB . pure+    (CB m) <*> (CB n) = CB (m <*> n)+    (CB m)  *> (CB n) = CB (m  *> n)+    (CB m) <*  (CB n) = CB (m <*  n)++instance MonadIO (Callback t) where+    liftIO = CB . liftIO++env :: Callback t CallbackEnv+env = CB ask++arbiterPtr :: Callback t ArbiterPtr+arbiterPtr = ceArbiter <$> env+++-- | Shapes involved in this collision.+shapes :: Callback t (Shape, Shape)+shapes = do+  arb_ptr <- arbiterPtr+  spce    <- space+  liftIO $ alloca $ \shape1_ptr_ptr ->+           alloca $ \shape2_ptr_ptr -> do+             cpArbiterGetShapes arb_ptr shape1_ptr_ptr shape2_ptr_ptr+             let get s_ptr_ptr = peek s_ptr_ptr >>= retriveShape spce+             (,) <$> get shape1_ptr_ptr <*> get shape2_ptr_ptr++foreign import ccall unsafe "wrapper.h"+    cpArbiterGetShapes :: ArbiterPtr -> Ptr ShapePtr -> Ptr ShapePtr -> IO ()++-- | Space from where these shapes come from.+space :: Callback t Space+space = ceSpace <$> env++-- | @True@ iff this is the first step that the shapes touched.+isFirstContact :: Callback t Bool+isFirstContact = do+  ptr <- arbiterPtr+  i   <- liftIO (cpArbiterIsFirstContact ptr)+  return (i /= 0)++foreign import ccall unsafe "wrapper.h"+    cpArbiterIsFirstContact :: ArbiterPtr -> IO Int++-- | The normal vector of the collision.+normal :: NotSeparate t => Callback t Vector+normal = arbVecFunc wrArbiterGetNormal++arbVecFunc :: (ArbiterPtr -> VectorPtr -> IO ()) -> Callback t Vector+arbVecFunc func = do+  arb_ptr <- arbiterPtr+  liftIO $ alloca $ \v_ptr -> do+    func arb_ptr v_ptr+    peek v_ptr++foreign import ccall unsafe "wrapper.h"+    wrArbiterGetNormal :: ArbiterPtr -> VectorPtr -> IO ()++-- | Points where the collision occured.+points :: NotSeparate t => Callback t [Position]+points = do+  let go :: [Position] -> Int -> ContactPtr -> IO [Position]+      go acc 0 _ = return acc+      go acc i p = do v <- #{peek cpContact, p} p+                      go (v:acc) (i-1) (p `advancePtr` negate 1)+  ptr <- arbiterPtr+  numContacts  <- liftIO $ #{peek cpArbiter, numContacts} ptr+  contacts_ptr <- liftIO $ #{peek cpArbiter, contacts} ptr+  if numContacts <= 0+    then return []+    else liftIO $ go [] numContacts (contacts_ptr `advancePtr` (numContacts-1))++-- | The total impulse that was applied to resolve the collision.+-- Returns incorrect results if elastic iterations are being used.+totalImpulse :: NotSeparate t => Callback (PostStep t) Vector+totalImpulse = arbVecFunc wrArbiterTotalImpulse++foreign import ccall unsafe "wrapper.h"+    wrArbiterTotalImpulse :: ArbiterPtr -> VectorPtr -> IO ()++-- | The total impulse with friction that was applied to resolve+-- the collision.  Returns incorrect results if elastic+-- iterations are being used.+totalImpulseWithFriction :: NotSeparate t => Callback (PostStep t) Vector+totalImpulseWithFriction = arbVecFunc wrArbiterTotalImpulseWithFriction++foreign import ccall unsafe "wrapper.h"+    wrArbiterTotalImpulseWithFriction :: ArbiterPtr -> VectorPtr -> IO ()++-- | Add an entity to the current 'Space' from where this+-- callback was called.  Don't add the same entity twice to a+-- space.+--+-- You can add entities only in 'PostStep' callbacks.  You should+-- not use @liftIO@ and @spaceAdd@.+currentSpaceAdd :: Entity a => a -> Callback (PostStep t) ()+currentSpaceAdd ent = do+  spce <- space+  liftIO (spaceAdd spce ent)++-- | Remove an entity from the current 'Space' from where this+-- callback was called.  Don't remove an entity that wasn't+-- added.+--+-- You can remove entities only in 'PostStep' callbacks.  You+-- should not use @liftIO@ and @spaceRemove@.+currentSpaceRemove :: Entity a => a -> Callback (PostStep t) ()+currentSpaceRemove ent = do+  spce <- space+  liftIO (spaceRemove spce ent)++-- | @postStep e cb@ registers a callback @cb@ for the 'PostStep'+-- phase on a given entity @e@.  @PostStep@ callbacks are called+-- once when the 'step' call finishes (and only on the current+-- time step).  This is the only kind of callbacks that may call+-- 'currentSpaceAdd' and 'currentSpaceRemove'.+--+-- Each entity may have /at most one/ callback registered on it.+-- If a second callback @cb2@ gets registered on the same entity+-- @e@, then callback @cb@ /will not/ be called, only @cb2@.+-- This is not a bug, but a feature.  This allows you to say, for+-- example, @postStep shape (currentSpaceRemove shape)@ every+-- time @shape@ collides.  Even if @shape@ collided many times in+-- a single time step, only the last callback would be called and+-- @shape@ would be removed just once.+--+-- Note that this function registers a callback from within+-- another callback, as this is the motivation of using+-- @PostStep@ callbacks.+postStep :: (Entity a, NotPostStep t) => a -> Callback (PostStep t) () -> Callback t ()+postStep e cb = do+  ce <- env+  liftIO $ unsafePostStep (ceSpace ce) e $ runReaderT (unCB cb) ce++-- | As 'postStep', registers a @PostStep@ callback.  Unlike+-- 'postStep', this function allows you to register a @PostStep@+-- callback from anywhere.  Also, from this callback you won't be+-- in 'Callback' monad.  It is therefore unsafe and should not be+-- used unless you really know what you are doing.+unsafePostStep :: Entity a => Space -> a -> IO () -> IO ()+unsafePostStep (P sp _ callbacks) e cb = do+  let f _ _ _ = cb -- discard arguments that we don't need+  cb_ptr <- makeChipmunkPostStepCB f+  withForeignPtr sp $ \sp_ptr ->+    withForeignPtr (entityPtr e) $ \e_ptr ->+      cpSpaceAddPostStepCallback sp_ptr cb_ptr (castPtr e_ptr) nullPtr+  let cb_ptr' = castFunPtr cb_ptr+  modifyIORef callbacks $ \cbs -> cbs {cbsPostStep = cb_ptr' : cbsPostStep cbs}++type ChipmunkPostStepCB = SpacePtr -> Ptr () -> Ptr () -> IO ()+type ChipmunkPostStepCBPtr = FunPtr ChipmunkPostStepCB+foreign import ccall "wrapper"+    makeChipmunkPostStepCB :: ChipmunkPostStepCB -> IO ChipmunkPostStepCBPtr+foreign import ccall unsafe "wrapper.h"+    cpSpaceAddPostStepCallback :: SpacePtr -> ChipmunkPostStepCBPtr -> Ptr () -> Ptr () -> IO ()+++++-- | A 4-tuple of callbacks, one for each kind of collision+-- event.+--+-- @beginHandler@ and @preSolveHandler@ should return a @Bool@+-- stating @True@ if the collision should be processed or @False@+-- if the collision should be ignored.  If @beginHandler@ returns+-- @False@, the collision will be completely ignored.  If+-- @preSolveHandler@ returns @False@, then the collision will be+-- ignored only for this time step.+--+-- You may also use @Nothing@ to use the default handlers.  The+-- default is to process all collisions.  That is, @Handler+-- Nothing Nothing Nothing Nothing@ is the same as+--+-- @+-- Handler {beginHandler     = Just (return True)+--         ,preSolveHandler  = Just (return True)+--         ,postSolveHandler = Just (return ())+--         ,separateHandler  = Just (return ())}+-- @+--+-- however using @Nothing@ is more efficient (the Chipmunk+-- library won't need to call a Haskell function).+--+-- Note that assigning @Nothing@ /does not/ mean that the default+-- set with 'setDefaultCollisionHandler' will be called.  That+-- default is called only if there isn't a registered handler for+-- the given collision types.+data CollisionHandler =+    Handler {beginHandler     :: Maybe (Callback Begin Bool)+            ,preSolveHandler  :: Maybe (Callback PreSolve Bool)+            ,postSolveHandler :: Maybe (Callback PostSolve ())+            ,separateHandler  :: Maybe (Callback Separate ())}++-- | Internal. Type of callback used by Chipmunk.+type ChipmunkCB a = ArbiterPtr -> SpacePtr -> Ptr () -> IO a+type ChipmunkCBPtr a = FunPtr (ChipmunkCB a)++-- | Internal. Create a new 'FunPtr' for a given callback.+adaptCallback :: MakeChipmunkCB a => Space+              -> Maybe (Callback t a) -> IO (ChipmunkCBPtr a)+adaptCallback _    Nothing  = return nullFunPtr+adaptCallback spce (Just c) = makeChipmunkCB f+    where+      f arb_ptr _ _ =+          let ce = CE {ceSpace   = spce+                      ,ceArbiter = arb_ptr}+          in runReaderT (unCB c) ce++-- | Internal. Transform callbacks of 'Bool's to 'CInt's.+asCInt :: Maybe (Callback t Bool) -> Maybe (Callback t CInt)+asCInt Nothing  = Nothing+asCInt (Just c) = Just (f <$> c) where f b = if b then 1 else 0++-- | Internal. Class of data types than can be given back as responses of+-- callbacks.+class MakeChipmunkCB a where+    makeChipmunkCB :: ChipmunkCB a -> IO (ChipmunkCBPtr a)++instance MakeChipmunkCB CInt where+    makeChipmunkCB = makeChipmunkCB_CInt+foreign import ccall "wrapper"+    makeChipmunkCB_CInt :: ChipmunkCB CInt -> IO (ChipmunkCBPtr CInt)++instance MakeChipmunkCB () where+    makeChipmunkCB = makeChipmunkCB_Void+foreign import ccall "wrapper"+    makeChipmunkCB_Void :: ChipmunkCB () -> IO (ChipmunkCBPtr ())++-- | Internal.  Create the 'FunPtr's and give them to C land.+addHandler :: Space -> (SpacePtr -> HandlerAdder)+           -> CollisionHandler -> IO HandlerFunPtrs+addHandler spce@(P sp _ _) handlerAdder handler = do+  beginCB     <- adaptCallback spce $ asCInt $ beginHandler handler+  preSolveCB  <- adaptCallback spce $ asCInt $ preSolveHandler handler+  postSolveCB <- adaptCallback spce $ postSolveHandler handler+  separateCB  <- adaptCallback spce $ separateHandler handler+  withForeignPtr sp $ \sp_ptr -> do+    handlerAdder sp_ptr beginCB preSolveCB postSolveCB separateCB nullPtr+  return (castFunPtr beginCB,     castFunPtr preSolveCB,+          castFunPtr postSolveCB, castFunPtr separateCB)++type HandlerAdder =  ChipmunkCBPtr CInt+                  -> ChipmunkCBPtr CInt+                  -> ChipmunkCBPtr ()+                  -> ChipmunkCBPtr ()+                  -> Ptr ()+                  -> IO ()++-- | Defines a new default collision handler.  This handler is+-- used whenever two shapes @a@ and @b@ collide such that no+-- other collision pair function was defined to @a@'s and @b@'s+-- collision types. The default is @Handler Nothing Nothing+-- Nothing Nothing@.+setDefaultCollisionHandler :: Space -> CollisionHandler -> IO ()+setDefaultCollisionHandler spce@(P _ _ callbacks) handler = do+  ptrs <- addHandler spce cpSpaceSetDefaultCollisionHandler handler+  cbs <- readIORef callbacks+  freeHandlerFunPtrs (cbsDefault cbs)+  writeIORef callbacks $ cbs {cbsDefault = ptrs}++foreign import ccall unsafe "wrapper.h"+    cpSpaceSetDefaultCollisionHandler :: SpacePtr -> HandlerAdder++-- | @addCollisionHandler sp (cta,ctb) handler@ defines @handler@+-- as the handler to be used whenever a collision occurs between+-- a shape of collision type @cta@ and another of collision type+-- @ctb@ (and vice versa).  Any other callback already registered+-- to handle @(cta,ctb)@ will be removed.+--+-- Note that you should /not/ add handlers to both combinations+-- of @(cta,ctb)@ and @(ctb,cta)@.  Doing so results in undefined+-- behaviour.  A good rule of thumb is to always use @cta <=+-- ctb@, although this is not necessary.+addCollisionHandler :: Space -> CollisionType -> CollisionType -> CollisionHandler -> IO ()+addCollisionHandler spce@(P _ _ callbacks) cta ctb handler = do+  -- Add the new handler, overriding anything that was already there.+  let handlerAdder p = cpSpaceAddCollisionHandler p cta ctb+  ptrs <- addHandler spce handlerAdder handler++  -- Free the previous one and record the new one, using+  --   updateLookupWithKey :: Ord k => (k -> a -> Maybe a) -> k+  --                       -> Map k a -> (Maybe a, Map k a)+  cbs <- readIORef callbacks+  let handlers = cbsHandlers cbs+      val = case handler of+              Handler Nothing Nothing Nothing Nothing -> Nothing+              _                                       -> Just ptrs+      (old,handlers') = M.updateLookupWithKey (\_ _ -> val) (cta,ctb) handlers+  maybe (return ()) freeHandlerFunPtrs old+  writeIORef callbacks $ cbs {cbsHandlers = handlers'}++foreign import ccall unsafe "wrapper.h"+    cpSpaceAddCollisionHandler :: SpacePtr -> CollisionType -> CollisionType -> HandlerAdder++-- | @removeCollisionHandler sp (cta,ctb)@ removes the handler+-- that was registered to handle @(cta,ctb)@, if any (see+-- 'addCollisionHandler').  Any collisions that would be handled+-- by the removed handler will be handled by the default one (see+-- 'setDefaultCollisionHandler').+--+-- Note that you should /always/ use the same order that was+-- passed to 'addCollisionHandler'. In other words, after+-- @addCollisionHandler sp (cta,ctb) handler@ you should use+-- @removeCollisionHandler sp (cta,ctb)@, and /never/+-- @removeCollisionHandler sp (ctb,cta)@ (note the swapped+-- tuple).+--+-- Although pointless, it is harmless to remove a callback that+-- was not added.+removeCollisionHandler :: Space -> CollisionType -> CollisionType -> IO ()+removeCollisionHandler (P sp _ callbacks) cta ctb = do+  cbs <- readIORef callbacks+  let handlers = cbsHandlers cbs+      (old,handlers') = M.updateLookupWithKey (\_ _ -> Nothing) (cta,ctb) handlers+  case old of+    Nothing   -> return () -- no need to free, no need to remove+    Just ptrs -> do freeHandlerFunPtrs ptrs+                    writeIORef callbacks $ cbs {cbsHandlers = handlers'}+                    withForeignPtr sp $ \sp_ptr -> do+                      cpSpaceRemoveCollisionHandler sp_ptr cta ctb++foreign import ccall unsafe "wrapper.h"+    cpSpaceRemoveCollisionHandler :: SpacePtr -> CollisionType -> CollisionType -> IO ()
Physics/Hipmunk/Common.hsc view
@@ -1,32 +1,33 @@ {-# CFILES-      chipmunk-5.0/chipmunk.c,-      chipmunk-5.0/cpArbiter.c,-      chipmunk-5.0/cpArray.c,-      chipmunk-5.0/cpBB.c,-      chipmunk-5.0/cpBody.c,-      chipmunk-5.0/cpCollision.c,-      chipmunk-5.0/cpHashSet.c,-      chipmunk-5.0/cpPolyShape.c,-      chipmunk-5.0/cpShape.c,-      chipmunk-5.0/cpSpace.c,-      chipmunk-5.0/cpSpaceHash.c,-      chipmunk-5.0/cpVect.c,-      chipmunk-5.0/constraints/cpConstraint.c,-      chipmunk-5.0/constraints/cpDampedRotaryString.c,-      chipmunk-5.0/constraints/cpDampedString.c,-      chipmunk-5.0/constraints/cpGearJoint.c,-      chipmunk-5.0/constraints/cpGrooveJoint.c,-      chipmunk-5.0/constraints/cpPinJoint.c,-      chipmunk-5.0/constraints/cpPivotJoint.c,-      chipmunk-5.0/constraints/cpRotaryLimitJoint.c,-      chipmunk-5.0/constraints/cpSimpleMotor.c,-      chipmunk-5.0/constraints/cpSlideJoint.c,+      chipmunk-r402/src/chipmunk.c,+      chipmunk-r402/src/constraints/cpConstraint.c,+      chipmunk-r402/src/constraints/cpDampedRotarySpring.c,+      chipmunk-r402/src/constraints/cpDampedSpring.c,+      chipmunk-r402/src/constraints/cpGearJoint.c,+      chipmunk-r402/src/constraints/cpGrooveJoint.c,+      chipmunk-r402/src/constraints/cpPinJoint.c,+      chipmunk-r402/src/constraints/cpPivotJoint.c,+      chipmunk-r402/src/constraints/cpRatchetJoint.c,+      chipmunk-r402/src/constraints/cpRotaryLimitJoint.c,+      chipmunk-r402/src/constraints/cpSimpleMotor.c,+      chipmunk-r402/src/constraints/cpSlideJoint.c,+      chipmunk-r402/src/cpArbiter.c,+      chipmunk-r402/src/cpArray.c,+      chipmunk-r402/src/cpBB.c,+      chipmunk-r402/src/cpBody.c,+      chipmunk-r402/src/cpCollision.c,+      chipmunk-r402/src/cpHashSet.c,+      chipmunk-r402/src/cpPolyShape.c,+      chipmunk-r402/src/cpShape.c,+      chipmunk-r402/src/cpSpace.c,+      chipmunk-r402/src/cpSpaceHash.c,+      chipmunk-r402/src/cpVect.c,       Physics/Hipmunk/wrapper.c #-}  ----------------------------------------------------------------------------- -- | -- Module      :  Physics/Hipmunk/Common.hsc--- Copyright   :  (c) 2008-2009 Felipe A. Lessa+-- Copyright   :  (c) 2008-2010 Felipe A. Lessa -- License     :  MIT (see LICENSE) -- -- Maintainer  :  felipe.lessa@gmail.com
Physics/Hipmunk/Constraint.hsc view
@@ -1,7 +1,7 @@ ----------------------------------------------------------------------------- -- | -- Module      :  Physics/Hipmunk/Constraint.hsc--- Copyright   :  (c) 2008-2009 Felipe A. Lessa+-- Copyright   :  (c) 2008-2010 Felipe A. Lessa -- License     :  MIT (see LICENSE) -- -- Maintainer  :  felipe.lessa@gmail.com@@ -40,6 +40,8 @@      DampedSpring(..),      -- ** Damped rotary spring      DampedRotarySpring(..),+     -- ** Ratchet joint+     Ratchet(..),      -- ** Rotary limit      RotaryLimit(..),      -- ** Simple motor@@ -78,6 +80,7 @@ {-# SPECIALISE newConstraint :: Body -> Body -> Gear -> IO (Constraint Gear) #-} {-# SPECIALISE newConstraint :: Body -> Body -> DampedSpring -> IO (Constraint DampedSpring) #-} {-# SPECIALISE newConstraint :: Body -> Body -> DampedRotarySpring -> IO (Constraint DampedRotarySpring) #-}+{-# SPECIALISE newConstraint :: Body -> Body -> Ratchet -> IO (Constraint Ratchet) #-} {-# SPECIALISE newConstraint :: Body -> Body -> RotaryLimit -> IO (Constraint RotaryLimit) #-} {-# SPECIALISE newConstraint :: Body -> Body -> SimpleMotor -> IO (Constraint SimpleMotor) #-} @@ -93,6 +96,7 @@ {-# SPECIALISE redefineC :: Constraint Gear -> Gear -> IO () #-} {-# SPECIALISE redefineC :: Constraint DampedSpring -> DampedSpring -> IO () #-} {-# SPECIALISE redefineC :: Constraint DampedRotarySpring -> DampedRotarySpring -> IO () #-}+{-# SPECIALISE redefineC :: Constraint Ratchet -> Ratchet -> IO () #-} {-# SPECIALISE redefineC :: Constraint RotaryLimit -> RotaryLimit -> IO () #-} {-# SPECIALISE redefineC :: Constraint SimpleMotor -> SimpleMotor -> IO () #-} @@ -206,6 +210,7 @@   redef ptr _ _ (Gear p r) = do       #{poke cpGearJoint, phase} ptr p       #{poke cpGearJoint, ratio} ptr r+      #{poke cpGearJoint, ratio_inv} ptr (1/r)  -- | A simple damped spring.  Generally this constraint --   should be used instead of @applyDampedSpring@.@@ -242,6 +247,19 @@       #{poke cpDampedRotarySpring, stiffness} ptr s       #{poke cpDampedRotarySpring, damping} ptr d +-- | A ratchet constraint.+data Ratchet = Ratchet {+      ratchetPhase :: !CpFloat {-^ Phase. -}+     ,ratchet      :: !CpFloat {-^ Ratchet. -}}+    deriving (Eq, Ord, Show)++instance ConstraintType Ratchet where+  size _ = #{size cpRatchetJoint}+  init_ (Ratchet p r) = wrRatchetJointInit p r+  redef ptr _ _ (Ratchet p r) = do+    #{poke cpRatchetJoint, phase} ptr p+    #{poke cpRatchetJoint, ratchet} ptr r+ -- | A rotary limit constraints the difference of angle --   between two bodies. data RotaryLimit = RotaryLimit {@@ -251,8 +269,8 @@  instance ConstraintType RotaryLimit where   size _ = #{size cpRotaryLimitJoint}-  init_ (RotaryLimit mn mx)        = wrRotaryLimitJointInit mn mx-  redef ptr _ _ (RotaryLimit mn mx)        = do+  init_ (RotaryLimit mn mx) = wrRotaryLimitJointInit mn mx+  redef ptr _ _ (RotaryLimit mn mx) = do       #{poke cpRotaryLimitJoint, min} ptr mn       #{poke cpRotaryLimitJoint, max} ptr mx @@ -309,6 +327,8 @@     wrDampedSpringInit :: CpFloat -> CpFloat -> CpFloat -> VectorPtr -> VectorPtr -> ConstraintInit foreign import ccall unsafe "wrapper.h"     wrDampedRotarySpringInit :: CpFloat -> CpFloat -> CpFloat -> ConstraintInit+foreign import ccall unsafe "wrapper.h"+    wrRatchetJointInit :: CpFloat -> CpFloat -> ConstraintInit foreign import ccall unsafe "wrapper.h"     wrRotaryLimitJointInit :: CpFloat -> CpFloat -> ConstraintInit foreign import ccall unsafe "wrapper.h"
Physics/Hipmunk/Internal.hsc view
@@ -1,7 +1,7 @@ ----------------------------------------------------------------------------- -- | -- Module      :  Physics/Hipmunk/Internal.hsc--- Copyright   :  (c) 2008-2009 Felipe A. Lessa+-- Copyright   :  (c) 2008-2010 Felipe A. Lessa -- License     :  MIT (see LICENSE) -- -- Maintainer  :  felipe.lessa@gmail.com@@ -30,13 +30,23 @@       SpacePtr,      Space(..),+     Callbacks(..),+     HandlerFunPtrs,      unP,+     retriveShape,+     freeHandlerFunPtrs, +     Entity(..),++     ArbiterPtr,+      Contact(..),      ContactPtr     )     where +import qualified Data.Map as M+import Control.Monad (when) import Data.IORef import Data.Map (Map) import Foreign@@ -137,8 +147,10 @@                !(IORef Callbacks)  -- Added callbacks type SpacePtr  = Ptr Space type Entities  = Map (Ptr ()) (Either (ForeignPtr ()) Shape)-type Callbacks = (Maybe (FunPtr ()), -- Default-                  Map (CollisionType_, CollisionType_) (FunPtr ()))+data Callbacks = CBs {cbsDefault  :: HandlerFunPtrs+                     ,cbsHandlers :: Map (CollisionType_, CollisionType_) HandlerFunPtrs+                     ,cbsPostStep :: [FunPtr ()]}+type HandlerFunPtrs = (FunPtr (), FunPtr (), FunPtr (), FunPtr ()) type CollisionType_ = #{type cpCollisionType} -- Duplicated to avoid bringing the documentation from Shape module. @@ -150,6 +162,39 @@  instance Ord Space where     P s1 _ _ `compare` P s2 _ _ = s1 `compare` s2++-- | Internal. Retrive a 'Shape' from a 'ShapePtr' and a 'Space'.+retriveShape :: Space -> ShapePtr -> IO Shape+retriveShape (P _ entities _) ptr = do+  ent <- readIORef entities+  let Just (Right shape) = M.lookup (castPtr ptr) ent+  return shape++-- | Internal.  Free all function pointers of this handler.+freeHandlerFunPtrs :: HandlerFunPtrs -> IO ()+freeHandlerFunPtrs (p1,p2,p3,p4) = f p1 >> f p2 >> f p3 >> f p4+    where f p = when (p /= nullFunPtr) (freeHaskellFunPtr p)+++++-- | Type class implemented by entities that can be+--   added to a space.+class Entity a where+    -- | Add an entity to a 'Space'. Don't add the same+    --   entity twice to a space.+    spaceAdd :: Space -> a -> IO ()+    -- | Remove an entity from a 'Space'. Don't remove+    --   an entity that wasn't added.+    spaceRemove :: Space -> a -> IO ()+    -- | Internal function.  Retrive the pointer of this entity.+    entityPtr :: a -> ForeignPtr a+++-- | Arbiters are used within callbacks.  We don't expose them to+-- the user.+data Arbiter = Arbiter+type ArbiterPtr = Ptr Arbiter   
Physics/Hipmunk/Shape.hsc view
@@ -1,7 +1,7 @@ ----------------------------------------------------------------------------- -- | -- Module      :  Physics/Hipmunk/Shape.hsc--- Copyright   :  (c) 2008-2009 Felipe A. Lessa+-- Copyright   :  (c) 2008-2010 Felipe A. Lessa -- License     :  MIT (see LICENSE) -- -- Maintainer  :  felipe.lessa@gmail.com@@ -160,6 +160,7 @@ --   meaning for Chipmunk other than the correspondence between --   shapes and the collision pair functions you add. (default is --   zero)+ type CollisionType = #{type cpCollisionType} getCollisionType :: Shape -> IO CollisionType getCollisionType (S shape _) =@@ -314,34 +315,32 @@ pairs :: (a -> a -> b) -> [a] -> [b] pairs f l = zipWith f l (tail $ cycle l) --- | @shapePointQuery shape p l g@ returns @True@ iff the point+-- | @shapePointQuery shape p@ returns @True@ iff the point --   in position @p@ (in world's coordinates) lies within the---   shape @shape@, is not of the same group and share at least---   one layer.-shapePointQuery :: Shape -> Position -> Layers -> Group -> IO Bool-shapePointQuery (S shape _) p layers group =+--   shape @shape@.+shapePointQuery :: Shape -> Position -> IO Bool+shapePointQuery (S shape _) p =   withForeignPtr shape $ \shape_ptr ->   with p $ \p_ptr -> do-    i <- wrShapePointQuery shape_ptr p_ptr layers group+    i <- wrShapePointQuery shape_ptr p_ptr     return (i /= 0)  foreign import ccall unsafe "wrapper.h"-    wrShapePointQuery :: ShapePtr -> VectorPtr -> Layers -> Group -> IO CInt+    wrShapePointQuery :: ShapePtr -> VectorPtr -> IO CInt --- | @shapeSegmentQuery shape p1 p2 l g@ returns @Just (t,n)@ iff---   the segment from @p1@ to @p2@ (in world's coordinates)---   intersects with the shape @shape@, is not of the same group---   and share at least one layer.  In that case, @0 <= t <= 1@---   indicates that one of the intersections is at point @p1 ++-- | @shapeSegmentQuery shape p1 p2@ returns @Just (t,n)@ iff the+--   segment from @p1@ to @p2@ (in world's coordinates)+--   intersects with the shape @shape@.  In that case, @0 <= t <=+--   1@ indicates that one of the intersections is at point @p1 + --   (p2 - p1) \`scale\` t@ with normal @n@.-shapeSegmentQuery :: Shape -> Position -> Position -> Layers -> Group+shapeSegmentQuery :: Shape -> Position -> Position                   -> IO (Maybe (CpFloat, Vector))-shapeSegmentQuery (S shape _) p1 p2 layers group =+shapeSegmentQuery (S shape _) p1 p2 =     withForeignPtr shape $ \shape_ptr ->     with p1 $ \p1_ptr ->     with p2 $ \p2_ptr ->     allocaBytes #{size cpSegmentQueryInfo} $ \info_ptr -> do-      i <- wrShapeSegmentQuery shape_ptr p1_ptr p2_ptr layers group info_ptr+      i <- wrShapeSegmentQuery shape_ptr p1_ptr p2_ptr info_ptr       if (i == 0) then return Nothing else do         t <- #{peek cpSegmentQueryInfo, t} info_ptr         n <- #{peek cpSegmentQueryInfo, n} info_ptr@@ -349,7 +348,7 @@  foreign import ccall unsafe "wrapper.h"     wrShapeSegmentQuery :: ShapePtr -> VectorPtr -> VectorPtr-                        -> Layers -> Group -> Ptr () -> IO CInt+                        -> Ptr () -> IO CInt   
Physics/Hipmunk/Space.hsc view
@@ -1,7 +1,7 @@ ----------------------------------------------------------------------------- -- | -- Module      :  Physics/Hipmunk/Space.hsc--- Copyright   :  (c) 2008-2009 Felipe A. Lessa+-- Copyright   :  (c) 2008-2010 Felipe A. Lessa -- License     :  MIT (see LICENSE) -- -- Maintainer  :  felipe.lessa@gmail.com@@ -21,7 +21,7 @@      Space,      newSpace,      freeSpace,-     Entity(..),+     Entity(spaceAdd, spaceRemove),      StaticShape(..),       -- * Properties@@ -55,26 +55,15 @@      spaceQueryList,       -- * Stepping-     step,--     -- ** Collision pair functions-     -- $callbacks-     Callback(..),-     setDefaultCallback,-     addCallback,-     removeCallback,--     -- ** Contacts-     Contact(..),-     sumImpulses,-     sumImpulsesWithFriction,+     step     )     where +import qualified Data.Foldable as F+import qualified Data.Map as M import Control.Exception (bracket)-import Data.Array.Storable+import Control.Monad (when) import Data.IORef-import qualified Data.Map as M import Foreign hiding (new) import Foreign.C.Types (CInt) #include "wrapper.h"@@ -113,6 +102,9 @@ --   run unchanged on every Haskell environment supporting --   FFI with C99, but also that you have to take care to --   avoid memory leaks. You've been warned! :)+--+--   Note: callbacks are implemented in+--   "Physics.Hipmunk.Callbacks" module.   -- | Creates a new, empty space.@@ -126,7 +118,8 @@     cpSpaceInit sp_ptr     addForeignPtrFinalizer cpSpaceDestroy sp     entities  <- newIORef M.empty-    callbacks <- newIORef (Nothing, M.empty)+    let n = nullFunPtr+    callbacks <- newIORef $ CBs (n,n,n,n) M.empty []     return (P sp entities callbacks)  foreign import ccall unsafe "wrapper.h"@@ -147,22 +140,19 @@   let err :: a       err = error "Physics.Hipmunk.Space: freeSpace already called here."   writeIORef entities err-  (def,cbs) <- readIORef callbacks+  CBs def cbs post <- readIORef callbacks   writeIORef callbacks err-  maybe (return ()) freeHaskellFunPtr def-  M.fold ((>>) . freeHaskellFunPtr) (return ()) cbs+  freeHandlerFunPtrs def+  freeAll freeHandlerFunPtrs cbs+  freeAll freeHaskellFunPtr  post +freeAll :: F.Foldable t => (a -> IO ()) -> t a -> IO ()+freeAll f = F.foldr ((>>) . f) (return ()) --- | Type class implemented by entities that can be---   added to a space.-class Entity a where-    -- | Add an entity to a 'Space'. Don't add the same-    --   entity twice to a space.-    spaceAdd :: Space -> a -> IO ()-    -- | Remove an entity from a 'Space'. Don't remove-    --   an entity that wasn't add.-    spaceRemove :: Space -> a -> IO () ++-- Entity class is imported from Internal.+ spaceAddHelper :: (a -> ForeignPtr b)                -> (SpacePtr -> Ptr b -> IO ())                -> (a -> Maybe Shape)@@ -202,6 +192,7 @@ instance Entity Body where     spaceAdd    = spaceAddHelper    unB cpSpaceAddBody (const Nothing)     spaceRemove = spaceRemoveHelper unB cpSpaceRemoveBody+    entityPtr   = unB foreign import ccall unsafe "wrapper.h"     cpSpaceAddBody :: SpacePtr -> BodyPtr -> IO () foreign import ccall unsafe "wrapper.h"@@ -210,14 +201,17 @@ instance Entity Shape where     spaceAdd    = spaceAddHelper    unS cpSpaceAddShape Just     spaceRemove = spaceRemoveHelper unS cpSpaceRemoveShape+    entityPtr   = unS foreign import ccall unsafe "wrapper.h"     cpSpaceAddShape :: SpacePtr -> ShapePtr -> IO ()-foreign import ccall unsafe "wrapper.h"+foreign import ccall {- !!! -} safe {- !!! -} "wrapper.h"     cpSpaceRemoveShape :: SpacePtr -> ShapePtr -> IO ()+    -- may call the 'separate' handler.  instance Entity (Constraint a) where     spaceAdd    = spaceAddHelper    unC cpSpaceAddConstraint (const Nothing)     spaceRemove = spaceRemoveHelper unC cpSpaceRemoveConstraint+    entityPtr   = castForeignPtr . unC foreign import ccall unsafe "wrapper.h"     cpSpaceAddConstraint :: SpacePtr -> ConstraintPtr -> IO () foreign import ccall unsafe "wrapper.h"@@ -239,10 +233,12 @@ instance Entity StaticShape where     spaceAdd    = spaceAddHelper    (unS . unStatic) cpSpaceAddStaticShape (Just . unStatic)     spaceRemove = spaceRemoveHelper (unS . unStatic) cpSpaceRemoveStaticShape+    entityPtr   = castForeignPtr . unS . unStatic foreign import ccall unsafe "wrapper.h"     cpSpaceAddStaticShape :: SpacePtr -> ShapePtr -> IO ()-foreign import ccall unsafe "wrapper.h"+foreign import ccall {- !!! -} safe {- !!! -} "wrapper.h"     cpSpaceRemoveStaticShape :: SpacePtr -> ShapePtr -> IO ()+    -- may call the 'separate' handler.   @@ -260,12 +256,13 @@       #{poke cpSpace, iterations} sp_ptr it  -- | The number of elastic iterations to use when solving---   constraints.  (default is 0, meaning old-style elastic code---   will be used, which probably isn't what you want).+--   constraints.  If @0@, then old-style elastic code is used.+--   (default is 0). type ElasticIterations = CInt getElasticIterations :: Space -> IO ElasticIterations getElasticIterations (P sp _ _) =     withForeignPtr sp #{peek cpSpace, elasticIterations}+{-# DEPRECATED setElasticIterations "Elastic iterations should no longer be needed" #-} setElasticIterations :: Space -> ElasticIterations -> IO () setElasticIterations (P sp _ _) it =     withForeignPtr sp $ \sp_ptr -> do@@ -366,7 +363,7 @@ -- --   * Isn't of the same group as @g@. -----   * Shares at least on layer with @l@.+--   * Shares at least one layer with @l@. -- --   The order in which the callback is called is unspecified. --   However it is guaranteed that it will be called once,@@ -407,250 +404,16 @@ --   the efficiency of contact persistence. Some tips may be --   found in <http://www.gaffer.org/game-physics/fix-your-timestep>. step :: Space -> Time -> IO ()-step (P sp _ _) dt =+step (P sp _ callbacks) dt = do   withForeignPtr sp $ \sp_ptr -> do     cpSpaceStep sp_ptr dt+  cbs@(CBs {cbsPostStep = post}) <- readIORef callbacks+  when (not $ null post) $ do+    freeAll freeHaskellFunPtr post+    writeIORef callbacks (cbs {cbsPostStep = []}) + -- IMPORTANT! This call can (and probably will) callback into Haskell. foreign import ccall {- !!! -} safe {- !!! -}     cpSpaceStep :: SpacePtr -> Time -> IO ()------- $callbacks---   A collision pair function is a callback triggered by 'step'---   in response to certain collision events. Its return value---   will determine whether or not the collision will be processed.---   If @False@, then the collision will be ignored.------   The callbacks themselves may execute arbitrary operations---   with a simple exception: /callbacks cannot add or remove/---   /entities from the space/. You can of course create a queue---   of add\/remove actions and then process it after 'step'---   returns.------   As for the events that trigger collision pair functions, the---   rule is simple. All shapes have a 'CollisionType'.  When---   shapes @a@ and @b@ collide, if there was a callback---   associated with @a@'s and @b@'s collision types, then it is---   called. Otherwise the default callback is called.  The---   default callback always returns @True@ (i.e. all collisions---   are treated).----- | A 'Callback' function can be of three types:------   * A 'Full' callback has access to all parameters passed---     by Chipmunk, but it is common not to need all of them.---     The two colliding 'Shape's are passed as arguments with---     a 'Contact' array and a normal coefficient (this coefficient---     should be multiplied to the contacts' normals as---     Chipmunk may have reversed the argument order). See 'Contact'---     for more information.------   * A 'Basic' callback can't access the 'Contact' information,---     but incurs a lower overhead per call.------   * A 'Constant' callback always accepts or reject the collision.---     For example, a @Constant False@ will never accept any---     collision.------   Although 'Basic' and 'Constant' can be implemented---   in terms of 'Full', they're optimized to incur less overhead.---   So try to use the simplest callback type---   (e.g. @Constant False@ instead of @Basic (\_ _ -> return False)@).-data Callback = Full (Shape -> Shape -> StorableArray Int Contact-                      -> CpFloat -> IO Bool)-              | Basic (Shape -> Shape -> IO Bool)-              | Constant !Bool----- | Internal. Type of callback used by Chipmunk.-type ChipmunkCB = ShapePtr -> ShapePtr -> ContactPtr -> CInt-                -> CpFloat -> Ptr () -> IO Int-type ChipmunkCBPtr = FunPtr ChipmunkCB----- | Internal. Constructs a 'ChipmunkCB' from a 'Callback',---   returning also the contents of the @data@ pointer.-adaptChipmunkCB :: Space -> Callback-                -> IO (ChipmunkCBPtr, Ptr (), Maybe (FunPtr ()))-adaptChipmunkCB _ (Constant bool) =-  let data_ = intPtrToPtr (if bool then 1 else 0)-  in return (wrConstantCallback, data_, Nothing)-adaptChipmunkCB spce (Basic basic) = makeChipmunkCB' $-  \ptr1 ptr2 _ _ _ _ -> do-    shape1 <- retriveShape spce ptr1-    shape2 <- retriveShape spce ptr2-    okay <- basic shape1 shape2-    return (if okay then 1 else 0)-adaptChipmunkCB spce (Full full) = makeChipmunkCB' $-  \ptr1 ptr2 cont_ptr cont_num normal_coef _ -> do-    shape1 <- retriveShape spce ptr1-    shape2 <- retriveShape spce ptr2--    -- Wrap the pointer in an array. Note that the memory-    -- is managed by Chipmunk, so we don't have finalizers.-    cont_fptr <- newForeignPtr_ cont_ptr-    let bounds = (0, fromIntegral $ cont_num-1)-    array <- unsafeForeignPtrToStorableArray cont_fptr bounds--    okay <- full shape1 shape2 array normal_coef-    return (if okay then 1 else 0)--makeChipmunkCB' :: ChipmunkCB-                -> IO (ChipmunkCBPtr, Ptr (), Maybe (FunPtr ()))-makeChipmunkCB' f = do-  f' <- makeChipmunkCB f-  return (f', nullPtr, Just $ castFunPtr f')--foreign import ccall "wrapper"-    makeChipmunkCB :: ChipmunkCB -> IO ChipmunkCBPtr--foreign import ccall unsafe "wrapper.h &wrConstantCallback"-    wrConstantCallback :: ChipmunkCBPtr---- | Internal. Retrive a 'Shape' from a 'ShapePtr' and a 'Space'.-retriveShape :: Space -> ShapePtr -> IO Shape-retriveShape (P _ entities _) ptr = do-  ent <- readIORef entities-  let Just (Right shape) = M.lookup (castPtr ptr) ent-  return shape----- | Defines a new default collision pair function.---   This callback is called whenever two shapes @a@---   and @b@ collide such that no other collision---   pair function was defined to @a@'s and @b@'s---   collision types. The default is @Constant True@.-setDefaultCallback :: Space -> Callback -> IO ()-setDefaultCallback spce@(P sp _ callbacks) func = do-  -- Find out whats our new function details-  -- (NULL for default means @Constant True@, optimize it)-  (cb,data_,hask) <--      case func of-        Constant True -> return (nullFunPtr, nullPtr, Nothing)-        _             -> adaptChipmunkCB spce func--  -- Free the previous one-  (def,cbs) <- readIORef callbacks-  case def of-    Nothing  -> return ()-    Just ptr -> freeHaskellFunPtr ptr--  -- Define the new-  writeIORef callbacks (hask,cbs)-  withForeignPtr sp $ \sp_ptr -> do-    cpSpaceSetDefaultCollisionPairFunc sp_ptr cb data_--foreign import ccall unsafe "wrapper.h"-    cpSpaceSetDefaultCollisionPairFunc-        :: SpacePtr -> ChipmunkCBPtr -> Ptr () -> IO ()----- | @addCallback sp (cta,ctb) f@ defines @f@ as the callback---   to be called whenever a collision occurs between---   a shape of collision type @cta@ and another of---   collision type @ctb@ (and vice versa). Any other callback---   already registered to handle @(cta,ctb)@ will be removed.------   Note that you should /not/ add callbacks to both---   combinations of @(cta,ctb)@ and @(ctb,cta)@. A good rule---   of thumb is to always use @cta <= ctb@, although this---   is not necessary.-addCallback :: Space -> (CollisionType, CollisionType) -> Callback -> IO ()-addCallback spce@(P sp _ callbacks) (cta,ctb) func = do-  -- Find out whats our new function details-  -- (NULL for a specific means @Constant False@, optimize it)-  (cb,data_,hask) <--      case func of-        Constant False -> return (nullFunPtr, nullPtr, Nothing)-        _              -> adaptChipmunkCB spce func--  -- Free the previous one, using-  --   updateLookupWithKey :: Ord k => (k -> a -> Maybe a) -> k-  --                       -> Map k a -> (Maybe a, Map k a)-  (def,cbs) <- readIORef callbacks-  let (old,cbs') = M.updateLookupWithKey (\_ _ -> hask) (cta,ctb) cbs-  case old of-    Nothing  -> return ()-    Just ptr -> freeHaskellFunPtr ptr--  -- Define the new-  writeIORef callbacks (def,cbs')-  withForeignPtr sp $ \sp_ptr -> do-    cpSpaceAddCollisionPairFunc sp_ptr cta ctb cb data_--foreign import ccall unsafe "wrapper.h"-    cpSpaceAddCollisionPairFunc-        :: SpacePtr -> CollisionType -> CollisionType-        -> ChipmunkCBPtr -> Ptr () -> IO ()---- | @removeCallback sp (cta,ctb)@ removes any callbacks that---   were registered to handle @(cta,ctb)@ (see 'addCallback').---   Any collisions that would be handled by the removed---   callback will be handled by the default one (see---   'setDefaultCallback').------   Note that you should /always/ use the same order that---   was passed to 'addCallback'. In other words, after---   @addCallback sp (cta,ctb) f@ you should use---   @removeCallback sp (cta,ctb)@, and /never/---   @removeCallback sp (ctb,cta)@.------   Although pointless, it is harmless to remove a callback---   that was not added.-removeCallback :: Space -> (CollisionType, CollisionType) -> IO ()-removeCallback (P sp _ callbacks) (cta,ctb) = do-  -- Free the callback-  (def,cbs) <- readIORef callbacks-  let (old,cbs') = M.updateLookupWithKey (\_ _ -> Nothing) (cta,ctb) cbs-  case old of-    Nothing  -> return ()-    Just ptr -> freeHaskellFunPtr ptr--  -- Remove the callback-  --   Note that we need to call Chipmunk even if old is Nothing-  --   because wrConstantCallback is not added to cbs. And-  --   removing what was not added is harmless here.-  writeIORef callbacks (def,cbs')-  withForeignPtr sp $ \sp_ptr -> do-    cpSpaceRemoveCollisionPairFunc sp_ptr cta ctb--foreign import ccall unsafe "wrapper.h"-    cpSpaceRemoveCollisionPairFunc-      :: SpacePtr -> CollisionType -> CollisionType -> IO ()----- | Sums the impulses applied to the given contact points.---   'sumImpulses' sums only the normal components.---   This function should be called only after 'step'---   returns.-sumImpulses :: StorableArray Int Contact -> IO Vector-sumImpulses = sumImpulsesInternal wrContactsSumImpulses--foreign import ccall unsafe "wrapper.h"-    wrContactsSumImpulses :: ContactPtr -> CInt-                          -> VectorPtr -> IO ()---- | Sums the impulses applied to the given contact points.---   This function sums both the normal and tangential components---   and should be called only after 'step' returns.-sumImpulsesWithFriction :: StorableArray Int Contact -> IO Vector-sumImpulsesWithFriction =-    sumImpulsesInternal wrContactsSumImpulsesWithFriction--foreign import ccall unsafe "wrapper.h"-    wrContactsSumImpulsesWithFriction :: ContactPtr -> CInt-                                      -> VectorPtr -> IO ()--sumImpulsesInternal :: (ContactPtr -> CInt -> VectorPtr -> IO ())-                    -> StorableArray Int Contact -> IO Vector-sumImpulsesInternal func sa = do-  (i1,i2) <- getBounds sa-  withStorableArray sa $ \sa_ptr ->-    with 0 $ \vec_ptr -> do-      func sa_ptr (fromIntegral $ i2-i1) vec_ptr-      peek vec_ptr 
Physics/Hipmunk/Unsafe.hsc view
@@ -1,7 +1,7 @@ ----------------------------------------------------------------------------- -- | -- Module      :  Physics/Hipmunk/Unsafe.hsc--- Copyright   :  (c) 2008-2009 Felipe A. Lessa+-- Copyright   :  (c) 2008-2010 Felipe A. Lessa -- License     :  MIT (see LICENSE) -- -- Maintainer  :  felipe.lessa@gmail.com@@ -32,7 +32,6 @@ import Physics.Hipmunk.Common import Physics.Hipmunk.Internal import Physics.Hipmunk.Shape-import Physics.Hipmunk.Constraint (Unknown)  -- | @unsafeShapeRedefine shape type off@ redefines @shape@ to --   have new parameters described on @type@ and to be at offset
Physics/Hipmunk/wrapper.c view
@@ -1,12 +1,6 @@ #include <stdlib.h> #include "wrapper.h" -// New functions-int wrConstantCallback(cpShape *a, cpShape *b, cpContact *contacts,-                       int numContacts, cpFloat normal_coef, void *data) {-    return (data == 0 ? 0 : 1);-}- // From cpBody.h void wrBodyUpdateVelocity(cpBody *b, cpVect *g, cpFloat d, cpFloat dt) {     cpBodyUpdateVelocity(b, *g, d, dt);@@ -42,16 +36,13 @@                         cpVect *a, cpVect *b, cpFloat r) {     cpSegmentShapeInit(seg, body, *a, *b, r); }-int wrShapePointQuery(cpShape *shape, cpVect *p,-                      cpLayers layers, cpGroup group) {-    return cpShapePointQuery(shape, *p, layers, group);+int wrShapePointQuery(cpShape *shape, cpVect *p) {+    return cpShapePointQuery(shape, *p); } -int cpShapeSegmentQuery(cpShape*, cpVect, cpVect, cpLayers, cpGroup, cpSegmentQueryInfo*); int wrShapeSegmentQuery(cpShape *shape, cpVect *a, cpVect *b,-                        cpLayers layers, cpGroup group,                         cpSegmentQueryInfo *info) {-    return cpShapeSegmentQuery(shape, *a, *b, layers, group, info);+    return cpShapeSegmentQuery(shape, *a, *b, info); }  @@ -96,6 +87,10 @@                               cpDampedRotarySpring *joint, cpBody *a, cpBody *b) {     cpDampedRotarySpringInit(joint, a, b, restAngle, stiffness, damping); }+void wrRatchetJointInit(cpFloat phase, cpFloat ratchet,+                        cpRatchetJoint* joint, cpBody* a, cpBody* b) {+    cpRatchetJointInit(joint, a, b, phase, ratchet);+} void wrRotaryLimitJointInit(cpFloat min, cpFloat max,                             cpRotaryLimitJoint *joint, cpBody *a, cpBody *b) {     cpRotaryLimitJointInit(joint, a, b, min, max);@@ -105,12 +100,14 @@ }  // From cpArbiter.h-void wrContactsSumImpulses(cpContact *contacts, int numContacts, cpVect *ret) {-    *ret = cpContactsSumImpulses(contacts, numContacts);+void wrArbiterTotalImpulse(cpArbiter *arb, cpVect *ret) {+    *ret = cpArbiterTotalImpulse(arb); }-void wrContactsSumImpulsesWithFriction(cpContact *contacts, int numContacts,-                                       cpVect *ret) {-    *ret = cpContactsSumImpulsesWithFriction(contacts, numContacts);+void wrArbiterTotalImpulseWithFriction(cpArbiter *arb, cpVect *ret) {+    *ret = cpArbiterTotalImpulseWithFriction(arb);+}+void wrArbiterGetNormal(cpArbiter *arb, cpVect *ret) {+    *ret = cpArbiterGetNormal(arb, 0); }  // From cpSpace.h
Physics/Hipmunk/wrapper.h view
@@ -4,9 +4,6 @@ #include "chipmunk.h" #include "chipmunk_unsafe.h" -// New functions-int wrConstantCallback(cpShape*, cpShape*, cpContact*, int, cpFloat, void*);- // From cpBody.h void wrBodyUpdateVelocity(cpBody*, cpVect*, cpFloat, cpFloat); void wrBodyApplyImpulse(cpBody*, cpVect*, cpVect*);@@ -18,8 +15,8 @@ // From cpShape.h void wrCircleShapeInit(cpCircleShape*, cpBody*, cpVect*, cpFloat); void wrSegmentShapeInit(cpSegmentShape*, cpBody*, cpVect*, cpVect*, cpFloat);-int wrShapePointQuery(cpShape*, cpVect*, cpLayers, cpGroup);-int wrShapeSegmentQuery(cpShape*, cpVect*, cpVect*, cpLayers, cpGroup, cpSegmentQueryInfo*);+int wrShapePointQuery(cpShape*, cpVect*);+int wrShapeSegmentQuery(cpShape*, cpVect*, cpVect*, cpSegmentQueryInfo*);  // From cpPolyShape.h void wrPolyShapeInit(cpPolyShape*, cpBody*, int, cpVect*, cpVect*);@@ -34,12 +31,14 @@ void wrGearJointInit(cpFloat, cpFloat, cpGearJoint*, cpBody*, cpBody*); void wrDampedSpringInit(cpFloat, cpFloat, cpFloat, cpVect*, cpVect*, cpDampedSpring*, cpBody*, cpBody*); void wrDampedRotarySpringInit(cpFloat, cpFloat, cpFloat, cpDampedRotarySpring*, cpBody*, cpBody*);+void wrRatchetJointInit(cpFloat, cpFloat, cpRatchetJoint*, cpBody*, cpBody*); void wrRotaryLimitJointInit(cpFloat, cpFloat, cpRotaryLimitJoint*, cpBody*, cpBody*); void wrSimpleMotorInit(cpFloat, cpSimpleMotor*, cpBody*, cpBody*);  // From cpArbiter.h-void wrContactsSumImpulses(cpContact*, int, cpVect*);-void wrContactsSumImpulsesWithFriction(cpContact*, int, cpVect*);+void wrArbiterTotalImpulse(cpArbiter*, cpVect*);+void wrArbiterTotalImpulseWithFriction(cpArbiter*, cpVect*);+void wrArbiterGetNormal(cpArbiter*, cpVect*);  // From cpSpace.h void wrSpacePointQuery(cpSpace*, cpVect*, cpLayers, cpGroup, cpSpacePointQueryFunc);
− chipmunk-5.0/chipmunk.c
@@ -1,78 +0,0 @@-/* Copyright (c) 2007 Scott Lembcke- * - * Permission is hereby granted, free of charge, to any person obtaining a copy- * of this software and associated documentation files (the "Software"), to deal- * in the Software without restriction, including without limitation the rights- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell- * copies of the Software, and to permit persons to whom the Software is- * furnished to do so, subject to the following conditions:- * - * The above copyright notice and this permission notice shall be included in- * all copies or substantial portions of the Software.- * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE- * SOFTWARE.- */- -#include <stdlib.h>--#include "chipmunk.h"--#ifdef __cplusplus-extern "C" {-#endif-	void cpInitCollisionFuncs(void);-#ifdef __cplusplus-}-#endif---void-cpInitChipmunk(void)-{-	cpInitCollisionFuncs();-}--cpFloat-cpMomentForCircle(cpFloat m, cpFloat r1, cpFloat r2, cpVect offset)-{-	return (1.0f/2.0f)*m*(r1*r1 + r2*r2) + m*cpvdot(offset, offset);-}--cpFloat-cpMomentForSegment(cpFloat m, cpVect a, cpVect b)-{-	cpFloat length = cpvlength(cpvsub(b, a));-	cpVect offset = cpvmult(cpvadd(a, b), 1.0f/2.0f);-	-	return m*length*length/12.0f + m*cpvdot(offset, offset);-}--cpFloat-cpMomentForPoly(cpFloat m, const int numVerts, cpVect *verts, cpVect offset)-{-	cpVect *tVerts = (cpVect *)calloc(numVerts, sizeof(cpVect));-	for(int i=0; i<numVerts; i++)-		tVerts[i] = cpvadd(verts[i], offset);-	-	cpFloat sum1 = 0.0f;-	cpFloat sum2 = 0.0f;-	for(int i=0; i<numVerts; i++){-		cpVect v1 = tVerts[i];-		cpVect v2 = tVerts[(i+1)%numVerts];-		-		cpFloat a = cpvcross(v2, v1);-		cpFloat b = cpvdot(v1, v1) + cpvdot(v1, v2) + cpvdot(v2, v2);-		-		sum1 += a*b;-		sum2 += a;-	}-	-	free(tVerts);-	return (m*sum1)/(6.0f*sum2);-}
− chipmunk-5.0/chipmunk.h
@@ -1,104 +0,0 @@-/* Copyright (c) 2007 Scott Lembcke- * - * Permission is hereby granted, free of charge, to any person obtaining a copy- * of this software and associated documentation files (the "Software"), to deal- * in the Software without restriction, including without limitation the rights- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell- * copies of the Software, and to permit persons to whom the Software is- * furnished to do so, subject to the following conditions:- * - * The above copyright notice and this permission notice shall be included in- * all copies or substantial portions of the Software.- * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE- * SOFTWARE.- */--#ifndef CHIPMUNK_HEADER-#define CHIPMUNK_HEADER--#ifdef __cplusplus-extern "C" {-#endif--#include "chipmunk_types.h"-	-static inline cpFloat-cpfmax(cpFloat a, cpFloat b)-{-	return (a > b) ? a : b;-}--static inline cpFloat-cpfmin(cpFloat a, cpFloat b)-{-	return (a < b) ? a : b;-}--static inline cpFloat-cpfabs(cpFloat n)-{-	return (n < 0) ? -n : n;-}--static inline cpFloat-cpfclamp(cpFloat f, cpFloat min, cpFloat max){-	return cpfmin(cpfmax(f, min), max);-}--#ifndef INFINITY-	#ifdef _MSC_VER-		union MSVC_EVIL_FLOAT_HACK-		{-			unsigned __int8 Bytes[4];-			float Value;-		};-		static union MSVC_EVIL_FLOAT_HACK INFINITY_HACK = {{0x00, 0x00, 0x80, 0x7F}};-		#define INFINITY (INFINITY_HACK.Value)-	#else-		#define INFINITY (1e1000)-	#endif-#endif--#include "cpVect.h"-#include "cpBB.h"-#include "cpBody.h"-#include "cpArray.h"-#include "cpHashSet.h"-#include "cpSpaceHash.h"--#include "cpShape.h"-#include "cpPolyShape.h"--#include "cpArbiter.h"-#include "cpCollision.h"-	-#include "constraints/cpConstraint.h"--#include "cpSpace.h"--#define CP_HASH_COEF (3344921057ul)-#define CP_HASH_PAIR(A, B) ((cpHashValue)(A)*CP_HASH_COEF ^ (cpHashValue)(B)*CP_HASH_COEF)--void cpInitChipmunk(void);--// Calculate the moment of inertia for a circle, r1 and r2 are the inner and outer diameters.-// (A solid circle has an inner diameter of 0)-cpFloat cpMomentForCircle(cpFloat m, cpFloat r1, cpFloat r2, cpVect offset);--// Calculate the moment of inertia for a line segment. (beveling radius not supported)-cpFloat cpMomentForSegment(cpFloat m, cpVect a, cpVect b);--// Calculate the moment of inertia for a solid polygon shape.-cpFloat cpMomentForPoly(cpFloat m, int numVerts, cpVect *verts, cpVect offset);--#ifdef __cplusplus-}-#endif--#endif
− chipmunk-5.0/chipmunk_types.h
@@ -1,26 +0,0 @@-typedef double cpFloat;-#define cpfsqrt sqrt-#define cpfsin sin-#define cpfcos cos-#define cpfatan2 atan2-#define cpfmod fmod-#define cpfexp exp-#define cpfpow pow-#define cpffloor floor-#define cpfceil ceil-	-//typedef float cpFloat;-//#define cpfsqrt sqrtf-//#define cpfsin sinf-//#define cpfcos cosf-//#define cpfatan2 atan2f-//#define cpfmod fmodf-//#define cpfexp expf-//#define cpfpow powf-//#define cpffloor floorf-//#define cpfceil ceilf--typedef size_t cpHashValue;-typedef unsigned int cpCollisionType;-typedef unsigned int cpLayers;-typedef unsigned int cpGroup;
− chipmunk-5.0/chipmunk_unsafe.h
@@ -1,54 +0,0 @@-/* Copyright (c) 2007 Scott Lembcke- * - * Permission is hereby granted, free of charge, to any person obtaining a copy- * of this software and associated documentation files (the "Software"), to deal- * in the Software without restriction, including without limitation the rights- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell- * copies of the Software, and to permit persons to whom the Software is- * furnished to do so, subject to the following conditions:- * - * The above copyright notice and this permission notice shall be included in- * all copies or substantial portions of the Software.- * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE- * SOFTWARE.- */----/* This header defines a number of "unsafe" operations on Chipmunk objects.- * In this case "unsafe" is referring to operations which may reduce the- * physical accuracy or numerical stability of the simulation, but will not- * cause crashes.- *- * The prime example is mutating collision shapes. Chipmunk does not support- * this directly. Mutating shapes using this API will caused objects in contact- * to be pushed apart using Chipmunk's overlap solver, but not using real- * persistent velocities. Probably not what you meant, but perhaps close enough.- */--#ifndef CHIPMUNK_UNSAFE_HEADER-#define CHIPMUNK_UNSAFE_HEADER--#ifdef __cplusplus-extern "C" {-#endif--void cpCircleShapeSetRadius(cpShape *shape, cpFloat radius);-void cpCircleShapeSetOffset(cpShape *shape, cpVect offset);--void cpSegmentShapeSetEndpoints(cpShape *shape, cpVect a, cpVect b);-void cpSegmentShapeSetRadius(cpShape *shape, cpFloat radius);--void cpPolyShapeSetVerts(cpShape *shape, int numVerts, cpVect *verts, cpVect offset);--#ifdef __cplusplus-}-#endif--#endif
− chipmunk-5.0/constraints/cpConstraint.c
@@ -1,60 +0,0 @@-/* Copyright (c) 2007 Scott Lembcke- * - * Permission is hereby granted, free of charge, to any person obtaining a copy- * of this software and associated documentation files (the "Software"), to deal- * in the Software without restriction, including without limitation the rights- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell- * copies of the Software, and to permit persons to whom the Software is- * furnished to do so, subject to the following conditions:- * - * The above copyright notice and this permission notice shall be included in- * all copies or substantial portions of the Software.- * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE- * SOFTWARE.- */--#include <stdlib.h>-#include <assert.h>--#include "../chipmunk.h"-#include "util.h"--// TODO: Comment me!--cpFloat cp_constraint_bias_coef = 0.1f;--void cpConstraintDestroy(cpConstraint *constraint){}--void-cpConstraintFree(cpConstraint *constraint)-{-	if(constraint) cpConstraintDestroy(constraint);-	free(constraint);-}--void-cpConstraintCheckCast(cpConstraint *constraint, const cpConstraintClass *klass)-{-	assert(constraint->klass == klass); // Bad cpConstraint type in cast-}---// *** defined in util.h--void-cpConstraintInit(cpConstraint *constraint, const cpConstraintClass *klass, cpBody *a, cpBody *b)-{-	constraint->klass = klass;-	constraint->a = a;-	constraint->b = b;-	-	constraint->maxForce = INFINITY;-	constraint->biasCoef = cp_constraint_bias_coef;-	constraint->maxBias = INFINITY;-}
− chipmunk-5.0/constraints/cpConstraint.h
@@ -1,90 +0,0 @@-/* Copyright (c) 2007 Scott Lembcke- * - * Permission is hereby granted, free of charge, to any person obtaining a copy- * of this software and associated documentation files (the "Software"), to deal- * in the Software without restriction, including without limitation the rights- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell- * copies of the Software, and to permit persons to whom the Software is- * furnished to do so, subject to the following conditions:- * - * The above copyright notice and this permission notice shall be included in- * all copies or substantial portions of the Software.- * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE- * SOFTWARE.- */--// TODO: Comment me!-	-extern cpFloat cp_constraint_bias_coef;--struct cpConstraintClass;-struct cpConstraint;--typedef void (*cpConstraintPreStepFunction)(struct cpConstraint *constraint, cpFloat dt, cpFloat dt_inv);-typedef void (*cpConstraintApplyImpulseFunction)(struct cpConstraint *constraint);-typedef cpFloat (*cpConstraintGetImpulseFunction)(struct cpConstraint *constraint);--typedef struct cpConstraintClass {-	cpConstraintPreStepFunction preStep;-	cpConstraintApplyImpulseFunction applyImpulse;-	cpConstraintGetImpulseFunction getImpulse;-} cpConstraintClass;----typedef struct cpConstraint {-	const cpConstraintClass *klass;-	-	cpBody *a, *b;-	cpFloat maxForce;-	cpFloat biasCoef;-	cpFloat maxBias;-	-	void *data;-} cpConstraint;--void cpConstraintDestroy(cpConstraint *constraint);-void cpConstraintFree(cpConstraint *constraint);---void cpConstraintCheckCast(cpConstraint *constraint, const cpConstraintClass *klass);--#define CP_DefineConstraintProperty(struct, type, member, name) \-static inline type \-struct##Get##name(cpConstraint *constraint){ \-	cpConstraintCheckCast(constraint, struct##GetClass()); \-	return ((struct *)constraint)->member; \-} \-static inline void \-struct##Set##name(cpConstraint *constraint, type value){ \-	cpConstraintCheckCast(constraint, struct##GetClass()); \-	((struct *)constraint)->member = value; \-} \-/* These are for compatibility with the interim trunk version, for some reason I thought I needed the underscores to make the macro work */ \-static inline type \-struct##_get_##member(cpConstraint *constraint){ \-	cpConstraintCheckCast(constraint, struct##GetClass()); \-	return ((struct *)constraint)->member; \-} \-static inline void \-struct##_set_##member(cpConstraint *constraint, type value){ \-	cpConstraintCheckCast(constraint, struct##GetClass()); \-	((struct *)constraint)->member = value; \-}--// Built in Joint types-#include "cpPinJoint.h"-#include "cpSlideJoint.h"-#include "cpPivotJoint.h"-#include "cpGrooveJoint.h"-#include "cpDampedSpring.h"-#include "cpDampedRotarySpring.h"-#include "cpRotaryLimitJoint.h"-#include "cpGearJoint.h"-#include "cpSimpleMotor.h"
− chipmunk-5.0/constraints/cpDampedRotarySpring.c
@@ -1,106 +0,0 @@-/* Copyright (c) 2007 Scott Lembcke- * - * Permission is hereby granted, free of charge, to any person obtaining a copy- * of this software and associated documentation files (the "Software"), to deal- * in the Software without restriction, including without limitation the rights- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell- * copies of the Software, and to permit persons to whom the Software is- * furnished to do so, subject to the following conditions:- * - * The above copyright notice and this permission notice shall be included in- * all copies or substantial portions of the Software.- * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE- * SOFTWARE.- */--#include <stdlib.h>-#include <math.h>--#include "../chipmunk.h"-#include "util.h"--static cpFloat-defaultSpringTorque(cpDampedRotarySpring *spring, cpFloat relativeAngle){-	return (relativeAngle - spring->restAngle)*spring->stiffness;-}--static void-preStep(cpDampedRotarySpring *spring, cpFloat dt, cpFloat dt_inv)-{-	cpBody *a = spring->constraint.a;-	cpBody *b = spring->constraint.b;-	-	spring->iSum = 1.0f/(a->i_inv + b->i_inv);--	spring->dt = dt;-	spring->target_wrn = 0.0f;--	// apply spring torque-	cpFloat j_spring = spring->springTorqueFunc((cpConstraint *)spring, a->a - b->a)*dt;-	a->w -= j_spring*a->i_inv;-	b->w += j_spring*b->i_inv;-}--static void-applyImpulse(cpDampedRotarySpring *spring)-{-	cpBody *a = spring->constraint.a;-	cpBody *b = spring->constraint.b;-	-	// compute relative velocity-	cpFloat wrn = a->w - b->w;//normal_relative_velocity(a, b, r1, r2, n) - spring->target_vrn;-	-	// compute velocity loss from drag-	// not 100% certain this is derived correctly, though it makes sense-	cpFloat w_damp = wrn*(1.0f - cpfexp(-spring->damping*spring->dt/spring->iSum));-	spring->target_wrn = wrn - w_damp;-	-	//apply_impulses(a, b, spring->r1, spring->r2, cpvmult(spring->n, v_damp*spring->nMass));-	cpFloat j_damp = w_damp*spring->iSum;-	a->w -= j_damp*a->i_inv;-	b->w += j_damp*b->i_inv;-}--static cpFloat-getImpulse(cpConstraint *constraint)-{-	return 0.0f;-}--static const cpConstraintClass klass = {-	(cpConstraintPreStepFunction)preStep,-	(cpConstraintApplyImpulseFunction)applyImpulse,-	(cpConstraintGetImpulseFunction)getImpulse,-};-CP_DefineClassGetter(cpDampedRotarySpring)--cpDampedRotarySpring *-cpDampedRotarySpringAlloc(void)-{-	return (cpDampedRotarySpring *)malloc(sizeof(cpDampedRotarySpring));-}--cpDampedRotarySpring *-cpDampedRotarySpringInit(cpDampedRotarySpring *spring, cpBody *a, cpBody *b, cpFloat restAngle, cpFloat stiffness, cpFloat damping)-{-	cpConstraintInit((cpConstraint *)spring, &klass, a, b);-	-	spring->restAngle = restAngle;-	spring->stiffness = stiffness;-	spring->damping = damping;-	spring->springTorqueFunc = (cpDampedRotarySpringTorqueFunc)defaultSpringTorque;-	-	return spring;-}--cpConstraint *-cpDampedRotarySpringNew(cpBody *a, cpBody *b, cpFloat restAngle, cpFloat stiffness, cpFloat damping)-{-	return (cpConstraint *)cpDampedRotarySpringInit(cpDampedRotarySpringAlloc(), a, b, restAngle, stiffness, damping);-}
− chipmunk-5.0/constraints/cpDampedRotarySpring.h
@@ -1,45 +0,0 @@-/* Copyright (c) 2007 Scott Lembcke- * - * Permission is hereby granted, free of charge, to any person obtaining a copy- * of this software and associated documentation files (the "Software"), to deal- * in the Software without restriction, including without limitation the rights- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell- * copies of the Software, and to permit persons to whom the Software is- * furnished to do so, subject to the following conditions:- * - * The above copyright notice and this permission notice shall be included in- * all copies or substantial portions of the Software.- * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE- * SOFTWARE.- */--typedef cpFloat (*cpDampedRotarySpringTorqueFunc)(struct cpConstraint *spring, cpFloat relativeAngle);--const cpConstraintClass *cpDampedRotarySpringGetClass();--typedef struct cpDampedRotarySpring {-	cpConstraint constraint;-	cpFloat restAngle;-	cpFloat stiffness;-	cpFloat damping;-	cpDampedRotarySpringTorqueFunc springTorqueFunc;-	-	cpFloat dt;-	cpFloat target_wrn;-	-	cpFloat iSum;-} cpDampedRotarySpring;--cpDampedRotarySpring *cpDampedRotarySpringAlloc(void);-cpDampedRotarySpring *cpDampedRotarySpringInit(cpDampedRotarySpring *joint, cpBody *a, cpBody *b, cpFloat restAngle, cpFloat stiffness, cpFloat damping);-cpConstraint *cpDampedRotarySpringNew(cpBody *a, cpBody *b, cpFloat restAngle, cpFloat stiffness, cpFloat damping);--CP_DefineConstraintProperty(cpDampedRotarySpring, cpFloat, restAngle, RestAngle);-CP_DefineConstraintProperty(cpDampedRotarySpring, cpFloat, stiffness, Stiffness);-CP_DefineConstraintProperty(cpDampedRotarySpring, cpFloat, damping, Damping);
− chipmunk-5.0/constraints/cpDampedSpring.c
@@ -1,117 +0,0 @@-/* Copyright (c) 2007 Scott Lembcke- * - * Permission is hereby granted, free of charge, to any person obtaining a copy- * of this software and associated documentation files (the "Software"), to deal- * in the Software without restriction, including without limitation the rights- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell- * copies of the Software, and to permit persons to whom the Software is- * furnished to do so, subject to the following conditions:- * - * The above copyright notice and this permission notice shall be included in- * all copies or substantial portions of the Software.- * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE- * SOFTWARE.- */--#include <stdlib.h>-#include <math.h>--#include "../chipmunk.h"-#include "util.h"--static cpFloat-defaultSpringForce(cpDampedSpring *spring, cpFloat dist){-	return (spring->restLength - dist)*spring->stiffness;-}--static void-preStep(cpDampedSpring *spring, cpFloat dt, cpFloat dt_inv)-{-	cpBody *a = spring->constraint.a;-	cpBody *b = spring->constraint.b;-	-	spring->r1 = cpvrotate(spring->anchr1, a->rot);-	spring->r2 = cpvrotate(spring->anchr2, b->rot);-	-	cpVect delta = cpvsub(cpvadd(b->p, spring->r2), cpvadd(a->p, spring->r1));-	cpFloat dist = cpvlength(delta);-	spring->n = cpvmult(delta, 1.0f/(dist ? dist : INFINITY));-	-	// calculate mass normal-	spring->nMass = 1.0f/k_scalar(a, b, spring->r1, spring->r2, spring->n);--	spring->dt = dt;-	spring->target_vrn = 0.0f;--	// apply spring force-	cpFloat f_spring = spring->springForceFunc((cpConstraint *)spring, dist);-	apply_impulses(a, b, spring->r1, spring->r2, cpvmult(spring->n, f_spring*dt));-}--static void-applyImpulse(cpDampedSpring *spring)-{-	cpBody *a = spring->constraint.a;-	cpBody *b = spring->constraint.b;-	-	cpVect n = spring->n;-	cpVect r1 = spring->r1;-	cpVect r2 = spring->r2;--	// compute relative velocity-	cpFloat vrn = normal_relative_velocity(a, b, r1, r2, n) - spring->target_vrn;-	-	// compute velocity loss from drag-	// not 100% certain this is derived correctly, though it makes sense-	cpFloat v_damp = -vrn*(1.0f - cpfexp(-spring->damping*spring->dt/spring->nMass));-	spring->target_vrn = vrn + v_damp;-	-	apply_impulses(a, b, spring->r1, spring->r2, cpvmult(spring->n, v_damp*spring->nMass));-}--static cpFloat-getImpulse(cpConstraint *constraint)-{-	return 0.0f;-}--static const cpConstraintClass klass = {-	(cpConstraintPreStepFunction)preStep,-	(cpConstraintApplyImpulseFunction)applyImpulse,-	(cpConstraintGetImpulseFunction)getImpulse,-};-CP_DefineClassGetter(cpDampedSpring)--cpDampedSpring *-cpDampedSpringAlloc(void)-{-	return (cpDampedSpring *)malloc(sizeof(cpDampedSpring));-}--cpDampedSpring *-cpDampedSpringInit(cpDampedSpring *spring, cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat restLength, cpFloat stiffness, cpFloat damping)-{-	cpConstraintInit((cpConstraint *)spring, cpDampedSpringGetClass(), a, b);-	-	spring->anchr1 = anchr1;-	spring->anchr2 = anchr2;-	-	spring->restLength = restLength;-	spring->stiffness = stiffness;-	spring->damping = damping;-	spring->springForceFunc = (cpDampedSpringForceFunc)defaultSpringForce;-	-	return spring;-}--cpConstraint *-cpDampedSpringNew(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat restLength, cpFloat stiffness, cpFloat damping)-{-	return (cpConstraint *)cpDampedSpringInit(cpDampedSpringAlloc(), a, b, anchr1, anchr2, restLength, stiffness, damping);-}
− chipmunk-5.0/constraints/cpDampedSpring.h
@@ -1,53 +0,0 @@-/* Copyright (c) 2007 Scott Lembcke- * - * Permission is hereby granted, free of charge, to any person obtaining a copy- * of this software and associated documentation files (the "Software"), to deal- * in the Software without restriction, including without limitation the rights- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell- * copies of the Software, and to permit persons to whom the Software is- * furnished to do so, subject to the following conditions:- * - * The above copyright notice and this permission notice shall be included in- * all copies or substantial portions of the Software.- * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE- * SOFTWARE.- */--struct cpDampedSpring;--typedef cpFloat (*cpDampedSpringForceFunc)(struct cpConstraint *spring, cpFloat dist);--const cpConstraintClass *cpDampedSpringGetClass();--typedef struct cpDampedSpring {-	cpConstraint constraint;-	cpVect anchr1, anchr2;-	cpFloat restLength;-	cpFloat stiffness;-	cpFloat damping;-	cpDampedSpringForceFunc springForceFunc;-	-	cpFloat dt;-	cpFloat target_vrn;-	-	cpVect r1, r2;-	cpFloat nMass;-	cpVect n;-} cpDampedSpring;--cpDampedSpring *cpDampedSpringAlloc(void);-cpDampedSpring *cpDampedSpringInit(cpDampedSpring *joint, cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat restLength, cpFloat stiffness, cpFloat damping);-cpConstraint *cpDampedSpringNew(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat restLength, cpFloat stiffness, cpFloat damping);--CP_DefineConstraintProperty(cpDampedSpring, cpVect, anchr1, Anchr1);-CP_DefineConstraintProperty(cpDampedSpring, cpVect, anchr2, Anchr2);-CP_DefineConstraintProperty(cpDampedSpring, cpFloat, restLength, RestLength);-CP_DefineConstraintProperty(cpDampedSpring, cpFloat, stiffness, Stiffness);-CP_DefineConstraintProperty(cpDampedSpring, cpFloat, damping, Damping);-CP_DefineConstraintProperty(cpDampedSpring, cpDampedSpringForceFunc, springForceFunc, SpringForceFunc);
− chipmunk-5.0/constraints/cpGearJoint.c
@@ -1,104 +0,0 @@-/* Copyright (c) 2007 Scott Lembcke- * - * Permission is hereby granted, free of charge, to any person obtaining a copy- * of this software and associated documentation files (the "Software"), to deal- * in the Software without restriction, including without limitation the rights- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell- * copies of the Software, and to permit persons to whom the Software is- * furnished to do so, subject to the following conditions:- * - * The above copyright notice and this permission notice shall be included in- * all copies or substantial portions of the Software.- * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE- * SOFTWARE.- */--#include <stdlib.h>--#include "../chipmunk.h"-#include "util.h"--static void-preStep(cpGearJoint *joint, cpFloat dt, cpFloat dt_inv)-{-	cpBody *a = joint->constraint.a;-	cpBody *b = joint->constraint.b;-	-	// calculate moment of inertia coefficient.-	joint->iSum = 1.0f/(a->i_inv*cpfabs(joint->ratio) + b->i_inv);-	-	// calculate bias velocity-	cpFloat maxBias = joint->constraint.maxBias;-	joint->bias = cpfclamp(-joint->constraint.biasCoef*dt_inv*(b->a*joint->ratio - a->a - joint->phase), -maxBias, maxBias);-	-	// compute max impulse-	joint->jMax = J_MAX(joint, dt);--	// apply joint torque-	a->w -= joint->jAcc*a->i_inv;-	b->w += joint->jAcc*b->i_inv*joint->ratio;-}--static void-applyImpulse(cpGearJoint *joint)-{-	cpBody *a = joint->constraint.a;-	cpBody *b = joint->constraint.b;-	-	// compute relative rotational velocity-	cpFloat wr = b->w*joint->ratio - a->w;-	-	// compute normal impulse	-	cpFloat j = (joint->bias - wr)*joint->iSum;-	cpFloat jOld = joint->jAcc;-	joint->jAcc = cpfclamp(jOld + j, -joint->jMax, joint->jMax);-	j = joint->jAcc - jOld;-	-	// apply impulse-	a->w -= j*a->i_inv;-	b->w += j*b->i_inv*joint->ratio;-}--static cpFloat-getImpulse(cpGearJoint *joint)-{-	return cpfabs(joint->jAcc);-}--static const cpConstraintClass klass = {-	(cpConstraintPreStepFunction)preStep,-	(cpConstraintApplyImpulseFunction)applyImpulse,-	(cpConstraintGetImpulseFunction)getImpulse,-};-CP_DefineClassGetter(cpGearJoint)--cpGearJoint *-cpGearJointAlloc(void)-{-	return (cpGearJoint *)malloc(sizeof(cpGearJoint));-}--cpGearJoint *-cpGearJointInit(cpGearJoint *joint, cpBody *a, cpBody *b, cpFloat phase, cpFloat ratio)-{-	cpConstraintInit((cpConstraint *)joint, &klass, a, b);-	-	joint->phase = phase;-	joint->ratio = ratio;-	-	joint->jAcc = 0.0f;-	-	return joint;-}--cpConstraint *-cpGearJointNew(cpBody *a, cpBody *b, cpFloat phase, cpFloat ratio)-{-	return (cpConstraint *)cpGearJointInit(cpGearJointAlloc(), a, b, phase, ratio);-}
− chipmunk-5.0/constraints/cpGearJoint.h
@@ -1,39 +0,0 @@-/* Copyright (c) 2007 Scott Lembcke- * - * Permission is hereby granted, free of charge, to any person obtaining a copy- * of this software and associated documentation files (the "Software"), to deal- * in the Software without restriction, including without limitation the rights- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell- * copies of the Software, and to permit persons to whom the Software is- * furnished to do so, subject to the following conditions:- * - * The above copyright notice and this permission notice shall be included in- * all copies or substantial portions of the Software.- * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE- * SOFTWARE.- */--const cpConstraintClass *cpGearJointGetClass();--typedef struct cpGearJoint {-	cpConstraint constraint;-	cpFloat phase, ratio;-	-	cpFloat iSum;-		-	cpFloat bias;-	cpFloat jAcc, jMax;-} cpGearJoint;--cpGearJoint *cpGearJointAlloc(void);-cpGearJoint *cpGearJointInit(cpGearJoint *joint, cpBody *a, cpBody *b, cpFloat phase, cpFloat ratio);-cpConstraint *cpGearJointNew(cpBody *a, cpBody *b, cpFloat phase, cpFloat ratio);--CP_DefineConstraintProperty(cpGearJoint, cpFloat, phase, Phase);-CP_DefineConstraintProperty(cpGearJoint, cpFloat, ratio, Ratio);
− chipmunk-5.0/constraints/cpGrooveJoint.c
@@ -1,138 +0,0 @@-/* Copyright (c) 2007 Scott Lembcke- * - * Permission is hereby granted, free of charge, to any person obtaining a copy- * of this software and associated documentation files (the "Software"), to deal- * in the Software without restriction, including without limitation the rights- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell- * copies of the Software, and to permit persons to whom the Software is- * furnished to do so, subject to the following conditions:- * - * The above copyright notice and this permission notice shall be included in- * all copies or substantial portions of the Software.- * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE- * SOFTWARE.- */--#include <stdlib.h>--#include "../chipmunk.h"-#include "util.h"--static void-preStep(cpGrooveJoint *joint, cpFloat dt, cpFloat dt_inv)-{-	cpBody *a = joint->constraint.a;-	cpBody *b = joint->constraint.b;-	-	// calculate endpoints in worldspace-	cpVect ta = cpBodyLocal2World(a, joint->grv_a);-	cpVect tb = cpBodyLocal2World(a, joint->grv_b);--	// calculate axis-	cpVect n = cpvrotate(joint->grv_n, a->rot);-	cpFloat d = cpvdot(ta, n);-	-	joint->grv_tn = n;-	joint->r2 = cpvrotate(joint->anchr2, b->rot);-	-	// calculate tangential distance along the axis of r2-	cpFloat td = cpvcross(cpvadd(b->p, joint->r2), n);-	// calculate clamping factor and r2-	if(td <= cpvcross(ta, n)){-		joint->clamp = 1.0f;-		joint->r1 = cpvsub(ta, a->p);-	} else if(td >= cpvcross(tb, n)){-		joint->clamp = -1.0f;-		joint->r1 = cpvsub(tb, a->p);-	} else {-		joint->clamp = 0.0f;-		joint->r1 = cpvsub(cpvadd(cpvmult(cpvperp(n), -td), cpvmult(n, d)), a->p);-	}-	-	// Calculate mass tensor-	k_tensor(a, b, joint->r1, joint->r2, &joint->k1, &joint->k2);	-	-	// compute max impulse-	joint->jMaxLen = J_MAX(joint, dt);-	-	// calculate bias velocity-	cpVect delta = cpvsub(cpvadd(b->p, joint->r2), cpvadd(a->p, joint->r1));-	joint->bias = cpvclamp(cpvmult(delta, -joint->constraint.biasCoef*dt_inv), joint->constraint.maxBias);-	-	// apply accumulated impulse-	apply_impulses(a, b, joint->r1, joint->r2, joint->jAcc);-}--static inline cpVect-grooveConstrain(cpGrooveJoint *joint, cpVect j){-	cpVect n = joint->grv_tn;-	cpVect jClamp = (joint->clamp*cpvcross(j, n) > 0.0f) ? j : cpvproject(j, n);-	return cpvclamp(jClamp, joint->jMaxLen);-}--static void-applyImpulse(cpGrooveJoint *joint)-{-	cpBody *a = joint->constraint.a;-	cpBody *b = joint->constraint.b;-	-	cpVect r1 = joint->r1;-	cpVect r2 = joint->r2;-	-	// compute impulse-	cpVect vr = relative_velocity(a, b, r1, r2);--	cpVect j = mult_k(cpvsub(joint->bias, vr), joint->k1, joint->k2);-	cpVect jOld = joint->jAcc;-	joint->jAcc = grooveConstrain(joint, cpvadd(jOld, j));-	j = cpvsub(joint->jAcc, jOld);-	-	// apply impulse-	apply_impulses(a, b, joint->r1, joint->r2, j);-}--static cpFloat-getImpulse(cpGrooveJoint *joint)-{-	return cpvlength(joint->jAcc);-}--static const cpConstraintClass klass = {-	(cpConstraintPreStepFunction)preStep,-	(cpConstraintApplyImpulseFunction)applyImpulse,-	(cpConstraintGetImpulseFunction)getImpulse,-};-CP_DefineClassGetter(cpGrooveJoint)--cpGrooveJoint *-cpGrooveJointAlloc(void)-{-	return (cpGrooveJoint *)malloc(sizeof(cpGrooveJoint));-}--cpGrooveJoint *-cpGrooveJointInit(cpGrooveJoint *joint, cpBody *a, cpBody *b, cpVect groove_a, cpVect groove_b, cpVect anchr2)-{-	cpConstraintInit((cpConstraint *)joint, &klass, a, b);-	-	joint->grv_a = groove_a;-	joint->grv_b = groove_b;-	joint->grv_n = cpvperp(cpvnormalize(cpvsub(groove_b, groove_a)));-	joint->anchr2 = anchr2;-	-	joint->jAcc = cpvzero;-	-	return joint;-}--cpConstraint *-cpGrooveJointNew(cpBody *a, cpBody *b, cpVect groove_a, cpVect groove_b, cpVect anchr2)-{-	return (cpConstraint *)cpGrooveJointInit(cpGrooveJointAlloc(), a, b, groove_a, groove_b, anchr2);-}
− chipmunk-5.0/constraints/cpGrooveJoint.h
@@ -1,44 +0,0 @@-/* Copyright (c) 2007 Scott Lembcke- * - * Permission is hereby granted, free of charge, to any person obtaining a copy- * of this software and associated documentation files (the "Software"), to deal- * in the Software without restriction, including without limitation the rights- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell- * copies of the Software, and to permit persons to whom the Software is- * furnished to do so, subject to the following conditions:- * - * The above copyright notice and this permission notice shall be included in- * all copies or substantial portions of the Software.- * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE- * SOFTWARE.- */--const cpConstraintClass *cpGrooveJointGetClass();--typedef struct cpGrooveJoint {-	cpConstraint constraint;-	cpVect grv_n, grv_a, grv_b;-	cpVect  anchr2;-	-	cpVect grv_tn;-	cpFloat clamp;-	cpVect r1, r2;-	cpVect k1, k2;-	-	cpVect jAcc;-	cpFloat jMaxLen;-	cpVect bias;-} cpGrooveJoint;--cpGrooveJoint *cpGrooveJointAlloc(void);-cpGrooveJoint *cpGrooveJointInit(cpGrooveJoint *joint, cpBody *a, cpBody *b, cpVect groove_a, cpVect groove_b, cpVect anchr2);-cpConstraint *cpGrooveJointNew(cpBody *a, cpBody *b, cpVect groove_a, cpVect groove_b, cpVect anchr2);--// TODO setters for the groove.-CP_DefineConstraintProperty(cpGrooveJoint, cpVect, anchr2, Anchr2);
− chipmunk-5.0/constraints/cpPinJoint.c
@@ -1,117 +0,0 @@-/* Copyright (c) 2007 Scott Lembcke- * - * Permission is hereby granted, free of charge, to any person obtaining a copy- * of this software and associated documentation files (the "Software"), to deal- * in the Software without restriction, including without limitation the rights- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell- * copies of the Software, and to permit persons to whom the Software is- * furnished to do so, subject to the following conditions:- * - * The above copyright notice and this permission notice shall be included in- * all copies or substantial portions of the Software.- * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE- * SOFTWARE.- */--#include <stdlib.h>-//#include <math.h>--#include "../chipmunk.h"-#include "util.h"--static void-preStep(cpPinJoint *joint, cpFloat dt, cpFloat dt_inv)-{-	cpBody *a = joint->constraint.a;-	cpBody *b = joint->constraint.b;-	-	joint->r1 = cpvrotate(joint->anchr1, a->rot);-	joint->r2 = cpvrotate(joint->anchr2, b->rot);-	-	cpVect delta = cpvsub(cpvadd(b->p, joint->r2), cpvadd(a->p, joint->r1));-	cpFloat dist = cpvlength(delta);-	joint->n = cpvmult(delta, 1.0f/(dist ? dist : INFINITY));-	-	// calculate mass normal-	joint->nMass = 1.0f/k_scalar(a, b, joint->r1, joint->r2, joint->n);-	-	// calculate bias velocity-	cpFloat maxBias = joint->constraint.maxBias;-	joint->bias = cpfclamp(-joint->constraint.biasCoef*dt_inv*(dist - joint->dist), -maxBias, maxBias);-	-	// compute max impulse-	joint->jnMax = J_MAX(joint, dt);-	-	// apply accumulated impulse-	cpVect j = cpvmult(joint->n, joint->jnAcc);-	apply_impulses(a, b, joint->r1, joint->r2, j);-}--static void-applyImpulse(cpPinJoint *joint)-{-	cpBody *a = joint->constraint.a;-	cpBody *b = joint->constraint.b;-	cpVect n = joint->n;--	// compute relative velocity-	cpFloat vrn = normal_relative_velocity(a, b, joint->r1, joint->r2, n);-	-	// compute normal impulse-	cpFloat jn = (joint->bias - vrn)*joint->nMass;-	cpFloat jnOld = joint->jnAcc;-	joint->jnAcc = cpfclamp(jnOld + jn, -joint->jnMax, joint->jnMax);-	jn = joint->jnAcc - jnOld;-	-	// apply impulse-	apply_impulses(a, b, joint->r1, joint->r2, cpvmult(n, jn));-}--static cpFloat-getImpulse(cpPinJoint *joint)-{-	return cpfabs(joint->jnAcc);-}--static const cpConstraintClass klass = {-	(cpConstraintPreStepFunction)preStep,-	(cpConstraintApplyImpulseFunction)applyImpulse,-	(cpConstraintGetImpulseFunction)getImpulse,-};-CP_DefineClassGetter(cpPinJoint);---cpPinJoint *-cpPinJointAlloc(void)-{-	return (cpPinJoint *)malloc(sizeof(cpPinJoint));-}--cpPinJoint *-cpPinJointInit(cpPinJoint *joint, cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2)-{-	cpConstraintInit((cpConstraint *)joint, &klass, a, b);-	-	joint->anchr1 = anchr1;-	joint->anchr2 = anchr2;-	-	cpVect p1 = cpvadd(a->p, cpvrotate(anchr1, a->rot));-	cpVect p2 = cpvadd(b->p, cpvrotate(anchr2, b->rot));-	joint->dist = cpvlength(cpvsub(p2, p1));--	joint->jnAcc = 0.0;-	-	return joint;-}--cpConstraint *-cpPinJointNew(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2)-{-	return (cpConstraint *)cpPinJointInit(cpPinJointAlloc(), a, b, anchr1, anchr2);-}
− chipmunk-5.0/constraints/cpPinJoint.h
@@ -1,43 +0,0 @@-/* Copyright (c) 2007 Scott Lembcke- * - * Permission is hereby granted, free of charge, to any person obtaining a copy- * of this software and associated documentation files (the "Software"), to deal- * in the Software without restriction, including without limitation the rights- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell- * copies of the Software, and to permit persons to whom the Software is- * furnished to do so, subject to the following conditions:- * - * The above copyright notice and this permission notice shall be included in- * all copies or substantial portions of the Software.- * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE- * SOFTWARE.- */- -const cpConstraintClass *cpPinJointGetClass();--typedef struct cpPinJoint {-	cpConstraint constraint;-	cpVect anchr1, anchr2;-	cpFloat dist;-	-	cpVect r1, r2;-	cpVect n;-	cpFloat nMass;-	-	cpFloat jnAcc, jnMax;-	cpFloat bias;-} cpPinJoint;--cpPinJoint *cpPinJointAlloc(void);-cpPinJoint *cpPinJointInit(cpPinJoint *joint, cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2);-cpConstraint *cpPinJointNew(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2);--CP_DefineConstraintProperty(cpPinJoint, cpVect, anchr1, Anchr1);-CP_DefineConstraintProperty(cpPinJoint, cpVect, anchr2, Anchr2);-CP_DefineConstraintProperty(cpPinJoint, cpFloat, dist, Dist);
− chipmunk-5.0/constraints/cpPivotJoint.c
@@ -1,116 +0,0 @@-/* Copyright (c) 2007 Scott Lembcke- * - * Permission is hereby granted, free of charge, to any person obtaining a copy- * of this software and associated documentation files (the "Software"), to deal- * in the Software without restriction, including without limitation the rights- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell- * copies of the Software, and to permit persons to whom the Software is- * furnished to do so, subject to the following conditions:- * - * The above copyright notice and this permission notice shall be included in- * all copies or substantial portions of the Software.- * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE- * SOFTWARE.- */--#include <stdlib.h>--#include "../chipmunk.h"-#include "util.h"--static void-preStep(cpPivotJoint *joint, cpFloat dt, cpFloat dt_inv)-{-	cpBody *a = joint->constraint.a;-	cpBody *b = joint->constraint.b;-	-	joint->r1 = cpvrotate(joint->anchr1, a->rot);-	joint->r2 = cpvrotate(joint->anchr2, b->rot);-	-	// Calculate mass tensor-	k_tensor(a, b, joint->r1, joint->r2, &joint->k1, &joint->k2);-	-	// compute max impulse-	joint->jMaxLen = J_MAX(joint, dt);-	-	// calculate bias velocity-	cpVect delta = cpvsub(cpvadd(b->p, joint->r2), cpvadd(a->p, joint->r1));-	joint->bias = cpvclamp(cpvmult(delta, -joint->constraint.biasCoef*dt_inv), joint->constraint.maxBias);-	-	// apply accumulated impulse-	apply_impulses(a, b, joint->r1, joint->r2, joint->jAcc);-}--static void-applyImpulse(cpPivotJoint *joint)-{-	cpBody *a = joint->constraint.a;-	cpBody *b = joint->constraint.b;-	-	cpVect r1 = joint->r1;-	cpVect r2 = joint->r2;-		-	// compute relative velocity-	cpVect vr = relative_velocity(a, b, r1, r2);-	-	// compute normal impulse-	cpVect j = mult_k(cpvsub(joint->bias, vr), joint->k1, joint->k2);-	cpVect jOld = joint->jAcc;-	joint->jAcc = cpvclamp(cpvadd(joint->jAcc, j), joint->jMaxLen);-	j = cpvsub(joint->jAcc, jOld);-	-	// apply impulse-	apply_impulses(a, b, joint->r1, joint->r2, j);-}--static cpFloat-getImpulse(cpConstraint *joint)-{-	return cpvlength(((cpPivotJoint *)joint)->jAcc);-}--static const cpConstraintClass klass = {-	(cpConstraintPreStepFunction)preStep,-	(cpConstraintApplyImpulseFunction)applyImpulse,-	(cpConstraintGetImpulseFunction)getImpulse,-};-CP_DefineClassGetter(cpPivotJoint)--cpPivotJoint *-cpPivotJointAlloc(void)-{-	return (cpPivotJoint *)malloc(sizeof(cpPivotJoint));-}--cpPivotJoint *-cpPivotJointInit(cpPivotJoint *joint, cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2)-{-	cpConstraintInit((cpConstraint *)joint, &klass, a, b);-	-//	joint->anchr1 = cpvunrotate(cpvsub(pivot, a->p), a->rot);-//	joint->anchr2 = cpvunrotate(cpvsub(pivot, b->p), b->rot);-	joint->anchr1 = anchr1;-	joint->anchr2 = anchr2;-	-	joint->jAcc = cpvzero;-	-	return joint;-}--cpConstraint *-cpPivotJointNew2(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2)-{-	return (cpConstraint *)cpPivotJointInit(cpPivotJointAlloc(), a, b, anchr1, anchr2);-}--cpConstraint *-cpPivotJointNew(cpBody *a, cpBody *b, cpVect pivot)-{-	return cpPivotJointNew2(a, b, cpBodyWorld2Local(a, pivot), cpBodyWorld2Local(b, pivot));-}
− chipmunk-5.0/constraints/cpPivotJoint.h
@@ -1,42 +0,0 @@-/* Copyright (c) 2007 Scott Lembcke- * - * Permission is hereby granted, free of charge, to any person obtaining a copy- * of this software and associated documentation files (the "Software"), to deal- * in the Software without restriction, including without limitation the rights- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell- * copies of the Software, and to permit persons to whom the Software is- * furnished to do so, subject to the following conditions:- * - * The above copyright notice and this permission notice shall be included in- * all copies or substantial portions of the Software.- * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE- * SOFTWARE.- */--const cpConstraintClass *cpPivotJointGetClass();--typedef struct cpPivotJoint {-	cpConstraint constraint;-	cpVect anchr1, anchr2;-	-	cpVect r1, r2;-	cpVect k1, k2;-	-	cpVect jAcc;-	cpFloat jMaxLen;-	cpVect bias;-} cpPivotJoint;--cpPivotJoint *cpPivotJointAlloc(void);-cpPivotJoint *cpPivotJointInit(cpPivotJoint *joint, cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2);-cpConstraint *cpPivotJointNew(cpBody *a, cpBody *b, cpVect pivot);-cpConstraint *cpPivotJointNew2(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2);--CP_DefineConstraintProperty(cpPivotJoint, cpVect, anchr1, Anchr1);-CP_DefineConstraintProperty(cpPivotJoint, cpVect, anchr2, Anchr2);
− chipmunk-5.0/constraints/cpRotaryLimitJoint.c
@@ -1,122 +0,0 @@-/* Copyright (c) 2007 Scott Lembcke- * - * Permission is hereby granted, free of charge, to any person obtaining a copy- * of this software and associated documentation files (the "Software"), to deal- * in the Software without restriction, including without limitation the rights- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell- * copies of the Software, and to permit persons to whom the Software is- * furnished to do so, subject to the following conditions:- * - * The above copyright notice and this permission notice shall be included in- * all copies or substantial portions of the Software.- * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE- * SOFTWARE.- */--#include <stdlib.h>--#include "../chipmunk.h"-#include "util.h"--static void-preStep(cpRotaryLimitJoint *joint, cpFloat dt, cpFloat dt_inv)-{-	cpBody *a = joint->constraint.a;-	cpBody *b = joint->constraint.b;-	-	cpFloat dist = b->a - a->a;-	cpFloat pdist = 0.0;-	if(dist > joint->max) {-		pdist = joint->max - dist;-	} else if(dist < joint->min) {-		pdist = joint->min - dist;-	}-	-	// calculate moment of inertia coefficient.-	joint->iSum = 1.0f/(a->i_inv + b->i_inv);-	-	// calculate bias velocity-	cpFloat maxBias = joint->constraint.maxBias;-	joint->bias = cpfclamp(-joint->constraint.biasCoef*dt_inv*(pdist), -maxBias, maxBias);-	-	// compute max impulse-	joint->jMax = J_MAX(joint, dt);--	// If the bias is 0, the joint is not at a limit. Reset the impulse.-	if(!joint->bias)-		joint->jAcc = 0.0f;--	// apply joint torque-	a->w -= joint->jAcc*a->i_inv;-	b->w += joint->jAcc*b->i_inv;-}--static void-applyImpulse(cpRotaryLimitJoint *joint)-{-	if(!joint->bias) return; // early exit--	cpBody *a = joint->constraint.a;-	cpBody *b = joint->constraint.b;-	-	// compute relative rotational velocity-	cpFloat wr = b->w - a->w;-	-	// compute normal impulse	-	cpFloat j = -(joint->bias + wr)*joint->iSum;-	cpFloat jOld = joint->jAcc;-	if(joint->bias < 0.0f){-		joint->jAcc = cpfclamp(jOld + j, 0.0f, joint->jMax);-	} else {-		joint->jAcc = cpfclamp(jOld + j, -joint->jMax, 0.0f);-	}-	j = joint->jAcc - jOld;-	-	// apply impulse-	a->w -= j*a->i_inv;-	b->w += j*b->i_inv;-}--static cpFloat-getImpulse(cpRotaryLimitJoint *joint)-{-	return cpfabs(joint->jAcc);-}--static const cpConstraintClass klass = {-	(cpConstraintPreStepFunction)preStep,-	(cpConstraintApplyImpulseFunction)applyImpulse,-	(cpConstraintGetImpulseFunction)getImpulse,-};-CP_DefineClassGetter(cpRotaryLimitJoint)--cpRotaryLimitJoint *-cpRotaryLimitJointAlloc(void)-{-	return (cpRotaryLimitJoint *)malloc(sizeof(cpRotaryLimitJoint));-}--cpRotaryLimitJoint *-cpRotaryLimitJointInit(cpRotaryLimitJoint *joint, cpBody *a, cpBody *b, cpFloat min, cpFloat max)-{-	cpConstraintInit((cpConstraint *)joint, &klass, a, b);-	-	joint->min = min;-	joint->max  = max;-	-	joint->jAcc = 0.0f;-	-	return joint;-}--cpConstraint *-cpRotaryLimitJointNew(cpBody *a, cpBody *b, cpFloat min, cpFloat max)-{-	return (cpConstraint *)cpRotaryLimitJointInit(cpRotaryLimitJointAlloc(), a, b, min, max);-}
− chipmunk-5.0/constraints/cpRotaryLimitJoint.h
@@ -1,39 +0,0 @@-/* Copyright (c) 2007 Scott Lembcke- * - * Permission is hereby granted, free of charge, to any person obtaining a copy- * of this software and associated documentation files (the "Software"), to deal- * in the Software without restriction, including without limitation the rights- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell- * copies of the Software, and to permit persons to whom the Software is- * furnished to do so, subject to the following conditions:- * - * The above copyright notice and this permission notice shall be included in- * all copies or substantial portions of the Software.- * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE- * SOFTWARE.- */--const cpConstraintClass *cpRotaryLimitJointGetClass();--typedef struct cpRotaryLimitJoint {-	cpConstraint constraint;-	cpFloat min, max;-	-	cpFloat iSum;-		-	cpFloat bias;-	cpFloat jAcc, jMax;-} cpRotaryLimitJoint;--cpRotaryLimitJoint *cpRotaryLimitJointAlloc(void);-cpRotaryLimitJoint *cpRotaryLimitJointInit(cpRotaryLimitJoint *joint, cpBody *a, cpBody *b, cpFloat min, cpFloat max);-cpConstraint *cpRotaryLimitJointNew(cpBody *a, cpBody *b, cpFloat min, cpFloat max);--CP_DefineConstraintProperty(cpRotaryLimitJoint, cpFloat, min, Min);-CP_DefineConstraintProperty(cpRotaryLimitJoint, cpFloat, max, Max);
− chipmunk-5.0/constraints/cpSimpleMotor.c
@@ -1,99 +0,0 @@-/* Copyright (c) 2007 Scott Lembcke- * - * Permission is hereby granted, free of charge, to any person obtaining a copy- * of this software and associated documentation files (the "Software"), to deal- * in the Software without restriction, including without limitation the rights- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell- * copies of the Software, and to permit persons to whom the Software is- * furnished to do so, subject to the following conditions:- * - * The above copyright notice and this permission notice shall be included in- * all copies or substantial portions of the Software.- * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE- * SOFTWARE.- */--#include <stdlib.h>--#include "../chipmunk.h"-#include "util.h"--static void-preStep(cpSimpleMotor *joint, cpFloat dt, cpFloat dt_inv)-{-	cpBody *a = joint->constraint.a;-	cpBody *b = joint->constraint.b;-	-	// calculate moment of inertia coefficient.-	joint->iSum = 1.0f/(a->i_inv + b->i_inv);-	-	// compute max impulse-	joint->jMax = J_MAX(joint, dt);--	// apply joint torque-	a->w -= joint->jAcc*a->i_inv;-	b->w += joint->jAcc*b->i_inv;-}--static void-applyImpulse(cpSimpleMotor *joint)-{-	cpBody *a = joint->constraint.a;-	cpBody *b = joint->constraint.b;-	-	// compute relative rotational velocity-	cpFloat wr = b->w - a->w + joint->rate;-	-	// compute normal impulse	-	cpFloat j = -wr*joint->iSum;-	cpFloat jOld = joint->jAcc;-	joint->jAcc = cpfclamp(jOld + j, -joint->jMax, joint->jMax);-	j = joint->jAcc - jOld;-	-	// apply impulse-	a->w -= j*a->i_inv;-	b->w += j*b->i_inv;-}--static cpFloat-getImpulse(cpSimpleMotor *joint)-{-	return cpfabs(joint->jAcc);-}--static const cpConstraintClass klass = {-	(cpConstraintPreStepFunction)preStep,-	(cpConstraintApplyImpulseFunction)applyImpulse,-	(cpConstraintGetImpulseFunction)getImpulse,-};-CP_DefineClassGetter(cpSimpleMotor)--cpSimpleMotor *-cpSimpleMotorAlloc(void)-{-	return (cpSimpleMotor *)malloc(sizeof(cpSimpleMotor));-}--cpSimpleMotor *-cpSimpleMotorInit(cpSimpleMotor *joint, cpBody *a, cpBody *b, cpFloat rate)-{-	cpConstraintInit((cpConstraint *)joint, &klass, a, b);-	-	joint->rate = rate;-	-	joint->jAcc = 0.0f;-	-	return joint;-}--cpConstraint *-cpSimpleMotorNew(cpBody *a, cpBody *b, cpFloat rate)-{-	return (cpConstraint *)cpSimpleMotorInit(cpSimpleMotorAlloc(), a, b, rate);-}
− chipmunk-5.0/constraints/cpSimpleMotor.h
@@ -1,37 +0,0 @@-/* Copyright (c) 2007 Scott Lembcke- * - * Permission is hereby granted, free of charge, to any person obtaining a copy- * of this software and associated documentation files (the "Software"), to deal- * in the Software without restriction, including without limitation the rights- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell- * copies of the Software, and to permit persons to whom the Software is- * furnished to do so, subject to the following conditions:- * - * The above copyright notice and this permission notice shall be included in- * all copies or substantial portions of the Software.- * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE- * SOFTWARE.- */--const cpConstraintClass *cpSimpleMotorGetClass();--typedef struct cpSimpleMotor {-	cpConstraint constraint;-	cpFloat rate;-	-	cpFloat iSum;-		-	cpFloat jAcc, jMax;-} cpSimpleMotor;--cpSimpleMotor *cpSimpleMotorAlloc(void);-cpSimpleMotor *cpSimpleMotorInit(cpSimpleMotor *joint, cpBody *a, cpBody *b, cpFloat rate);-cpConstraint *cpSimpleMotorNew(cpBody *a, cpBody *b, cpFloat rate);--CP_DefineConstraintProperty(cpSimpleMotor, cpFloat, rate, Rate);
− chipmunk-5.0/constraints/cpSlideJoint.c
@@ -1,131 +0,0 @@-/* Copyright (c) 2007 Scott Lembcke- * - * Permission is hereby granted, free of charge, to any person obtaining a copy- * of this software and associated documentation files (the "Software"), to deal- * in the Software without restriction, including without limitation the rights- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell- * copies of the Software, and to permit persons to whom the Software is- * furnished to do so, subject to the following conditions:- * - * The above copyright notice and this permission notice shall be included in- * all copies or substantial portions of the Software.- * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE- * SOFTWARE.- */--#include <stdlib.h>--#include "../chipmunk.h"-#include "util.h"--static void-preStep(cpSlideJoint *joint, cpFloat dt, cpFloat dt_inv)-{-	cpBody *a = joint->constraint.a;-	cpBody *b = joint->constraint.b;-	-	joint->r1 = cpvrotate(joint->anchr1, a->rot);-	joint->r2 = cpvrotate(joint->anchr2, b->rot);-	-	cpVect delta = cpvsub(cpvadd(b->p, joint->r2), cpvadd(a->p, joint->r1));-	cpFloat dist = cpvlength(delta);-	cpFloat pdist = 0.0;-	if(dist > joint->max) {-		pdist = dist - joint->max;-	} else if(dist < joint->min) {-		pdist = joint->min - dist;-		dist = -dist;-	}-	joint->n = cpvmult(delta, 1.0f/(dist ? dist : INFINITY));-	-	// calculate mass normal-	joint->nMass = 1.0f/k_scalar(a, b, joint->r1, joint->r2, joint->n);-	-	// calculate bias velocity-	cpFloat maxBias = joint->constraint.maxBias;-	joint->bias = cpfclamp(-joint->constraint.biasCoef*dt_inv*(pdist), -maxBias, maxBias);-	-	// compute max impulse-	joint->jnMax = J_MAX(joint, dt);--	// apply accumulated impulse-	if(!joint->bias) //{-		// if bias is 0, then the joint is not at a limit.-		joint->jnAcc = 0.0f;-//	} else {-		cpVect j = cpvmult(joint->n, joint->jnAcc);-		apply_impulses(a, b, joint->r1, joint->r2, j);-//	}-}--static void-applyImpulse(cpSlideJoint *joint)-{-	if(!joint->bias) return;  // early exit--	cpBody *a = joint->constraint.a;-	cpBody *b = joint->constraint.b;-	-	cpVect n = joint->n;-	cpVect r1 = joint->r1;-	cpVect r2 = joint->r2;-		-	// compute relative velocity-	cpVect vr = relative_velocity(a, b, r1, r2);-	cpFloat vrn = cpvdot(vr, n);-	-	// compute normal impulse-	cpFloat jn = (joint->bias - vrn)*joint->nMass;-	cpFloat jnOld = joint->jnAcc;-	joint->jnAcc = cpfclamp(jnOld + jn, -joint->jnMax, 0.0f);-	jn = joint->jnAcc - jnOld;-	-	// apply impulse-	apply_impulses(a, b, joint->r1, joint->r2, cpvmult(n, jn));-}--static cpFloat-getImpulse(cpConstraint *joint)-{-	return cpfabs(((cpSlideJoint *)joint)->jnAcc);-}--static const cpConstraintClass klass = {-	(cpConstraintPreStepFunction)preStep,-	(cpConstraintApplyImpulseFunction)applyImpulse,-	(cpConstraintGetImpulseFunction)getImpulse,-};-CP_DefineClassGetter(cpSlideJoint)--cpSlideJoint *-cpSlideJointAlloc(void)-{-	return (cpSlideJoint *)malloc(sizeof(cpSlideJoint));-}--cpSlideJoint *-cpSlideJointInit(cpSlideJoint *joint, cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat min, cpFloat max)-{-	cpConstraintInit((cpConstraint *)joint, &klass, a, b);-	-	joint->anchr1 = anchr1;-	joint->anchr2 = anchr2;-	joint->min = min;-	joint->max = max;-	-	joint->jnAcc = 0.0;-	-	return joint;-}--cpConstraint *-cpSlideJointNew(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat min, cpFloat max)-{-	return (cpConstraint *)cpSlideJointInit(cpSlideJointAlloc(), a, b, anchr1, anchr2, min, max);-}
− chipmunk-5.0/constraints/cpSlideJoint.h
@@ -1,44 +0,0 @@-/* Copyright (c) 2007 Scott Lembcke- * - * Permission is hereby granted, free of charge, to any person obtaining a copy- * of this software and associated documentation files (the "Software"), to deal- * in the Software without restriction, including without limitation the rights- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell- * copies of the Software, and to permit persons to whom the Software is- * furnished to do so, subject to the following conditions:- * - * The above copyright notice and this permission notice shall be included in- * all copies or substantial portions of the Software.- * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE- * SOFTWARE.- */--const cpConstraintClass *cpSlideJointGetClass();--typedef struct cpSlideJoint {-	cpConstraint constraint;-	cpVect anchr1, anchr2;-	cpFloat min, max;-	-	cpVect r1, r2;-	cpVect n;-	cpFloat nMass;-	-	cpFloat jnAcc, jnMax;-	cpFloat bias;-} cpSlideJoint;--cpSlideJoint *cpSlideJointAlloc(void);-cpSlideJoint *cpSlideJointInit(cpSlideJoint *joint, cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat min, cpFloat max);-cpConstraint *cpSlideJointNew(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat min, cpFloat max);--CP_DefineConstraintProperty(cpSlideJoint, cpVect, anchr1, Anchr1);-CP_DefineConstraintProperty(cpSlideJoint, cpVect, anchr2, Anchr2);-CP_DefineConstraintProperty(cpSlideJoint, cpFloat, min, Min);-CP_DefineConstraintProperty(cpSlideJoint, cpFloat, max, Max);
− chipmunk-5.0/constraints/util.h
@@ -1,110 +0,0 @@-/* Copyright (c) 2007 Scott Lembcke- * - * Permission is hereby granted, free of charge, to any person obtaining a copy- * of this software and associated documentation files (the "Software"), to deal- * in the Software without restriction, including without limitation the rights- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell- * copies of the Software, and to permit persons to whom the Software is- * furnished to do so, subject to the following conditions:- * - * The above copyright notice and this permission notice shall be included in- * all copies or substantial portions of the Software.- * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE- * SOFTWARE.- */--#define CP_DefineClassGetter(t) const cpConstraintClass * t##GetClass(){return (cpConstraintClass *)&klass;}--void cpConstraintInit(cpConstraint *constraint, const cpConstraintClass *klass, cpBody *a, cpBody *b);--#define J_MAX(constraint, dt) (((cpConstraint *)constraint)->maxForce*(dt))--static inline cpVect-relative_velocity(cpBody *a, cpBody *b, cpVect r1, cpVect r2){-	cpVect v1_sum = cpvadd(a->v, cpvmult(cpvperp(r1), a->w));-	cpVect v2_sum = cpvadd(b->v, cpvmult(cpvperp(r2), b->w));-	-	return cpvsub(v2_sum, v1_sum);-}--static inline cpFloat-normal_relative_velocity(cpBody *a, cpBody *b, cpVect r1, cpVect r2, cpVect n){-	return cpvdot(relative_velocity(a, b, r1, r2), n);-}--static inline void-apply_impulses(cpBody *a , cpBody *b, cpVect r1, cpVect r2, cpVect j)-{-	cpBodyApplyImpulse(a, cpvneg(j), r1);-	cpBodyApplyImpulse(b, j, r2);-}--static inline void-apply_bias_impulses(cpBody *a , cpBody *b, cpVect r1, cpVect r2, cpVect j)-{-	cpBodyApplyBiasImpulse(a, cpvneg(j), r1);-	cpBodyApplyBiasImpulse(b, j, r2);-}--static inline cpVect-clamp_vect(cpVect v, cpFloat len)-{-	return cpvclamp(v, len);-//	return (cpvdot(v,v) > len*len) ? cpvmult(cpvnormalize(v), len) : v;-}--static inline cpFloat-k_scalar(cpBody *a, cpBody *b, cpVect r1, cpVect r2, cpVect n)-{-	cpFloat mass_sum = a->m_inv + b->m_inv;-	cpFloat r1cn = cpvcross(r1, n);-	cpFloat r2cn = cpvcross(r2, n);--	return mass_sum + a->i_inv*r1cn*r1cn + b->i_inv*r2cn*r2cn;-}--static inline void-k_tensor(cpBody *a, cpBody *b, cpVect r1, cpVect r2, cpVect *k1, cpVect *k2)-{-		// calculate mass matrix-	// If I wasn't lazy and wrote a proper matrix class, this wouldn't be so gross...-	cpFloat k11, k12, k21, k22;-	cpFloat m_sum = a->m_inv + b->m_inv;-	-	// start with I*m_sum-	k11 = m_sum; k12 = 0.0f;-	k21 = 0.0f;  k22 = m_sum;-	-	// add the influence from r1-	cpFloat a_i_inv = a->i_inv;-	cpFloat r1xsq =  r1.x * r1.x * a_i_inv;-	cpFloat r1ysq =  r1.y * r1.y * a_i_inv;-	cpFloat r1nxy = -r1.x * r1.y * a_i_inv;-	k11 += r1ysq; k12 += r1nxy;-	k21 += r1nxy; k22 += r1xsq;-	-	// add the influnce from r2-	cpFloat b_i_inv = b->i_inv;-	cpFloat r2xsq =  r2.x * r2.x * b_i_inv;-	cpFloat r2ysq =  r2.y * r2.y * b_i_inv;-	cpFloat r2nxy = -r2.x * r2.y * b_i_inv;-	k11 += r2ysq; k12 += r2nxy;-	k21 += r2nxy; k22 += r2xsq;-	-	// invert-	cpFloat det_inv = 1.0f/(k11*k22 - k12*k21);-	*k1 = cpv( k22*det_inv, -k12*det_inv);-	*k2 = cpv(-k21*det_inv,  k11*det_inv);-}--static inline cpVect-mult_k(cpVect vr, cpVect k1, cpVect k2)-{-	return cpv(cpvdot(vr, k1), cpvdot(vr, k2));-}
− chipmunk-5.0/cpArbiter.c
@@ -1,254 +0,0 @@-/* Copyright (c) 2007 Scott Lembcke- * - * Permission is hereby granted, free of charge, to any person obtaining a copy- * of this software and associated documentation files (the "Software"), to deal- * in the Software without restriction, including without limitation the rights- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell- * copies of the Software, and to permit persons to whom the Software is- * furnished to do so, subject to the following conditions:- * - * The above copyright notice and this permission notice shall be included in- * all copies or substantial portions of the Software.- * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE- * SOFTWARE.- */- -#include <stdlib.h>--#include "chipmunk.h"-#include "constraints/util.h"--cpFloat cp_bias_coef = 0.1f;-cpFloat cp_collision_slop = 0.1f;--cpContact*-cpContactInit(cpContact *con, cpVect p, cpVect n, cpFloat dist, cpHashValue hash)-{-	con->p = p;-	con->n = n;-	con->dist = dist;-	-	con->jnAcc = 0.0f;-	con->jtAcc = 0.0f;-	con->jBias = 0.0f;-	-	con->hash = hash;-		-	return con;-}--cpVect-cpContactsSumImpulses(cpContact *contacts, int numContacts)-{-	cpVect sum = cpvzero;-	-	for(int i=0; i<numContacts; i++){-		cpContact *con = &contacts[i];-		sum = cpvadd(sum, cpvmult(con->n, con->jnAcc));-	}-		-	return sum;-}--cpVect-cpContactsSumImpulsesWithFriction(cpContact *contacts, int numContacts)-{-	cpVect sum = cpvzero;-	-	for(int i=0; i<numContacts; i++){-		cpContact *con = &contacts[i];-		sum = cpvadd(sum, cpvrotate(con->n, cpv(con->jnAcc, con->jtAcc)));-	}-		-	return sum;-}--cpFloat-cpContactsEstimateCrushingImpulse(cpContact *contacts, int numContacts)-{-	cpFloat fsum = 0.0f;-	cpVect vsum = cpvzero;-	-	for(int i=0; i<numContacts; i++){-		cpContact *con = &contacts[i];-		cpVect j = cpvrotate(con->n, cpv(con->jnAcc, con->jtAcc));-		-		fsum += cpvlength(j);-		vsum = cpvadd(vsum, j);-	}-	-	cpFloat vmag = cpvlength(vsum);-	return (1.0f - vmag/fsum);-}--cpArbiter*-cpArbiterAlloc(void)-{-	return (cpArbiter *)calloc(1, sizeof(cpArbiter));-}--cpArbiter*-cpArbiterInit(cpArbiter *arb, cpShape *a, cpShape *b, int stamp)-{-	arb->numContacts = 0;-	arb->contacts = NULL;-	-	arb->a = a;-	arb->b = b;-	-	arb->stamp = stamp;-		-	return arb;-}--cpArbiter*-cpArbiterNew(cpShape *a, cpShape *b, int stamp)-{-	return cpArbiterInit(cpArbiterAlloc(), a, b, stamp);-}--void-cpArbiterDestroy(cpArbiter *arb)-{-	free(arb->contacts);-}--void-cpArbiterFree(cpArbiter *arb)-{-	if(arb) cpArbiterDestroy(arb);-	free(arb);-}--void-cpArbiterInject(cpArbiter *arb, cpContact *contacts, int numContacts)-{-	// Iterate over the possible pairs to look for hash value matches.-	for(int i=0; i<arb->numContacts; i++){-		cpContact *old = &arb->contacts[i];-		-		for(int j=0; j<numContacts; j++){-			cpContact *new_contact = &contacts[j];-			-			// This could trigger false positives, but is fairly unlikely nor serious if it does.-			if(new_contact->hash == old->hash){-				// Copy the persistant contact information.-				new_contact->jnAcc = old->jnAcc;-				new_contact->jtAcc = old->jtAcc;-			}-		}-	}--	free(arb->contacts);-	-	arb->contacts = contacts;-	arb->numContacts = numContacts;-}--void-cpArbiterPreStep(cpArbiter *arb, cpFloat dt_inv)-{-	cpShape *shapea = arb->a;-	cpShape *shapeb = arb->b;-		-	cpFloat e = shapea->e * shapeb->e;-	arb->u = shapea->u * shapeb->u;-	arb->target_v = cpvsub(shapeb->surface_v, shapea->surface_v);--	cpBody *a = shapea->body;-	cpBody *b = shapeb->body;-	-	for(int i=0; i<arb->numContacts; i++){-		cpContact *con = &arb->contacts[i];-		-		// Calculate the offsets.-		con->r1 = cpvsub(con->p, a->p);-		con->r2 = cpvsub(con->p, b->p);-		-		// Calculate the mass normal and mass tangent.-		con->nMass = 1.0f/k_scalar(a, b, con->r1, con->r2, con->n);-		con->tMass = 1.0f/k_scalar(a, b, con->r1, con->r2, cpvperp(con->n));-				-		// Calculate the target bias velocity.-		con->bias = -cp_bias_coef*dt_inv*cpfmin(0.0f, con->dist + cp_collision_slop);-		con->jBias = 0.0f;-		-		// Calculate the target bounce velocity.-		con->bounce = normal_relative_velocity(a, b, con->r1, con->r2, con->n)*e;//cpvdot(con->n, cpvsub(v2, v1))*e;-	}-}--void-cpArbiterApplyCachedImpulse(cpArbiter *arb)-{-	cpShape *shapea = arb->a;-	cpShape *shapeb = arb->b;-		-	arb->u = shapea->u * shapeb->u;-	arb->target_v = cpvsub(shapeb->surface_v, shapea->surface_v);--	cpBody *a = shapea->body;-	cpBody *b = shapeb->body;-	-	for(int i=0; i<arb->numContacts; i++){-		cpContact *con = &arb->contacts[i];-		apply_impulses(a, b, con->r1, con->r2, cpvrotate(con->n, cpv(con->jnAcc, con->jtAcc)));-	}-}--void-cpArbiterApplyImpulse(cpArbiter *arb, cpFloat eCoef)-{-	cpBody *a = arb->a->body;-	cpBody *b = arb->b->body;--	for(int i=0; i<arb->numContacts; i++){-		cpContact *con = &arb->contacts[i];-		cpVect n = con->n;-		cpVect r1 = con->r1;-		cpVect r2 = con->r2;-		-		// Calculate the relative bias velocities.-		cpVect vb1 = cpvadd(a->v_bias, cpvmult(cpvperp(r1), a->w_bias));-		cpVect vb2 = cpvadd(b->v_bias, cpvmult(cpvperp(r2), b->w_bias));-		cpFloat vbn = cpvdot(cpvsub(vb2, vb1), n);-		-		// Calculate and clamp the bias impulse.-		cpFloat jbn = (con->bias - vbn)*con->nMass;-		cpFloat jbnOld = con->jBias;-		con->jBias = cpfmax(jbnOld + jbn, 0.0f);-		jbn = con->jBias - jbnOld;-		-		// Apply the bias impulse.-		apply_bias_impulses(a, b, r1, r2, cpvmult(n, jbn));--		// Calculate the relative velocity.-		cpVect vr = relative_velocity(a, b, r1, r2);-		cpFloat vrn = cpvdot(vr, n);-		-		// Calculate and clamp the normal impulse.-		cpFloat jn = -(con->bounce*eCoef + vrn)*con->nMass;-		cpFloat jnOld = con->jnAcc;-		con->jnAcc = cpfmax(jnOld + jn, 0.0f);-		jn = con->jnAcc - jnOld;-		-		// Calculate the relative tangent velocity.-		cpFloat vrt = cpvdot(cpvadd(vr, arb->target_v), cpvperp(n));-		-		// Calculate and clamp the friction impulse.-		cpFloat jtMax = arb->u*con->jnAcc;-		cpFloat jt = -vrt*con->tMass;-		cpFloat jtOld = con->jtAcc;-		con->jtAcc = cpfclamp(jtOld + jt, -jtMax, jtMax);-		jt = con->jtAcc - jtOld;-		-		// Apply the final impulse.-		apply_impulses(a, b, r1, r2, cpvrotate(n, cpv(jn, jt)));-	}-}
− chipmunk-5.0/cpArbiter.h
@@ -1,85 +0,0 @@-/* Copyright (c) 2007 Scott Lembcke- * - * Permission is hereby granted, free of charge, to any person obtaining a copy- * of this software and associated documentation files (the "Software"), to deal- * in the Software without restriction, including without limitation the rights- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell- * copies of the Software, and to permit persons to whom the Software is- * furnished to do so, subject to the following conditions:- * - * The above copyright notice and this permission notice shall be included in- * all copies or substantial portions of the Software.- * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE- * SOFTWARE.- */--// Determines how fast penetrations resolve themselves.-extern cpFloat cp_bias_coef;-// Amount of allowed penetration. Used to reduce vibrating contacts.-extern cpFloat cp_collision_slop;--// Data structure for contact points.-typedef struct cpContact{-	// Contact point and normal.-	cpVect p, n;-	// Penetration distance.-	cpFloat dist;-	-	// Calculated by cpArbiterPreStep().-	cpVect r1, r2;-	cpFloat nMass, tMass, bounce;--	// Persistant contact information.-	cpFloat jnAcc, jtAcc, jBias;-	cpFloat bias;-	-	// Hash value used to (mostly) uniquely identify a contact.-	cpHashValue hash;-} cpContact;--// Contacts are always allocated in groups.-cpContact* cpContactInit(cpContact *con, cpVect p, cpVect n, cpFloat dist, cpHashValue hash);--// Sum the contact impulses. (Can be used after cpSpaceStep() returns)-cpVect cpContactsSumImpulses(cpContact *contacts, int numContacts);-cpVect cpContactsSumImpulsesWithFriction(cpContact *contacts, int numContacts);--// Data structure for tracking collisions between shapes.-typedef struct cpArbiter{-	// Information on the contact points between the objects.-	int numContacts;-	cpContact *contacts;-	-	// The two shapes involved in the collision.-	cpShape *a, *b;-	-	// Calculated by cpArbiterPreStep().-	cpFloat u;-	cpVect target_v;-	-	// Time stamp of the arbiter. (from cpSpace)-	int stamp;-} cpArbiter;--// Basic allocation/destruction functions.-cpArbiter* cpArbiterAlloc(void);-cpArbiter* cpArbiterInit(cpArbiter *arb, cpShape *a, cpShape *b, int stamp);-cpArbiter* cpArbiterNew(cpShape *a, cpShape *b, int stamp);--void cpArbiterDestroy(cpArbiter *arb);-void cpArbiterFree(cpArbiter *arb);--// These functions are all intended to be used internally.-// Inject new contact points into the arbiter while preserving contact history.-void cpArbiterInject(cpArbiter *arb, cpContact *contacts, int numContacts);-// Precalculate values used by the solver.-void cpArbiterPreStep(cpArbiter *arb, cpFloat dt_inv);-void cpArbiterApplyCachedImpulse(cpArbiter *arb);-// Run an iteration of the solver on the arbiter.-void cpArbiterApplyImpulse(cpArbiter *arb, cpFloat eCoef);
− chipmunk-5.0/cpArray.c
@@ -1,114 +0,0 @@-/* Copyright (c) 2007 Scott Lembcke- * - * Permission is hereby granted, free of charge, to any person obtaining a copy- * of this software and associated documentation files (the "Software"), to deal- * in the Software without restriction, including without limitation the rights- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell- * copies of the Software, and to permit persons to whom the Software is- * furnished to do so, subject to the following conditions:- * - * The above copyright notice and this permission notice shall be included in- * all copies or substantial portions of the Software.- * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE- * SOFTWARE.- */- -#include <stdlib.h>-#include <string.h>--#include "chipmunk.h"---//#define CP_ARRAY_INCREMENT 10--// NOTE: cpArray is rarely used and will probably go away.--cpArray*-cpArrayAlloc(void)-{-	return (cpArray *)calloc(1, sizeof(cpArray));-}--cpArray*-cpArrayInit(cpArray *arr, int size)-{-	arr->num = 0;-	-	size = (size ? size : 4);-	arr->max = size;-	arr->arr = (void **)malloc(size*sizeof(void**));-	-	return arr;-}--cpArray*-cpArrayNew(int size)-{-	return cpArrayInit(cpArrayAlloc(), size);-}--void-cpArrayDestroy(cpArray *arr)-{-	free(arr->arr);-}--void-cpArrayFree(cpArray *arr)-{-	if(!arr) return;-	cpArrayDestroy(arr);-	free(arr);-}--void-cpArrayPush(cpArray *arr, void *object)-{-	if(arr->num == arr->max){-		arr->max *= 2;-		arr->arr = (void **)realloc(arr->arr, arr->max*sizeof(void**));-	}-	-	arr->arr[arr->num] = object;-	arr->num++;-}--void-cpArrayDeleteIndex(cpArray *arr, int index)-{-	int last = --arr->num;-	arr->arr[index] = arr->arr[last];-}--void-cpArrayDeleteObj(cpArray *arr, void *obj)-{-	for(int i=0; i<arr->num; i++){-		if(arr->arr[i] == obj){-			cpArrayDeleteIndex(arr, i);-			return;-		}-	}-}--void-cpArrayEach(cpArray *arr, cpArrayIter iterFunc, void *data)-{-	for(int i=0; i<arr->num; i++)-		iterFunc(arr->arr[i], data);-}--int-cpArrayContains(cpArray *arr, void *ptr)-{-	for(int i=0; i<arr->num; i++)-		if(arr->arr[i] == ptr) return 1;-	-	return 0;-}
− chipmunk-5.0/cpArray.h
@@ -1,45 +0,0 @@-/* Copyright (c) 2007 Scott Lembcke- * - * Permission is hereby granted, free of charge, to any person obtaining a copy- * of this software and associated documentation files (the "Software"), to deal- * in the Software without restriction, including without limitation the rights- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell- * copies of the Software, and to permit persons to whom the Software is- * furnished to do so, subject to the following conditions:- * - * The above copyright notice and this permission notice shall be included in- * all copies or substantial portions of the Software.- * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE- * SOFTWARE.- */- -// NOTE: cpArray is rarely used and will probably go away.--typedef struct cpArray{-	int num, max;-	void **arr;-} cpArray;--typedef void (*cpArrayIter)(void *ptr, void *data);--cpArray *cpArrayAlloc(void);-cpArray *cpArrayInit(cpArray *arr, int size);-cpArray *cpArrayNew(int size);--void cpArrayDestroy(cpArray *arr);-void cpArrayFree(cpArray *arr);--void cpArrayClear(cpArray *arr);--void cpArrayPush(cpArray *arr, void *object);-void cpArrayDeleteIndex(cpArray *arr, int index);-void cpArrayDeleteObj(cpArray *arr, void *obj);--void cpArrayEach(cpArray *arr, cpArrayIter iterFunc, void *data);-int cpArrayContains(cpArray *arr, void *ptr);
− chipmunk-5.0/cpBB.c
@@ -1,47 +0,0 @@-/* Copyright (c) 2007 Scott Lembcke- * - * Permission is hereby granted, free of charge, to any person obtaining a copy- * of this software and associated documentation files (the "Software"), to deal- * in the Software without restriction, including without limitation the rights- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell- * copies of the Software, and to permit persons to whom the Software is- * furnished to do so, subject to the following conditions:- * - * The above copyright notice and this permission notice shall be included in- * all copies or substantial portions of the Software.- * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE- * SOFTWARE.- */- -#include <math.h>-#include <stdlib.h>--#include "chipmunk.h"--cpVect-cpBBClampVect(const cpBB bb, const cpVect v)-{-	cpFloat x = cpfmin(cpfmax(bb.l, v.x), bb.r);-	cpFloat y = cpfmin(cpfmax(bb.b, v.y), bb.t);-	return cpv(x, y);-}--cpVect-cpBBWrapVect(const cpBB bb, const cpVect v)-{-	cpFloat ix = fabsf(bb.r - bb.l);-	cpFloat modx = cpfmod(v.x - bb.l, ix);-	cpFloat x = (modx > 0.0f) ? modx : modx + ix;-	-	cpFloat iy = fabsf(bb.t - bb.b);-	cpFloat mody = cpfmod(v.y - bb.b, iy);-	cpFloat y = (mody > 0.0f) ? mody : mody + iy;-	-	return cpv(x + bb.l, y + bb.b);-}
− chipmunk-5.0/cpBB.h
@@ -1,53 +0,0 @@-/* Copyright (c) 2007 Scott Lembcke- * - * Permission is hereby granted, free of charge, to any person obtaining a copy- * of this software and associated documentation files (the "Software"), to deal- * in the Software without restriction, including without limitation the rights- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell- * copies of the Software, and to permit persons to whom the Software is- * furnished to do so, subject to the following conditions:- * - * The above copyright notice and this permission notice shall be included in- * all copies or substantial portions of the Software.- * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE- * SOFTWARE.- */- -typedef struct cpBB{-	cpFloat l, b, r ,t;-} cpBB;--static inline cpBB-cpBBNew(const cpFloat l, const cpFloat b,-		const cpFloat r, const cpFloat t)-{-	cpBB bb = {l, b, r, t};-	return bb;-}--static inline int-cpBBintersects(const cpBB a, const cpBB b)-{-	return (a.l<=b.r && b.l<=a.r && a.b<=b.t && b.b<=a.t);-}--static inline int-cpBBcontainsBB(const cpBB bb, const cpBB other)-{-	return (bb.l < other.l && bb.r > other.r && bb.b < other.b && bb.t > other.t);-}--static inline int-cpBBcontainsVect(const cpBB bb, const cpVect v)-{-	return (bb.l < v.x && bb.r > v.x && bb.b < v.y && bb.t > v.y);-}--cpVect cpBBClampVect(const cpBB bb, const cpVect v); // clamps the vector to lie within the bbox-cpVect cpBBWrapVect(const cpBB bb, const cpVect v); // wrap a vector to a bbox
− chipmunk-5.0/cpBody.c
@@ -1,179 +0,0 @@-/* Copyright (c) 2007 Scott Lembcke- * - * Permission is hereby granted, free of charge, to any person obtaining a copy- * of this software and associated documentation files (the "Software"), to deal- * in the Software without restriction, including without limitation the rights- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell- * copies of the Software, and to permit persons to whom the Software is- * furnished to do so, subject to the following conditions:- * - * The above copyright notice and this permission notice shall be included in- * all copies or substantial portions of the Software.- * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE- * SOFTWARE.- */- -#include <stdlib.h>-#include <float.h>--#include "chipmunk.h"--cpBody*-cpBodyAlloc(void)-{-	return (cpBody *)malloc(sizeof(cpBody));-}--cpBody*-cpBodyInit(cpBody *body, cpFloat m, cpFloat i)-{-	body->velocity_func = cpBodyUpdateVelocity;-	body->position_func = cpBodyUpdatePosition;-	-	cpBodySetMass(body, m);-	cpBodySetMoment(body, i);--	body->p = cpvzero;-	body->v = cpvzero;-	body->f = cpvzero;-	-	cpBodySetAngle(body, 0.0f);-	body->w = 0.0f;-	body->t = 0.0f;-	-	body->v_bias = cpvzero;-	body->w_bias = 0.0f;-	-	body->data = NULL;-//	body->active = 1;--	return body;-}--cpBody*-cpBodyNew(cpFloat m, cpFloat i)-{-	return cpBodyInit(cpBodyAlloc(), m, i);-}--void cpBodyDestroy(cpBody *body){}--void-cpBodyFree(cpBody *body)-{-	if(body) cpBodyDestroy(body);-	free(body);-}--void-cpBodySetMass(cpBody *body, cpFloat mass)-{-	body->m = mass;-	body->m_inv = 1.0f/mass;-}--void-cpBodySetMoment(cpBody *body, cpFloat moment)-{-	body->i = moment;-	body->i_inv = 1.0f/moment;-}--void-cpBodySetAngle(cpBody *body, cpFloat angle)-{-	body->a = angle;//fmod(a, (cpFloat)M_PI*2.0f);-	body->rot = cpvforangle(angle);-}--void-cpBodySlew(cpBody *body, cpVect pos, cpFloat dt)-{-	cpVect delta = cpvsub(pos, body->p);-	body->v = cpvmult(delta, 1.0/dt);-}--void-cpBodyUpdateVelocity(cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt)-{-	body->v = cpvadd(cpvmult(body->v, damping), cpvmult(cpvadd(gravity, cpvmult(body->f, body->m_inv)), dt));-	body->w = body->w*damping + body->t*body->i_inv*dt;-}--void-cpBodyUpdatePosition(cpBody *body, cpFloat dt)-{-	body->p = cpvadd(body->p, cpvmult(cpvadd(body->v, body->v_bias), dt));-	cpBodySetAngle(body, body->a + (body->w + body->w_bias)*dt);-	-	body->v_bias = cpvzero;-	body->w_bias = 0.0f;-}--void-cpBodyResetForces(cpBody *body)-{-	body->f = cpvzero;-	body->t = 0.0f;-}--void-cpBodyApplyForce(cpBody *body, cpVect force, cpVect r)-{-	body->f = cpvadd(body->f, force);-	body->t += cpvcross(r, force);-}--void-cpApplyDampedSpring(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat rlen, cpFloat k, cpFloat dmp, cpFloat dt)-{-	// Calculate the world space anchor coordinates.-	cpVect r1 = cpvrotate(anchr1, a->rot);-	cpVect r2 = cpvrotate(anchr2, b->rot);-	-	cpVect delta = cpvsub(cpvadd(b->p, r2), cpvadd(a->p, r1));-	cpFloat dist = cpvlength(delta);-	cpVect n = dist ? cpvmult(delta, 1.0f/dist) : cpvzero;-	-	cpFloat f_spring = (dist - rlen)*k;--	// Calculate the world relative velocities of the anchor points.-	cpVect v1 = cpvadd(a->v, cpvmult(cpvperp(r1), a->w));-	cpVect v2 = cpvadd(b->v, cpvmult(cpvperp(r2), b->w));-	-	// Calculate the damping force.-	// This really should be in the impulse solver and can produce problems when using large damping values.-	cpFloat vrn = cpvdot(cpvsub(v2, v1), n);-	cpFloat f_damp = vrn*cpfmin(dmp, 1.0f/(dt*(a->m_inv + b->m_inv)));-	-	// Apply!-	cpVect f = cpvmult(n, f_spring + f_damp);-	cpBodyApplyForce(a, f, r1);-	cpBodyApplyForce(b, cpvneg(f), r2);-}--//int-//cpBodyMarkLowEnergy(cpBody *body, cpFloat dvsq, int max)-//{-//	cpFloat ke = body->m*cpvdot(body->v, body->v);-//	cpFloat re = body->i*body->w*body->w;-//	-//	if(ke + re > body->m*dvsq)-//		body->active = 1;-//	else if(body->active)-//		body->active = (body->active + 1)%(max + 1);-//	else {-//		body->v = cpvzero;-//		body->v_bias = cpvzero;-//		body->w = 0.0f;-//		body->w_bias = 0.0f;-//	}-//	-//	return body->active;-//}
− chipmunk-5.0/cpBody.h
@@ -1,153 +0,0 @@-/* Copyright (c) 2007 Scott Lembcke- * - * Permission is hereby granted, free of charge, to any person obtaining a copy- * of this software and associated documentation files (the "Software"), to deal- * in the Software without restriction, including without limitation the rights- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell- * copies of the Software, and to permit persons to whom the Software is- * furnished to do so, subject to the following conditions:- * - * The above copyright notice and this permission notice shall be included in- * all copies or substantial portions of the Software.- * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE- * SOFTWARE.- */--struct cpBody;-typedef void (*cpBodyVelocityFunc)(struct cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt);-typedef void (*cpBodyPositionFunc)(struct cpBody *body, cpFloat dt);-- -typedef struct cpBody{-	// *** Integration Functions.ntoehu--	// Function that is called to integrate the body's velocity. (Defaults to cpBodyUpdateVelocity)-	cpBodyVelocityFunc velocity_func;-	-	// Function that is called to integrate the body's position. (Defaults to cpBodyUpdatePosition)-	cpBodyPositionFunc position_func;-	-	// *** Mass Properties-	-	// Mass and it's inverse.-	// Always use cpBodySetMass() whenever changing the mass as these values must agree.-	cpFloat m, m_inv;-	-	// Moment of inertia and it's inverse.-	// Always use cpBodySetMass() whenever changing the mass as these values must agree.-	cpFloat i, i_inv;-	-	// *** Positional Properties-	-	// Linear components of motion (position, velocity, and force)-	cpVect p, v, f;-	-	// Angular components of motion (angle, angular velocity, and torque)-	// Always use cpBodySetAngle() to set the angle of the body as a and rot must agree.-	cpFloat a, w, t;-	-	// Cached unit length vector representing the angle of the body.-	// Used for fast vector rotation using cpvrotate().-	cpVect rot;-	-	// *** User Definable Fields-	-	// User defined data pointer.-	void *data;-	-	// *** Internally Used Fields-	-	// Velocity bias values used when solving penetrations and correcting constraints.-	cpVect v_bias;-	cpFloat w_bias;-	-//	int active;-} cpBody;--// Basic allocation/destruction functions-cpBody *cpBodyAlloc(void);-cpBody *cpBodyInit(cpBody *body, cpFloat m, cpFloat i);-cpBody *cpBodyNew(cpFloat m, cpFloat i);--void cpBodyDestroy(cpBody *body);-void cpBodyFree(cpBody *body);--#define CP_DefineBodyGetter(type, member, name) static inline type cpBodyGet##name(cpBody *body){return body->member;}-#define CP_DefineBodySetter(type, member, name) static inline void cpBodySet##name(cpBody *body, type value){body->member = value;}--#define CP_DefineBodyProperty(type, member, name) \-CP_DefineBodyGetter(type, member, name) \-CP_DefineBodySetter(type, member, name)---// Accessors for cpBody struct members-CP_DefineBodyGetter(cpFloat, m, Mass);-void cpBodySetMass(cpBody *body, cpFloat m);--CP_DefineBodyGetter(cpFloat, i, Moment);-void cpBodySetMoment(cpBody *body, cpFloat i);---CP_DefineBodyProperty(cpVect, p, Pos);-CP_DefineBodyProperty(cpVect, v, Vel);-CP_DefineBodyProperty(cpVect, f, Force);-CP_DefineBodyGetter(cpFloat, a, Angle);-void cpBodySetAngle(cpBody *body, cpFloat a);-CP_DefineBodyProperty(cpFloat, w, AngVel);-CP_DefineBodyProperty(cpFloat, t, Torque);-CP_DefineBodyGetter(cpVect, rot, Rot);--//  Modify the velocity of the body so that it will move to the specified absolute coordinates in the next timestep.-// Intended for objects that are moved manually with a custom velocity integration function.-void cpBodySlew(cpBody *body, cpVect pos, cpFloat dt);--// Default Integration functions.-void cpBodyUpdateVelocity(cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt);-void cpBodyUpdatePosition(cpBody *body, cpFloat dt);--// Convert body local to world coordinates-static inline cpVect-cpBodyLocal2World(cpBody *body, cpVect v)-{-	return cpvadd(body->p, cpvrotate(v, body->rot));-}--// Convert world to body local coordinates-static inline cpVect-cpBodyWorld2Local(cpBody *body, cpVect v)-{-	return cpvunrotate(cpvsub(v, body->p), body->rot);-}--// Apply an impulse (in world coordinates) to the body at a point relative to the center of gravity (also in world coordinates).-static inline void-cpBodyApplyImpulse(cpBody *body, cpVect j, cpVect r)-{-	body->v = cpvadd(body->v, cpvmult(j, body->m_inv));-	body->w += body->i_inv*cpvcross(r, j);-}--// Not intended for external use. Used by cpArbiter.c and cpConstraint.c.-static inline void-cpBodyApplyBiasImpulse(cpBody *body, cpVect j, cpVect r)-{-	body->v_bias = cpvadd(body->v_bias, cpvmult(j, body->m_inv));-	body->w_bias += body->i_inv*cpvcross(r, j);-}--// Zero the forces on a body.-void cpBodyResetForces(cpBody *body);-// Apply a force (in world coordinates) to a body at a point relative to the center of gravity (also in world coordinates).-void cpBodyApplyForce(cpBody *body, cpVect f, cpVect r);--// Apply a damped spring force between two bodies.-// Warning: Large damping values can be unstable. Use a cpDampedSpring constraint for this instead.-void cpApplyDampedSpring(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat rlen, cpFloat k, cpFloat dmp, cpFloat dt);--//int cpBodyMarkLowEnergy(cpBody *body, cpFloat dvsq, int max);
− chipmunk-5.0/cpCollision.c
@@ -1,403 +0,0 @@-/* Copyright (c) 2007 Scott Lembcke- * - * Permission is hereby granted, free of charge, to any person obtaining a copy- * of this software and associated documentation files (the "Software"), to deal- * in the Software without restriction, including without limitation the rights- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell- * copies of the Software, and to permit persons to whom the Software is- * furnished to do so, subject to the following conditions:- * - * The above copyright notice and this permission notice shall be included in- * all copies or substantial portions of the Software.- * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE- * SOFTWARE.- */- -#include <stdlib.h>-#include <math.h>-#include <stdio.h>-#include <assert.h>--#include "chipmunk.h"--typedef int (*collisionFunc)(cpShape*, cpShape*, cpContact**);--// Add contact points for circle to circle collisions.-// Used by several collision tests.-static int-circle2circleQuery(cpVect p1, cpVect p2, cpFloat r1, cpFloat r2, cpContact **con)-{-	cpFloat mindist = r1 + r2;-	cpVect delta = cpvsub(p2, p1);-	cpFloat distsq = cpvlengthsq(delta);-	if(distsq >= mindist*mindist) return 0;-	-	cpFloat dist = cpfsqrt(distsq);-	// To avoid singularities, do nothing in the case of dist = 0.-	cpFloat non_zero_dist = (dist ? dist : INFINITY);--	// Allocate and initialize the contact.-	(*con) = (cpContact *)malloc(sizeof(cpContact));-	cpContactInit(-		(*con),-		cpvadd(p1, cpvmult(delta, 0.5 + (r1 - 0.5*mindist)/non_zero_dist)),-		cpvmult(delta, 1.0/non_zero_dist),-		dist - mindist,-		0-	);-	-	return 1;-}--// Collide circle shapes.-static int-circle2circle(cpShape *shape1, cpShape *shape2, cpContact **arr)-{-	cpCircleShape *circ1 = (cpCircleShape *)shape1;-	cpCircleShape *circ2 = (cpCircleShape *)shape2;-	-	return circle2circleQuery(circ1->tc, circ2->tc, circ1->r, circ2->r, arr);-}--// Collide circles to segment shapes.-static int-circle2segment(cpShape *circleShape, cpShape *segmentShape, cpContact **con)-{-	cpCircleShape *circ = (cpCircleShape *)circleShape;-	cpSegmentShape *seg = (cpSegmentShape *)segmentShape;-	-	// Radius sum-	cpFloat rsum = circ->r + seg->r;-	-	// Calculate normal distance from segment.-	cpFloat dn = cpvdot(seg->tn, circ->tc) - cpvdot(seg->ta, seg->tn);-	cpFloat dist = cpfabs(dn) - rsum;-	if(dist > 0.0f) return 0;-	-	// Calculate tangential distance along segment.-	cpFloat dt = -cpvcross(seg->tn, circ->tc);-	cpFloat dtMin = -cpvcross(seg->tn, seg->ta);-	cpFloat dtMax = -cpvcross(seg->tn, seg->tb);-	-	// Decision tree to decide which feature of the segment to collide with.-	if(dt < dtMin){-		if(dt < (dtMin - rsum)){-			return 0;-		} else {-			return circle2circleQuery(circ->tc, seg->ta, circ->r, seg->r, con);-		}-	} else {-		if(dt < dtMax){-			cpVect n = (dn < 0.0f) ? seg->tn : cpvneg(seg->tn);-			(*con) = (cpContact *)malloc(sizeof(cpContact));-			cpContactInit(-				(*con),-				cpvadd(circ->tc, cpvmult(n, circ->r + dist*0.5f)),-				n,-				dist,-				0				 -			);-			return 1;-		} else {-			if(dt < (dtMax + rsum)) {-				return circle2circleQuery(circ->tc, seg->tb, circ->r, seg->r, con);-			} else {-				return 0;-			}-		}-	}-	-	return 1;-}--// Helper function for allocating contact point lists.-static cpContact *-addContactPoint(cpContact **arr, int *max, int *num)-{-	if(*arr == NULL){-		// Allocate the array if it hasn't been done.-		(*max) = 2;-		(*num) = 0;-		(*arr) = (cpContact *)malloc((*max)*sizeof(cpContact));-	} else if(*num == *max){-		// Extend it if necessary.-		(*max) *= 2;-		(*arr) = (cpContact *)realloc(*arr, (*max)*sizeof(cpContact));-	}-	-	cpContact *con = &(*arr)[*num];-	(*num)++;-	-	return con;-}--// Find the minimum separating axis for the give poly and axis list.-static inline int-findMSA(cpPolyShape *poly, cpPolyShapeAxis *axes, int num, cpFloat *min_out)-{-	int min_index = 0;-	cpFloat min = cpPolyShapeValueOnAxis(poly, axes->n, axes->d);-	if(min > 0.0) return -1;-	-	for(int i=1; i<num; i++){-		cpFloat dist = cpPolyShapeValueOnAxis(poly, axes[i].n, axes[i].d);-		if(dist > 0.0) {-			return -1;-		} else if(dist > min){-			min = dist;-			min_index = i;-		}-	}-	-	(*min_out) = min;-	return min_index;-}--// Add contacts for penetrating vertexes.-static inline int-findVerts(cpContact **arr, cpPolyShape *poly1, cpPolyShape *poly2, cpVect n, cpFloat dist)-{-	int max = 0;-	int num = 0;-	-	for(int i=0; i<poly1->numVerts; i++){-		cpVect v = poly1->tVerts[i];-		if(cpPolyShapeContainsVertPartial(poly2, v, cpvneg(n)))-			cpContactInit(addContactPoint(arr, &max, &num), v, n, dist, CP_HASH_PAIR(poly1, i));-	}-	-	for(int i=0; i<poly2->numVerts; i++){-		cpVect v = poly2->tVerts[i];-		if(cpPolyShapeContainsVertPartial(poly1, v, n))-			cpContactInit(addContactPoint(arr, &max, &num), v, n, dist, CP_HASH_PAIR(poly2, i));-	}-	-	//	if(!num)-	//		addContactPoint(arr, &size, &num, cpContactNew(shape1->body->p, n, dist, 0));--	return num;-}--// Collide poly shapes together.-static int-poly2poly(cpShape *shape1, cpShape *shape2, cpContact **arr)-{-	cpPolyShape *poly1 = (cpPolyShape *)shape1;-	cpPolyShape *poly2 = (cpPolyShape *)shape2;-	-	cpFloat min1;-	int mini1 = findMSA(poly2, poly1->tAxes, poly1->numVerts, &min1);-	if(mini1 == -1) return 0;-	-	cpFloat min2;-	int mini2 = findMSA(poly1, poly2->tAxes, poly2->numVerts, &min2);-	if(mini2 == -1) return 0;-	-	// There is overlap, find the penetrating verts-	if(min1 > min2)-		return findVerts(arr, poly1, poly2, poly1->tAxes[mini1].n, min1);-	else-		return findVerts(arr, poly1, poly2, cpvneg(poly2->tAxes[mini2].n), min2);-}--// Like cpPolyValueOnAxis(), but for segments.-static inline float-segValueOnAxis(cpSegmentShape *seg, cpVect n, cpFloat d)-{-	cpFloat a = cpvdot(n, seg->ta) - seg->r;-	cpFloat b = cpvdot(n, seg->tb) - seg->r;-	return cpfmin(a, b) - d;-}--// Identify vertexes that have penetrated the segment.-static inline void-findPointsBehindSeg(cpContact **arr, int *max, int *num, cpSegmentShape *seg, cpPolyShape *poly, cpFloat pDist, cpFloat coef) -{-	cpFloat dta = cpvcross(seg->tn, seg->ta);-	cpFloat dtb = cpvcross(seg->tn, seg->tb);-	cpVect n = cpvmult(seg->tn, coef);-	-	for(int i=0; i<poly->numVerts; i++){-		cpVect v = poly->tVerts[i];-		if(cpvdot(v, n) < cpvdot(seg->tn, seg->ta)*coef + seg->r){-			cpFloat dt = cpvcross(seg->tn, v);-			if(dta >= dt && dt >= dtb){-				cpContactInit(addContactPoint(arr, max, num), v, n, pDist, CP_HASH_PAIR(poly, i));-			}-		}-	}-}--// This one is complicated and gross. Just don't go there...-// TODO: Comment me!-static int-seg2poly(cpShape *shape1, cpShape *shape2, cpContact **arr)-{-	cpSegmentShape *seg = (cpSegmentShape *)shape1;-	cpPolyShape *poly = (cpPolyShape *)shape2;-	cpPolyShapeAxis *axes = poly->tAxes;-	-	cpFloat segD = cpvdot(seg->tn, seg->ta);-	cpFloat minNorm = cpPolyShapeValueOnAxis(poly, seg->tn, segD) - seg->r;-	cpFloat minNeg = cpPolyShapeValueOnAxis(poly, cpvneg(seg->tn), -segD) - seg->r;-	if(minNeg > 0.0f || minNorm > 0.0f) return 0;-	-	int mini = 0;-	cpFloat poly_min = segValueOnAxis(seg, axes->n, axes->d);-	if(poly_min > 0.0f) return 0;-	for(int i=0; i<poly->numVerts; i++){-		cpFloat dist = segValueOnAxis(seg, axes[i].n, axes[i].d);-		if(dist > 0.0f){-			return 0;-		} else if(dist > poly_min){-			poly_min = dist;-			mini = i;-		}-	}-	-	int max = 0;-	int num = 0;-	-	cpVect poly_n = cpvneg(axes[mini].n);-	-	cpVect va = cpvadd(seg->ta, cpvmult(poly_n, seg->r));-	cpVect vb = cpvadd(seg->tb, cpvmult(poly_n, seg->r));-	if(cpPolyShapeContainsVert(poly, va))-		cpContactInit(addContactPoint(arr, &max, &num), va, poly_n, poly_min, CP_HASH_PAIR(seg, 0));-	if(cpPolyShapeContainsVert(poly, vb))-		cpContactInit(addContactPoint(arr, &max, &num), vb, poly_n, poly_min, CP_HASH_PAIR(seg, 1));--	// Floating point precision problems here.-	// This will have to do for now.-	poly_min -= cp_collision_slop;-	if(minNorm >= poly_min || minNeg >= poly_min) {-		if(minNorm > minNeg)-			findPointsBehindSeg(arr, &max, &num, seg, poly, minNorm, 1.0f);-		else-			findPointsBehindSeg(arr, &max, &num, seg, poly, minNeg, -1.0f);-	}-	-	// If no other collision points are found, try colliding endpoints.-	if(num == 0){-		cpVect poly_a = poly->tVerts[mini];-		cpVect poly_b = poly->tVerts[(mini + 1)%poly->numVerts];-		-		if(circle2circleQuery(seg->ta, poly_a, seg->r, 0.0f, arr))-			return 1;-			-		if(circle2circleQuery(seg->tb, poly_a, seg->r, 0.0f, arr))-			return 1;-			-		if(circle2circleQuery(seg->ta, poly_b, seg->r, 0.0f, arr))-			return 1;-			-		if(circle2circleQuery(seg->tb, poly_b, seg->r, 0.0f, arr))-			return 1;-	}--	return num;-}--// This one is less gross, but still gross.-// TODO: Comment me!-static int-circle2poly(cpShape *shape1, cpShape *shape2, cpContact **con)-{-	cpCircleShape *circ = (cpCircleShape *)shape1;-	cpPolyShape *poly = (cpPolyShape *)shape2;-	cpPolyShapeAxis *axes = poly->tAxes;-	-	int mini = 0;-	cpFloat min = cpvdot(axes->n, circ->tc) - axes->d - circ->r;-	for(int i=0; i<poly->numVerts; i++){-		cpFloat dist = cpvdot(axes[i].n, circ->tc) - axes[i].d - circ->r;-		if(dist > 0.0){-			return 0;-		} else if(dist > min) {-			min = dist;-			mini = i;-		}-	}-	-	cpVect n = axes[mini].n;-	cpVect a = poly->tVerts[mini];-	cpVect b = poly->tVerts[(mini + 1)%poly->numVerts];-	cpFloat dta = cpvcross(n, a);-	cpFloat dtb = cpvcross(n, b);-	cpFloat dt = cpvcross(n, circ->tc);-		-	if(dt < dtb){-		return circle2circleQuery(circ->tc, b, circ->r, 0.0f, con);-	} else if(dt < dta) {-		(*con) = (cpContact *)malloc(sizeof(cpContact));-		cpContactInit(-			(*con),-			cpvsub(circ->tc, cpvmult(n, circ->r + min/2.0f)),-			cpvneg(n),-			min,-			0				 -		);-	-		return 1;-	} else {-		return circle2circleQuery(circ->tc, a, circ->r, 0.0f, con);-	}-}--//static const collisionFunc builtinCollisionFuncs[9] = {-//	circle2circle,-//	NULL,-//	NULL,-//	circle2segment,-//	NULL,-//	NULL,-//	circle2poly,-//	seg2poly,-//	poly2poly,-//};-//static const collisionFunc *colfuncs = builtinCollisionFuncs;--static collisionFunc *colfuncs = NULL;--static void-addColFunc(cpShapeType a, cpShapeType b, collisionFunc func)-{-	colfuncs[a + b*CP_NUM_SHAPES] = func;-}--#ifdef __cplusplus-extern "C" {-#endif-	// Initializes the array of collision functions.-	// Called by cpInitChipmunk().-	void-	cpInitCollisionFuncs(void)-	{-		if(!colfuncs)-			colfuncs = (collisionFunc *)calloc(CP_NUM_SHAPES*CP_NUM_SHAPES, sizeof(collisionFunc));-		-		addColFunc(CP_CIRCLE_SHAPE,  CP_CIRCLE_SHAPE,  circle2circle);-		addColFunc(CP_CIRCLE_SHAPE,  CP_SEGMENT_SHAPE, circle2segment);-		addColFunc(CP_SEGMENT_SHAPE, CP_POLY_SHAPE,    seg2poly);-		addColFunc(CP_CIRCLE_SHAPE,  CP_POLY_SHAPE,    circle2poly);-		addColFunc(CP_POLY_SHAPE,    CP_POLY_SHAPE,    poly2poly);-	}	-#ifdef __cplusplus-}-#endif--int-cpCollideShapes(cpShape *a, cpShape *b, cpContact **arr)-{-	// Their shape types must be in order.-	assert(a->klass->type <= b->klass->type);-	-	collisionFunc cfunc = colfuncs[a->klass->type + b->klass->type*CP_NUM_SHAPES];-	return (cfunc) ? cfunc(a, b, arr) : 0;-}
− chipmunk-5.0/cpCollision.h
@@ -1,23 +0,0 @@-/* Copyright (c) 2007 Scott Lembcke- * - * Permission is hereby granted, free of charge, to any person obtaining a copy- * of this software and associated documentation files (the "Software"), to deal- * in the Software without restriction, including without limitation the rights- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell- * copies of the Software, and to permit persons to whom the Software is- * furnished to do so, subject to the following conditions:- * - * The above copyright notice and this permission notice shall be included in- * all copies or substantial portions of the Software.- * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE- * SOFTWARE.- */--// Collides two cpShape structures. (this function is lonely :( )-int cpCollideShapes(cpShape *a, cpShape *b, cpContact **arr);
− chipmunk-5.0/cpHashSet.c
@@ -1,225 +0,0 @@-/* Copyright (c) 2007 Scott Lembcke- * - * Permission is hereby granted, free of charge, to any person obtaining a copy- * of this software and associated documentation files (the "Software"), to deal- * in the Software without restriction, including without limitation the rights- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell- * copies of the Software, and to permit persons to whom the Software is- * furnished to do so, subject to the following conditions:- * - * The above copyright notice and this permission notice shall be included in- * all copies or substantial portions of the Software.- * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE- * SOFTWARE.- */- -#include <stdlib.h>-#include <assert.h>--#include "chipmunk.h"-#include "prime.h"--void-cpHashSetDestroy(cpHashSet *set)-{-	// Free the chains.-	for(int i=0; i<set->size; i++){-		// Free the bins in the chain.-		cpHashSetBin *bin = set->table[i];-		while(bin){-			cpHashSetBin *next = bin->next;-			free(bin);-			bin = next;-		}-	}-	-	// Free the table.-	free(set->table);-}--void-cpHashSetFree(cpHashSet *set)-{-	if(set) cpHashSetDestroy(set);-	free(set);-}--cpHashSet *-cpHashSetAlloc(void)-{-	return (cpHashSet *)calloc(1, sizeof(cpHashSet));-}--cpHashSet *-cpHashSetInit(cpHashSet *set, int size, cpHashSetEqlFunc eqlFunc, cpHashSetTransFunc trans)-{-	set->size = next_prime(size);-	set->entries = 0;-	-	set->eql = eqlFunc;-	set->trans = trans;-	-	set->default_value = NULL;-	-	set->table = (cpHashSetBin **)calloc(set->size, sizeof(cpHashSetBin *));-	-	return set;-}--cpHashSet *-cpHashSetNew(int size, cpHashSetEqlFunc eqlFunc, cpHashSetTransFunc trans)-{-	return cpHashSetInit(cpHashSetAlloc(), size, eqlFunc, trans);-}--static int-setIsFull(cpHashSet *set)-{-	return (set->entries >= set->size);-}--static void-cpHashSetResize(cpHashSet *set)-{-	// Get the next approximate doubled prime.-	int newSize = next_prime(set->size + 1);-	// Allocate a new table.-	cpHashSetBin **newTable = (cpHashSetBin **)calloc(newSize, sizeof(cpHashSetBin *));-	-	// Iterate over the chains.-	for(int i=0; i<set->size; i++){-		// Rehash the bins into the new table.-		cpHashSetBin *bin = set->table[i];-		while(bin){-			cpHashSetBin *next = bin->next;-			-			int index = bin->hash%newSize;-			bin->next = newTable[index];-			newTable[index] = bin;-			-			bin = next;-		}-	}-	-	free(set->table);-	-	set->table = newTable;-	set->size = newSize;-}--void *-cpHashSetInsert(cpHashSet *set, cpHashValue hash, void *ptr, void *data)-{-	int index = hash%set->size;-	-	// Find the bin with the matching element.-	cpHashSetBin *bin = set->table[index];-	while(bin && !set->eql(ptr, bin->elt))-		bin = bin->next;-	-	// Create it necessary.-	if(!bin){-		bin = (cpHashSetBin *)malloc(sizeof(cpHashSetBin));-		bin->hash = hash;-		bin->elt = set->trans(ptr, data); // Transform the pointer.-		-		bin->next = set->table[index];-		set->table[index] = bin;-		-		set->entries++;-		-		// Resize the set if it's full.-		if(setIsFull(set))-			cpHashSetResize(set);-	}-	-	return bin->elt;-}--void *-cpHashSetRemove(cpHashSet *set, cpHashValue hash, void *ptr)-{-	int index = hash%set->size;-	-	// Pointer to the previous bin pointer.-	cpHashSetBin **prev_ptr = &set->table[index];-	// Pointer the the current bin.-	cpHashSetBin *bin = set->table[index];-	-	// Find the bin-	while(bin && !set->eql(ptr, bin->elt)){-		prev_ptr = &bin->next;-		bin = bin->next;-	}-	-	// Remove it if it exists.-	if(bin){-		// Update the previous bin pointer to point to the next bin.-		(*prev_ptr) = bin->next;-		set->entries--;-		-		void *return_value = bin->elt;-		-//		*bin = (cpHashSetBin){};-		free(bin);-		-		return return_value;-	}-	-	return NULL;-}--void *-cpHashSetFind(cpHashSet *set, cpHashValue hash, void *ptr)-{	-	int index = hash%set->size;-	cpHashSetBin *bin = set->table[index];-	while(bin && !set->eql(ptr, bin->elt))-		bin = bin->next;-		-	return (bin ? bin->elt : set->default_value);-}--void-cpHashSetEach(cpHashSet *set, cpHashSetIterFunc func, void *data)-{-	for(int i=0; i<set->size; i++){-		cpHashSetBin *bin = set->table[i];-		while(bin){-			cpHashSetBin *next = bin->next;-			func(bin->elt, data);-			bin = next;-		}-	}-}--void-cpHashSetReject(cpHashSet *set, cpHashSetRejectFunc func, void *data)-{-	// Iterate over all the chains.-	for(int i=0; i<set->size; i++){-		// The rest works similarly to cpHashSetRemove() above.-		cpHashSetBin **prev_ptr = &set->table[i];-		cpHashSetBin *bin = set->table[i];-		while(bin){-			cpHashSetBin *next = bin->next;-			-			if(func(bin->elt, data)){-				prev_ptr = &bin->next;-			} else {-				(*prev_ptr) = next;--				set->entries--;-				free(bin);-			}-			-			bin = next;-		}-	}-}
− chipmunk-5.0/cpHashSet.h
@@ -1,79 +0,0 @@-/* Copyright (c) 2007 Scott Lembcke- * - * Permission is hereby granted, free of charge, to any person obtaining a copy- * of this software and associated documentation files (the "Software"), to deal- * in the Software without restriction, including without limitation the rights- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell- * copies of the Software, and to permit persons to whom the Software is- * furnished to do so, subject to the following conditions:- * - * The above copyright notice and this permission notice shall be included in- * all copies or substantial portions of the Software.- * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE- * SOFTWARE.- */- -// cpHashSet uses a chained hashtable implementation.-// Other than the transformation functions, there is nothing fancy going on.--// cpHashSetBin's form the linked lists in the chained hash table.-typedef struct cpHashSetBin {-	// Pointer to the element.-	void *elt;-	// Hash value of the element.-	cpHashValue hash;-	// Next element in the chain.-	struct cpHashSetBin *next;-} cpHashSetBin;--// Equality function. Returns true if ptr is equal to elt.-typedef int (*cpHashSetEqlFunc)(void *ptr, void *elt);-// Used by cpHashSetInsert(). Called to transform the ptr into an element.-typedef void *(*cpHashSetTransFunc)(void *ptr, void *data);-// Iterator function for a hashset.-typedef void (*cpHashSetIterFunc)(void *elt, void *data);-// Reject function. Returns true if elt should be dropped.-typedef int (*cpHashSetRejectFunc)(void *elt, void *data);--typedef struct cpHashSet {-	// Number of elements stored in the table.-	int entries;-	// Number of cells in the table.-	int size;-	-	cpHashSetEqlFunc eql;-	cpHashSetTransFunc trans;-	-	// Default value returned by cpHashSetFind() when no element is found.-	// Defaults to NULL.-	void *default_value;-	-	cpHashSetBin **table;-} cpHashSet;--// Basic allocation/destruction functions.-void cpHashSetDestroy(cpHashSet *set);-void cpHashSetFree(cpHashSet *set);--cpHashSet *cpHashSetAlloc(void);-cpHashSet *cpHashSetInit(cpHashSet *set, int size, cpHashSetEqlFunc eqlFunc, cpHashSetTransFunc trans);-cpHashSet *cpHashSetNew(int size, cpHashSetEqlFunc eqlFunc, cpHashSetTransFunc trans);--// Insert an element into the set, returns the element.-// If it doesn't already exist, the transformation function is applied.-void *cpHashSetInsert(cpHashSet *set, cpHashValue hash, void *ptr, void *data);-// Remove and return an element from the set.-void *cpHashSetRemove(cpHashSet *set, cpHashValue hash, void *ptr);-// Find an element in the set. Returns the default value if the element isn't found.-void *cpHashSetFind(cpHashSet *set, cpHashValue hash, void *ptr);--// Iterate over a hashset.-void cpHashSetEach(cpHashSet *set, cpHashSetIterFunc func, void *data);-// Iterate over a hashset while rejecting certain elements.-void cpHashSetReject(cpHashSet *set, cpHashSetRejectFunc func, void *data);
− chipmunk-5.0/cpPolyShape.c
@@ -1,219 +0,0 @@-/* Copyright (c) 2007 Scott Lembcke- * - * Permission is hereby granted, free of charge, to any person obtaining a copy- * of this software and associated documentation files (the "Software"), to deal- * in the Software without restriction, including without limitation the rights- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell- * copies of the Software, and to permit persons to whom the Software is- * furnished to do so, subject to the following conditions:- * - * The above copyright notice and this permission notice shall be included in- * all copies or substantial portions of the Software.- * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE- * SOFTWARE.- */- -#include <stdlib.h>-#include <stdio.h>-#include <assert.h>--#include "chipmunk.h"--cpPolyShape *-cpPolyShapeAlloc(void)-{-	return (cpPolyShape *)calloc(1, sizeof(cpPolyShape));-}--static void-cpPolyShapeTransformVerts(cpPolyShape *poly, cpVect p, cpVect rot)-{-	cpVect *src = poly->verts;-	cpVect *dst = poly->tVerts;-	-	for(int i=0; i<poly->numVerts; i++)-		dst[i] = cpvadd(p, cpvrotate(src[i], rot));-}--static void-cpPolyShapeTransformAxes(cpPolyShape *poly, cpVect p, cpVect rot)-{-	cpPolyShapeAxis *src = poly->axes;-	cpPolyShapeAxis *dst = poly->tAxes;-	-	for(int i=0; i<poly->numVerts; i++){-		cpVect n = cpvrotate(src[i].n, rot);-		dst[i].n = n;-		dst[i].d = cpvdot(p, n) + src[i].d;-	}-}--static cpBB-cpPolyShapeCacheData(cpShape *shape, cpVect p, cpVect rot)-{-	cpPolyShape *poly = (cpPolyShape *)shape;-	-	cpFloat l, b, r, t;-	-	cpPolyShapeTransformAxes(poly, p, rot);-	cpPolyShapeTransformVerts(poly, p, rot);-	-	cpVect *verts = poly->tVerts;-	l = r = verts[0].x;-	b = t = verts[0].y;-	-	// TODO do as part of cpPolyShapeTransformVerts?-	for(int i=1; i<poly->numVerts; i++){-		cpVect v = verts[i];-		-		l = cpfmin(l, v.x);-		r = cpfmax(r, v.x);-		-		b = cpfmin(b, v.y);-		t = cpfmax(t, v.y);-	}-	-	return cpBBNew(l, b, r, t);-}--static void-cpPolyShapeDestroy(cpShape *shape)-{-	cpPolyShape *poly = (cpPolyShape *)shape;-	-	free(poly->verts);-	free(poly->tVerts);-	-	free(poly->axes);-	free(poly->tAxes);-}--static int-cpPolyShapePointQuery(cpShape *shape, cpVect p){-	return cpBBcontainsVect(shape->bb, p) && cpPolyShapeContainsVert((cpPolyShape *)shape, p);-}--static void-cpPolyShapeSegmentQuery(cpShape *shape, cpVect a, cpVect b, cpSegmentQueryInfo *info)-{-	cpPolyShape *poly = (cpPolyShape *)shape;-	cpPolyShapeAxis *axes = poly->tAxes;-	cpVect *verts = poly->tVerts;-	int numVerts = poly->numVerts;-	-	for(int i=0; i<numVerts; i++){-		cpVect n = axes[i].n;-		cpFloat an = cpvdot(a, n);-		if(axes[i].d > an) continue;-		-		cpFloat bn = cpvdot(b, n);-		cpFloat t = (axes[i].d - an)/(bn - an);-		if(t < 0.0f || 1.0f < t) continue;-		-		cpVect point = cpvlerp(a, b, t);-		cpFloat dt = -cpvcross(n, point);-		cpFloat dtMin = -cpvcross(n, verts[i]);-		cpFloat dtMax = -cpvcross(n, verts[(i+1)%numVerts]);-		-		if(dtMin <= dt && dt <= dtMax){-			info->shape = shape;-			info->t = t;-			info->n = n;-		}-	}-}--static const cpShapeClass polyClass = {-	CP_POLY_SHAPE,-	cpPolyShapeCacheData,-	cpPolyShapeDestroy,-	cpPolyShapePointQuery,-	cpPolyShapeSegmentQuery,-};--int-cpPolyValidate(cpVect *verts, int numVerts)-{-	for(int i=0; i<numVerts; i++){-		cpVect a = verts[i];-		cpVect b = verts[(i+1)%numVerts];-		cpVect c = verts[(i+2)%numVerts];-		-		if(cpvcross(cpvsub(b, a), cpvsub(c, b)) >= 0.0f)-			return 0;-	}-	-	return 1;-}--int-cpPolyShapeGetNumVerts(cpShape *shape)-{-	assert(shape->klass == &polyClass);-	return ((cpPolyShape *)shape)->numVerts;-}--cpVect-cpPolyShapeGetVert(cpShape *shape, int index)-{-	assert(shape->klass == &polyClass);-	assert(index < cpPolyShapeGetNumVerts(shape));-	-	return ((cpPolyShape *)shape)->verts[index];-}---static void-setUpVerts(cpPolyShape *poly, int numVerts, cpVect *verts, cpVect offset)-{-	poly->numVerts = numVerts;--	poly->verts = (cpVect *)calloc(numVerts, sizeof(cpVect));-	poly->tVerts = (cpVect *)calloc(numVerts, sizeof(cpVect));-	poly->axes = (cpPolyShapeAxis *)calloc(numVerts, sizeof(cpPolyShapeAxis));-	poly->tAxes = (cpPolyShapeAxis *)calloc(numVerts, sizeof(cpPolyShapeAxis));-	-	for(int i=0; i<numVerts; i++){-		cpVect a = cpvadd(offset, verts[i]);-		cpVect b = cpvadd(offset, verts[(i+1)%numVerts]);-		cpVect n = cpvnormalize(cpvperp(cpvsub(b, a)));--		poly->verts[i] = a;-		poly->axes[i].n = n;-		poly->axes[i].d = cpvdot(n, a);-	}-}--cpPolyShape *-cpPolyShapeInit(cpPolyShape *poly, cpBody *body, int numVerts, cpVect *verts, cpVect offset)-{-	// Fail if the user attempts to pass a concave poly, or a bad winding.-	assert(cpPolyValidate(verts, numVerts));-	-	setUpVerts(poly, numVerts, verts, offset);-	cpShapeInit((cpShape *)poly, &polyClass, body);--	return poly;-}--cpShape *-cpPolyShapeNew(cpBody *body, int numVerts, cpVect *verts, cpVect offset)-{-	return (cpShape *)cpPolyShapeInit(cpPolyShapeAlloc(), body, numVerts, verts, offset);-}--// Unsafe API (chipmunk_unsafe.h)--void-cpPolyShapeSetVerts(cpShape *shape, int numVerts, cpVect *verts, cpVect offset)-{-	assert(shape->klass == &polyClass);-	cpPolyShapeDestroy(shape);-	setUpVerts((cpPolyShape *)shape, numVerts, verts, offset);-}
− chipmunk-5.0/cpPolyShape.h
@@ -1,100 +0,0 @@-/* Copyright (c) 2007 Scott Lembcke- * - * Permission is hereby granted, free of charge, to any person obtaining a copy- * of this software and associated documentation files (the "Software"), to deal- * in the Software without restriction, including without limitation the rights- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell- * copies of the Software, and to permit persons to whom the Software is- * furnished to do so, subject to the following conditions:- * - * The above copyright notice and this permission notice shall be included in- * all copies or substantial portions of the Software.- * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE- * SOFTWARE.- */--// Axis structure used by cpPolyShape.-typedef struct cpPolyShapeAxis{-	// normal-	cpVect n;-	// distance from origin-	cpFloat d;-} cpPolyShapeAxis;--// Convex polygon shape structure.-typedef struct cpPolyShape{-	cpShape shape;-	-	// Vertex and axis lists.-	int numVerts;-	cpVect *verts;-	cpPolyShapeAxis *axes;--	// Transformed vertex and axis lists.-	cpVect *tVerts;-	cpPolyShapeAxis *tAxes;-} cpPolyShape;--// Basic allocation functions.-cpPolyShape *cpPolyShapeAlloc(void);-cpPolyShape *cpPolyShapeInit(cpPolyShape *poly, cpBody *body, int numVerts, cpVect *verts, cpVect offset);-cpShape *cpPolyShapeNew(cpBody *body, int numVerts, cpVect *verts, cpVect offset);--// Check that a set of vertexes has a correct winding and that they are convex-int cpPolyValidate(cpVect *verts, int numVerts);--int cpPolyShapeGetNumVerts(cpShape *shape);-cpVect cpPolyShapeGetVert(cpShape *shape, int index);--// *** inlined utility functions--// Returns the minimum distance of the polygon to the axis.-static inline cpFloat-cpPolyShapeValueOnAxis(const cpPolyShape *poly, const cpVect n, const cpFloat d)-{-	cpVect *verts = poly->tVerts;-	cpFloat min = cpvdot(n, verts[0]);-	-	int i;-	for(i=1; i<poly->numVerts; i++)-		min = cpfmin(min, cpvdot(n, verts[i]));-	-	return min - d;-}--// Returns true if the polygon contains the vertex.-static inline int-cpPolyShapeContainsVert(cpPolyShape *poly, cpVect v)-{-	cpPolyShapeAxis *axes = poly->tAxes;-	-	int i;-	for(i=0; i<poly->numVerts; i++){-		cpFloat dist = cpvdot(axes[i].n, v) - axes[i].d;-		if(dist > 0.0) return 0;-	}-	-	return 1;-}--// Same as cpPolyShapeContainsVert() but ignores faces pointing away from the normal.-static inline int-cpPolyShapeContainsVertPartial(cpPolyShape *poly, cpVect v, cpVect n)-{-	cpPolyShapeAxis *axes = poly->tAxes;-	-	int i;-	for(i=0; i<poly->numVerts; i++){-		if(cpvdot(axes[i].n, n) < 0.0f) continue;-		cpFloat dist = cpvdot(axes[i].n, v) - axes[i].d;-		if(dist > 0.0) return 0;-	}-	-	return 1;-}
− chipmunk-5.0/cpShape.c
@@ -1,401 +0,0 @@-/* Copyright (c) 2007 Scott Lembcke- * - * Permission is hereby granted, free of charge, to any person obtaining a copy- * of this software and associated documentation files (the "Software"), to deal- * in the Software without restriction, including without limitation the rights- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell- * copies of the Software, and to permit persons to whom the Software is- * furnished to do so, subject to the following conditions:- * - * The above copyright notice and this permission notice shall be included in- * all copies or substantial portions of the Software.- * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE- * SOFTWARE.- */- -#include <stdlib.h>-#include <assert.h>-#include <stdio.h>-#include <math.h>--#include "chipmunk.h"--#define CP_DefineShapeGetter(struct, type, member, name) \-CP_DeclareShapeGetter(struct, type, name){ \-	assert(shape->klass == &struct##Class); \-	return ((struct *)shape)->member; \-}-cpHashValue SHAPE_ID_COUNTER = 0;--void-cpResetShapeIdCounter(void)-{-	SHAPE_ID_COUNTER = 0;-}---cpShape*-cpShapeInit(cpShape *shape, const cpShapeClass *klass, cpBody *body)-{-	shape->klass = klass;-	-	shape->id = SHAPE_ID_COUNTER;-	SHAPE_ID_COUNTER++;-	-	shape->body = body;-	-	shape->e = 0.0f;-	shape->u = 0.0f;-	shape->surface_v = cpvzero;-	-	shape->collision_type = 0;-	shape->group = 0;-	shape->layers = -1;-	-	shape->data = NULL;-	-	cpShapeCacheBB(shape);-	-	return shape;-}--void-cpShapeDestroy(cpShape *shape)-{-	if(shape->klass->destroy) shape->klass->destroy(shape);-}--void-cpShapeFree(cpShape *shape)-{-	if(shape) cpShapeDestroy(shape);-	free(shape);-}--cpBB-cpShapeCacheBB(cpShape *shape)-{-	cpBody *body = shape->body;-	-	shape->bb = shape->klass->cacheData(shape, body->p, body->rot);-	return shape->bb;-}--int-cpShapePointQuery(cpShape *shape, cpVect p, cpLayers layers, cpGroup group){-	if(!(group && shape->group && group == shape->group) && (layers&shape->layers)){-		return shape->klass->pointQuery(shape, p);-	}-	-	return 0;-}--int-cpShapeSegmentQuery(cpShape *shape, cpVect a, cpVect b, cpLayers layers, cpGroup group, cpSegmentQueryInfo *info){-	if(!(group && shape->group && group == shape->group) && (layers&shape->layers)){-		shape->klass->segmentQuery(shape, a, b, info);-	}-	-	return (info->shape != NULL);-}--void-cpSegmentQueryInfoPrint(cpSegmentQueryInfo *info)-{-	printf("Segment Query:\n");-	printf("\tt: %f\n", info->t);-//	printf("\tdist: %f\n", info->dist);-//	printf("\tpoint: %s\n", cpvstr(info->point));-	printf("\tn: %s\n", cpvstr(info->n));-}-----cpCircleShape *-cpCircleShapeAlloc(void)-{-	return (cpCircleShape *)calloc(1, sizeof(cpCircleShape));-}--static inline cpBB-bbFromCircle(const cpVect c, const cpFloat r)-{-	return cpBBNew(c.x-r, c.y-r, c.x+r, c.y+r);-}--static cpBB-cpCircleShapeCacheData(cpShape *shape, cpVect p, cpVect rot)-{-	cpCircleShape *circle = (cpCircleShape *)shape;-	-	circle->tc = cpvadd(p, cpvrotate(circle->c, rot));-	return bbFromCircle(circle->tc, circle->r);-}--static int-cpCircleShapePointQuery(cpShape *shape, cpVect p){-	cpCircleShape *circle = (cpCircleShape *)shape;-	return cpvnear(circle->tc, p, circle->r);-}--static void-circleSegmentQuery(cpShape *shape, cpVect center, cpFloat r, cpVect a, cpVect b, cpSegmentQueryInfo *info)-{-	// umm... gross I normally frown upon such things-	a = cpvsub(a, center);-	b = cpvsub(b, center);-	-	cpFloat qa = cpvdot(a, a) - 2.0f*cpvdot(a, b) + cpvdot(b, b);-	cpFloat qb = -2.0f*cpvdot(a, a) + 2.0f*cpvdot(a, b);-	cpFloat qc = cpvdot(a, a) - r*r;-	-	cpFloat det = qb*qb - 4.0f*qa*qc;-	-	if(det >= 0.0f){-		cpFloat t = (-qb - cpfsqrt(det))/(2.0f*qa);-		if(0.0 <= t && t <= 1.0f){-			info->shape = shape;-			info->t = t;-			info->n = cpvnormalize(cpvlerp(a, b, t));-		}-	}-}--static void-cpCircleShapeSegmentQuery(cpShape *shape, cpVect a, cpVect b, cpSegmentQueryInfo *info)-{-	cpCircleShape *circle = (cpCircleShape *)shape;-	circleSegmentQuery(shape, circle->tc, circle->r, a, b, info);-}--static const cpShapeClass cpCircleShapeClass = {-	CP_CIRCLE_SHAPE,-	cpCircleShapeCacheData,-	NULL,-	cpCircleShapePointQuery,-	cpCircleShapeSegmentQuery,-};--cpCircleShape *-cpCircleShapeInit(cpCircleShape *circle, cpBody *body, cpFloat radius, cpVect offset)-{-	circle->c = offset;-	circle->r = radius;-	-	cpShapeInit((cpShape *)circle, &cpCircleShapeClass, body);-	-	return circle;-}--cpShape *-cpCircleShapeNew(cpBody *body, cpFloat radius, cpVect offset)-{-	return (cpShape *)cpCircleShapeInit(cpCircleShapeAlloc(), body, radius, offset);-}--CP_DefineShapeGetter(cpCircleShape, cpVect, c, Center)-CP_DefineShapeGetter(cpCircleShape, cpFloat, r, Radius)--cpSegmentShape *-cpSegmentShapeAlloc(void)-{-	return (cpSegmentShape *)calloc(1, sizeof(cpSegmentShape));-}--static cpBB-cpSegmentShapeCacheData(cpShape *shape, cpVect p, cpVect rot)-{-	cpSegmentShape *seg = (cpSegmentShape *)shape;-	-	seg->ta = cpvadd(p, cpvrotate(seg->a, rot));-	seg->tb = cpvadd(p, cpvrotate(seg->b, rot));-	seg->tn = cpvrotate(seg->n, rot);-	-	cpFloat l,r,s,t;-	-	if(seg->ta.x < seg->tb.x){-		l = seg->ta.x;-		r = seg->tb.x;-	} else {-		l = seg->tb.x;-		r = seg->ta.x;-	}-	-	if(seg->ta.y < seg->tb.y){-		s = seg->ta.y;-		t = seg->tb.y;-	} else {-		s = seg->tb.y;-		t = seg->ta.y;-	}-	-	cpFloat rad = seg->r;-	return cpBBNew(l - rad, s - rad, r + rad, t + rad);-}--static int-cpSegmentShapePointQuery(cpShape *shape, cpVect p){-	if(!cpBBcontainsVect(shape->bb, p)) return 0;-	-	cpSegmentShape *seg = (cpSegmentShape *)shape;-	-	// Calculate normal distance from segment.-	cpFloat dn = cpvdot(seg->tn, p) - cpvdot(seg->ta, seg->tn);-	cpFloat dist = cpfabs(dn) - seg->r;-	if(dist > 0.0f) return 0;-	-	// Calculate tangential distance along segment.-	cpFloat dt = -cpvcross(seg->tn, p);-	cpFloat dtMin = -cpvcross(seg->tn, seg->ta);-	cpFloat dtMax = -cpvcross(seg->tn, seg->tb);-	-	// Decision tree to decide which feature of the segment to collide with.-	if(dt <= dtMin){-		if(dt < (dtMin - seg->r)){-			return 0;-		} else {-			return cpvlengthsq(cpvsub(seg->ta, p)) < (seg->r*seg->r);-		}-	} else {-		if(dt < dtMax){-			return 1;-		} else {-			if(dt < (dtMax + seg->r)) {-				return cpvlengthsq(cpvsub(seg->tb, p)) < (seg->r*seg->r);-			} else {-				return 0;-			}-		}-	}-	-	return 1;	-}--static void-cpSegmentShapeSegmentQuery(cpShape *shape, cpVect a, cpVect b, cpSegmentQueryInfo *info)-{-	cpSegmentShape *seg = (cpSegmentShape *)shape;-	cpVect n = seg->tn;-	// flip n if a is behind the axis-	if(cpvdot(a, n) < cpvdot(seg->ta, n))-		n = cpvneg(n);-	-	cpFloat an = cpvdot(a, n);-	cpFloat bn = cpvdot(b, n);-	cpFloat d = cpvdot(seg->ta, n) + seg->r;-	-	cpFloat t = (d - an)/(bn - an);-	if(0.0f < t && t < 1.0f){-		cpVect point = cpvlerp(a, b, t);-		cpFloat dt = -cpvcross(seg->tn, point);-		cpFloat dtMin = -cpvcross(seg->tn, seg->ta);-		cpFloat dtMax = -cpvcross(seg->tn, seg->tb);-		-		if(dtMin < dt && dt < dtMax){-			info->shape = shape;-			info->t = t;-			info->n = n;-			-			return; // don't continue on and check endcaps-		}-	}-	-	if(seg->r) {-		cpSegmentQueryInfo info1 = {.shape = NULL};-		cpSegmentQueryInfo info2 = {.shape = NULL};-		circleSegmentQuery(shape, seg->ta, seg->r, a, b, &info1);-		circleSegmentQuery(shape, seg->tb, seg->r, a, b, &info2);-		-		if(info1.shape && !info2.shape){-			(*info) = info1;-		} else if(info2.shape && !info1.shape){-			(*info) = info2;-		} else if(info1.shape && info2.shape){-			if(info1.t < info2.t){-				(*info) = info1;-			} else {-				(*info) = info2;-			}-		}-	}-}--static const cpShapeClass cpSegmentShapeClass = {-	CP_SEGMENT_SHAPE,-	cpSegmentShapeCacheData,-	NULL,-	cpSegmentShapePointQuery,-	cpSegmentShapeSegmentQuery,-};--cpSegmentShape *-cpSegmentShapeInit(cpSegmentShape *seg, cpBody *body, cpVect a, cpVect b, cpFloat r)-{-	seg->a = a;-	seg->b = b;-	seg->n = cpvperp(cpvnormalize(cpvsub(b, a)));-	-	seg->r = r;-	-	cpShapeInit((cpShape *)seg, &cpSegmentShapeClass, body);-	-	return seg;-}--cpShape*-cpSegmentShapeNew(cpBody *body, cpVect a, cpVect b, cpFloat r)-{-	return (cpShape *)cpSegmentShapeInit(cpSegmentShapeAlloc(), body, a, b, r);-}--CP_DefineShapeGetter(cpSegmentShape, cpVect, a, A)-CP_DefineShapeGetter(cpSegmentShape, cpVect, b, B)-CP_DefineShapeGetter(cpSegmentShape, cpVect, n, Normal)-CP_DefineShapeGetter(cpSegmentShape, cpFloat, r, Radius)--// Unsafe API (chipmunk_unsafe.h)--void-cpCircleShapeSetRadius(cpShape *shape, cpFloat radius)-{-	assert(shape->klass == &cpCircleShapeClass);-	cpCircleShape *circle = (cpCircleShape *)shape;-	-	circle->r = radius;-}--void-cpCircleShapeSetOffset(cpShape *shape, cpVect offset)-{-	assert(shape->klass == &cpCircleShapeClass);-	cpCircleShape *circle = (cpCircleShape *)shape;-	-	circle->c = offset;-}--void-cpSegmentShapeSetEndpoints(cpShape *shape, cpVect a, cpVect b)-{-	assert(shape->klass == &cpSegmentShapeClass);-	cpSegmentShape *seg = (cpSegmentShape *)shape;-	-	seg->a = a;-	seg->b = b;-	seg->n = cpvperp(cpvnormalize(cpvsub(b, a)));-}--void-cpSegmentShapeSetRadius(cpShape *shape, cpFloat radius)-{-	assert(shape->klass == &cpSegmentShapeClass);-	cpSegmentShape *seg = (cpSegmentShape *)shape;-	-	seg->r = radius;-}
− chipmunk-5.0/cpShape.h
@@ -1,155 +0,0 @@-/* Copyright (c) 2007 Scott Lembcke- * - * Permission is hereby granted, free of charge, to any person obtaining a copy- * of this software and associated documentation files (the "Software"), to deal- * in the Software without restriction, including without limitation the rights- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell- * copies of the Software, and to permit persons to whom the Software is- * furnished to do so, subject to the following conditions:- * - * The above copyright notice and this permission notice shall be included in- * all copies or substantial portions of the Software.- * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE- * SOFTWARE.- */- -// Forward declarations required for defining other structs.-struct cpShape;-struct cpShapeClass;--typedef struct cpSegmentQueryInfo{-	struct cpShape *shape; // shape that was hit, NULL if no collision-	cpFloat t; // line(t) = a + (b - a)t, will always be in the range [0, 1]-	cpVect n; // normal of hit surface-} cpSegmentQueryInfo;--// For determinism, you can reset the shape id counter.-void cpResetShapeIdCounter(void);--// Enumeration of shape types.-typedef enum cpShapeType{-	CP_CIRCLE_SHAPE,-	CP_SEGMENT_SHAPE,-	CP_POLY_SHAPE,-	CP_NUM_SHAPES-} cpShapeType;--// Shape class. Holds function pointers and type data.-typedef struct cpShapeClass {-	cpShapeType type;-	-	// Called by cpShapeCacheBB().-	cpBB (*cacheData)(struct cpShape *shape, cpVect p, cpVect rot);-	// Called to by cpShapeDestroy().-	void (*destroy)(struct cpShape *shape);-	-	// called by cpShapePointQuery().-	int (*pointQuery)(struct cpShape *shape, cpVect p);-	-	// called by cpShapeSegmentQuery()-	 void (*segmentQuery)(struct cpShape *shape, cpVect a, cpVect b, cpSegmentQueryInfo *info);-} cpShapeClass;--// Basic shape struct that the others inherit from.-typedef struct cpShape{-	// The "class" of a shape as defined above -	const cpShapeClass *klass;-	-	// cpBody that the shape is attached to.-	cpBody *body;--	// Cached BBox for the shape.-	cpBB bb;-	-	// *** Surface properties.-	-	// Coefficient of restitution. (elasticity)-	cpFloat e;-	// Coefficient of friction.-	cpFloat u;-	// Surface velocity used when solving for friction.-	cpVect surface_v;--	// *** User Definable Fields--	// User defined data pointer for the shape.-	void *data;-	-	// User defined collision type for the shape.-	cpCollisionType collision_type;-	// User defined collision group for the shape.-	cpGroup group;-	// User defined layer bitmask for the shape.-	cpLayers layers;-	-	// *** Internally Used Fields-	-	// Unique id used as the hash value.-	cpHashValue id;-} cpShape;--// Low level shape initialization func.-cpShape* cpShapeInit(cpShape *shape, const struct cpShapeClass *klass, cpBody *body);--// Basic destructor functions. (allocation functions are not shared)-void cpShapeDestroy(cpShape *shape);-void cpShapeFree(cpShape *shape);--// Cache the BBox of the shape.-cpBB cpShapeCacheBB(cpShape *shape);--// Test if a point lies within a shape.-int cpShapePointQuery(cpShape *shape, cpVect p, cpLayers layers, cpGroup group);-void cpSegmentQueryInfoPrint(cpSegmentQueryInfo *info);--#define CP_DeclareShapeGetter(struct, type, name) type struct##Get##name(cpShape *shape)--// Circle shape structure.-typedef struct cpCircleShape{-	cpShape shape;-	-	// Center in body space coordinates-	cpVect c;-	// Radius.-	cpFloat r;-	-	// Transformed center. (world space coordinates)-	cpVect tc;-} cpCircleShape;--// Basic allocation functions for cpCircleShape.-cpCircleShape *cpCircleShapeAlloc(void);-cpCircleShape *cpCircleShapeInit(cpCircleShape *circle, cpBody *body, cpFloat radius, cpVect offset);-cpShape *cpCircleShapeNew(cpBody *body, cpFloat radius, cpVect offset);--CP_DeclareShapeGetter(cpCircleShape, cpVect, Offset);-CP_DeclareShapeGetter(cpCircleShape, cpFloat, Radius);--// Segment shape structure.-typedef struct cpSegmentShape{-	cpShape shape;-	-	// Endpoints and normal of the segment. (body space coordinates)-	cpVect a, b, n;-	// Radius of the segment. (Thickness)-	cpFloat r;--	// Transformed endpoints and normal. (world space coordinates)-	cpVect ta, tb, tn;-} cpSegmentShape;--// Basic allocation functions for cpSegmentShape.-cpSegmentShape* cpSegmentShapeAlloc(void);-cpSegmentShape* cpSegmentShapeInit(cpSegmentShape *seg, cpBody *body, cpVect a, cpVect b, cpFloat radius);-cpShape* cpSegmentShapeNew(cpBody *body, cpVect a, cpVect b, cpFloat radius);--CP_DeclareShapeGetter(cpSegmentShape, cpVect, A);-CP_DeclareShapeGetter(cpSegmentShape, cpVect, B);-CP_DeclareShapeGetter(cpSegmentShape, cpVect, Normal);-CP_DeclareShapeGetter(cpSegmentShape, cpFloat, Radius);
− chipmunk-5.0/cpSpace.c
@@ -1,571 +0,0 @@-/* Copyright (c) 2007 Scott Lembcke- * - * Permission is hereby granted, free of charge, to any person obtaining a copy- * of this software and associated documentation files (the "Software"), to deal- * in the Software without restriction, including without limitation the rights- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell- * copies of the Software, and to permit persons to whom the Software is- * furnished to do so, subject to the following conditions:- * - * The above copyright notice and this permission notice shall be included in- * all copies or substantial portions of the Software.- * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE- * SOFTWARE.- */- -#include <stdlib.h>-#include <stdio.h>-#include <string.h>-#include <math.h>-#include <assert.h>--#include "chipmunk.h"--int cp_contact_persistence = 3;--#pragma mark Contact Set Helpers--// Equal function for contactSet.-static int-contactSetEql(cpShape **shapes, cpArbiter *arb)-{-	cpShape *a = shapes[0];-	cpShape *b = shapes[1];-	-	return ((a == arb->a && b == arb->b) || (b == arb->a && a == arb->b));-}--// Transformation function for contactSet.-static void *-contactSetTrans(cpShape **shapes, cpSpace *space)-{-	cpShape *a = shapes[0];-	cpShape *b = shapes[1];-	-	return cpArbiterNew(a, b, space->stamp);-}--#pragma mark Collision Pair Function Helpers--// Collision pair function wrapper struct.-typedef struct collFuncData {-	cpCollFunc func;-	void *data;-} collFuncData;--// Equals function for collFuncSet.-static int-collFuncSetEql(cpCollisionType *ids, cpCollPairFunc *pair)-{-	cpCollisionType a = ids[0];-	cpCollisionType b = ids[1];-	-	return ((a == pair->a && b == pair->b) || (b == pair->a && a == pair->b));-}--// Transformation function for collFuncSet.-static void *-collFuncSetTrans(cpCollisionType *ids, collFuncData *funcData)-{-	cpCollPairFunc *pair = (cpCollPairFunc *)malloc(sizeof(cpCollPairFunc));-	pair->a = ids[0];-	pair->b = ids[1];-	pair->func = funcData->func;-	pair->data = funcData->data;--	return pair;-}--#pragma mark Misc Helper Funcs--// Default collision pair function.-static int-alwaysCollide(cpShape *a, cpShape *b, cpContact *arr, int numCon, cpFloat normal_coef, void *data)-{-	return 1;-}--// BBfunc callback for the spatial hash.-static cpBB shapeBBFunc(cpShape *shape){return shape->bb;}--// Iterator functions for destructors.-static void             freeWrap(void         *ptr, void *unused){            free(ptr);}-static void        shapeFreeWrap(cpShape      *ptr, void *unused){     cpShapeFree(ptr);}-static void      arbiterFreeWrap(cpArbiter    *ptr, void *unused){   cpArbiterFree(ptr);}-static void         bodyFreeWrap(cpBody       *ptr, void *unused){      cpBodyFree(ptr);}-static void   constraintFreeWrap(cpConstraint *ptr, void *unused){cpConstraintFree(ptr);}--#pragma mark Memory Management Functions--cpSpace*-cpSpaceAlloc(void)-{-	return (cpSpace *)calloc(1, sizeof(cpSpace));-}--#define DEFAULT_DIM_SIZE 100.0f-#define DEFAULT_COUNT 1000-#define DEFAULT_ITERATIONS 10-#define DEFAULT_ELASTIC_ITERATIONS 0--cpSpace*-cpSpaceInit(cpSpace *space)-{-	space->iterations = DEFAULT_ITERATIONS;-	space->elasticIterations = DEFAULT_ELASTIC_ITERATIONS;-//	space->sleepTicks = 300;-	-	space->gravity = cpvzero;-	space->damping = 1.0f;-	-	space->stamp = 0;--	space->staticShapes = cpSpaceHashNew(DEFAULT_DIM_SIZE, DEFAULT_COUNT, (cpSpaceHashBBFunc)shapeBBFunc);-	space->activeShapes = cpSpaceHashNew(DEFAULT_DIM_SIZE, DEFAULT_COUNT, (cpSpaceHashBBFunc)shapeBBFunc);-	-	space->bodies = cpArrayNew(0);-	space->arbiters = cpArrayNew(0);-	space->contactSet = cpHashSetNew(0, (cpHashSetEqlFunc)contactSetEql, (cpHashSetTransFunc)contactSetTrans);-	-	space->constraints = cpArrayNew(0);-	-	cpCollPairFunc pairFunc = {0, 0, alwaysCollide, NULL};-	space->defaultPairFunc = pairFunc;-	space->collFuncSet = cpHashSetNew(0, (cpHashSetEqlFunc)collFuncSetEql, (cpHashSetTransFunc)collFuncSetTrans);-	space->collFuncSet->default_value = &space->defaultPairFunc;-	-	return space;-}--cpSpace*-cpSpaceNew(void)-{-	return cpSpaceInit(cpSpaceAlloc());-}--void-cpSpaceDestroy(cpSpace *space)-{-	cpSpaceHashFree(space->staticShapes);-	cpSpaceHashFree(space->activeShapes);-	-	cpArrayFree(space->bodies);-	-	cpArrayFree(space->constraints);-	-	if(space->contactSet)-		cpHashSetEach(space->contactSet, (cpHashSetIterFunc)&arbiterFreeWrap, NULL);-	-	cpHashSetFree(space->contactSet);-	cpArrayFree(space->arbiters);-	-	if(space->collFuncSet)-		cpHashSetEach(space->collFuncSet, &freeWrap, NULL);-	cpHashSetFree(space->collFuncSet);-}--void-cpSpaceFree(cpSpace *space)-{-	if(space) cpSpaceDestroy(space);-	free(space);-}--void-cpSpaceFreeChildren(cpSpace *space)-{-	cpSpaceHashEach(space->staticShapes, (cpSpaceHashIterator)&shapeFreeWrap, NULL);-	cpSpaceHashEach(space->activeShapes, (cpSpaceHashIterator)&shapeFreeWrap, NULL);-	cpArrayEach(space->bodies,           (cpArrayIter)&bodyFreeWrap,          NULL);-	cpArrayEach(space->constraints,      (cpArrayIter)&constraintFreeWrap,    NULL);-}--#pragma mark Collision Pair Function Management--void-cpSpaceAddCollisionPairFunc(cpSpace *space, cpCollisionType a, cpCollisionType b, cpCollFunc func, void *data)-{-	cpCollisionType ids[] = {a, b};-	cpHashValue hash = CP_HASH_PAIR(a, b);-	// Remove any old function so the new one will get added.-	cpSpaceRemoveCollisionPairFunc(space, a, b);-		-	collFuncData funcData = {func, data};-	cpHashSetInsert(space->collFuncSet, hash, ids, &funcData);-}--void-cpSpaceRemoveCollisionPairFunc(cpSpace *space, cpCollisionType a, cpCollisionType b)-{-	cpCollisionType ids[] = {a, b};-	cpHashValue hash = CP_HASH_PAIR(a, b);-	cpCollPairFunc *old_pair = (cpCollPairFunc *)cpHashSetRemove(space->collFuncSet, hash, ids);-	free(old_pair);-}--void-cpSpaceSetDefaultCollisionPairFunc(cpSpace *space, cpCollFunc func, void *data)-{-	cpCollPairFunc pairFunc = {0, 0, (func ? func : alwaysCollide), (func ? data : NULL)};-	space->defaultPairFunc = pairFunc;-}--#pragma mark Body, Shape, and Joint Management--cpShape *-cpSpaceAddShape(cpSpace *space, cpShape *shape)-{-	assert(shape->body);-	cpSpaceHashInsert(space->activeShapes, shape, shape->id, shape->bb);-	-	return shape;-}--cpShape *-cpSpaceAddStaticShape(cpSpace *space, cpShape *shape)-{-	assert(shape->body);--	cpShapeCacheBB(shape);-	cpSpaceHashInsert(space->staticShapes, shape, shape->id, shape->bb);-	-	return shape;-}--cpBody *-cpSpaceAddBody(cpSpace *space, cpBody *body)-{-	cpArrayPush(space->bodies, body);-	-	return body;-}--cpConstraint *-cpSpaceAddConstraint(cpSpace *space, cpConstraint *constraint)-{-	cpArrayPush(space->constraints, constraint);-	-	return constraint;-}--static void-shapeRemovalArbiterReject(cpSpace *space, cpShape *shape)-{-	cpArray *old_ary = space->arbiters;-	int num = old_ary->num;-	-	if(num == 0) return;-	-	// make a new arbiters array and copy over all valid arbiters-	cpArray *new_ary = cpArrayNew(num);-	-	for(int i=0; i<num; i++){-		cpArbiter *arb = (cpArbiter *)old_ary->arr[i];-		if(arb->a != shape && arb->b != shape){-			cpArrayPush(new_ary, arb);-		}-	}-	-	space->arbiters = new_ary;-	cpArrayFree(old_ary);-}--void-cpSpaceRemoveShape(cpSpace *space, cpShape *shape)-{-	cpSpaceHashRemove(space->activeShapes, shape, shape->id);-	shapeRemovalArbiterReject(space, shape);-}--void-cpSpaceRemoveStaticShape(cpSpace *space, cpShape *shape)-{-	cpSpaceHashRemove(space->staticShapes, shape, shape->id);-	shapeRemovalArbiterReject(space, shape);-}--void-cpSpaceRemoveBody(cpSpace *space, cpBody *body)-{-	cpArrayDeleteObj(space->bodies, body);-}--void-cpSpaceRemoveConstraint(cpSpace *space, cpConstraint *constraint)-{-	cpArrayDeleteObj(space->constraints, constraint);-}--#pragma mark Point Query Functions--typedef struct pointQueryContext {-	cpLayers layers;-	cpGroup group;-	cpSpacePointQueryFunc func;-	void *data;-} pointQueryContext;--static void -pointQueryHelper(cpVect *point, cpShape *shape, pointQueryContext *context)-{-	if(cpShapePointQuery(shape, *point, context->layers, context->group))-		context->func(shape, context->data);-}--void-cpSpacePointQuery(cpSpace *space, cpVect point, cpLayers layers, cpGroup group, cpSpacePointQueryFunc func, void *data)-{-	pointQueryContext context = {layers, group, func, data};-	cpSpaceHashPointQuery(space->activeShapes, point, (cpSpaceHashQueryFunc)pointQueryHelper, &context);-	cpSpaceHashPointQuery(space->staticShapes, point, (cpSpaceHashQueryFunc)pointQueryHelper, &context);-}--static void-rememberLastPointQuery(cpShape *shape, cpShape **outShape)-{-	(*outShape) = shape;-}--cpShape *-cpSpacePointQueryFirst(cpSpace *space, cpVect point, cpLayers layers, cpGroup group)-{-	cpShape *shape = NULL;-	cpSpacePointQuery(space, point, layers, group, (cpSpacePointQueryFunc)rememberLastPointQuery, &shape);-	-	return shape;-}--void-cpSpaceEachBody(cpSpace *space, cpSpaceBodyIterator func, void *data)-{-	cpArray *bodies = space->bodies;-	-	for(int i=0; i<bodies->num; i++)-		func((cpBody *)bodies->arr[i], data);-}--#pragma mark Spatial Hash Management--// Iterator function used for updating shape BBoxes.-static void-updateBBCache(cpShape *shape, void *unused)-{-	cpShapeCacheBB(shape);-}--void-cpSpaceResizeStaticHash(cpSpace *space, cpFloat dim, int count)-{-	cpSpaceHashResize(space->staticShapes, dim, count);-	cpSpaceHashRehash(space->staticShapes);-}--void-cpSpaceResizeActiveHash(cpSpace *space, cpFloat dim, int count)-{-	cpSpaceHashResize(space->activeShapes, dim, count);-}--void -cpSpaceRehashStatic(cpSpace *space)-{-	cpSpaceHashEach(space->staticShapes, (cpSpaceHashIterator)&updateBBCache, NULL);-	cpSpaceHashRehash(space->staticShapes);-}--#pragma mark Collision Detection Functions--static inline int-queryReject(cpShape *a, cpShape *b)-{-	return-		// BBoxes must overlap-		!cpBBintersects(a->bb, b->bb)-		// Don't collide shapes attached to the same body.-		|| a->body == b->body-		// Don't collide objects in the same non-zero group-		|| (a->group && b->group && a->group == b->group)-		// Don't collide objects that don't share at least on layer.-		|| !(a->layers & b->layers);-}--// Callback from the spatial hash.-static void-queryFunc(cpShape *a, cpShape *b, cpSpace *space)-{-	// Reject any of the simple cases-	if(queryReject(a,b)) return;-	-	// Shape 'a' should have the lower shape type. (required by cpCollideShapes() )-	if(a->klass->type > b->klass->type){-		cpShape *temp = a;-		a = b;-		b = temp;-	}-	-	// Narrow-phase collision detection.-	cpContact *contacts = NULL;-	int numContacts = cpCollideShapes(a, b, &contacts);-	if(!numContacts) return; // Shapes are not colliding.-	-	// Get an arbiter from space->contactSet for the two shapes.-	// This is where the persistant contact magic comes from.-	cpShape *shape_pair[] = {a, b};-	cpArbiter *arb = (cpArbiter *)cpHashSetInsert(space->contactSet, CP_HASH_PAIR(a, b), shape_pair, space);-	-	// Timestamp the arbiter.-	arb->stamp = space->stamp;-	// For collisions between two similar primitive types, the order could have been swapped.-	arb->a = a; arb->b = b;-	// Inject the new contact points into the arbiter.-	cpArbiterInject(arb, contacts, numContacts);-	-	// Add the arbiter to the list of active arbiters.-	cpArrayPush(space->arbiters, arb);-}--// Iterator for active/static hash collisions.-static void-active2staticIter(cpShape *shape, cpSpace *space)-{-	cpSpaceHashQuery(space->staticShapes, shape, shape->bb, (cpSpaceHashQueryFunc)&queryFunc, space);-}--// Hashset reject func to throw away old arbiters.-static int-contactSetReject(cpArbiter *arb, cpSpace *space)-{-	if((space->stamp - arb->stamp) > cp_contact_persistence){-		cpArbiterFree(arb);-		return 0;-	}-	-	return 1;-}--static void-filterArbiterByCallback(cpSpace *space)-{-	int num = space->arbiters->num;-	-	// copy to the stack-	cpArbiter *ary[num];-	memcpy(ary, space->arbiters->arr, num*sizeof(void *));-	-	for(int i=0; i<num; i++){-		cpArbiter *arb = ary[i];-		-		// The collision pair function requires objects to be ordered by their collision types.-		cpShape *a = arb->a;-		cpShape *b = arb->b;-		cpFloat normal_coef = 1.0f;-		-		// Find the collision pair function for the shapes.-		cpCollisionType ids[] = {a->collision_type, b->collision_type};-		cpHashValue hash = CP_HASH_PAIR(a->collision_type, b->collision_type);-		cpCollPairFunc *pairFunc = (cpCollPairFunc *)cpHashSetFind(space->collFuncSet, hash, ids);-		if(!pairFunc->func) continue; // A NULL pair function means don't collide at all.-		-		// Swap them if necessary.-		if(a->collision_type != pairFunc->a){-			cpShape *temp = a;-			a = b;-			b = temp;-			normal_coef = -1.0f;-		}-		-		if(!pairFunc->func(a, b, arb->contacts, arb->numContacts, normal_coef, pairFunc->data)){-			cpArrayDeleteObj(space->arbiters, arb);-		}-	}-}--#pragma mark All Important cpSpaceStep() Function--void-cpSpaceStep(cpSpace *space, cpFloat dt)-{-	if(!dt) return; // prevents div by zero.-	cpFloat dt_inv = 1.0f/dt;--	cpArray *bodies = space->bodies;-	cpArray *constraints = space->constraints;-	-	// Empty the arbiter list.-	cpHashSetReject(space->contactSet, (cpHashSetRejectFunc)&contactSetReject, space);-	space->arbiters->num = 0;--	// Integrate positions.-	for(int i=0; i<bodies->num; i++){-		cpBody *body = (cpBody *)bodies->arr[i];-		body->position_func(body, dt);-	}-	-	// Pre-cache BBoxes and shape data.-	cpSpaceHashEach(space->activeShapes, (cpSpaceHashIterator)&updateBBCache, NULL);-	-	// Collide!-	cpSpaceHashEach(space->activeShapes, (cpSpaceHashIterator)&active2staticIter, space);-	cpSpaceHashQueryRehash(space->activeShapes, (cpSpaceHashQueryFunc)&queryFunc, space);-	-	// Filter arbiter list based on collision callbacks-	filterArbiterByCallback(space);--	// Prestep the arbiters.-	cpArray *arbiters = space->arbiters;-	for(int i=0; i<arbiters->num; i++)-		cpArbiterPreStep((cpArbiter *)arbiters->arr[i], dt_inv);--	// Prestep the constraints.-	for(int i=0; i<constraints->num; i++){-		cpConstraint *constraint = (cpConstraint *)constraints->arr[i];-		constraint->klass->preStep(constraint, dt, dt_inv);-	}--	for(int i=0; i<space->elasticIterations; i++){-		for(int j=0; j<arbiters->num; j++)-			cpArbiterApplyImpulse((cpArbiter *)arbiters->arr[j], 1.0f);-			-		for(int j=0; j<constraints->num; j++){-			cpConstraint *constraint = (cpConstraint *)constraints->arr[j];-			constraint->klass->applyImpulse(constraint);-		}-	}--	// Integrate velocities.-	cpFloat damping = cpfpow(1.0f/space->damping, -dt);-	for(int i=0; i<bodies->num; i++){-		cpBody *body = (cpBody *)bodies->arr[i];-		body->velocity_func(body, space->gravity, damping, dt);-	}--	for(int i=0; i<arbiters->num; i++)-		cpArbiterApplyCachedImpulse((cpArbiter *)arbiters->arr[i]);-	-	// Run the impulse solver.-	// run the old-style elastic solver if elastic iterations are disabled-	cpFloat elasticCoef = (space->elasticIterations ? 0.0f : 1.0f);-	for(int i=0; i<space->iterations; i++){-		for(int j=0; j<arbiters->num; j++)-			cpArbiterApplyImpulse((cpArbiter *)arbiters->arr[j], elasticCoef);-			-		for(int j=0; j<constraints->num; j++){-			cpConstraint *constraint = (cpConstraint *)constraints->arr[j];-			constraint->klass->applyImpulse(constraint);-		}-	}--//	cpFloat dvsq = cpvdot(space->gravity, space->gravity);-//	dvsq *= dt*dt * space->damping*space->damping;-//	for(int i=0; i<bodies->num; i++)-//		cpBodyMarkLowEnergy(bodies->arr[i], dvsq, space->sleepTicks);-	-	// Increment the stamp.-	space->stamp++;-}
− chipmunk-5.0/cpSpace.h
@@ -1,120 +0,0 @@-/* Copyright (c) 2007 Scott Lembcke- * - * Permission is hereby granted, free of charge, to any person obtaining a copy- * of this software and associated documentation files (the "Software"), to deal- * in the Software without restriction, including without limitation the rights- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell- * copies of the Software, and to permit persons to whom the Software is- * furnished to do so, subject to the following conditions:- * - * The above copyright notice and this permission notice shall be included in- * all copies or substantial portions of the Software.- * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE- * SOFTWARE.- */- -// Number of frames that contact information should persist.-extern int cp_contact_persistence;--// User collision pair function.-typedef int (*cpCollFunc)(cpShape *a, cpShape *b, cpContact *contacts, int numContacts, cpFloat normal_coef, void *data);--// Structure for holding collision pair function information.-// Used internally.-typedef struct cpCollPairFunc {-	cpCollisionType a;-	cpCollisionType b;-	cpCollFunc func;-	void *data;-} cpCollPairFunc;--typedef struct cpSpace{-	// *** User definable fields-	-	// Number of iterations to use in the impulse solver to solve contacts.-	int iterations;-	-	// Number of iterations to use in the impulse solver to solve elastic collisions.-	int elasticIterations;-	-	// Default gravity to supply when integrating rigid body motions.-	cpVect gravity;-	-	// Default damping to supply when integrating rigid body motions.-	cpFloat damping;-	-	// *** Internally Used Fields-	-	// Time stamp. Is incremented on every call to cpSpaceStep().-	int stamp;--	// The static and active shape spatial hashes.-	cpSpaceHash *staticShapes;-	cpSpaceHash *activeShapes;-	-	// List of bodies in the system.-	cpArray *bodies;-	// List of active arbiters for the impulse solver.-	cpArray *arbiters;-	// Persistant contact set.-	cpHashSet *contactSet;-	-	// List of constraints in the system.-	cpArray *constraints;-	-	// Set of collisionpair functions.-	cpHashSet *collFuncSet;-	// Default collision pair function.-	cpCollPairFunc defaultPairFunc;-} cpSpace;--// Basic allocation/destruction functions.-cpSpace* cpSpaceAlloc(void);-cpSpace* cpSpaceInit(cpSpace *space);-cpSpace* cpSpaceNew(void);--void cpSpaceDestroy(cpSpace *space);-void cpSpaceFree(cpSpace *space);--// Convenience function. Frees all referenced entities. (bodies, shapes and constraints)-void cpSpaceFreeChildren(cpSpace *space);--// Collision pair function management functions.-void cpSpaceAddCollisionPairFunc(cpSpace *space, cpCollisionType a, cpCollisionType b,-                                 cpCollFunc func, void *data);-void cpSpaceRemoveCollisionPairFunc(cpSpace *space, cpCollisionType a, cpCollisionType b);-void cpSpaceSetDefaultCollisionPairFunc(cpSpace *space, cpCollFunc func, void *data);--// Add and remove entities from the system.-cpShape *cpSpaceAddShape(cpSpace *space, cpShape *shape);-cpShape *cpSpaceAddStaticShape(cpSpace *space, cpShape *shape);-cpBody *cpSpaceAddBody(cpSpace *space, cpBody *body);-cpConstraint *cpSpaceAddConstraint(cpSpace *space, cpConstraint *constraint);--void cpSpaceRemoveShape(cpSpace *space, cpShape *shape);-void cpSpaceRemoveStaticShape(cpSpace *space, cpShape *shape);-void cpSpaceRemoveBody(cpSpace *space, cpBody *body);-void cpSpaceRemoveConstraint(cpSpace *space, cpConstraint *constraint);--// Point query callback function-typedef void (*cpSpacePointQueryFunc)(cpShape *shape, void *data);-void cpSpacePointQuery(cpSpace *space, cpVect point, cpLayers layers, cpGroup group, cpSpacePointQueryFunc func, void *data);-cpShape *cpSpacePointQueryFirst(cpSpace *space, cpVect point, cpLayers layers, cpGroup group);--// Iterator function for iterating the bodies in a space.-typedef void (*cpSpaceBodyIterator)(cpBody *body, void *data);-void cpSpaceEachBody(cpSpace *space, cpSpaceBodyIterator func, void *data);--// Spatial hash management functions.-void cpSpaceResizeStaticHash(cpSpace *space, cpFloat dim, int count);-void cpSpaceResizeActiveHash(cpSpace *space, cpFloat dim, int count);-void cpSpaceRehashStatic(cpSpace *space);--// Update the space.-void cpSpaceStep(cpSpace *space, cpFloat dt);
− chipmunk-5.0/cpSpaceHash.c
@@ -1,460 +0,0 @@-/* Copyright (c) 2007 Scott Lembcke- * - * Permission is hereby granted, free of charge, to any person obtaining a copy- * of this software and associated documentation files (the "Software"), to deal- * in the Software without restriction, including without limitation the rights- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell- * copies of the Software, and to permit persons to whom the Software is- * furnished to do so, subject to the following conditions:- * - * The above copyright notice and this permission notice shall be included in- * all copies or substantial portions of the Software.- * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE- * SOFTWARE.- */--#include <math.h>-#include <stdlib.h>-#include <stdio.h>-#include <assert.h>--#include "chipmunk.h"-#include "prime.h"--static cpHandle*-cpHandleAlloc(void)-{-	return (cpHandle *)malloc(sizeof(cpHandle));-}--static cpHandle*-cpHandleInit(cpHandle *hand, void *obj)-{-	hand->obj = obj;-	hand->retain = 0;-	hand->stamp = 0;-	-	return hand;-}--static cpHandle*-cpHandleNew(void *obj)-{-	return cpHandleInit(cpHandleAlloc(), obj);-}--static inline void-cpHandleRetain(cpHandle *hand)-{-	hand->retain++;-}--static inline void-cpHandleFree(cpHandle *hand)-{-	free(hand);-}--static inline void-cpHandleRelease(cpHandle *hand)-{-	hand->retain--;-	if(hand->retain == 0)-		cpHandleFree(hand);-}---cpSpaceHash*-cpSpaceHashAlloc(void)-{-	return (cpSpaceHash *)calloc(1, sizeof(cpSpaceHash));-}--// Frees the old table, and allocates a new one.-static void-cpSpaceHashAllocTable(cpSpaceHash *hash, int numcells)-{-	free(hash->table);-	-	hash->numcells = numcells;-	hash->table = (cpSpaceHashBin **)calloc(numcells, sizeof(cpSpaceHashBin *));-}--// Equality function for the handleset.-static int-handleSetEql(void *obj, void *elt)-{-	cpHandle *hand = (cpHandle *)elt;-	return (obj == hand->obj);-}--// Transformation function for the handleset.-static void *-handleSetTrans(void *obj, void *unused)-{-	cpHandle *hand = cpHandleNew(obj);-	cpHandleRetain(hand);-	-	return hand;-}--cpSpaceHash*-cpSpaceHashInit(cpSpaceHash *hash, cpFloat celldim, int numcells, cpSpaceHashBBFunc bbfunc)-{-	cpSpaceHashAllocTable(hash, next_prime(numcells));-	hash->celldim = celldim;-	hash->bbfunc = bbfunc;-	-	hash->bins = NULL;-	hash->handleSet = cpHashSetNew(0, &handleSetEql, &handleSetTrans);-	-	hash->stamp = 1;-	-	return hash;-}--cpSpaceHash*-cpSpaceHashNew(cpFloat celldim, int cells, cpSpaceHashBBFunc bbfunc)-{-	return cpSpaceHashInit(cpSpaceHashAlloc(), celldim, cells, bbfunc);-}--static inline void-clearHashCell(cpSpaceHash *hash, int index)-{-	cpSpaceHashBin *bin = hash->table[index];-	while(bin){-		cpSpaceHashBin *next = bin->next;-		-		// Release the lock on the handle.-		cpHandleRelease(bin->handle);-		// Recycle the bin.-		bin->next = hash->bins;-		hash->bins = bin;-		-		bin = next;-	}-	-	hash->table[index] = NULL;-}--// Clear all cells in the hashtable.-static void-clearHash(cpSpaceHash *hash)-{-	for(int i=0; i<hash->numcells; i++)-		clearHashCell(hash, i);-}--// Free the recycled hash bins.-static void-freeBins(cpSpaceHash *hash)-{-	cpSpaceHashBin *bin = hash->bins;-	while(bin){-		cpSpaceHashBin *next = bin->next;-		free(bin);-		bin = next;-	}-}--// Hashset iterator function to free the handles.-static void-handleFreeWrap(void *elt, void *unused)-{-	cpHandle *hand = (cpHandle *)elt;-	cpHandleFree(hand);-}--void-cpSpaceHashDestroy(cpSpaceHash *hash)-{-	clearHash(hash);-	freeBins(hash);-	-	// Free the handles.-	cpHashSetEach(hash->handleSet, &handleFreeWrap, NULL);-	cpHashSetFree(hash->handleSet);-	-	free(hash->table);-}--void-cpSpaceHashFree(cpSpaceHash *hash)-{-	if(!hash) return;-	cpSpaceHashDestroy(hash);-	free(hash);-}--void-cpSpaceHashResize(cpSpaceHash *hash, cpFloat celldim, int numcells)-{-	// Clear the hash to release the old handle locks.-	clearHash(hash);-	-	hash->celldim = celldim;-	cpSpaceHashAllocTable(hash, next_prime(numcells));-}--// Return true if the chain contains the handle.-static inline int-containsHandle(cpSpaceHashBin *bin, cpHandle *hand)-{-	while(bin){-		if(bin->handle == hand) return 1;-		bin = bin->next;-	}-	-	return 0;-}--// Get a recycled or new bin.-static inline cpSpaceHashBin *-getEmptyBin(cpSpaceHash *hash)-{-	cpSpaceHashBin *bin = hash->bins;-	-	// Make a new one if necessary.-	if(bin == NULL) return (cpSpaceHashBin *)malloc(sizeof(cpSpaceHashBin));--	hash->bins = bin->next;-	return bin;-}--// The hash function itself.-static inline cpHashValue-hash_func(cpHashValue x, cpHashValue y, cpHashValue n)-{-	return (x*2185031351ul ^ y*4232417593ul) % n;-}--static inline void-hashHandle(cpSpaceHash *hash, cpHandle *hand, cpBB bb)-{-	// Find the dimensions in cell coordinates.-	cpFloat dim = hash->celldim;-	int l = bb.l/dim;-	int r = bb.r/dim;-	int b = bb.b/dim;-	int t = bb.t/dim;-	-	int n = hash->numcells;-	for(int i=l; i<=r; i++){-		for(int j=b; j<=t; j++){-			int index = hash_func(i,j,n);-			cpSpaceHashBin *bin = hash->table[index];-			-			// Don't add an object twice to the same cell.-			if(containsHandle(bin, hand)) continue;--			cpHandleRetain(hand);-			// Insert a new bin for the handle in this cell.-			cpSpaceHashBin *newBin = getEmptyBin(hash);-			newBin->handle = hand;-			newBin->next = bin;-			hash->table[index] = newBin;-		}-	}-}--void-cpSpaceHashInsert(cpSpaceHash *hash, void *obj, cpHashValue id, cpBB bb)-{-	cpHandle *hand = (cpHandle *)cpHashSetInsert(hash->handleSet, id, obj, NULL);-	hashHandle(hash, hand, bb);-}--void-cpSpaceHashRehashObject(cpSpaceHash *hash, void *obj, cpHashValue id)-{-	cpHandle *hand = (cpHandle *)cpHashSetFind(hash->handleSet, id, obj);-	hashHandle(hash, hand, hash->bbfunc(obj));-}--// Hashset iterator function for rehashing the spatial hash. (hash hash hash hash?)-static void-handleRehashHelper(void *elt, void *data)-{-	cpHandle *hand = (cpHandle *)elt;-	cpSpaceHash *hash = (cpSpaceHash *)data;-	-	hashHandle(hash, hand, hash->bbfunc(hand->obj));-}--void-cpSpaceHashRehash(cpSpaceHash *hash)-{-	clearHash(hash);-	-	// Rehash all of the handles.-	cpHashSetEach(hash->handleSet, &handleRehashHelper, hash);-}--void-cpSpaceHashRemove(cpSpaceHash *hash, void *obj, cpHashValue id)-{-	cpHandle *hand = (cpHandle *)cpHashSetRemove(hash->handleSet, id, obj);-	-	if(hand){-		hand->obj = NULL;-		cpHandleRelease(hand);-	}-}--// Used by the cpSpaceHashEach() iterator.-typedef struct eachPair {-	cpSpaceHashIterator func;-	void *data;-} eachPair;--// Calls the user iterator function. (Gross I know.)-static void-eachHelper(void *elt, void *data)-{-	cpHandle *hand = (cpHandle *)elt;-	eachPair *pair = (eachPair *)data;-	-	pair->func(hand->obj, pair->data);-}--// Iterate over the objects in the spatial hash.-void-cpSpaceHashEach(cpSpaceHash *hash, cpSpaceHashIterator func, void *data)-{-	// Bundle the callback up to send to the hashset iterator.-	eachPair pair = {func, data};-	-	cpHashSetEach(hash->handleSet, &eachHelper, &pair);-}--// Calls the callback function for the objects in a given chain.-static inline void-query(cpSpaceHash *hash, cpSpaceHashBin *bin, void *obj, cpSpaceHashQueryFunc func, void *data)-{-	for(; bin; bin = bin->next){-		cpHandle *hand = bin->handle;-		void *other = hand->obj;-		-		// Skip over certain conditions-		if(-			// Have we already tried this pair in this query?-			hand->stamp == hash->stamp-			// Is obj the same as other?-			|| obj == other -			// Has other been removed since the last rehash?-			|| !other-			) continue;-		-		func(obj, other, data);--		// Stamp that the handle was checked already against this object.-		hand->stamp = hash->stamp;-	}-}--void-cpSpaceHashPointQuery(cpSpaceHash *hash, cpVect point, cpSpaceHashQueryFunc func, void *data)-{-	cpFloat dim = hash->celldim;-	int index = hash_func((int)(point.x/dim), (int)(point.y/dim), hash->numcells);-	-	query(hash, hash->table[index], &point, func, data);--	// Increment the stamp.-	// Only one cell is checked, but query() requires it anyway.-	hash->stamp++;-}--void-cpSpaceHashQuery(cpSpaceHash *hash, void *obj, cpBB bb, cpSpaceHashQueryFunc func, void *data)-{-	// Get the dimensions in cell coordinates.-	cpFloat dim = hash->celldim;-	int l = bb.l/dim;-	int r = bb.r/dim;-	int b = bb.b/dim;-	int t = bb.t/dim;-	-	int n = hash->numcells;-	-	// Iterate over the cells and query them.-	for(int i=l; i<=r; i++){-		for(int j=b; j<=t; j++){-			int index = hash_func(i,j,n);-			query(hash, hash->table[index], obj, func, data);-		}-	}-	-	// Increment the stamp.-	hash->stamp++;-}--// Similar to struct eachPair above.-typedef struct queryRehashPair {-	cpSpaceHash *hash;-	cpSpaceHashQueryFunc func;-	void *data;-} queryRehashPair;--// Hashset iterator func used with cpSpaceHashQueryRehash().-static void-handleQueryRehashHelper(void *elt, void *data)-{-	cpHandle *hand = (cpHandle *)elt;-	-	// Unpack the user callback data.-	queryRehashPair *pair = (queryRehashPair *)data;-	cpSpaceHash *hash = pair->hash;-	cpSpaceHashQueryFunc func = pair->func;--	cpFloat dim = hash->celldim;-	int n = hash->numcells;--	void *obj = hand->obj;-	cpBB bb = hash->bbfunc(obj);--	int l = bb.l/dim;-	int r = bb.r/dim;-	int b = bb.b/dim;-	int t = bb.t/dim;--	for(int i=l; i<=r; i++){-		for(int j=b; j<=t; j++){-//			// exit the loops if the object has been deleted in func().-//			if(!hand->obj) goto break_out;-			-			int index = hash_func(i,j,n);-			cpSpaceHashBin *bin = hash->table[index];-			-			if(containsHandle(bin, hand)) continue;-			-			cpHandleRetain(hand); // this MUST be done first in case the object is removed in func()-			query(hash, bin, obj, func, pair->data);-			-			cpSpaceHashBin *newBin = getEmptyBin(hash);-			newBin->handle = hand;-			newBin->next = bin;-			hash->table[index] = newBin;-		}-	}-	-//	break_out:-	// Increment the stamp for each object we hash.-	hash->stamp++;-}--void-cpSpaceHashQueryRehash(cpSpaceHash *hash, cpSpaceHashQueryFunc func, void *data)-{-	clearHash(hash);-	-	queryRehashPair pair = {hash, func, data};-	cpHashSetEach(hash->handleSet, &handleQueryRehashHelper, &pair);-}
− chipmunk-5.0/cpSpaceHash.h
@@ -1,100 +0,0 @@-/* Copyright (c) 2007 Scott Lembcke- * - * Permission is hereby granted, free of charge, to any person obtaining a copy- * of this software and associated documentation files (the "Software"), to deal- * in the Software without restriction, including without limitation the rights- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell- * copies of the Software, and to permit persons to whom the Software is- * furnished to do so, subject to the following conditions:- * - * The above copyright notice and this permission notice shall be included in- * all copies or substantial portions of the Software.- * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE- * SOFTWARE.- */--// The spatial hash is Chipmunk's default (and currently only) spatial index type.-// Based on a chained hash table.--// Used internally to track objects added to the hash-typedef struct cpHandle{-	// Pointer to the object-	void *obj;-	// Retain count-	int retain;-	// Query stamp. Used to make sure two objects-	// aren't identified twice in the same query.-	int stamp;-} cpHandle;--// Linked list element for in the chains.-typedef struct cpSpaceHashBin{-	cpHandle *handle;-	struct cpSpaceHashBin *next;-} cpSpaceHashBin;--// BBox callback. Called whenever the hash needs a bounding box from an object.-typedef cpBB (*cpSpaceHashBBFunc)(void *obj);--typedef struct cpSpaceHash{-	// Number of cells in the table.-	int numcells;-	// Dimentions of the cells.-	cpFloat celldim;-	-	// BBox callback.-	cpSpaceHashBBFunc bbfunc;--	// Hashset of all the handles.-	cpHashSet *handleSet;-	-	cpSpaceHashBin **table;-	// List of recycled bins.-	cpSpaceHashBin *bins;--	// Incremented on each query. See cpHandle.stamp.-	int stamp;-} cpSpaceHash;--//Basic allocation/destruction functions.-cpSpaceHash *cpSpaceHashAlloc(void);-cpSpaceHash *cpSpaceHashInit(cpSpaceHash *hash, cpFloat celldim, int cells, cpSpaceHashBBFunc bbfunc);-cpSpaceHash *cpSpaceHashNew(cpFloat celldim, int cells, cpSpaceHashBBFunc bbfunc);--void cpSpaceHashDestroy(cpSpaceHash *hash);-void cpSpaceHashFree(cpSpaceHash *hash);--// Resize the hashtable. (Does not rehash! You must call cpSpaceHashRehash() if needed.)-void cpSpaceHashResize(cpSpaceHash *hash, cpFloat celldim, int numcells);--// Add an object to the hash.-void cpSpaceHashInsert(cpSpaceHash *hash, void *obj, cpHashValue id, cpBB bb);-// Remove an object from the hash.-void cpSpaceHashRemove(cpSpaceHash *hash, void *obj, cpHashValue id);--// Iterator function-typedef void (*cpSpaceHashIterator)(void *obj, void *data);-// Iterate over the objects in the hash.-void cpSpaceHashEach(cpSpaceHash *hash, cpSpaceHashIterator func, void *data);--// Rehash the contents of the hash.-void cpSpaceHashRehash(cpSpaceHash *hash);-// Rehash only a specific object.-void cpSpaceHashRehashObject(cpSpaceHash *hash, void *obj, cpHashValue id);--// Query callback.-typedef void (*cpSpaceHashQueryFunc)(void *obj1, void *obj2, void *data);-// Point query the hash. A reference to the query point is passed as obj1 to the query callback.-void cpSpaceHashPointQuery(cpSpaceHash *hash, cpVect point, cpSpaceHashQueryFunc func, void *data);-// Query the hash for a given BBox.-void cpSpaceHashQuery(cpSpaceHash *hash, void *obj, cpBB bb, cpSpaceHashQueryFunc func, void *data);-// Run a query for the object, then insert it. (Optimized case)-void cpSpaceHashQueryInsert(cpSpaceHash *hash, void *obj, cpBB bb, cpSpaceHashQueryFunc func, void *data);-// Rehashes while querying for each object. (Optimized case) -void cpSpaceHashQueryRehash(cpSpaceHash *hash, cpSpaceHashQueryFunc func, void *data);
− chipmunk-5.0/cpVect.c
@@ -1,51 +0,0 @@-/* Copyright (c) 2007 Scott Lembcke- * - * Permission is hereby granted, free of charge, to any person obtaining a copy- * of this software and associated documentation files (the "Software"), to deal- * in the Software without restriction, including without limitation the rights- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell- * copies of the Software, and to permit persons to whom the Software is- * furnished to do so, subject to the following conditions:- * - * The above copyright notice and this permission notice shall be included in- * all copies or substantial portions of the Software.- * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE- * SOFTWARE.- */- -#include <stdio.h>-#include <math.h>--#include "chipmunk.h"--cpFloat-cpvlength(const cpVect v)-{-	return cpfsqrt( cpvdot(v, v) );-}--cpVect-cpvforangle(const cpFloat a)-{-	return cpv(cpfcos(a), cpfsin(a));-}--cpFloat-cpvtoangle(const cpVect v)-{-	return cpfatan2(v.y, v.x);-}--char*-cpvstr(const cpVect v)-{-	static char str[256];-	sprintf(str, "(% .3f, % .3f)", v.x, v.y);-	return str;-}
− chipmunk-5.0/cpVect.h
@@ -1,153 +0,0 @@-/* Copyright (c) 2007 Scott Lembcke- * - * Permission is hereby granted, free of charge, to any person obtaining a copy- * of this software and associated documentation files (the "Software"), to deal- * in the Software without restriction, including without limitation the rights- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell- * copies of the Software, and to permit persons to whom the Software is- * furnished to do so, subject to the following conditions:- * - * The above copyright notice and this permission notice shall be included in- * all copies or substantial portions of the Software.- * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE- * SOFTWARE.- */- -typedef struct cpVect{-	cpFloat x,y;-} cpVect;--static const cpVect cpvzero={0.0f,0.0f};--static inline cpVect-cpv(const cpFloat x, const cpFloat y)-{-	cpVect v = {x, y};-	return v;-}--// non-inlined functions-cpFloat cpvlength(const cpVect v);-cpVect cpvforangle(const cpFloat a); // convert radians to a normalized vector-cpFloat cpvtoangle(const cpVect v); // convert a vector to radians-char *cpvstr(const cpVect v); // get a string representation of a vector--static inline cpVect-cpvadd(const cpVect v1, const cpVect v2)-{-	return cpv(v1.x + v2.x, v1.y + v2.y);-}--static inline cpVect-cpvneg(const cpVect v)-{-	return cpv(-v.x, -v.y);-}--static inline cpVect-cpvsub(const cpVect v1, const cpVect v2)-{-	return cpv(v1.x - v2.x, v1.y - v2.y);-}--static inline cpVect-cpvmult(const cpVect v, const cpFloat s)-{-	return cpv(v.x*s, v.y*s);-}--static inline cpFloat-cpvdot(const cpVect v1, const cpVect v2)-{-	return v1.x*v2.x + v1.y*v2.y;-}--static inline cpFloat-cpvcross(const cpVect v1, const cpVect v2)-{-	return v1.x*v2.y - v1.y*v2.x;-}--static inline cpVect-cpvperp(const cpVect v)-{-	return cpv(-v.y, v.x);-}--static inline cpVect-cpvrperp(const cpVect v)-{-	return cpv(v.y, -v.x);-}--static inline cpVect-cpvproject(const cpVect v1, const cpVect v2)-{-	return cpvmult(v2, cpvdot(v1, v2)/cpvdot(v2, v2));-}--static inline cpVect-cpvrotate(const cpVect v1, const cpVect v2)-{-	return cpv(v1.x*v2.x - v1.y*v2.y, v1.x*v2.y + v1.y*v2.x);-}--static inline cpVect-cpvunrotate(const cpVect v1, const cpVect v2)-{-	return cpv(v1.x*v2.x + v1.y*v2.y, v1.y*v2.x - v1.x*v2.y);-}--static inline cpFloat-cpvlengthsq(const cpVect v)-{-	return cpvdot(v, v);-}--static inline cpVect-cpvlerp(const cpVect v1, const cpVect v2, const cpFloat t)-{-	return cpvadd(cpvmult(v1, 1.0f - t), cpvmult(v2, t));-}--static inline cpVect-cpvnormalize(const cpVect v)-{-	return cpvmult(v, 1.0f/cpvlength(v));-}--static inline cpVect-cpvnormalize_safe(const cpVect v)-{-	return (v.x == 0.0f && v.y == 0.0f ? cpvzero : cpvnormalize(v));-}--static inline cpVect-cpvclamp(const cpVect v, const cpFloat len)-{-	return (cpvdot(v,v) > len*len) ? cpvmult(cpvnormalize(v), len) : v;-}--static inline cpFloat-cpvdist(const cpVect v1, const cpVect v2)-{-	return cpvlength(cpvsub(v1, v2));-}--static inline cpFloat-cpvdistsq(const cpVect v1, const cpVect v2)-{-	return cpvlengthsq(cpvsub(v1, v2));-}--static inline int-cpvnear(const cpVect v1, const cpVect v2, const cpFloat dist)-{-	return cpvdistsq(v1, v2) < dist*dist;-}
− chipmunk-5.0/prime.h
@@ -1,68 +0,0 @@-/* Copyright (c) 2007 Scott Lembcke- * - * Permission is hereby granted, free of charge, to any person obtaining a copy- * of this software and associated documentation files (the "Software"), to deal- * in the Software without restriction, including without limitation the rights- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell- * copies of the Software, and to permit persons to whom the Software is- * furnished to do so, subject to the following conditions:- * - * The above copyright notice and this permission notice shall be included in- * all copies or substantial portions of the Software.- * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE- * SOFTWARE.- */- -// Used for resizing hash tables.-// Values approximately double.--static int primes[] = {-	5,          //2^2  + 1-	11,         //2^3  + 3-	17,         //2^4  + 1-	37,         //2^5  + 5-	67,         //2^6  + 3-	131,        //2^7  + 3-	257,        //2^8  + 1-	521,        //2^9  + 9-	1031,       //2^10 + 7-	2053,       //2^11 + 5-	4099,       //2^12 + 3-	8209,       //2^13 + 17-	16411,      //2^14 + 27-	32771,      //2^15 + 3-	65537,      //2^16 + 1-	131101,     //2^17 + 29-	262147,     //2^18 + 3-	524309,     //2^19 + 21-	1048583,    //2^20 + 7-	2097169,    //2^21 + 17-	4194319,    //2^22 + 15-	8388617,    //2^23 + 9-	16777259,   //2^24 + 43-	33554467,   //2^25 + 35-	67108879,   //2^26 + 15-	134217757,  //2^27 + 29-	268435459,  //2^28 + 3-	536870923,  //2^29 + 11-	1073741827, //2^30 + 3-	0,-};--static inline int-next_prime(int n)-{-	int i = 0;-	while(n > primes[i]){-		i++;-		assert(primes[i]); // realistically this should never happen-	}-	-	return primes[i];-}
+ chipmunk-r402/LICENSE.txt view
@@ -0,0 +1,19 @@+Copyright (c) 2007 Scott Lembcke and Howling Moon Software++Permission is hereby granted, free of charge, to any person obtaining a copy+of this software and associated documentation files (the "Software"), to deal+in the Software without restriction, including without limitation the rights+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the Software is+furnished to do so, subject to the following conditions:++The above copyright notice and this permission notice shall be included in+all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+SOFTWARE.
+ chipmunk-r402/README.txt view
@@ -0,0 +1,45 @@+ABOUT:+Chipmunk is a simple, lightweight and fast 2D rigid body physics library written in C. It's licensed under the unrestrictive, OSI approved MIT license. My aim is to give 2D developers access the same quality of physics you find in newer 3D games. I hope you enjoy using Chipmunk, and please consider donating to help make it worth our time to continue to support Chipmunk with great new features.++CONTRACTING:+Howling Moon Software (my company) is available for contracting if you want to make the physics in your game really stand out. Given our unique experience with the library, we can help you use Chipmunk to it's fullest potential. Feel free to contact us through our webpage: http://howlingmoonsoftware.com/contracting.php++BUILDING:+Mac OS X: There is an included XCode project file for building the static library and demo application. Alteratively you could use the CMake files.++iPhone: The XCode project can build a static library with all the proper compiler settings. Additionally, if you run the iphonestatic.sh script in the macosx/ directory, it will build you a fat library compiled as release for the device and debug for the simulator. After building that, just copy the static lib and include/chipmunk/ directory to your project.++UNIX: A forum user was kind enough to make a set of CMake files for Chipmunk. This will require you to have CMake installed. To build run 'cmake .' then 'make'. This should build a dynamic library, a static library, and the demo application.++Windows: There is an included MSVC project for building the library and demo application. I do not personally maintain the MSVC project and it apparently hasn't worked for a while. If you are a MSVC whiz, consider lending a hand.++Ruby: I've been using maintaining a Ruby extension for Chipmunk, but at this time is not up to date with all the latest changes. A forum member has been working on an FFI based extention, and that may be a better way to take advantage of Chipmunk from Ruby. Another forum user has offered to maintain the non-FFI version of the extension. Stay tuned.++GETTING STARTED:+First of all, you can find the C API documentation here: http://code.google.com/p/chipmunk-physics/wiki/Documentation++A good starting point is to take a look at the included Demo application. The demos all just set up a Chipmunk simulation space and the demo app draws the graphics directly out of that. This makes it easy to see how the Chipmunk API works without worrying about the graphics code. You are free to use the demo drawing routines in your own projects, though it is certainly not the recommended way of drawing Chipmunk objects as it pokes around at the undocumented parts of Chipmunk.++FORUM:+http://www.slembcke.net/forums++CONTACT:+slembcke@gmail.com (also on Google Talk)++CHANGES SINCE 5.0.0:+ * FIX: fixed a NaN issue that was causing raycasts for horizontal or vertical lines to end up in an infinite loop+ * FIX: fixed a number of memory leaks+ * FIX: fixed warnings for various compiler/OS combinations+ * API: Rejecting a collision from a begin() callback permanently rejects the collision until separation+ * API: Erroneous collision type parameterns removed from cpSpaceDefaulteCollisionHandler()+ * MOVE: FFI declarations of inlined functions into their own header+ * MOVE: Rearranged the project structure to separate out the header files into a separate include/ directory.+ * NEW: Added a static library target for the iPhone.+ * NEW: Type changes when building on the iPhone to make it friendlier to other iPhone APIs+ * NEW: Added an AABB query to complement point and segment queries+ * NEW: CP_NO_GROUP and CP_ALL_LAYERS constants++CHANGES SINCE 4.x:+ * Brand new Joint/Constraint API: New constraints can be added easily and are much more flexible than the old joint system+ * Efficient Segment Queries - Like raycasting, but with line segments.+ * Brand new collision callback API: Collision begin/separate events, API for removal of objects within callbacks, more programable control over collision handling.
+ chipmunk-r402/include/chipmunk/chipmunk.h view
@@ -0,0 +1,139 @@+/* Copyright (c) 2007 Scott Lembcke+ * + * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ * + * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+ * SOFTWARE.+ */++#ifndef CHIPMUNK_HEADER+#define CHIPMUNK_HEADER++#ifdef __cplusplus+extern "C" {+#endif++void cpAbort(char *message, char *condition, char *file, int line);+#ifdef NDEBUG+	#define	cpAssert(condition, message)	((void)0)+#else+	#define cpAssert(condition, message) if(!(condition)) cpAbort(message, #condition, __FILE__, __LINE__)+#endif++#include "chipmunk_types.h"+	+static inline cpFloat+cpfmax(cpFloat a, cpFloat b)+{+	return (a > b) ? a : b;+}++static inline cpFloat+cpfmin(cpFloat a, cpFloat b)+{+	return (a < b) ? a : b;+}++static inline cpFloat+cpfabs(cpFloat n)+{+	return (n < 0) ? -n : n;+}++static inline cpFloat+cpfclamp(cpFloat f, cpFloat min, cpFloat max)+{+	return cpfmin(cpfmax(f, min), max);+}++static inline cpFloat+cpflerp(cpFloat f1, cpFloat f2, cpFloat t)+{+	return f1*(1.0f - t) + f2*t;+}++static inline cpFloat+cpflerpconst(cpFloat f1, cpFloat f2, cpFloat d)+{+	return f1 + cpfclamp(f2 - f1, -d, d);+}++#ifndef INFINITY+	#ifdef _MSC_VER+		union MSVC_EVIL_FLOAT_HACK+		{+			unsigned __int8 Bytes[4];+			float Value;+		};+		static union MSVC_EVIL_FLOAT_HACK INFINITY_HACK = {{0x00, 0x00, 0x80, 0x7F}};+		#define INFINITY (INFINITY_HACK.Value)+	#endif+	+	#ifdef __GNUC__+		#define INFINITY (__builtin_inf())+	#endif+	+	#ifndef INFINITY+		#define INFINITY (1e1000)+	#endif+#endif++// Maximum allocated size for various Chipmunk buffer sizes+#define CP_BUFFER_BYTES (32*1024)++#define cpmalloc malloc+#define cpcalloc calloc+#define cprealloc realloc+#define cpfree free++#include "cpVect.h"+#include "cpBB.h"+#include "cpBody.h"+#include "cpArray.h"+#include "cpHashSet.h"+#include "cpSpaceHash.h"++#include "cpShape.h"+#include "cpPolyShape.h"++#include "cpArbiter.h"+#include "cpCollision.h"+	+#include "constraints/cpConstraint.h"++#include "cpSpace.h"++#define CP_HASH_COEF (3344921057ul)+#define CP_HASH_PAIR(A, B) ((cpHashValue)(A)*CP_HASH_COEF ^ (cpHashValue)(B)*CP_HASH_COEF)++extern char *cpVersionString;+void cpInitChipmunk(void);++// Calculate the moment of inertia for a circle, r1 and r2 are the inner and outer diameters.+// (A solid circle has an inner diameter of 0)+cpFloat cpMomentForCircle(cpFloat m, cpFloat r1, cpFloat r2, cpVect offset);++// Calculate the moment of inertia for a line segment. (beveling radius not supported)+cpFloat cpMomentForSegment(cpFloat m, cpVect a, cpVect b);++// Calculate the moment of inertia for a solid polygon shape.+cpFloat cpMomentForPoly(cpFloat m, int numVerts, cpVect *verts, cpVect offset);++#ifdef __cplusplus+}+#endif++#endif
+ chipmunk-r402/include/chipmunk/chipmunk_ffi.h view
@@ -0,0 +1,42 @@+// Create non static inlined copies of Chipmunk functions, useful for working with dynamic FFIs+// This file should only be included in chipmunk.c++#define MAKE_REF(name) __typeof__(name) *_##name = name++MAKE_REF(cpv); // makes a variable named _cpv that contains the function pointer for cpv()+MAKE_REF(cpvadd);+MAKE_REF(cpvneg);+MAKE_REF(cpvsub);+MAKE_REF(cpvmult);+MAKE_REF(cpvdot);+MAKE_REF(cpvcross);+MAKE_REF(cpvperp);+MAKE_REF(cpvrperp);+MAKE_REF(cpvproject);+MAKE_REF(cpvrotate);+MAKE_REF(cpvunrotate);+MAKE_REF(cpvlengthsq);+MAKE_REF(cpvlerp);+MAKE_REF(cpvnormalize);+MAKE_REF(cpvnormalize_safe);+MAKE_REF(cpvclamp);+MAKE_REF(cpvlerpconst);+MAKE_REF(cpvdist);+MAKE_REF(cpvnear);+MAKE_REF(cpvdistsq);++MAKE_REF(cpBBNew);+MAKE_REF(cpBBintersects);+MAKE_REF(cpBBcontainsBB);+MAKE_REF(cpBBcontainsVect);+MAKE_REF(cpBBmerge);+MAKE_REF(cpBBexpand);++MAKE_REF(cpBodyWorld2Local);+MAKE_REF(cpBodyLocal2World);+MAKE_REF(cpBodyApplyImpulse);++MAKE_REF(cpArbiterIsFirstContact);+MAKE_REF(cpArbiterGetShapes);+MAKE_REF(cpArbiterGetNormal);+MAKE_REF(cpArbiterGetPoint);
+ chipmunk-r402/include/chipmunk/chipmunk_types.h view
@@ -0,0 +1,55 @@+#ifdef __APPLE__+   #import "TargetConditionals.h"+#endif++// Use single precision floats on the iPhone.+#ifdef TARGET_OS_IPHONE+	#define CP_USE_DOUBLES 0+#else+	// use doubles by default for higher precision+	#define CP_USE_DOUBLES 1+#endif++#if CP_USE_DOUBLES+	typedef double cpFloat;+	#define cpfsqrt sqrt+	#define cpfsin sin+	#define cpfcos cos+	#define cpfacos acos+	#define cpfatan2 atan2+	#define cpfmod fmod+	#define cpfexp exp+	#define cpfpow pow+	#define cpffloor floor+	#define cpfceil ceil+#else+	typedef float cpFloat;+	#define cpfsqrt sqrtf+	#define cpfsin sinf+	#define cpfcos cosf+	#define cpfacos acosf+	#define cpfatan2 atan2f+	#define cpfmod fmodf+	#define cpfexp expf+	#define cpfpow powf+	#define cpffloor floorf+	#define cpfceil ceilf+#endif++#if TARGET_OS_IPHONE+	// CGPoints are structurally the same, and allow+	// easy interoperability with other iPhone libraries+	#import <CoreGraphics/CGGeometry.h>+	typedef CGPoint cpVect;+#else+	typedef struct cpVect{cpFloat x,y;} cpVect;+#endif++typedef unsigned int cpHashValue;+typedef void * cpDataPointer;+typedef unsigned int cpCollisionType;+typedef unsigned int cpLayers;+typedef unsigned int cpGroup;++#define CP_NO_GROUP ((cpGroup)0)+#define CP_ALL_LAYERS (~(cpLayers)0)
+ chipmunk-r402/include/chipmunk/chipmunk_unsafe.h view
@@ -0,0 +1,54 @@+/* Copyright (c) 2007 Scott Lembcke+ * + * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ * + * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+ * SOFTWARE.+ */++++/* This header defines a number of "unsafe" operations on Chipmunk objects.+ * In this case "unsafe" is referring to operations which may reduce the+ * physical accuracy or numerical stability of the simulation, but will not+ * cause crashes.+ *+ * The prime example is mutating collision shapes. Chipmunk does not support+ * this directly. Mutating shapes using this API will caused objects in contact+ * to be pushed apart using Chipmunk's overlap solver, but not using real+ * persistent velocities. Probably not what you meant, but perhaps close enough.+ */++#ifndef CHIPMUNK_UNSAFE_HEADER+#define CHIPMUNK_UNSAFE_HEADER++#ifdef __cplusplus+extern "C" {+#endif++void cpCircleShapeSetRadius(cpShape *shape, cpFloat radius);+void cpCircleShapeSetOffset(cpShape *shape, cpVect offset);++void cpSegmentShapeSetEndpoints(cpShape *shape, cpVect a, cpVect b);+void cpSegmentShapeSetRadius(cpShape *shape, cpFloat radius);++void cpPolyShapeSetVerts(cpShape *shape, int numVerts, cpVect *verts, cpVect offset);++#ifdef __cplusplus+}+#endif++#endif
+ chipmunk-r402/include/chipmunk/constraints/cpConstraint.h view
@@ -0,0 +1,92 @@+/* Copyright (c) 2007 Scott Lembcke+ * + * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ * + * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+ * SOFTWARE.+ */++// TODO: Comment me!+	+extern cpFloat cp_constraint_bias_coef;++struct cpConstraintClass;+struct cpConstraint;++typedef void (*cpConstraintPreStepFunction)(struct cpConstraint *constraint, cpFloat dt, cpFloat dt_inv);+typedef void (*cpConstraintApplyImpulseFunction)(struct cpConstraint *constraint);+typedef cpFloat (*cpConstraintGetImpulseFunction)(struct cpConstraint *constraint);++typedef struct cpConstraintClass {+	cpConstraintPreStepFunction preStep;+	cpConstraintApplyImpulseFunction applyImpulse;+	cpConstraintGetImpulseFunction getImpulse;+} cpConstraintClass;++++typedef struct cpConstraint {+	const cpConstraintClass *klass;+	+	cpBody *a, *b;+	cpFloat maxForce;+	cpFloat biasCoef;+	cpFloat maxBias;+	+	cpDataPointer data;+} cpConstraint;++#ifdef CP_USE_DEPRECATED_API_4+typedef cpConstraint cpJoint;+#endif++void cpConstraintDestroy(cpConstraint *constraint);+void cpConstraintFree(cpConstraint *constraint);+++#define cpConstraintCheckCast(constraint, struct) \+	cpAssert(constraint->klass == struct##GetClass(), "Constraint is not a "#struct);+++#define CP_DefineConstraintGetter(struct, type, member, name) \+static inline type \+struct##Get##name(cpConstraint *constraint){ \+	cpConstraintCheckCast(constraint, struct); \+	return ((struct *)constraint)->member; \+} \++#define CP_DefineConstraintSetter(struct, type, member, name) \+static inline void \+struct##Set##name(cpConstraint *constraint, type value){ \+	cpConstraintCheckCast(constraint, struct); \+	((struct *)constraint)->member = value; \+} \++#define CP_DefineConstraintProperty(struct, type, member, name) \+CP_DefineConstraintGetter(struct, type, member, name) \+CP_DefineConstraintSetter(struct, type, member, name)++// Built in Joint types+#include "cpPinJoint.h"+#include "cpSlideJoint.h"+#include "cpPivotJoint.h"+#include "cpGrooveJoint.h"+#include "cpDampedSpring.h"+#include "cpDampedRotarySpring.h"+#include "cpRotaryLimitJoint.h"+#include "cpRatchetJoint.h"+#include "cpGearJoint.h"+#include "cpSimpleMotor.h"
+ chipmunk-r402/include/chipmunk/constraints/cpDampedRotarySpring.h view
@@ -0,0 +1,46 @@+/* Copyright (c) 2007 Scott Lembcke+ * + * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ * + * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+ * SOFTWARE.+ */++typedef cpFloat (*cpDampedRotarySpringTorqueFunc)(struct cpConstraint *spring, cpFloat relativeAngle);++const cpConstraintClass *cpDampedRotarySpringGetClass();++typedef struct cpDampedRotarySpring {+	cpConstraint constraint;+	cpFloat restAngle;+	cpFloat stiffness;+	cpFloat damping;+	cpDampedRotarySpringTorqueFunc springTorqueFunc;+	+	cpFloat dt;+	cpFloat target_wrn;+	+	cpFloat iSum;+} cpDampedRotarySpring;++cpDampedRotarySpring *cpDampedRotarySpringAlloc(void);+cpDampedRotarySpring *cpDampedRotarySpringInit(cpDampedRotarySpring *joint, cpBody *a, cpBody *b, cpFloat restAngle, cpFloat stiffness, cpFloat damping);+cpConstraint *cpDampedRotarySpringNew(cpBody *a, cpBody *b, cpFloat restAngle, cpFloat stiffness, cpFloat damping);++CP_DefineConstraintProperty(cpDampedRotarySpring, cpFloat, restAngle, RestAngle);+CP_DefineConstraintProperty(cpDampedRotarySpring, cpFloat, stiffness, Stiffness);+CP_DefineConstraintProperty(cpDampedRotarySpring, cpFloat, damping, Damping);+CP_DefineConstraintProperty(cpDampedRotarySpring, cpDampedRotarySpringTorqueFunc, springTorqueFunc, SpringTorqueFunc);
+ chipmunk-r402/include/chipmunk/constraints/cpDampedSpring.h view
@@ -0,0 +1,53 @@+/* Copyright (c) 2007 Scott Lembcke+ * + * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ * + * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+ * SOFTWARE.+ */++struct cpDampedSpring;++typedef cpFloat (*cpDampedSpringForceFunc)(struct cpConstraint *spring, cpFloat dist);++const cpConstraintClass *cpDampedSpringGetClass();++typedef struct cpDampedSpring {+	cpConstraint constraint;+	cpVect anchr1, anchr2;+	cpFloat restLength;+	cpFloat stiffness;+	cpFloat damping;+	cpDampedSpringForceFunc springForceFunc;+	+	cpFloat dt;+	cpFloat target_vrn;+	+	cpVect r1, r2;+	cpFloat nMass;+	cpVect n;+} cpDampedSpring;++cpDampedSpring *cpDampedSpringAlloc(void);+cpDampedSpring *cpDampedSpringInit(cpDampedSpring *joint, cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat restLength, cpFloat stiffness, cpFloat damping);+cpConstraint *cpDampedSpringNew(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat restLength, cpFloat stiffness, cpFloat damping);++CP_DefineConstraintProperty(cpDampedSpring, cpVect, anchr1, Anchr1);+CP_DefineConstraintProperty(cpDampedSpring, cpVect, anchr2, Anchr2);+CP_DefineConstraintProperty(cpDampedSpring, cpFloat, restLength, RestLength);+CP_DefineConstraintProperty(cpDampedSpring, cpFloat, stiffness, Stiffness);+CP_DefineConstraintProperty(cpDampedSpring, cpFloat, damping, Damping);+CP_DefineConstraintProperty(cpDampedSpring, cpDampedSpringForceFunc, springForceFunc, SpringForceFunc);
+ chipmunk-r402/include/chipmunk/constraints/cpGearJoint.h view
@@ -0,0 +1,41 @@+/* Copyright (c) 2007 Scott Lembcke+ * + * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ * + * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+ * SOFTWARE.+ */++const cpConstraintClass *cpGearJointGetClass();++typedef struct cpGearJoint {+	cpConstraint constraint;+	cpFloat phase, ratio;+	cpFloat ratio_inv;+	+	cpFloat iSum;+		+	cpFloat bias;+	cpFloat jAcc, jMax;+} cpGearJoint;++cpGearJoint *cpGearJointAlloc(void);+cpGearJoint *cpGearJointInit(cpGearJoint *joint, cpBody *a, cpBody *b, cpFloat phase, cpFloat ratio);+cpConstraint *cpGearJointNew(cpBody *a, cpBody *b, cpFloat phase, cpFloat ratio);++CP_DefineConstraintProperty(cpGearJoint, cpFloat, phase, Phase);+CP_DefineConstraintGetter(cpGearJoint, cpFloat, ratio, Ratio);+void cpGearJointSetRatio(cpConstraint *constraint, cpFloat value);
+ chipmunk-r402/include/chipmunk/constraints/cpGrooveJoint.h view
@@ -0,0 +1,44 @@+/* Copyright (c) 2007 Scott Lembcke+ * + * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ * + * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+ * SOFTWARE.+ */++const cpConstraintClass *cpGrooveJointGetClass();++typedef struct cpGrooveJoint {+	cpConstraint constraint;+	cpVect grv_n, grv_a, grv_b;+	cpVect  anchr2;+	+	cpVect grv_tn;+	cpFloat clamp;+	cpVect r1, r2;+	cpVect k1, k2;+	+	cpVect jAcc;+	cpFloat jMaxLen;+	cpVect bias;+} cpGrooveJoint;++cpGrooveJoint *cpGrooveJointAlloc(void);+cpGrooveJoint *cpGrooveJointInit(cpGrooveJoint *joint, cpBody *a, cpBody *b, cpVect groove_a, cpVect groove_b, cpVect anchr2);+cpConstraint *cpGrooveJointNew(cpBody *a, cpBody *b, cpVect groove_a, cpVect groove_b, cpVect anchr2);++// TODO setters for the groove.+CP_DefineConstraintProperty(cpGrooveJoint, cpVect, anchr2, Anchr2);
+ chipmunk-r402/include/chipmunk/constraints/cpPinJoint.h view
@@ -0,0 +1,43 @@+/* Copyright (c) 2007 Scott Lembcke+ * + * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ * + * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+ * SOFTWARE.+ */+ +const cpConstraintClass *cpPinJointGetClass();++typedef struct cpPinJoint {+	cpConstraint constraint;+	cpVect anchr1, anchr2;+	cpFloat dist;+	+	cpVect r1, r2;+	cpVect n;+	cpFloat nMass;+	+	cpFloat jnAcc, jnMax;+	cpFloat bias;+} cpPinJoint;++cpPinJoint *cpPinJointAlloc(void);+cpPinJoint *cpPinJointInit(cpPinJoint *joint, cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2);+cpConstraint *cpPinJointNew(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2);++CP_DefineConstraintProperty(cpPinJoint, cpVect, anchr1, Anchr1);+CP_DefineConstraintProperty(cpPinJoint, cpVect, anchr2, Anchr2);+CP_DefineConstraintProperty(cpPinJoint, cpFloat, dist, Dist);
+ chipmunk-r402/include/chipmunk/constraints/cpPivotJoint.h view
@@ -0,0 +1,42 @@+/* Copyright (c) 2007 Scott Lembcke+ * + * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ * + * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+ * SOFTWARE.+ */++const cpConstraintClass *cpPivotJointGetClass();++typedef struct cpPivotJoint {+	cpConstraint constraint;+	cpVect anchr1, anchr2;+	+	cpVect r1, r2;+	cpVect k1, k2;+	+	cpVect jAcc;+	cpFloat jMaxLen;+	cpVect bias;+} cpPivotJoint;++cpPivotJoint *cpPivotJointAlloc(void);+cpPivotJoint *cpPivotJointInit(cpPivotJoint *joint, cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2);+cpConstraint *cpPivotJointNew(cpBody *a, cpBody *b, cpVect pivot);+cpConstraint *cpPivotJointNew2(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2);++CP_DefineConstraintProperty(cpPivotJoint, cpVect, anchr1, Anchr1);+CP_DefineConstraintProperty(cpPivotJoint, cpVect, anchr2, Anchr2);
+ chipmunk-r402/include/chipmunk/constraints/cpRatchetJoint.h view
@@ -0,0 +1,40 @@+/* Copyright (c) 2007 Scott Lembcke+ * + * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ * + * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+ * SOFTWARE.+ */++const cpConstraintClass *cpRatchetJointGetClass();++typedef struct cpRatchetJoint {+	cpConstraint constraint;+	cpFloat angle, phase, ratchet;+	+	cpFloat iSum;+		+	cpFloat bias;+	cpFloat jAcc, jMax;+} cpRatchetJoint;++cpRatchetJoint *cpRatchetJointAlloc(void);+cpRatchetJoint *cpRatchetJointInit(cpRatchetJoint *joint, cpBody *a, cpBody *b, cpFloat phase, cpFloat ratchet);+cpConstraint *cpRatchetJointNew(cpBody *a, cpBody *b, cpFloat phase, cpFloat ratchet);++CP_DefineConstraintProperty(cpRatchetJoint, cpFloat, angle, Angle);+CP_DefineConstraintProperty(cpRatchetJoint, cpFloat, phase, Phase);+CP_DefineConstraintProperty(cpRatchetJoint, cpFloat, ratchet, Ratchet);
+ chipmunk-r402/include/chipmunk/constraints/cpRotaryLimitJoint.h view
@@ -0,0 +1,39 @@+/* Copyright (c) 2007 Scott Lembcke+ * + * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ * + * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+ * SOFTWARE.+ */++const cpConstraintClass *cpRotaryLimitJointGetClass();++typedef struct cpRotaryLimitJoint {+	cpConstraint constraint;+	cpFloat min, max;+	+	cpFloat iSum;+		+	cpFloat bias;+	cpFloat jAcc, jMax;+} cpRotaryLimitJoint;++cpRotaryLimitJoint *cpRotaryLimitJointAlloc(void);+cpRotaryLimitJoint *cpRotaryLimitJointInit(cpRotaryLimitJoint *joint, cpBody *a, cpBody *b, cpFloat min, cpFloat max);+cpConstraint *cpRotaryLimitJointNew(cpBody *a, cpBody *b, cpFloat min, cpFloat max);++CP_DefineConstraintProperty(cpRotaryLimitJoint, cpFloat, min, Min);+CP_DefineConstraintProperty(cpRotaryLimitJoint, cpFloat, max, Max);
+ chipmunk-r402/include/chipmunk/constraints/cpSimpleMotor.h view
@@ -0,0 +1,37 @@+/* Copyright (c) 2007 Scott Lembcke+ * + * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ * + * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+ * SOFTWARE.+ */++const cpConstraintClass *cpSimpleMotorGetClass();++typedef struct cpSimpleMotor {+	cpConstraint constraint;+	cpFloat rate;+	+	cpFloat iSum;+		+	cpFloat jAcc, jMax;+} cpSimpleMotor;++cpSimpleMotor *cpSimpleMotorAlloc(void);+cpSimpleMotor *cpSimpleMotorInit(cpSimpleMotor *joint, cpBody *a, cpBody *b, cpFloat rate);+cpConstraint *cpSimpleMotorNew(cpBody *a, cpBody *b, cpFloat rate);++CP_DefineConstraintProperty(cpSimpleMotor, cpFloat, rate, Rate);
+ chipmunk-r402/include/chipmunk/constraints/cpSlideJoint.h view
@@ -0,0 +1,44 @@+/* Copyright (c) 2007 Scott Lembcke+ * + * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ * + * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+ * SOFTWARE.+ */++const cpConstraintClass *cpSlideJointGetClass();++typedef struct cpSlideJoint {+	cpConstraint constraint;+	cpVect anchr1, anchr2;+	cpFloat min, max;+	+	cpVect r1, r2;+	cpVect n;+	cpFloat nMass;+	+	cpFloat jnAcc, jnMax;+	cpFloat bias;+} cpSlideJoint;++cpSlideJoint *cpSlideJointAlloc(void);+cpSlideJoint *cpSlideJointInit(cpSlideJoint *joint, cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat min, cpFloat max);+cpConstraint *cpSlideJointNew(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat min, cpFloat max);++CP_DefineConstraintProperty(cpSlideJoint, cpVect, anchr1, Anchr1);+CP_DefineConstraintProperty(cpSlideJoint, cpVect, anchr2, Anchr2);+CP_DefineConstraintProperty(cpSlideJoint, cpFloat, min, Min);+CP_DefineConstraintProperty(cpSlideJoint, cpFloat, max, Max);
+ chipmunk-r402/include/chipmunk/constraints/util.h view
@@ -0,0 +1,116 @@+/* Copyright (c) 2007 Scott Lembcke+ * + * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ * + * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+ * SOFTWARE.+ */++#define CP_DefineClassGetter(t) const cpConstraintClass * t##GetClass(){return (cpConstraintClass *)&klass;}++void cpConstraintInit(cpConstraint *constraint, const cpConstraintClass *klass, cpBody *a, cpBody *b);++#define J_MAX(constraint, dt) (((cpConstraint *)constraint)->maxForce*(dt))++static inline cpVect+relative_velocity(cpBody *a, cpBody *b, cpVect r1, cpVect r2){+	cpVect v1_sum = cpvadd(a->v, cpvmult(cpvperp(r1), a->w));+	cpVect v2_sum = cpvadd(b->v, cpvmult(cpvperp(r2), b->w));+	+	return cpvsub(v2_sum, v1_sum);+}++static inline cpFloat+normal_relative_velocity(cpBody *a, cpBody *b, cpVect r1, cpVect r2, cpVect n){+	return cpvdot(relative_velocity(a, b, r1, r2), n);+}++static inline void+apply_impulses(cpBody *a , cpBody *b, cpVect r1, cpVect r2, cpVect j)+{+	cpBodyApplyImpulse(a, cpvneg(j), r1);+	cpBodyApplyImpulse(b, j, r2);+}++static inline void+apply_bias_impulses(cpBody *a , cpBody *b, cpVect r1, cpVect r2, cpVect j)+{+	cpBodyApplyBiasImpulse(a, cpvneg(j), r1);+	cpBodyApplyBiasImpulse(b, j, r2);+}++static inline cpVect+clamp_vect(cpVect v, cpFloat len)+{+	return cpvclamp(v, len);+//	return (cpvdot(v,v) > len*len) ? cpvmult(cpvnormalize(v), len) : v;+}++static inline cpFloat+k_scalar(cpBody *a, cpBody *b, cpVect r1, cpVect r2, cpVect n)+{+	cpFloat mass_sum = a->m_inv + b->m_inv;+	cpFloat r1cn = cpvcross(r1, n);+	cpFloat r2cn = cpvcross(r2, n);+	+	cpFloat value = mass_sum + a->i_inv*r1cn*r1cn + b->i_inv*r2cn*r2cn;+	cpAssert(value != 0.0, "Unsolvable collision or constraint.");+	+	return value;+}++static inline void+k_tensor(cpBody *a, cpBody *b, cpVect r1, cpVect r2, cpVect *k1, cpVect *k2)+{+	// calculate mass matrix+	// If I wasn't lazy and wrote a proper matrix class, this wouldn't be so gross...+	cpFloat k11, k12, k21, k22;+	cpFloat m_sum = a->m_inv + b->m_inv;+	+	// start with I*m_sum+	k11 = m_sum; k12 = 0.0f;+	k21 = 0.0f;  k22 = m_sum;+	+	// add the influence from r1+	cpFloat a_i_inv = a->i_inv;+	cpFloat r1xsq =  r1.x * r1.x * a_i_inv;+	cpFloat r1ysq =  r1.y * r1.y * a_i_inv;+	cpFloat r1nxy = -r1.x * r1.y * a_i_inv;+	k11 += r1ysq; k12 += r1nxy;+	k21 += r1nxy; k22 += r1xsq;+	+	// add the influnce from r2+	cpFloat b_i_inv = b->i_inv;+	cpFloat r2xsq =  r2.x * r2.x * b_i_inv;+	cpFloat r2ysq =  r2.y * r2.y * b_i_inv;+	cpFloat r2nxy = -r2.x * r2.y * b_i_inv;+	k11 += r2ysq; k12 += r2nxy;+	k21 += r2nxy; k22 += r2xsq;+	+	// invert+	cpFloat determinant = k11*k22 - k12*k21;+	cpAssert(determinant != 0.0, "Unsolvable constraint.");+	+	cpFloat det_inv = 1.0f/determinant;+	*k1 = cpv( k22*det_inv, -k12*det_inv);+	*k2 = cpv(-k21*det_inv,  k11*det_inv);+}++static inline cpVect+mult_k(cpVect vr, cpVect k1, cpVect k2)+{+	return cpv(cpvdot(vr, k1), cpvdot(vr, k2));+}
+ chipmunk-r402/include/chipmunk/cpArbiter.h view
@@ -0,0 +1,136 @@+/* Copyright (c) 2007 Scott Lembcke+ * + * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ * + * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+ * SOFTWARE.+ */+ + struct cpArbiter;+ struct cpSpace;+ struct cpCollisionHandler;++// Determines how fast penetrations resolve themselves.+extern cpFloat cp_bias_coef;+// Amount of allowed penetration. Used to reduce vibrating contacts.+extern cpFloat cp_collision_slop;++// Data structure for contact points.+typedef struct cpContact {+	// Contact point and normal.+	cpVect p, n;+	// Penetration distance.+	cpFloat dist;+	+	// Calculated by cpArbiterPreStep().+	cpVect r1, r2;+	cpFloat nMass, tMass, bounce;++	// Persistant contact information.+	cpFloat jnAcc, jtAcc, jBias;+	cpFloat bias;+	+	// Hash value used to (mostly) uniquely identify a contact.+	cpHashValue hash;+} cpContact;++// Contacts are always allocated in groups.+cpContact* cpContactInit(cpContact *con, cpVect p, cpVect n, cpFloat dist, cpHashValue hash);++// Sum the contact impulses. (Can be used after cpSpaceStep() returns)+cpVect cpContactsSumImpulses(cpContact *contacts, int numContacts);+cpVect cpContactsSumImpulsesWithFriction(cpContact *contacts, int numContacts);++typedef enum cpArbiterState {+	cpArbiterStateNormal,+	cpArbiterStateFirstColl,+	cpArbiterStateIgnore,+} cpArbiterState;++// Data structure for tracking collisions between shapes.+typedef struct cpArbiter {+	// Information on the contact points between the objects.+	int numContacts;+	cpContact *contacts;+	+	// The two shapes involved in the collision.+	// These variables are NOT in the order defined by the collision handler.+	cpShape *private_a, *private_b;+	+	// Calculated before calling the pre-solve collision handler+	// Override them with custom values if you want specialized behavior+	cpFloat e;+	cpFloat u;+	 // Used for surface_v calculations, implementation may change+	cpVect surface_vr;+	+	// Time stamp of the arbiter. (from cpSpace)+	int stamp;+	+	struct cpCollisionHandler *handler;+	+	// Are the shapes swapped in relation to the collision handler?+	char swappedColl;+	char state;+} cpArbiter;++// Arbiters are allocated in large buffers by the space and don't require a destroy function+cpArbiter* cpArbiterInit(cpArbiter *arb, cpShape *a, cpShape *b);++// These functions are all intended to be used internally.+// Inject new contact points into the arbiter while preserving contact history.+void cpArbiterUpdate(cpArbiter *arb, cpContact *contacts, int numContacts, struct cpCollisionHandler *handler, cpShape *a, cpShape *b);+// Precalculate values used by the solver.+void cpArbiterPreStep(cpArbiter *arb, cpFloat dt_inv);+void cpArbiterApplyCachedImpulse(cpArbiter *arb);+// Run an iteration of the solver on the arbiter.+void cpArbiterApplyImpulse(cpArbiter *arb, cpFloat eCoef);++// Arbiter Helper Functions+cpVect cpArbiterTotalImpulse(cpArbiter *arb);+cpVect cpArbiterTotalImpulseWithFriction(cpArbiter *arb);+void cpArbiterIgnore(cpArbiter *arb);+++static inline void+cpArbiterGetShapes(cpArbiter *arb, cpShape **a, cpShape **b)+{+	if(arb->swappedColl){+		(*a) = arb->private_b, (*b) = arb->private_a;+	} else {+		(*a) = arb->private_a, (*b) = arb->private_b;+	}+}+#define CP_ARBITER_GET_SHAPES(arb, a, b) cpShape *a, *b; cpArbiterGetShapes(arb, &a, &b);++static inline int+cpArbiterIsFirstContact(cpArbiter *arb)+{+	return arb->state == cpArbiterStateFirstColl;+}++static inline cpVect+cpArbiterGetNormal(cpArbiter *arb, int i)+{+	cpVect n = arb->contacts[i].n;+	return arb->swappedColl ? cpvneg(n) : n;+}++static inline cpVect+cpArbiterGetPoint(cpArbiter *arb, int i)+{+	return arb->contacts[i].p;+}
+ chipmunk-r402/include/chipmunk/cpArray.h view
@@ -0,0 +1,46 @@+/* Copyright (c) 2007 Scott Lembcke+ * + * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ * + * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+ * SOFTWARE.+ */+ +// NOTE: cpArray is rarely used and will probably go away.++typedef struct cpArray{+	int num, max;+	void **arr;+} cpArray;++typedef void (*cpArrayIter)(void *ptr, void *data);++cpArray *cpArrayAlloc(void);+cpArray *cpArrayInit(cpArray *arr, int size);+cpArray *cpArrayNew(int size);++void cpArrayDestroy(cpArray *arr);+void cpArrayFree(cpArray *arr);++void cpArrayClear(cpArray *arr);++void cpArrayPush(cpArray *arr, void *object);+void *cpArrayPop(cpArray *arr);+void cpArrayDeleteIndex(cpArray *arr, int idx);+void cpArrayDeleteObj(cpArray *arr, void *obj);++void cpArrayEach(cpArray *arr, cpArrayIter iterFunc, void *data);+int cpArrayContains(cpArray *arr, void *ptr);
+ chipmunk-r402/include/chipmunk/cpBB.h view
@@ -0,0 +1,74 @@+/* Copyright (c) 2007 Scott Lembcke+ * + * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ * + * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+ * SOFTWARE.+ */+ +typedef struct cpBB{+	cpFloat l, b, r ,t;+} cpBB;++static inline cpBB+cpBBNew(const cpFloat l, const cpFloat b,+		const cpFloat r, const cpFloat t)+{+	cpBB bb = {l, b, r, t};+	return bb;+}++static inline int+cpBBintersects(const cpBB a, const cpBB b)+{+	return (a.l<=b.r && b.l<=a.r && a.b<=b.t && b.b<=a.t);+}++static inline int+cpBBcontainsBB(const cpBB bb, const cpBB other)+{+	return (bb.l < other.l && bb.r > other.r && bb.b < other.b && bb.t > other.t);+}++static inline int+cpBBcontainsVect(const cpBB bb, const cpVect v)+{+	return (bb.l < v.x && bb.r > v.x && bb.b < v.y && bb.t > v.y);+}++static inline cpBB+cpBBmerge(const cpBB a, const cpBB b){+	return cpBBNew(+		cpfmin(a.l, b.l),+		cpfmin(a.b, b.b),+		cpfmax(a.r, b.r),+		cpfmax(a.t, b.t)+	);+}++static inline cpBB+cpBBexpand(const cpBB bb, const cpVect v){+	return cpBBNew(+		cpfmin(bb.l, v.x),+		cpfmin(bb.b, v.y),+		cpfmax(bb.r, v.x),+		cpfmax(bb.t, v.y)+	);+}++cpVect cpBBClampVect(const cpBB bb, const cpVect v); // clamps the vector to lie within the bbox+// TODO edge case issue+cpVect cpBBWrapVect(const cpBB bb, const cpVect v); // wrap a vector to a bbox
+ chipmunk-r402/include/chipmunk/cpBody.h view
@@ -0,0 +1,160 @@+/* Copyright (c) 2007 Scott Lembcke+ * + * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ * + * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+ * SOFTWARE.+ */++struct cpBody;+typedef void (*cpBodyVelocityFunc)(struct cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt);+typedef void (*cpBodyPositionFunc)(struct cpBody *body, cpFloat dt);++extern cpBodyVelocityFunc cpBodyUpdateVelocityDefault;+extern cpBodyPositionFunc cpBodyUpdatePositionDefault;+ +typedef struct cpBody{+	// *** Integration Functions.ntoehu++	// Function that is called to integrate the body's velocity. (Defaults to cpBodyUpdateVelocity)+	cpBodyVelocityFunc velocity_func;+	+	// Function that is called to integrate the body's position. (Defaults to cpBodyUpdatePosition)+	cpBodyPositionFunc position_func;+	+	// *** Mass Properties+	+	// Mass and it's inverse.+	// Always use cpBodySetMass() whenever changing the mass as these values must agree.+	cpFloat m, m_inv;+	+	// Moment of inertia and it's inverse.+	// Always use cpBodySetMass() whenever changing the mass as these values must agree.+	cpFloat i, i_inv;+	+	// *** Positional Properties+	+	// Linear components of motion (position, velocity, and force)+	cpVect p, v, f;+	+	// Angular components of motion (angle, angular velocity, and torque)+	// Always use cpBodySetAngle() to set the angle of the body as a and rot must agree.+	cpFloat a, w, t;+	+	// Cached unit length vector representing the angle of the body.+	// Used for fast vector rotation using cpvrotate().+	cpVect rot;+	+	// *** User Definable Fields+	+	// User defined data pointer.+	cpDataPointer data;+	+	// Maximum velocities this body can move at after integrating velocity+	cpFloat v_limit, w_limit;+	+	// *** Internally Used Fields+	+	// Velocity bias values used when solving penetrations and correcting constraints.+	cpVect v_bias;+	cpFloat w_bias;+	+//	int active;+} cpBody;++// Basic allocation/destruction functions+cpBody *cpBodyAlloc(void);+cpBody *cpBodyInit(cpBody *body, cpFloat m, cpFloat i);+cpBody *cpBodyNew(cpFloat m, cpFloat i);++void cpBodyDestroy(cpBody *body);+void cpBodyFree(cpBody *body);++#define CP_DefineBodyGetter(type, member, name) static inline type cpBodyGet##name(cpBody *body){return body->member;}+#define CP_DefineBodySetter(type, member, name) static inline void cpBodySet##name(cpBody *body, type value){body->member = value;}++#define CP_DefineBodyProperty(type, member, name) \+CP_DefineBodyGetter(type, member, name) \+CP_DefineBodySetter(type, member, name)+++// Accessors for cpBody struct members+CP_DefineBodyGetter(cpFloat, m, Mass);+void cpBodySetMass(cpBody *body, cpFloat m);++CP_DefineBodyGetter(cpFloat, i, Moment);+void cpBodySetMoment(cpBody *body, cpFloat i);+++CP_DefineBodyProperty(cpVect, p, Pos);+CP_DefineBodyProperty(cpVect, v, Vel);+CP_DefineBodyProperty(cpVect, f, Force);+CP_DefineBodyGetter(cpFloat, a, Angle);+void cpBodySetAngle(cpBody *body, cpFloat a);+CP_DefineBodyProperty(cpFloat, w, AngVel);+CP_DefineBodyProperty(cpFloat, t, Torque);+CP_DefineBodyGetter(cpVect, rot, Rot);+CP_DefineBodyProperty(cpFloat, v_limit, VelLimit);+CP_DefineBodyProperty(cpFloat, w_limit, AngVelLimit);++//  Modify the velocity of the body so that it will move to the specified absolute coordinates in the next timestep.+// Intended for objects that are moved manually with a custom velocity integration function.+void cpBodySlew(cpBody *body, cpVect pos, cpFloat dt);++// Default Integration functions.+void cpBodyUpdateVelocity(cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt);+void cpBodyUpdatePosition(cpBody *body, cpFloat dt);++// Convert body local to world coordinates+static inline cpVect+cpBodyLocal2World(cpBody *body, cpVect v)+{+	return cpvadd(body->p, cpvrotate(v, body->rot));+}++// Convert world to body local coordinates+static inline cpVect+cpBodyWorld2Local(cpBody *body, cpVect v)+{+	return cpvunrotate(cpvsub(v, body->p), body->rot);+}++// Apply an impulse (in world coordinates) to the body at a point relative to the center of gravity (also in world coordinates).+static inline void+cpBodyApplyImpulse(cpBody *body, cpVect j, cpVect r)+{+	body->v = cpvadd(body->v, cpvmult(j, body->m_inv));+	body->w += body->i_inv*cpvcross(r, j);+}++// Not intended for external use. Used by cpArbiter.c and cpConstraint.c.+static inline void+cpBodyApplyBiasImpulse(cpBody *body, cpVect j, cpVect r)+{+	body->v_bias = cpvadd(body->v_bias, cpvmult(j, body->m_inv));+	body->w_bias += body->i_inv*cpvcross(r, j);+}++// Zero the forces on a body.+void cpBodyResetForces(cpBody *body);+// Apply a force (in world coordinates) to a body at a point relative to the center of gravity (also in world coordinates).+void cpBodyApplyForce(cpBody *body, cpVect f, cpVect r);++// Apply a damped spring force between two bodies.+// Warning: Large damping values can be unstable. Use a cpDampedSpring constraint for this instead.+void cpApplyDampedSpring(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat rlen, cpFloat k, cpFloat dmp, cpFloat dt);++//int cpBodyMarkLowEnergy(cpBody *body, cpFloat dvsq, int max);
+ chipmunk-r402/include/chipmunk/cpCollision.h view
@@ -0,0 +1,23 @@+/* Copyright (c) 2007 Scott Lembcke+ * + * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ * + * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+ * SOFTWARE.+ */++// Collides two cpShape structures. (this function is lonely :( )+int cpCollideShapes(cpShape *a, cpShape *b, cpContact *arr);
+ chipmunk-r402/include/chipmunk/cpHashSet.h view
@@ -0,0 +1,82 @@+/* Copyright (c) 2007 Scott Lembcke+ * + * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ * + * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+ * SOFTWARE.+ */+ +// cpHashSet uses a chained hashtable implementation.+// Other than the transformation functions, there is nothing fancy going on.++// cpHashSetBin's form the linked lists in the chained hash table.+typedef struct cpHashSetBin {+	// Pointer to the element.+	void *elt;+	// Hash value of the element.+	cpHashValue hash;+	// Next element in the chain.+	struct cpHashSetBin *next;+} cpHashSetBin;++// Equality function. Returns true if ptr is equal to elt.+typedef int (*cpHashSetEqlFunc)(void *ptr, void *elt);+// Used by cpHashSetInsert(). Called to transform the ptr into an element.+typedef void *(*cpHashSetTransFunc)(void *ptr, void *data);+// Iterator function for a hashset.+typedef void (*cpHashSetIterFunc)(void *elt, void *data);+// Filter function. Returns false if elt should be dropped.+typedef int (*cpHashSetFilterFunc)(void *elt, void *data);++typedef struct cpHashSet {+	// Number of elements stored in the table.+	int entries;+	// Number of cells in the table.+	int size;+	+	cpHashSetEqlFunc eql;+	cpHashSetTransFunc trans;+	+	// Default value returned by cpHashSetFind() when no element is found.+	// Defaults to NULL.+	void *default_value;+	+	// The table and recycled bins+	cpHashSetBin **table, *pooledBins;+	+	cpArray *allocatedBuffers;+} cpHashSet;++// Basic allocation/destruction functions.+void cpHashSetDestroy(cpHashSet *set);+void cpHashSetFree(cpHashSet *set);++cpHashSet *cpHashSetAlloc(void);+cpHashSet *cpHashSetInit(cpHashSet *set, int size, cpHashSetEqlFunc eqlFunc, cpHashSetTransFunc trans);+cpHashSet *cpHashSetNew(int size, cpHashSetEqlFunc eqlFunc, cpHashSetTransFunc trans);++// Insert an element into the set, returns the element.+// If it doesn't already exist, the transformation function is applied.+void *cpHashSetInsert(cpHashSet *set, cpHashValue hash, void *ptr, void *data);+// Remove and return an element from the set.+void *cpHashSetRemove(cpHashSet *set, cpHashValue hash, void *ptr);+// Find an element in the set. Returns the default value if the element isn't found.+void *cpHashSetFind(cpHashSet *set, cpHashValue hash, void *ptr);++// Iterate over a hashset.+void cpHashSetEach(cpHashSet *set, cpHashSetIterFunc func, void *data);+// Iterate over a hashset, retain .+void cpHashSetFilter(cpHashSet *set, cpHashSetFilterFunc func, void *data);
+ chipmunk-r402/include/chipmunk/cpPolyShape.h view
@@ -0,0 +1,100 @@+/* Copyright (c) 2007 Scott Lembcke+ * + * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ * + * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+ * SOFTWARE.+ */++// Axis structure used by cpPolyShape.+typedef struct cpPolyShapeAxis{+	// normal+	cpVect n;+	// distance from origin+	cpFloat d;+} cpPolyShapeAxis;++// Convex polygon shape structure.+typedef struct cpPolyShape{+	cpShape shape;+	+	// Vertex and axis lists.+	int numVerts;+	cpVect *verts;+	cpPolyShapeAxis *axes;++	// Transformed vertex and axis lists.+	cpVect *tVerts;+	cpPolyShapeAxis *tAxes;+} cpPolyShape;++// Basic allocation functions.+cpPolyShape *cpPolyShapeAlloc(void);+cpPolyShape *cpPolyShapeInit(cpPolyShape *poly, cpBody *body, int numVerts, cpVect *verts, cpVect offset);+cpShape *cpPolyShapeNew(cpBody *body, int numVerts, cpVect *verts, cpVect offset);++// Check that a set of vertexes has a correct winding and that they are convex+int cpPolyValidate(cpVect *verts, int numVerts);++int cpPolyShapeGetNumVerts(cpShape *shape);+cpVect cpPolyShapeGetVert(cpShape *shape, int idx);++// *** inlined utility functions++// Returns the minimum distance of the polygon to the axis.+static inline cpFloat+cpPolyShapeValueOnAxis(const cpPolyShape *poly, const cpVect n, const cpFloat d)+{+	cpVect *verts = poly->tVerts;+	cpFloat min = cpvdot(n, verts[0]);+	+	int i;+	for(i=1; i<poly->numVerts; i++)+		min = cpfmin(min, cpvdot(n, verts[i]));+	+	return min - d;+}++// Returns true if the polygon contains the vertex.+static inline int+cpPolyShapeContainsVert(cpPolyShape *poly, cpVect v)+{+	cpPolyShapeAxis *axes = poly->tAxes;+	+	int i;+	for(i=0; i<poly->numVerts; i++){+		cpFloat dist = cpvdot(axes[i].n, v) - axes[i].d;+		if(dist > 0.0f) return 0;+	}+	+	return 1;+}++// Same as cpPolyShapeContainsVert() but ignores faces pointing away from the normal.+static inline int+cpPolyShapeContainsVertPartial(cpPolyShape *poly, cpVect v, cpVect n)+{+	cpPolyShapeAxis *axes = poly->tAxes;+	+	int i;+	for(i=0; i<poly->numVerts; i++){+		if(cpvdot(axes[i].n, n) < 0.0f) continue;+		cpFloat dist = cpvdot(axes[i].n, v) - axes[i].d;+		if(dist > 0.0f) return 0;+	}+	+	return 1;+}
+ chipmunk-r402/include/chipmunk/cpShape.h view
@@ -0,0 +1,174 @@+/* Copyright (c) 2007 Scott Lembcke+ * + * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ * + * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+ * SOFTWARE.+ */+ +// Forward declarations required for defining other structs.+struct cpShape;+struct cpShapeClass;++typedef struct cpSegmentQueryInfo{+	struct cpShape *shape; // shape that was hit, NULL if no collision+	cpFloat t; // Distance along query segment, will always be in the range [0, 1].+	cpVect n; // normal of hit surface+} cpSegmentQueryInfo;++// Enumeration of shape types.+typedef enum cpShapeType{+	CP_CIRCLE_SHAPE,+	CP_SEGMENT_SHAPE,+	CP_POLY_SHAPE,+	CP_NUM_SHAPES+} cpShapeType;++// Shape class. Holds function pointers and type data.+typedef struct cpShapeClass {+	cpShapeType type;+	+	// Called by cpShapeCacheBB().+	cpBB (*cacheData)(struct cpShape *shape, cpVect p, cpVect rot);+	// Called to by cpShapeDestroy().+	void (*destroy)(struct cpShape *shape);+	+	// called by cpShapePointQuery().+	int (*pointQuery)(struct cpShape *shape, cpVect p);+	+	// called by cpShapeSegmentQuery()+	 void (*segmentQuery)(struct cpShape *shape, cpVect a, cpVect b, cpSegmentQueryInfo *info);+} cpShapeClass;++// Basic shape struct that the others inherit from.+typedef struct cpShape{+	// The "class" of a shape as defined above +	const cpShapeClass *klass;+	+	// cpBody that the shape is attached to.+	cpBody *body;++	// Cached BBox for the shape.+	cpBB bb;+	+	// Sensors invoke callbacks, but do not generate collisions+	int sensor;+	+	// *** Surface properties.+	+	// Coefficient of restitution. (elasticity)+	cpFloat e;+	// Coefficient of friction.+	cpFloat u;+	// Surface velocity used when solving for friction.+	cpVect surface_v;++	// *** User Definable Fields++	// User defined data pointer for the shape.+	cpDataPointer data;+	+	// User defined collision type for the shape.+	cpCollisionType collision_type;+	// User defined collision group for the shape.+	cpGroup group;+	// User defined layer bitmask for the shape.+	cpLayers layers;+	+	// *** Internally Used Fields+	+	// Unique id used as the hash value.+	cpHashValue hashid;+} cpShape;++// Low level shape initialization func.+cpShape* cpShapeInit(cpShape *shape, const struct cpShapeClass *klass, cpBody *body);++// Basic destructor functions. (allocation functions are not shared)+void cpShapeDestroy(cpShape *shape);+void cpShapeFree(cpShape *shape);++// Cache the BBox of the shape.+cpBB cpShapeCacheBB(cpShape *shape);++// Test if a point lies within a shape.+int cpShapePointQuery(cpShape *shape, cpVect p);++#define CP_DeclareShapeGetter(struct, type, name) type struct##Get##name(cpShape *shape)++// Circle shape structure.+typedef struct cpCircleShape{+	cpShape shape;+	+	// Center in body space coordinates+	cpVect c;+	// Radius.+	cpFloat r;+	+	// Transformed center. (world space coordinates)+	cpVect tc;+} cpCircleShape;++// Basic allocation functions for cpCircleShape.+cpCircleShape *cpCircleShapeAlloc(void);+cpCircleShape *cpCircleShapeInit(cpCircleShape *circle, cpBody *body, cpFloat radius, cpVect offset);+cpShape *cpCircleShapeNew(cpBody *body, cpFloat radius, cpVect offset);++CP_DeclareShapeGetter(cpCircleShape, cpVect, Offset);+CP_DeclareShapeGetter(cpCircleShape, cpFloat, Radius);++// Segment shape structure.+typedef struct cpSegmentShape{+	cpShape shape;+	+	// Endpoints and normal of the segment. (body space coordinates)+	cpVect a, b, n;+	// Radius of the segment. (Thickness)+	cpFloat r;++	// Transformed endpoints and normal. (world space coordinates)+	cpVect ta, tb, tn;+} cpSegmentShape;++// Basic allocation functions for cpSegmentShape.+cpSegmentShape* cpSegmentShapeAlloc(void);+cpSegmentShape* cpSegmentShapeInit(cpSegmentShape *seg, cpBody *body, cpVect a, cpVect b, cpFloat radius);+cpShape* cpSegmentShapeNew(cpBody *body, cpVect a, cpVect b, cpFloat radius);++CP_DeclareShapeGetter(cpSegmentShape, cpVect, A);+CP_DeclareShapeGetter(cpSegmentShape, cpVect, B);+CP_DeclareShapeGetter(cpSegmentShape, cpVect, Normal);+CP_DeclareShapeGetter(cpSegmentShape, cpFloat, Radius);++// For determinism, you can reset the shape id counter.+void cpResetShapeIdCounter(void);++// Directed segment queries against individual shapes.+void cpSegmentQueryInfoPrint(cpSegmentQueryInfo *info);++int cpShapeSegmentQuery(cpShape *shape, cpVect a, cpVect b, cpSegmentQueryInfo *info);++static inline cpVect+cpSegmentQueryHitPoint(cpVect start, cpVect end, cpSegmentQueryInfo info)+{+	return cpvlerp(start, end, info.t);+}++static inline cpFloat+cpSegmentQueryHitDist(cpVect start, cpVect end, cpSegmentQueryInfo info)+{+	return cpvdist(start, end)*info.t;+}
+ chipmunk-r402/include/chipmunk/cpSpace.h view
@@ -0,0 +1,184 @@+/* Copyright (c) 2007 Scott Lembcke+ * + * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ * + * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+ * SOFTWARE.+ */++struct cpSpace;++// Number of frames that contact information should persist.+extern int cp_contact_persistence;++// User collision handler function types.+typedef int (*cpCollisionBeginFunc)(cpArbiter *arb, struct cpSpace *space, void *data);+typedef int (*cpCollisionPreSolveFunc)(cpArbiter *arb, struct cpSpace *space, void *data);+typedef void (*cpCollisionPostSolveFunc)(cpArbiter *arb, struct cpSpace *space, void *data);+typedef void (*cpCollisionSeparateFunc)(cpArbiter *arb, struct cpSpace *space, void *data);++// Structure for holding collision pair function information.+// Used internally.+typedef struct cpCollisionHandler {+	cpCollisionType a;+	cpCollisionType b;+	cpCollisionBeginFunc begin;+	cpCollisionPreSolveFunc preSolve;+	cpCollisionPostSolveFunc postSolve;+	cpCollisionSeparateFunc separate;+	void *data;+} cpCollisionHandler;++#define CP_CONTACTS_BUFFER_SIZE (CP_BUFFER_BYTES/sizeof(cpContact) - 1)+#define CP_MAX_CONTACTS_PER_ARBITER 6++typedef struct cpContactBuffer {+	int stamp;+	struct cpContactBuffer *next;+	+	unsigned int numContacts;+	cpContact contacts[CP_CONTACTS_BUFFER_SIZE];+} cpContactBuffer;++typedef struct cpSpace{+	// *** User definable fields+	+	// Number of iterations to use in the impulse solver to solve contacts.+	int iterations;+	+	// Number of iterations to use in the impulse solver to solve elastic collisions.+	int elasticIterations;+	+	// Default gravity to supply when integrating rigid body motions.+	cpVect gravity;+	+	// Default damping to supply when integrating rigid body motions.+	cpFloat damping;+	+	// *** Internally Used Fields+	+	// When the space is locked, you should not add or remove objects;+	int locked;+	+	// Time stamp. Is incremented on every call to cpSpaceStep().+	int stamp;++	// The static and active shape spatial hashes.+	cpSpaceHash *staticShapes;+	cpSpaceHash *activeShapes;+	+	// List of bodies in the system.+	cpArray *bodies;+	+	// List of active arbiters for the impulse solver.+	cpArray *arbiters, *pooledArbiters;+	+	// Linked list ring of contact buffers.+	// Head is the current buffer. Tail is the oldest buffer.+	// The list points in the direction of tail->head.+	cpContactBuffer *contactBuffersHead, *contactBuffersTail;+	+	// List of buffers to be free()ed when destroying the space.+	cpArray *allocatedBuffers;+	+	// Persistant contact set.+	cpHashSet *contactSet;+	+	// List of constraints in the system.+	cpArray *constraints;+	+	// Set of collisionpair functions.+	cpHashSet *collFuncSet;+	// Default collision handler.+	cpCollisionHandler defaultHandler;+	+	cpHashSet *postStepCallbacks;+} cpSpace;++// Basic allocation/destruction functions.+cpSpace* cpSpaceAlloc(void);+cpSpace* cpSpaceInit(cpSpace *space);+cpSpace* cpSpaceNew(void);++void cpSpaceDestroy(cpSpace *space);+void cpSpaceFree(cpSpace *space);++// Convenience function. Frees all referenced entities. (bodies, shapes and constraints)+void cpSpaceFreeChildren(cpSpace *space);++// Collision handler management functions.+void cpSpaceSetDefaultCollisionHandler(+	cpSpace *space,+	cpCollisionBeginFunc begin,+	cpCollisionPreSolveFunc preSolve,+	cpCollisionPostSolveFunc postSolve,+	cpCollisionSeparateFunc separate,+	void *data+);+void cpSpaceAddCollisionHandler(+	cpSpace *space,+	cpCollisionType a, cpCollisionType b,+	cpCollisionBeginFunc begin,+	cpCollisionPreSolveFunc preSolve,+	cpCollisionPostSolveFunc postSolve,+	cpCollisionSeparateFunc separate,+	void *data+);+void cpSpaceRemoveCollisionHandler(cpSpace *space, cpCollisionType a, cpCollisionType b);++// Add and remove entities from the system.+cpShape *cpSpaceAddShape(cpSpace *space, cpShape *shape);+cpShape *cpSpaceAddStaticShape(cpSpace *space, cpShape *shape);+cpBody *cpSpaceAddBody(cpSpace *space, cpBody *body);+cpConstraint *cpSpaceAddConstraint(cpSpace *space, cpConstraint *constraint);++void cpSpaceRemoveShape(cpSpace *space, cpShape *shape);+void cpSpaceRemoveStaticShape(cpSpace *space, cpShape *shape);+void cpSpaceRemoveBody(cpSpace *space, cpBody *body);+void cpSpaceRemoveConstraint(cpSpace *space, cpConstraint *constraint);++// Post Step function definition+typedef void (*cpPostStepFunc)(cpSpace *space, void *obj, void *data);+// Register a post step function to be called after cpSpaceStep() has finished.+// obj is used a key, you can only register one callback per unique value for obj+void cpSpaceAddPostStepCallback(cpSpace *space, cpPostStepFunc func, void *obj, void *data);++// Point query callback function+typedef void (*cpSpacePointQueryFunc)(cpShape *shape, void *data);+void cpSpacePointQuery(cpSpace *space, cpVect point, cpLayers layers, cpGroup group, cpSpacePointQueryFunc func, void *data);+cpShape *cpSpacePointQueryFirst(cpSpace *space, cpVect point, cpLayers layers, cpGroup group);++// Segment query callback function+typedef void (*cpSpaceSegmentQueryFunc)(cpShape *shape, cpFloat t, cpVect n, void *data);+int cpSpaceSegmentQuery(cpSpace *space, cpVect start, cpVect end, cpLayers layers, cpGroup group, cpSpaceSegmentQueryFunc func, void *data);+cpShape *cpSpaceSegmentQueryFirst(cpSpace *space, cpVect start, cpVect end, cpLayers layers, cpGroup group, cpSegmentQueryInfo *out);++// BB query callback function+typedef void (*cpSpaceBBQueryFunc)(cpShape *shape, void *data);+void cpSpaceBBQuery(cpSpace *space, cpBB bb, cpLayers layers, cpGroup group, cpSpaceBBQueryFunc func, void *data);+++// Iterator function for iterating the bodies in a space.+typedef void (*cpSpaceBodyIterator)(cpBody *body, void *data);+void cpSpaceEachBody(cpSpace *space, cpSpaceBodyIterator func, void *data);++// Spatial hash management functions.+void cpSpaceResizeStaticHash(cpSpace *space, cpFloat dim, int count);+void cpSpaceResizeActiveHash(cpSpace *space, cpFloat dim, int count);+void cpSpaceRehashStatic(cpSpace *space);++// Update the space.+void cpSpaceStep(cpSpace *space, cpFloat dt);
+ chipmunk-r402/include/chipmunk/cpSpaceHash.h view
@@ -0,0 +1,109 @@+/* Copyright (c) 2007 Scott Lembcke+ * + * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ * + * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+ * SOFTWARE.+ */++// The spatial hash is Chipmunk's default (and currently only) spatial index type.+// Based on a chained hash table.++// Used internally to track objects added to the hash+typedef struct cpHandle{+	// Pointer to the object+	void *obj;+	// Retain count+	int retain;+	// Query stamp. Used to make sure two objects+	// aren't identified twice in the same query.+	int stamp;+} cpHandle;++// Linked list element for in the chains.+typedef struct cpSpaceHashBin{+	cpHandle *handle;+	struct cpSpaceHashBin *next;+} cpSpaceHashBin;++// BBox callback. Called whenever the hash needs a bounding box from an object.+typedef cpBB (*cpSpaceHashBBFunc)(void *obj);++typedef struct cpSpaceHash{+	// Number of cells in the table.+	int numcells;+	// Dimentions of the cells.+	cpFloat celldim;+	+	// BBox callback.+	cpSpaceHashBBFunc bbfunc;++	// Hashset of the handles and the recycled ones.+	cpHashSet *handleSet;+	cpArray *pooledHandles;+	+	// The table and the recycled bins.+	cpSpaceHashBin **table, *pooledBins;+	+	// list of buffers to free on destruction.+	cpArray *allocatedBuffers;+	+	// Incremented on each query. See cpHandle.stamp.+	int stamp;+} cpSpaceHash;++//Basic allocation/destruction functions.+cpSpaceHash *cpSpaceHashAlloc(void);+cpSpaceHash *cpSpaceHashInit(cpSpaceHash *hash, cpFloat celldim, int cells, cpSpaceHashBBFunc bbfunc);+cpSpaceHash *cpSpaceHashNew(cpFloat celldim, int cells, cpSpaceHashBBFunc bbfunc);++void cpSpaceHashDestroy(cpSpaceHash *hash);+void cpSpaceHashFree(cpSpaceHash *hash);++// Resize the hashtable. (Does not rehash! You must call cpSpaceHashRehash() if needed.)+void cpSpaceHashResize(cpSpaceHash *hash, cpFloat celldim, int numcells);++// Add an object to the hash.+void cpSpaceHashInsert(cpSpaceHash *hash, void *obj, cpHashValue id, cpBB bb);+// Remove an object from the hash.+void cpSpaceHashRemove(cpSpaceHash *hash, void *obj, cpHashValue id);++// Iterator function+typedef void (*cpSpaceHashIterator)(void *obj, void *data);+// Iterate over the objects in the hash.+void cpSpaceHashEach(cpSpaceHash *hash, cpSpaceHashIterator func, void *data);++// Rehash the contents of the hash.+void cpSpaceHashRehash(cpSpaceHash *hash);+// Rehash only a specific object.+void cpSpaceHashRehashObject(cpSpaceHash *hash, void *obj, cpHashValue id);++// Query callback.+typedef void (*cpSpaceHashQueryFunc)(void *obj1, void *obj2, void *data);+// Point query the hash. A reference to the query point is passed as obj1 to the query callback.+void cpSpaceHashPointQuery(cpSpaceHash *hash, cpVect point, cpSpaceHashQueryFunc func, void *data);+// Query the hash for a given BBox.+void cpSpaceHashQuery(cpSpaceHash *hash, void *obj, cpBB bb, cpSpaceHashQueryFunc func, void *data);+// Run a query for the object, then insert it. (Optimized case)+void cpSpaceHashQueryInsert(cpSpaceHash *hash, void *obj, cpBB bb, cpSpaceHashQueryFunc func, void *data);+// Rehashes while querying for each object. (Optimized case) +void cpSpaceHashQueryRehash(cpSpaceHash *hash, cpSpaceHashQueryFunc func, void *data);++// Segment Query callback.+// Return value is uesd for early exits of the query.+// If while traversing the grid, the raytrace function detects that an entire grid cell is beyond the hit point, it will stop the trace.+typedef cpFloat (*cpSpaceHashSegmentQueryFunc)(void *obj1, void *obj2, void *data);+void cpSpaceHashSegmentQuery(cpSpaceHash *hash, void *obj, cpVect a, cpVect b, cpFloat t_exit, cpSpaceHashSegmentQueryFunc func, void *data);
+ chipmunk-r402/include/chipmunk/cpVect.h view
@@ -0,0 +1,157 @@+/* Copyright (c) 2007 Scott Lembcke+ * + * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ * + * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+ * SOFTWARE.+ */++static const cpVect cpvzero={0.0f,0.0f};++static inline cpVect+cpv(const cpFloat x, const cpFloat y)+{+	cpVect v = {x, y};+	return v;+}++// non-inlined functions+cpFloat cpvlength(const cpVect v);+cpVect cpvslerp(const cpVect v1, const cpVect v2, const cpFloat t);+cpVect cpvslerpconst(const cpVect v1, const cpVect v2, const cpFloat a);+cpVect cpvforangle(const cpFloat a); // convert radians to a normalized vector+cpFloat cpvtoangle(const cpVect v); // convert a vector to radians+char *cpvstr(const cpVect v); // get a string representation of a vector++static inline cpVect+cpvadd(const cpVect v1, const cpVect v2)+{+	return cpv(v1.x + v2.x, v1.y + v2.y);+}++static inline cpVect+cpvneg(const cpVect v)+{+	return cpv(-v.x, -v.y);+}++static inline cpVect+cpvsub(const cpVect v1, const cpVect v2)+{+	return cpv(v1.x - v2.x, v1.y - v2.y);+}++static inline cpVect+cpvmult(const cpVect v, const cpFloat s)+{+	return cpv(v.x*s, v.y*s);+}++static inline cpFloat+cpvdot(const cpVect v1, const cpVect v2)+{+	return v1.x*v2.x + v1.y*v2.y;+}++static inline cpFloat+cpvcross(const cpVect v1, const cpVect v2)+{+	return v1.x*v2.y - v1.y*v2.x;+}++static inline cpVect+cpvperp(const cpVect v)+{+	return cpv(-v.y, v.x);+}++static inline cpVect+cpvrperp(const cpVect v)+{+	return cpv(v.y, -v.x);+}++static inline cpVect+cpvproject(const cpVect v1, const cpVect v2)+{+	return cpvmult(v2, cpvdot(v1, v2)/cpvdot(v2, v2));+}++static inline cpVect+cpvrotate(const cpVect v1, const cpVect v2)+{+	return cpv(v1.x*v2.x - v1.y*v2.y, v1.x*v2.y + v1.y*v2.x);+}++static inline cpVect+cpvunrotate(const cpVect v1, const cpVect v2)+{+	return cpv(v1.x*v2.x + v1.y*v2.y, v1.y*v2.x - v1.x*v2.y);+}++static inline cpFloat+cpvlengthsq(const cpVect v)+{+	return cpvdot(v, v);+}++static inline cpVect+cpvlerp(const cpVect v1, const cpVect v2, const cpFloat t)+{+	return cpvadd(cpvmult(v1, 1.0f - t), cpvmult(v2, t));+}++static inline cpVect+cpvnormalize(const cpVect v)+{+	return cpvmult(v, 1.0f/cpvlength(v));+}++static inline cpVect+cpvnormalize_safe(const cpVect v)+{+	return (v.x == 0.0f && v.y == 0.0f ? cpvzero : cpvnormalize(v));+}++static inline cpVect+cpvclamp(const cpVect v, const cpFloat len)+{+	return (cpvdot(v,v) > len*len) ? cpvmult(cpvnormalize(v), len) : v;+}++static inline cpVect+cpvlerpconst(cpVect v1, cpVect v2, cpFloat d)+{+	return cpvadd(v1, cpvclamp(cpvsub(v2, v1), d));+}++static inline cpFloat+cpvdist(const cpVect v1, const cpVect v2)+{+	return cpvlength(cpvsub(v1, v2));+}++static inline cpFloat+cpvdistsq(const cpVect v1, const cpVect v2)+{+	return cpvlengthsq(cpvsub(v1, v2));+}++static inline int+cpvnear(const cpVect v1, const cpVect v2, const cpFloat dist)+{+	return cpvdistsq(v1, v2) < dist*dist;+}
+ chipmunk-r402/src/chipmunk.c view
@@ -0,0 +1,101 @@+/* Copyright (c) 2007 Scott Lembcke+ * + * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ * + * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+ * SOFTWARE.+ */+ +#include <stdlib.h>+#include <stdio.h>++#include "chipmunk.h"++#ifdef __cplusplus+extern "C" {+#endif+	void cpInitCollisionFuncs(void);+#ifdef __cplusplus+}+#endif++void+cpAbort(char *message, char *condition, char *file, int line)+{+	fprintf(stderr,+		"Aborting due to Chipmunk error: %s\n"+		"\tFailed condition: %s\n"+		"\tSource:%s:%d\n",+		message, condition, file, line+	);+	+	abort();+}+++char *cpVersionString = "5.x.x";++void+cpInitChipmunk(void)+{+#ifndef NDEBUG+	printf("Initializing Chipmunk v%s (Debug Enabled)\n", cpVersionString);+	printf("Compile with NDEBUG defined to disable debug mode and runtime assertion checks\n");+#endif+	+	cpInitCollisionFuncs();+}++cpFloat+cpMomentForCircle(cpFloat m, cpFloat r1, cpFloat r2, cpVect offset)+{+	return (1.0f/2.0f)*m*(r1*r1 + r2*r2) + m*cpvdot(offset, offset);+}++cpFloat+cpMomentForSegment(cpFloat m, cpVect a, cpVect b)+{+	cpFloat length = cpvlength(cpvsub(b, a));+	cpVect offset = cpvmult(cpvadd(a, b), 1.0f/2.0f);+	+	return m*length*length/12.0f + m*cpvdot(offset, offset);+}++cpFloat+cpMomentForPoly(cpFloat m, const int numVerts, cpVect *verts, cpVect offset)+{+	cpVect *tVerts = (cpVect *)cpcalloc(numVerts, sizeof(cpVect));+	for(int i=0; i<numVerts; i++)+		tVerts[i] = cpvadd(verts[i], offset);+	+	cpFloat sum1 = 0.0f;+	cpFloat sum2 = 0.0f;+	for(int i=0; i<numVerts; i++){+		cpVect v1 = tVerts[i];+		cpVect v2 = tVerts[(i+1)%numVerts];+		+		cpFloat a = cpvcross(v2, v1);+		cpFloat b = cpvdot(v1, v1) + cpvdot(v1, v2) + cpvdot(v2, v2);+		+		sum1 += a*b;+		sum2 += a;+	}+	+	cpfree(tVerts);+	return (m*sum1)/(6.0f*sum2);+}++#include "chipmunk_ffi.h"
+ chipmunk-r402/src/constraints/cpConstraint.c view
@@ -0,0 +1,54 @@+/* Copyright (c) 2007 Scott Lembcke+ * + * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ * + * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+ * SOFTWARE.+ */++#include <stdlib.h>++#include "chipmunk.h"+#include "constraints/util.h"++// TODO: Comment me!++cpFloat cp_constraint_bias_coef = 0.1f;++void cpConstraintDestroy(cpConstraint *constraint){}++void+cpConstraintFree(cpConstraint *constraint)+{+	if(constraint){+		cpConstraintDestroy(constraint);+		cpfree(constraint);+	}+}++// *** defined in util.h++void+cpConstraintInit(cpConstraint *constraint, const cpConstraintClass *klass, cpBody *a, cpBody *b)+{+	constraint->klass = klass;+	constraint->a = a;+	constraint->b = b;+	+	constraint->maxForce = (cpFloat)INFINITY;+	constraint->biasCoef = cp_constraint_bias_coef;+	constraint->maxBias = (cpFloat)INFINITY;+}
+ chipmunk-r402/src/constraints/cpDampedRotarySpring.c view
@@ -0,0 +1,106 @@+/* Copyright (c) 2007 Scott Lembcke+ * + * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ * + * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+ * SOFTWARE.+ */++#include <stdlib.h>+#include <math.h>++#include "chipmunk.h"+#include "constraints/util.h"++static cpFloat+defaultSpringTorque(cpDampedRotarySpring *spring, cpFloat relativeAngle){+	return (relativeAngle - spring->restAngle)*spring->stiffness;+}++static void+preStep(cpDampedRotarySpring *spring, cpFloat dt, cpFloat dt_inv)+{+	cpBody *a = spring->constraint.a;+	cpBody *b = spring->constraint.b;+	+	spring->iSum = 1.0f/(a->i_inv + b->i_inv);++	spring->dt = dt;+	spring->target_wrn = 0.0f;++	// apply spring torque+	cpFloat j_spring = spring->springTorqueFunc((cpConstraint *)spring, a->a - b->a)*dt;+	a->w -= j_spring*a->i_inv;+	b->w += j_spring*b->i_inv;+}++static void+applyImpulse(cpDampedRotarySpring *spring)+{+	cpBody *a = spring->constraint.a;+	cpBody *b = spring->constraint.b;+	+	// compute relative velocity+	cpFloat wrn = a->w - b->w;//normal_relative_velocity(a, b, r1, r2, n) - spring->target_vrn;+	+	// compute velocity loss from drag+	// not 100% certain this is derived correctly, though it makes sense+	cpFloat w_damp = wrn*(1.0f - cpfexp(-spring->damping*spring->dt/spring->iSum));+	spring->target_wrn = wrn - w_damp;+	+	//apply_impulses(a, b, spring->r1, spring->r2, cpvmult(spring->n, v_damp*spring->nMass));+	cpFloat j_damp = w_damp*spring->iSum;+	a->w -= j_damp*a->i_inv;+	b->w += j_damp*b->i_inv;+}++static cpFloat+getImpulse(cpConstraint *constraint)+{+	return 0.0f;+}++static const cpConstraintClass klass = {+	(cpConstraintPreStepFunction)preStep,+	(cpConstraintApplyImpulseFunction)applyImpulse,+	(cpConstraintGetImpulseFunction)getImpulse,+};+CP_DefineClassGetter(cpDampedRotarySpring)++cpDampedRotarySpring *+cpDampedRotarySpringAlloc(void)+{+	return (cpDampedRotarySpring *)cpmalloc(sizeof(cpDampedRotarySpring));+}++cpDampedRotarySpring *+cpDampedRotarySpringInit(cpDampedRotarySpring *spring, cpBody *a, cpBody *b, cpFloat restAngle, cpFloat stiffness, cpFloat damping)+{+	cpConstraintInit((cpConstraint *)spring, &klass, a, b);+	+	spring->restAngle = restAngle;+	spring->stiffness = stiffness;+	spring->damping = damping;+	spring->springTorqueFunc = (cpDampedRotarySpringTorqueFunc)defaultSpringTorque;+	+	return spring;+}++cpConstraint *+cpDampedRotarySpringNew(cpBody *a, cpBody *b, cpFloat restAngle, cpFloat stiffness, cpFloat damping)+{+	return (cpConstraint *)cpDampedRotarySpringInit(cpDampedRotarySpringAlloc(), a, b, restAngle, stiffness, damping);+}
+ chipmunk-r402/src/constraints/cpDampedSpring.c view
@@ -0,0 +1,117 @@+/* Copyright (c) 2007 Scott Lembcke+ * + * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ * + * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+ * SOFTWARE.+ */++#include <stdlib.h>+#include <math.h>++#include "chipmunk.h"+#include "constraints/util.h"++static cpFloat+defaultSpringForce(cpDampedSpring *spring, cpFloat dist){+	return (spring->restLength - dist)*spring->stiffness;+}++static void+preStep(cpDampedSpring *spring, cpFloat dt, cpFloat dt_inv)+{+	cpBody *a = spring->constraint.a;+	cpBody *b = spring->constraint.b;+	+	spring->r1 = cpvrotate(spring->anchr1, a->rot);+	spring->r2 = cpvrotate(spring->anchr2, b->rot);+	+	cpVect delta = cpvsub(cpvadd(b->p, spring->r2), cpvadd(a->p, spring->r1));+	cpFloat dist = cpvlength(delta);+	spring->n = cpvmult(delta, 1.0f/(dist ? dist : INFINITY));+	+	// calculate mass normal+	spring->nMass = 1.0f/k_scalar(a, b, spring->r1, spring->r2, spring->n);++	spring->dt = dt;+	spring->target_vrn = 0.0f;++	// apply spring force+	cpFloat f_spring = spring->springForceFunc((cpConstraint *)spring, dist);+	apply_impulses(a, b, spring->r1, spring->r2, cpvmult(spring->n, f_spring*dt));+}++static void+applyImpulse(cpDampedSpring *spring)+{+	cpBody *a = spring->constraint.a;+	cpBody *b = spring->constraint.b;+	+	cpVect n = spring->n;+	cpVect r1 = spring->r1;+	cpVect r2 = spring->r2;++	// compute relative velocity+	cpFloat vrn = normal_relative_velocity(a, b, r1, r2, n) - spring->target_vrn;+	+	// compute velocity loss from drag+	// not 100% certain this is derived correctly, though it makes sense+	cpFloat v_damp = -vrn*(1.0f - cpfexp(-spring->damping*spring->dt/spring->nMass));+	spring->target_vrn = vrn + v_damp;+	+	apply_impulses(a, b, spring->r1, spring->r2, cpvmult(spring->n, v_damp*spring->nMass));+}++static cpFloat+getImpulse(cpConstraint *constraint)+{+	return 0.0f;+}++static const cpConstraintClass klass = {+	(cpConstraintPreStepFunction)preStep,+	(cpConstraintApplyImpulseFunction)applyImpulse,+	(cpConstraintGetImpulseFunction)getImpulse,+};+CP_DefineClassGetter(cpDampedSpring)++cpDampedSpring *+cpDampedSpringAlloc(void)+{+	return (cpDampedSpring *)cpmalloc(sizeof(cpDampedSpring));+}++cpDampedSpring *+cpDampedSpringInit(cpDampedSpring *spring, cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat restLength, cpFloat stiffness, cpFloat damping)+{+	cpConstraintInit((cpConstraint *)spring, cpDampedSpringGetClass(), a, b);+	+	spring->anchr1 = anchr1;+	spring->anchr2 = anchr2;+	+	spring->restLength = restLength;+	spring->stiffness = stiffness;+	spring->damping = damping;+	spring->springForceFunc = (cpDampedSpringForceFunc)defaultSpringForce;+	+	return spring;+}++cpConstraint *+cpDampedSpringNew(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat restLength, cpFloat stiffness, cpFloat damping)+{+	return (cpConstraint *)cpDampedSpringInit(cpDampedSpringAlloc(), a, b, anchr1, anchr2, restLength, stiffness, damping);+}
+ chipmunk-r402/src/constraints/cpGearJoint.c view
@@ -0,0 +1,114 @@+/* Copyright (c) 2007 Scott Lembcke+ * + * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ * + * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+ * SOFTWARE.+ */++#include <stdlib.h>++#include "chipmunk.h"+#include "constraints/util.h"++static void+preStep(cpGearJoint *joint, cpFloat dt, cpFloat dt_inv)+{+	cpBody *a = joint->constraint.a;+	cpBody *b = joint->constraint.b;+	+	// calculate moment of inertia coefficient.+	joint->iSum = 1.0f/(a->i_inv*joint->ratio_inv + joint->ratio*b->i_inv);+	+	// calculate bias velocity+	cpFloat maxBias = joint->constraint.maxBias;+	joint->bias = cpfclamp(-joint->constraint.biasCoef*dt_inv*(b->a*joint->ratio - a->a - joint->phase), -maxBias, maxBias);+	+	// compute max impulse+	joint->jMax = J_MAX(joint, dt);++	// apply joint torque+	cpFloat j = joint->jAcc;+	a->w -= j*a->i_inv*joint->ratio_inv;+	b->w += j*b->i_inv;+}++static void+applyImpulse(cpGearJoint *joint)+{+	cpBody *a = joint->constraint.a;+	cpBody *b = joint->constraint.b;+	+	// compute relative rotational velocity+	cpFloat wr = b->w*joint->ratio - a->w;+	+	// compute normal impulse	+	cpFloat j = (joint->bias - wr)*joint->iSum;+	cpFloat jOld = joint->jAcc;+	joint->jAcc = cpfclamp(jOld + j, -joint->jMax, joint->jMax);+	j = joint->jAcc - jOld;+	+	// apply impulse+	a->w -= j*a->i_inv*joint->ratio_inv;+	b->w += j*b->i_inv;+}++static cpFloat+getImpulse(cpGearJoint *joint)+{+	return cpfabs(joint->jAcc);+}++static const cpConstraintClass klass = {+	(cpConstraintPreStepFunction)preStep,+	(cpConstraintApplyImpulseFunction)applyImpulse,+	(cpConstraintGetImpulseFunction)getImpulse,+};+CP_DefineClassGetter(cpGearJoint)++cpGearJoint *+cpGearJointAlloc(void)+{+	return (cpGearJoint *)cpmalloc(sizeof(cpGearJoint));+}++cpGearJoint *+cpGearJointInit(cpGearJoint *joint, cpBody *a, cpBody *b, cpFloat phase, cpFloat ratio)+{+	cpConstraintInit((cpConstraint *)joint, &klass, a, b);+	+	joint->phase = phase;+	joint->ratio = ratio;+	joint->ratio_inv = 1.0f/ratio;+	+	joint->jAcc = 0.0f;+	+	return joint;+}++cpConstraint *+cpGearJointNew(cpBody *a, cpBody *b, cpFloat phase, cpFloat ratio)+{+	return (cpConstraint *)cpGearJointInit(cpGearJointAlloc(), a, b, phase, ratio);+}++void+cpGearJointSetRatio(cpConstraint *constraint, cpFloat value)+{+	cpConstraintCheckCast(constraint, cpGearJoint);+	((cpGearJoint *)constraint)->ratio = value;+	((cpGearJoint *)constraint)->ratio_inv = 1.0f/value;+}
+ chipmunk-r402/src/constraints/cpGrooveJoint.c view
@@ -0,0 +1,138 @@+/* Copyright (c) 2007 Scott Lembcke+ * + * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ * + * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+ * SOFTWARE.+ */++#include <stdlib.h>++#include "chipmunk.h"+#include "constraints/util.h"++static void+preStep(cpGrooveJoint *joint, cpFloat dt, cpFloat dt_inv)+{+	cpBody *a = joint->constraint.a;+	cpBody *b = joint->constraint.b;+	+	// calculate endpoints in worldspace+	cpVect ta = cpBodyLocal2World(a, joint->grv_a);+	cpVect tb = cpBodyLocal2World(a, joint->grv_b);++	// calculate axis+	cpVect n = cpvrotate(joint->grv_n, a->rot);+	cpFloat d = cpvdot(ta, n);+	+	joint->grv_tn = n;+	joint->r2 = cpvrotate(joint->anchr2, b->rot);+	+	// calculate tangential distance along the axis of r2+	cpFloat td = cpvcross(cpvadd(b->p, joint->r2), n);+	// calculate clamping factor and r2+	if(td <= cpvcross(ta, n)){+		joint->clamp = 1.0f;+		joint->r1 = cpvsub(ta, a->p);+	} else if(td >= cpvcross(tb, n)){+		joint->clamp = -1.0f;+		joint->r1 = cpvsub(tb, a->p);+	} else {+		joint->clamp = 0.0f;+		joint->r1 = cpvsub(cpvadd(cpvmult(cpvperp(n), -td), cpvmult(n, d)), a->p);+	}+	+	// Calculate mass tensor+	k_tensor(a, b, joint->r1, joint->r2, &joint->k1, &joint->k2);	+	+	// compute max impulse+	joint->jMaxLen = J_MAX(joint, dt);+	+	// calculate bias velocity+	cpVect delta = cpvsub(cpvadd(b->p, joint->r2), cpvadd(a->p, joint->r1));+	joint->bias = cpvclamp(cpvmult(delta, -joint->constraint.biasCoef*dt_inv), joint->constraint.maxBias);+	+	// apply accumulated impulse+	apply_impulses(a, b, joint->r1, joint->r2, joint->jAcc);+}++static inline cpVect+grooveConstrain(cpGrooveJoint *joint, cpVect j){+	cpVect n = joint->grv_tn;+	cpVect jClamp = (joint->clamp*cpvcross(j, n) > 0.0f) ? j : cpvproject(j, n);+	return cpvclamp(jClamp, joint->jMaxLen);+}++static void+applyImpulse(cpGrooveJoint *joint)+{+	cpBody *a = joint->constraint.a;+	cpBody *b = joint->constraint.b;+	+	cpVect r1 = joint->r1;+	cpVect r2 = joint->r2;+	+	// compute impulse+	cpVect vr = relative_velocity(a, b, r1, r2);++	cpVect j = mult_k(cpvsub(joint->bias, vr), joint->k1, joint->k2);+	cpVect jOld = joint->jAcc;+	joint->jAcc = grooveConstrain(joint, cpvadd(jOld, j));+	j = cpvsub(joint->jAcc, jOld);+	+	// apply impulse+	apply_impulses(a, b, joint->r1, joint->r2, j);+}++static cpFloat+getImpulse(cpGrooveJoint *joint)+{+	return cpvlength(joint->jAcc);+}++static const cpConstraintClass klass = {+	(cpConstraintPreStepFunction)preStep,+	(cpConstraintApplyImpulseFunction)applyImpulse,+	(cpConstraintGetImpulseFunction)getImpulse,+};+CP_DefineClassGetter(cpGrooveJoint)++cpGrooveJoint *+cpGrooveJointAlloc(void)+{+	return (cpGrooveJoint *)cpmalloc(sizeof(cpGrooveJoint));+}++cpGrooveJoint *+cpGrooveJointInit(cpGrooveJoint *joint, cpBody *a, cpBody *b, cpVect groove_a, cpVect groove_b, cpVect anchr2)+{+	cpConstraintInit((cpConstraint *)joint, &klass, a, b);+	+	joint->grv_a = groove_a;+	joint->grv_b = groove_b;+	joint->grv_n = cpvperp(cpvnormalize(cpvsub(groove_b, groove_a)));+	joint->anchr2 = anchr2;+	+	joint->jAcc = cpvzero;+	+	return joint;+}++cpConstraint *+cpGrooveJointNew(cpBody *a, cpBody *b, cpVect groove_a, cpVect groove_b, cpVect anchr2)+{+	return (cpConstraint *)cpGrooveJointInit(cpGrooveJointAlloc(), a, b, groove_a, groove_b, anchr2);+}
+ chipmunk-r402/src/constraints/cpPinJoint.c view
@@ -0,0 +1,117 @@+/* Copyright (c) 2007 Scott Lembcke+ * + * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ * + * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+ * SOFTWARE.+ */++#include <stdlib.h>+//#include <math.h>++#include "chipmunk.h"+#include "constraints/util.h"++static void+preStep(cpPinJoint *joint, cpFloat dt, cpFloat dt_inv)+{+	cpBody *a = joint->constraint.a;+	cpBody *b = joint->constraint.b;+	+	joint->r1 = cpvrotate(joint->anchr1, a->rot);+	joint->r2 = cpvrotate(joint->anchr2, b->rot);+	+	cpVect delta = cpvsub(cpvadd(b->p, joint->r2), cpvadd(a->p, joint->r1));+	cpFloat dist = cpvlength(delta);+	joint->n = cpvmult(delta, 1.0f/(dist ? dist : (cpFloat)INFINITY));+	+	// calculate mass normal+	joint->nMass = 1.0f/k_scalar(a, b, joint->r1, joint->r2, joint->n);+	+	// calculate bias velocity+	cpFloat maxBias = joint->constraint.maxBias;+	joint->bias = cpfclamp(-joint->constraint.biasCoef*dt_inv*(dist - joint->dist), -maxBias, maxBias);+	+	// compute max impulse+	joint->jnMax = J_MAX(joint, dt);+	+	// apply accumulated impulse+	cpVect j = cpvmult(joint->n, joint->jnAcc);+	apply_impulses(a, b, joint->r1, joint->r2, j);+}++static void+applyImpulse(cpPinJoint *joint)+{+	cpBody *a = joint->constraint.a;+	cpBody *b = joint->constraint.b;+	cpVect n = joint->n;++	// compute relative velocity+	cpFloat vrn = normal_relative_velocity(a, b, joint->r1, joint->r2, n);+	+	// compute normal impulse+	cpFloat jn = (joint->bias - vrn)*joint->nMass;+	cpFloat jnOld = joint->jnAcc;+	joint->jnAcc = cpfclamp(jnOld + jn, -joint->jnMax, joint->jnMax);+	jn = joint->jnAcc - jnOld;+	+	// apply impulse+	apply_impulses(a, b, joint->r1, joint->r2, cpvmult(n, jn));+}++static cpFloat+getImpulse(cpPinJoint *joint)+{+	return cpfabs(joint->jnAcc);+}++static const cpConstraintClass klass = {+	(cpConstraintPreStepFunction)preStep,+	(cpConstraintApplyImpulseFunction)applyImpulse,+	(cpConstraintGetImpulseFunction)getImpulse,+};+CP_DefineClassGetter(cpPinJoint);+++cpPinJoint *+cpPinJointAlloc(void)+{+	return (cpPinJoint *)cpmalloc(sizeof(cpPinJoint));+}++cpPinJoint *+cpPinJointInit(cpPinJoint *joint, cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2)+{+	cpConstraintInit((cpConstraint *)joint, &klass, a, b);+	+	joint->anchr1 = anchr1;+	joint->anchr2 = anchr2;+	+	cpVect p1 = cpvadd(a->p, cpvrotate(anchr1, a->rot));+	cpVect p2 = cpvadd(b->p, cpvrotate(anchr2, b->rot));+	joint->dist = cpvlength(cpvsub(p2, p1));++	joint->jnAcc = 0.0f;+	+	return joint;+}++cpConstraint *+cpPinJointNew(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2)+{+	return (cpConstraint *)cpPinJointInit(cpPinJointAlloc(), a, b, anchr1, anchr2);+}
+ chipmunk-r402/src/constraints/cpPivotJoint.c view
@@ -0,0 +1,114 @@+/* Copyright (c) 2007 Scott Lembcke+ * + * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ * + * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+ * SOFTWARE.+ */++#include <stdlib.h>++#include "chipmunk.h"+#include "constraints/util.h"++static void+preStep(cpPivotJoint *joint, cpFloat dt, cpFloat dt_inv)+{+	cpBody *a = joint->constraint.a;+	cpBody *b = joint->constraint.b;+	+	joint->r1 = cpvrotate(joint->anchr1, a->rot);+	joint->r2 = cpvrotate(joint->anchr2, b->rot);+	+	// Calculate mass tensor+	k_tensor(a, b, joint->r1, joint->r2, &joint->k1, &joint->k2);+	+	// compute max impulse+	joint->jMaxLen = J_MAX(joint, dt);+	+	// calculate bias velocity+	cpVect delta = cpvsub(cpvadd(b->p, joint->r2), cpvadd(a->p, joint->r1));+	joint->bias = cpvclamp(cpvmult(delta, -joint->constraint.biasCoef*dt_inv), joint->constraint.maxBias);+	+	// apply accumulated impulse+	apply_impulses(a, b, joint->r1, joint->r2, joint->jAcc);+}++static void+applyImpulse(cpPivotJoint *joint)+{+	cpBody *a = joint->constraint.a;+	cpBody *b = joint->constraint.b;+	+	cpVect r1 = joint->r1;+	cpVect r2 = joint->r2;+		+	// compute relative velocity+	cpVect vr = relative_velocity(a, b, r1, r2);+	+	// compute normal impulse+	cpVect j = mult_k(cpvsub(joint->bias, vr), joint->k1, joint->k2);+	cpVect jOld = joint->jAcc;+	joint->jAcc = cpvclamp(cpvadd(joint->jAcc, j), joint->jMaxLen);+	j = cpvsub(joint->jAcc, jOld);+	+	// apply impulse+	apply_impulses(a, b, joint->r1, joint->r2, j);+}++static cpFloat+getImpulse(cpConstraint *joint)+{+	return cpvlength(((cpPivotJoint *)joint)->jAcc);+}++static const cpConstraintClass klass = {+	(cpConstraintPreStepFunction)preStep,+	(cpConstraintApplyImpulseFunction)applyImpulse,+	(cpConstraintGetImpulseFunction)getImpulse,+};+CP_DefineClassGetter(cpPivotJoint)++cpPivotJoint *+cpPivotJointAlloc(void)+{+	return (cpPivotJoint *)cpmalloc(sizeof(cpPivotJoint));+}++cpPivotJoint *+cpPivotJointInit(cpPivotJoint *joint, cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2)+{+	cpConstraintInit((cpConstraint *)joint, &klass, a, b);+	+	joint->anchr1 = anchr1;+	joint->anchr2 = anchr2;+	+	joint->jAcc = cpvzero;+	+	return joint;+}++cpConstraint *+cpPivotJointNew2(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2)+{+	return (cpConstraint *)cpPivotJointInit(cpPivotJointAlloc(), a, b, anchr1, anchr2);+}++cpConstraint *+cpPivotJointNew(cpBody *a, cpBody *b, cpVect pivot)+{+	return cpPivotJointNew2(a, b, cpBodyWorld2Local(a, pivot), cpBodyWorld2Local(b, pivot));+}
+ chipmunk-r402/src/constraints/cpRatchetJoint.c view
@@ -0,0 +1,128 @@+/* Copyright (c) 2007 Scott Lembcke+ * + * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ * + * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+ * SOFTWARE.+ */++#include <stdio.h>+#include <stdlib.h>+#include <math.h>++#include "chipmunk.h"+#include "constraints/util.h"++static void+preStep(cpRatchetJoint *joint, cpFloat dt, cpFloat dt_inv)+{+	cpBody *a = joint->constraint.a;+	cpBody *b = joint->constraint.b;+	+	cpFloat angle = joint->angle;+	cpFloat phase = joint->phase;+	cpFloat ratchet = joint->ratchet;+	+	cpFloat delta = b->a - a->a;+	cpFloat diff = angle - delta;+	cpFloat pdist = 0.0f;+	+	if(diff*ratchet > 0.0f){+		pdist = diff;+	} else {+		joint->angle = cpffloor((delta - phase)/ratchet)*ratchet + phase;+	}+	+	// calculate moment of inertia coefficient.+	joint->iSum = 1.0f/(a->i_inv + b->i_inv);+	+	// calculate bias velocity+	cpFloat maxBias = joint->constraint.maxBias;+	joint->bias = cpfclamp(-joint->constraint.biasCoef*dt_inv*pdist, -maxBias, maxBias);+	+	// compute max impulse+	joint->jMax = J_MAX(joint, dt);++	// If the bias is 0, the joint is not at a limit. Reset the impulse.+	if(!joint->bias)+		joint->jAcc = 0.0f;++	// apply joint torque+	a->w -= joint->jAcc*a->i_inv;+	b->w += joint->jAcc*b->i_inv;+}++static void+applyImpulse(cpRatchetJoint *joint)+{+	if(!joint->bias) return; // early exit++	cpBody *a = joint->constraint.a;+	cpBody *b = joint->constraint.b;+	+	// compute relative rotational velocity+	cpFloat wr = b->w - a->w;+	cpFloat ratchet = joint->ratchet;+	+	// compute normal impulse	+	cpFloat j = -(joint->bias + wr)*joint->iSum;+	cpFloat jOld = joint->jAcc;+	joint->jAcc = cpfclamp((jOld + j)*ratchet, 0.0f, joint->jMax*cpfabs(ratchet))/ratchet;+	j = joint->jAcc - jOld;+	+	// apply impulse+	a->w -= j*a->i_inv;+	b->w += j*b->i_inv;+}++static cpFloat+getImpulse(cpRatchetJoint *joint)+{+	return cpfabs(joint->jAcc);+}++static const cpConstraintClass klass = {+	(cpConstraintPreStepFunction)preStep,+	(cpConstraintApplyImpulseFunction)applyImpulse,+	(cpConstraintGetImpulseFunction)getImpulse,+};+CP_DefineClassGetter(cpRatchetJoint)++cpRatchetJoint *+cpRatchetJointAlloc(void)+{+	return (cpRatchetJoint *)cpmalloc(sizeof(cpRatchetJoint));+}++cpRatchetJoint *+cpRatchetJointInit(cpRatchetJoint *joint, cpBody *a, cpBody *b, cpFloat phase, cpFloat ratchet)+{+	cpConstraintInit((cpConstraint *)joint, &klass, a, b);+	+	joint->angle = 0.0f;+	joint->phase = phase;+	joint->ratchet = ratchet;+	+	joint->angle = b->a - a->a;+	+	return joint;+}++cpConstraint *+cpRatchetJointNew(cpBody *a, cpBody *b, cpFloat phase, cpFloat ratchet)+{+	return (cpConstraint *)cpRatchetJointInit(cpRatchetJointAlloc(), a, b, phase, ratchet);+}
+ chipmunk-r402/src/constraints/cpRotaryLimitJoint.c view
@@ -0,0 +1,122 @@+/* Copyright (c) 2007 Scott Lembcke+ * + * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ * + * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+ * SOFTWARE.+ */++#include <stdlib.h>++#include "chipmunk.h"+#include "constraints/util.h"++static void+preStep(cpRotaryLimitJoint *joint, cpFloat dt, cpFloat dt_inv)+{+	cpBody *a = joint->constraint.a;+	cpBody *b = joint->constraint.b;+	+	cpFloat dist = b->a - a->a;+	cpFloat pdist = 0.0f;+	if(dist > joint->max) {+		pdist = joint->max - dist;+	} else if(dist < joint->min) {+		pdist = joint->min - dist;+	}+	+	// calculate moment of inertia coefficient.+	joint->iSum = 1.0f/(a->i_inv + b->i_inv);+	+	// calculate bias velocity+	cpFloat maxBias = joint->constraint.maxBias;+	joint->bias = cpfclamp(-joint->constraint.biasCoef*dt_inv*(pdist), -maxBias, maxBias);+	+	// compute max impulse+	joint->jMax = J_MAX(joint, dt);++	// If the bias is 0, the joint is not at a limit. Reset the impulse.+	if(!joint->bias)+		joint->jAcc = 0.0f;++	// apply joint torque+	a->w -= joint->jAcc*a->i_inv;+	b->w += joint->jAcc*b->i_inv;+}++static void+applyImpulse(cpRotaryLimitJoint *joint)+{+	if(!joint->bias) return; // early exit++	cpBody *a = joint->constraint.a;+	cpBody *b = joint->constraint.b;+	+	// compute relative rotational velocity+	cpFloat wr = b->w - a->w;+	+	// compute normal impulse	+	cpFloat j = -(joint->bias + wr)*joint->iSum;+	cpFloat jOld = joint->jAcc;+	if(joint->bias < 0.0f){+		joint->jAcc = cpfclamp(jOld + j, 0.0f, joint->jMax);+	} else {+		joint->jAcc = cpfclamp(jOld + j, -joint->jMax, 0.0f);+	}+	j = joint->jAcc - jOld;+	+	// apply impulse+	a->w -= j*a->i_inv;+	b->w += j*b->i_inv;+}++static cpFloat+getImpulse(cpRotaryLimitJoint *joint)+{+	return cpfabs(joint->jAcc);+}++static const cpConstraintClass klass = {+	(cpConstraintPreStepFunction)preStep,+	(cpConstraintApplyImpulseFunction)applyImpulse,+	(cpConstraintGetImpulseFunction)getImpulse,+};+CP_DefineClassGetter(cpRotaryLimitJoint)++cpRotaryLimitJoint *+cpRotaryLimitJointAlloc(void)+{+	return (cpRotaryLimitJoint *)cpmalloc(sizeof(cpRotaryLimitJoint));+}++cpRotaryLimitJoint *+cpRotaryLimitJointInit(cpRotaryLimitJoint *joint, cpBody *a, cpBody *b, cpFloat min, cpFloat max)+{+	cpConstraintInit((cpConstraint *)joint, &klass, a, b);+	+	joint->min = min;+	joint->max  = max;+	+	joint->jAcc = 0.0f;+	+	return joint;+}++cpConstraint *+cpRotaryLimitJointNew(cpBody *a, cpBody *b, cpFloat min, cpFloat max)+{+	return (cpConstraint *)cpRotaryLimitJointInit(cpRotaryLimitJointAlloc(), a, b, min, max);+}
+ chipmunk-r402/src/constraints/cpSimpleMotor.c view
@@ -0,0 +1,99 @@+/* Copyright (c) 2007 Scott Lembcke+ * + * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ * + * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+ * SOFTWARE.+ */++#include <stdlib.h>++#include "chipmunk.h"+#include "constraints/util.h"++static void+preStep(cpSimpleMotor *joint, cpFloat dt, cpFloat dt_inv)+{+	cpBody *a = joint->constraint.a;+	cpBody *b = joint->constraint.b;+	+	// calculate moment of inertia coefficient.+	joint->iSum = 1.0f/(a->i_inv + b->i_inv);+	+	// compute max impulse+	joint->jMax = J_MAX(joint, dt);++	// apply joint torque+	a->w -= joint->jAcc*a->i_inv;+	b->w += joint->jAcc*b->i_inv;+}++static void+applyImpulse(cpSimpleMotor *joint)+{+	cpBody *a = joint->constraint.a;+	cpBody *b = joint->constraint.b;+	+	// compute relative rotational velocity+	cpFloat wr = b->w - a->w + joint->rate;+	+	// compute normal impulse	+	cpFloat j = -wr*joint->iSum;+	cpFloat jOld = joint->jAcc;+	joint->jAcc = cpfclamp(jOld + j, -joint->jMax, joint->jMax);+	j = joint->jAcc - jOld;+	+	// apply impulse+	a->w -= j*a->i_inv;+	b->w += j*b->i_inv;+}++static cpFloat+getImpulse(cpSimpleMotor *joint)+{+	return cpfabs(joint->jAcc);+}++static const cpConstraintClass klass = {+	(cpConstraintPreStepFunction)preStep,+	(cpConstraintApplyImpulseFunction)applyImpulse,+	(cpConstraintGetImpulseFunction)getImpulse,+};+CP_DefineClassGetter(cpSimpleMotor)++cpSimpleMotor *+cpSimpleMotorAlloc(void)+{+	return (cpSimpleMotor *)cpmalloc(sizeof(cpSimpleMotor));+}++cpSimpleMotor *+cpSimpleMotorInit(cpSimpleMotor *joint, cpBody *a, cpBody *b, cpFloat rate)+{+	cpConstraintInit((cpConstraint *)joint, &klass, a, b);+	+	joint->rate = rate;+	+	joint->jAcc = 0.0f;+	+	return joint;+}++cpConstraint *+cpSimpleMotorNew(cpBody *a, cpBody *b, cpFloat rate)+{+	return (cpConstraint *)cpSimpleMotorInit(cpSimpleMotorAlloc(), a, b, rate);+}
+ chipmunk-r402/src/constraints/cpSlideJoint.c view
@@ -0,0 +1,131 @@+/* Copyright (c) 2007 Scott Lembcke+ * + * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ * + * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+ * SOFTWARE.+ */++#include <stdlib.h>++#include "chipmunk.h"+#include "constraints/util.h"++static void+preStep(cpSlideJoint *joint, cpFloat dt, cpFloat dt_inv)+{+	cpBody *a = joint->constraint.a;+	cpBody *b = joint->constraint.b;+	+	joint->r1 = cpvrotate(joint->anchr1, a->rot);+	joint->r2 = cpvrotate(joint->anchr2, b->rot);+	+	cpVect delta = cpvsub(cpvadd(b->p, joint->r2), cpvadd(a->p, joint->r1));+	cpFloat dist = cpvlength(delta);+	cpFloat pdist = 0.0f;+	if(dist > joint->max) {+		pdist = dist - joint->max;+	} else if(dist < joint->min) {+		pdist = joint->min - dist;+		dist = -dist;+	}+	joint->n = cpvmult(delta, 1.0f/(dist ? dist : (cpFloat)INFINITY));+	+	// calculate mass normal+	joint->nMass = 1.0f/k_scalar(a, b, joint->r1, joint->r2, joint->n);+	+	// calculate bias velocity+	cpFloat maxBias = joint->constraint.maxBias;+	joint->bias = cpfclamp(-joint->constraint.biasCoef*dt_inv*(pdist), -maxBias, maxBias);+	+	// compute max impulse+	joint->jnMax = J_MAX(joint, dt);++	// apply accumulated impulse+	if(!joint->bias) //{+		// if bias is 0, then the joint is not at a limit.+		joint->jnAcc = 0.0f;+//	} else {+		cpVect j = cpvmult(joint->n, joint->jnAcc);+		apply_impulses(a, b, joint->r1, joint->r2, j);+//	}+}++static void+applyImpulse(cpSlideJoint *joint)+{+	if(!joint->bias) return;  // early exit++	cpBody *a = joint->constraint.a;+	cpBody *b = joint->constraint.b;+	+	cpVect n = joint->n;+	cpVect r1 = joint->r1;+	cpVect r2 = joint->r2;+		+	// compute relative velocity+	cpVect vr = relative_velocity(a, b, r1, r2);+	cpFloat vrn = cpvdot(vr, n);+	+	// compute normal impulse+	cpFloat jn = (joint->bias - vrn)*joint->nMass;+	cpFloat jnOld = joint->jnAcc;+	joint->jnAcc = cpfclamp(jnOld + jn, -joint->jnMax, 0.0f);+	jn = joint->jnAcc - jnOld;+	+	// apply impulse+	apply_impulses(a, b, joint->r1, joint->r2, cpvmult(n, jn));+}++static cpFloat+getImpulse(cpConstraint *joint)+{+	return cpfabs(((cpSlideJoint *)joint)->jnAcc);+}++static const cpConstraintClass klass = {+	(cpConstraintPreStepFunction)preStep,+	(cpConstraintApplyImpulseFunction)applyImpulse,+	(cpConstraintGetImpulseFunction)getImpulse,+};+CP_DefineClassGetter(cpSlideJoint)++cpSlideJoint *+cpSlideJointAlloc(void)+{+	return (cpSlideJoint *)cpmalloc(sizeof(cpSlideJoint));+}++cpSlideJoint *+cpSlideJointInit(cpSlideJoint *joint, cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat min, cpFloat max)+{+	cpConstraintInit((cpConstraint *)joint, &klass, a, b);+	+	joint->anchr1 = anchr1;+	joint->anchr2 = anchr2;+	joint->min = min;+	joint->max = max;+	+	joint->jnAcc = 0.0f;+	+	return joint;+}++cpConstraint *+cpSlideJointNew(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat min, cpFloat max)+{+	return (cpConstraint *)cpSlideJointInit(cpSlideJointAlloc(), a, b, anchr1, anchr2, min, max);+}
+ chipmunk-r402/src/cpArbiter.c view
@@ -0,0 +1,274 @@+/* Copyright (c) 2007 Scott Lembcke+ * + * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ * + * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+ * SOFTWARE.+ */+ +#include <stdlib.h>++#include "chipmunk.h"+#include "constraints/util.h"++cpFloat cp_bias_coef = 0.1f;+cpFloat cp_collision_slop = 0.1f;++cpContact*+cpContactInit(cpContact *con, cpVect p, cpVect n, cpFloat dist, cpHashValue hash)+{+	con->p = p;+	con->n = n;+	con->dist = dist;+	+	con->jnAcc = 0.0f;+	con->jtAcc = 0.0f;+	con->jBias = 0.0f;+	+	con->hash = hash;+		+	return con;+}++cpVect+cpArbiterTotalImpulse(cpArbiter *arb)+{+	cpContact *contacts = arb->contacts;+	cpVect sum = cpvzero;+	+	for(int i=0, count=arb->numContacts; i<count; i++){+		cpContact *con = &contacts[i];+		sum = cpvadd(sum, cpvmult(con->n, con->jnAcc));+	}+		+	return sum;+}++cpVect+cpArbiterTotalImpulseWithFriction(cpArbiter *arb)+{+	cpContact *contacts = arb->contacts;+	cpVect sum = cpvzero;+	+	for(int i=0, count=arb->numContacts; i<count; i++){+		cpContact *con = &contacts[i];+		sum = cpvadd(sum, cpvrotate(con->n, cpv(con->jnAcc, con->jtAcc)));+	}+		+	return sum;+}++cpFloat+cpContactsEstimateCrushingImpulse(cpContact *contacts, int numContacts)+{+	cpFloat fsum = 0.0f;+	cpVect vsum = cpvzero;+	+	for(int i=0; i<numContacts; i++){+		cpContact *con = &contacts[i];+		cpVect j = cpvrotate(con->n, cpv(con->jnAcc, con->jtAcc));+		+		fsum += cpvlength(j);+		vsum = cpvadd(vsum, j);+	}+	+	cpFloat vmag = cpvlength(vsum);+	return (1.0f - vmag/fsum);+}++void+cpArbiterIgnore(cpArbiter *arb)+{+	arb->state = cpArbiterStateIgnore;+}++cpArbiter*+cpArbiterAlloc(void)+{+	return (cpArbiter *)cpcalloc(1, sizeof(cpArbiter));+}++cpArbiter*+cpArbiterInit(cpArbiter *arb, cpShape *a, cpShape *b)+{+	arb->numContacts = 0;+	arb->contacts = NULL;+	+	arb->private_a = a;+	arb->private_b = b;+	+	arb->stamp = -1;+	arb->state = cpArbiterStateFirstColl;+	+	return arb;+}++cpArbiter*+cpArbiterNew(cpShape *a, cpShape *b)+{+	return cpArbiterInit(cpArbiterAlloc(), a, b);+}++void+cpArbiterDestroy(cpArbiter *arb)+{+//	if(arb->contacts) cpfree(arb->contacts);+}++void+cpArbiterFree(cpArbiter *arb)+{+	if(arb){+		cpArbiterDestroy(arb);+		cpfree(arb);+	}+}++void+cpArbiterUpdate(cpArbiter *arb, cpContact *contacts, int numContacts, cpCollisionHandler *handler, cpShape *a, cpShape *b)+{+	// Arbiters without contact data may exist if a collision function rejected the collision.+	if(arb->contacts){+		// Iterate over the possible pairs to look for hash value matches.+		for(int i=0; i<arb->numContacts; i++){+			cpContact *old = &arb->contacts[i];+			+			for(int j=0; j<numContacts; j++){+				cpContact *new_contact = &contacts[j];+				+				// This could trigger false positives, but is fairly unlikely nor serious if it does.+				if(new_contact->hash == old->hash){+					// Copy the persistant contact information.+					new_contact->jnAcc = old->jnAcc;+					new_contact->jtAcc = old->jtAcc;+				}+			}+		}++//		cpfree(arb->contacts);+	}+	+	arb->contacts = contacts;+	arb->numContacts = numContacts;+	+	arb->handler = handler;+	arb->swappedColl = (a->collision_type != handler->a);+	+	arb->e = a->e * b->e;+	arb->u = a->u * b->u;+	arb->surface_vr = cpvsub(a->surface_v, b->surface_v);+	+	// For collisions between two similar primitive types, the order could have been swapped.+	arb->private_a = a; arb->private_b = b;+}++void+cpArbiterPreStep(cpArbiter *arb, cpFloat dt_inv)+{+	cpShape *shapea = arb->private_a;+	cpShape *shapeb = arb->private_b;++	cpBody *a = shapea->body;+	cpBody *b = shapeb->body;+	+	for(int i=0; i<arb->numContacts; i++){+		cpContact *con = &arb->contacts[i];+		+		// Calculate the offsets.+		con->r1 = cpvsub(con->p, a->p);+		con->r2 = cpvsub(con->p, b->p);+		+		// Calculate the mass normal and mass tangent.+		con->nMass = 1.0f/k_scalar(a, b, con->r1, con->r2, con->n);+		con->tMass = 1.0f/k_scalar(a, b, con->r1, con->r2, cpvperp(con->n));+				+		// Calculate the target bias velocity.+		con->bias = -cp_bias_coef*dt_inv*cpfmin(0.0f, con->dist + cp_collision_slop);+		con->jBias = 0.0f;+		+		// Calculate the target bounce velocity.+		con->bounce = normal_relative_velocity(a, b, con->r1, con->r2, con->n)*arb->e;//cpvdot(con->n, cpvsub(v2, v1))*e;+	}+}++void+cpArbiterApplyCachedImpulse(cpArbiter *arb)+{+	cpShape *shapea = arb->private_a;+	cpShape *shapeb = arb->private_b;+		+	arb->u = shapea->u * shapeb->u;+	arb->surface_vr = cpvsub(shapeb->surface_v, shapea->surface_v);++	cpBody *a = shapea->body;+	cpBody *b = shapeb->body;+	+	for(int i=0; i<arb->numContacts; i++){+		cpContact *con = &arb->contacts[i];+		apply_impulses(a, b, con->r1, con->r2, cpvrotate(con->n, cpv(con->jnAcc, con->jtAcc)));+	}+}++void+cpArbiterApplyImpulse(cpArbiter *arb, cpFloat eCoef)+{+	cpBody *a = arb->private_a->body;+	cpBody *b = arb->private_b->body;++	for(int i=0; i<arb->numContacts; i++){+		cpContact *con = &arb->contacts[i];+		cpVect n = con->n;+		cpVect r1 = con->r1;+		cpVect r2 = con->r2;+		+		// Calculate the relative bias velocities.+		cpVect vb1 = cpvadd(a->v_bias, cpvmult(cpvperp(r1), a->w_bias));+		cpVect vb2 = cpvadd(b->v_bias, cpvmult(cpvperp(r2), b->w_bias));+		cpFloat vbn = cpvdot(cpvsub(vb2, vb1), n);+		+		// Calculate and clamp the bias impulse.+		cpFloat jbn = (con->bias - vbn)*con->nMass;+		cpFloat jbnOld = con->jBias;+		con->jBias = cpfmax(jbnOld + jbn, 0.0f);+		jbn = con->jBias - jbnOld;+		+		// Apply the bias impulse.+		apply_bias_impulses(a, b, r1, r2, cpvmult(n, jbn));++		// Calculate the relative velocity.+		cpVect vr = relative_velocity(a, b, r1, r2);+		cpFloat vrn = cpvdot(vr, n);+		+		// Calculate and clamp the normal impulse.+		cpFloat jn = -(con->bounce*eCoef + vrn)*con->nMass;+		cpFloat jnOld = con->jnAcc;+		con->jnAcc = cpfmax(jnOld + jn, 0.0f);+		jn = con->jnAcc - jnOld;+		+		// Calculate the relative tangent velocity.+		cpFloat vrt = cpvdot(cpvadd(vr, arb->surface_vr), cpvperp(n));+		+		// Calculate and clamp the friction impulse.+		cpFloat jtMax = arb->u*con->jnAcc;+		cpFloat jt = -vrt*con->tMass;+		cpFloat jtOld = con->jtAcc;+		con->jtAcc = cpfclamp(jtOld + jt, -jtMax, jtMax);+		jt = con->jtAcc - jtOld;+		+		// Apply the final impulse.+		apply_impulses(a, b, r1, r2, cpvrotate(n, cpv(jn, jt)));+	}+}
+ chipmunk-r402/src/cpArray.c view
@@ -0,0 +1,128 @@+/* Copyright (c) 2007 Scott Lembcke+ * + * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ * + * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+ * SOFTWARE.+ */+ +#include <stdlib.h>+#include <string.h>++#include "chipmunk.h"+++//#define CP_ARRAY_INCREMENT 10++// NOTE: cpArray is rarely used and will probably go away.++cpArray*+cpArrayAlloc(void)+{+	return (cpArray *)cpcalloc(1, sizeof(cpArray));+}++cpArray*+cpArrayInit(cpArray *arr, int size)+{+	arr->num = 0;+	+	size = (size ? size : 4);+	arr->max = size;+	arr->arr = (void **)cpmalloc(size*sizeof(void**));+	+	return arr;+}++cpArray*+cpArrayNew(int size)+{+	return cpArrayInit(cpArrayAlloc(), size);+}++void+cpArrayDestroy(cpArray *arr)+{+	cpfree(arr->arr);+}++void+cpArrayFree(cpArray *arr)+{+	if(arr){+		cpArrayDestroy(arr);+		cpfree(arr);+	}+}++void+cpArrayPush(cpArray *arr, void *object)+{+	if(arr->num == arr->max){+		arr->max *= 2;+		arr->arr = (void **)cprealloc(arr->arr, arr->max*sizeof(void**));+	}+	+	arr->arr[arr->num] = object;+	arr->num++;+}++void *+cpArrayPop(cpArray *arr)+{+	arr->num--;+	+	void *value = arr->arr[arr->num];+	arr->arr[arr->num] = NULL;+	+	return value;+}++void+cpArrayDeleteIndex(cpArray *arr, int idx)+{+	arr->num--;+	+	arr->arr[idx] = arr->arr[arr->num];+	arr->arr[arr->num] = NULL;+}++void+cpArrayDeleteObj(cpArray *arr, void *obj)+{+	for(int i=0; i<arr->num; i++){+		if(arr->arr[i] == obj){+			cpArrayDeleteIndex(arr, i);+			return;+		}+	}+}++void+cpArrayEach(cpArray *arr, cpArrayIter iterFunc, void *data)+{+	for(int i=0; i<arr->num; i++)+		iterFunc(arr->arr[i], data);+}++int+cpArrayContains(cpArray *arr, void *ptr)+{+	for(int i=0; i<arr->num; i++)+		if(arr->arr[i] == ptr) return 1;+	+	return 0;+}
+ chipmunk-r402/src/cpBB.c view
@@ -0,0 +1,47 @@+/* Copyright (c) 2007 Scott Lembcke+ * + * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ * + * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+ * SOFTWARE.+ */+ +#include <math.h>+#include <stdlib.h>++#include "chipmunk.h"++cpVect+cpBBClampVect(const cpBB bb, const cpVect v)+{+	cpFloat x = cpfmin(cpfmax(bb.l, v.x), bb.r);+	cpFloat y = cpfmin(cpfmax(bb.b, v.y), bb.t);+	return cpv(x, y);+}++cpVect+cpBBWrapVect(const cpBB bb, const cpVect v)+{+	cpFloat ix = cpfabs(bb.r - bb.l);+	cpFloat modx = cpfmod(v.x - bb.l, ix);+	cpFloat x = (modx > 0.0f) ? modx : modx + ix;+	+	cpFloat iy = cpfabs(bb.t - bb.b);+	cpFloat mody = cpfmod(v.y - bb.b, iy);+	cpFloat y = (mody > 0.0f) ? mody : mody + iy;+	+	return cpv(x + bb.l, y + bb.b);+}
+ chipmunk-r402/src/cpBody.c view
@@ -0,0 +1,188 @@+/* Copyright (c) 2007 Scott Lembcke+ * + * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ * + * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+ * SOFTWARE.+ */+ +#include <stdlib.h>+#include <float.h>++#include "chipmunk.h"++cpBody*+cpBodyAlloc(void)+{+	return (cpBody *)cpmalloc(sizeof(cpBody));+}++cpBodyVelocityFunc cpBodyUpdateVelocityDefault = cpBodyUpdateVelocity;+cpBodyPositionFunc cpBodyUpdatePositionDefault = cpBodyUpdatePosition;++cpBody*+cpBodyInit(cpBody *body, cpFloat m, cpFloat i)+{+	body->velocity_func = cpBodyUpdateVelocityDefault;+	body->position_func = cpBodyUpdatePositionDefault;+	+	cpBodySetMass(body, m);+	cpBodySetMoment(body, i);++	body->p = cpvzero;+	body->v = cpvzero;+	body->f = cpvzero;+	+	cpBodySetAngle(body, 0.0f);+	body->w = 0.0f;+	body->t = 0.0f;+	+	body->v_bias = cpvzero;+	body->w_bias = 0.0f;+	+	body->data = NULL;+	body->v_limit = (cpFloat)INFINITY;+	body->w_limit = (cpFloat)INFINITY;+//	body->active = 1;++	return body;+}++cpBody*+cpBodyNew(cpFloat m, cpFloat i)+{+	return cpBodyInit(cpBodyAlloc(), m, i);+}++void cpBodyDestroy(cpBody *body){}++void+cpBodyFree(cpBody *body)+{+	if(body){+		cpBodyDestroy(body);+		cpfree(body);+	}+}++void+cpBodySetMass(cpBody *body, cpFloat mass)+{+	body->m = mass;+	body->m_inv = 1.0f/mass;+}++void+cpBodySetMoment(cpBody *body, cpFloat moment)+{+	body->i = moment;+	body->i_inv = 1.0f/moment;+}++void+cpBodySetAngle(cpBody *body, cpFloat angle)+{+	body->a = angle;//fmod(a, (cpFloat)M_PI*2.0f);+	body->rot = cpvforangle(angle);+}++void+cpBodySlew(cpBody *body, cpVect pos, cpFloat dt)+{+	cpVect delta = cpvsub(pos, body->p);+	body->v = cpvmult(delta, 1.0f/dt);+}++void+cpBodyUpdateVelocity(cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt)+{+	body->v = cpvclamp(cpvadd(cpvmult(body->v, damping), cpvmult(cpvadd(gravity, cpvmult(body->f, body->m_inv)), dt)), body->v_limit);+	+	cpFloat w_limit = body->w_limit;+	body->w = cpfclamp(body->w*damping + body->t*body->i_inv*dt, -w_limit, w_limit);+}++void+cpBodyUpdatePosition(cpBody *body, cpFloat dt)+{+	body->p = cpvadd(body->p, cpvmult(cpvadd(body->v, body->v_bias), dt));+	cpBodySetAngle(body, body->a + (body->w + body->w_bias)*dt);+	+	body->v_bias = cpvzero;+	body->w_bias = 0.0f;+}++void+cpBodyResetForces(cpBody *body)+{+	body->f = cpvzero;+	body->t = 0.0f;+}++void+cpBodyApplyForce(cpBody *body, cpVect force, cpVect r)+{+	body->f = cpvadd(body->f, force);+	body->t += cpvcross(r, force);+}++void+cpApplyDampedSpring(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat rlen, cpFloat k, cpFloat dmp, cpFloat dt)+{+	// Calculate the world space anchor coordinates.+	cpVect r1 = cpvrotate(anchr1, a->rot);+	cpVect r2 = cpvrotate(anchr2, b->rot);+	+	cpVect delta = cpvsub(cpvadd(b->p, r2), cpvadd(a->p, r1));+	cpFloat dist = cpvlength(delta);+	cpVect n = dist ? cpvmult(delta, 1.0f/dist) : cpvzero;+	+	cpFloat f_spring = (dist - rlen)*k;++	// Calculate the world relative velocities of the anchor points.+	cpVect v1 = cpvadd(a->v, cpvmult(cpvperp(r1), a->w));+	cpVect v2 = cpvadd(b->v, cpvmult(cpvperp(r2), b->w));+	+	// Calculate the damping force.+	// This really should be in the impulse solver and can produce problems when using large damping values.+	cpFloat vrn = cpvdot(cpvsub(v2, v1), n);+	cpFloat f_damp = vrn*cpfmin(dmp, 1.0f/(dt*(a->m_inv + b->m_inv)));+	+	// Apply!+	cpVect f = cpvmult(n, f_spring + f_damp);+	cpBodyApplyForce(a, f, r1);+	cpBodyApplyForce(b, cpvneg(f), r2);+}++//int+//cpBodyMarkLowEnergy(cpBody *body, cpFloat dvsq, int max)+//{+//	cpFloat ke = body->m*cpvdot(body->v, body->v);+//	cpFloat re = body->i*body->w*body->w;+//	+//	if(ke + re > body->m*dvsq)+//		body->active = 1;+//	else if(body->active)+//		body->active = (body->active + 1)%(max + 1);+//	else {+//		body->v = cpvzero;+//		body->v_bias = cpvzero;+//		body->w = 0.0f;+//		body->w_bias = 0.0f;+//	}+//	+//	return body->active;+//}
+ chipmunk-r402/src/cpCollision.c view
@@ -0,0 +1,391 @@+/* Copyright (c) 2007 Scott Lembcke+ * + * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ * + * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+ * SOFTWARE.+ */+ +#include <stdlib.h>+#include <math.h>+#include <stdio.h>++#include "chipmunk.h"++typedef int (*collisionFunc)(cpShape *, cpShape *, cpContact *);++// Add contact points for circle to circle collisions.+// Used by several collision tests.+static int+circle2circleQuery(cpVect p1, cpVect p2, cpFloat r1, cpFloat r2, cpContact *con)+{+	cpFloat mindist = r1 + r2;+	cpVect delta = cpvsub(p2, p1);+	cpFloat distsq = cpvlengthsq(delta);+	if(distsq >= mindist*mindist) return 0;+	+	cpFloat dist = cpfsqrt(distsq);+	// To avoid singularities, do nothing in the case of dist = 0.+	cpFloat non_zero_dist = (dist ? dist : INFINITY);++	// Allocate and initialize the contact.+	cpContactInit(+		con,+		cpvadd(p1, cpvmult(delta, 0.5f + (r1 - 0.5f*mindist)/non_zero_dist)),+		cpvmult(delta, 1.0f/non_zero_dist),+		dist - mindist,+		0+	);+	+	return 1;+}++// Collide circle shapes.+static int+circle2circle(cpShape *shape1, cpShape *shape2, cpContact *arr)+{+	cpCircleShape *circ1 = (cpCircleShape *)shape1;+	cpCircleShape *circ2 = (cpCircleShape *)shape2;+	+	return circle2circleQuery(circ1->tc, circ2->tc, circ1->r, circ2->r, arr);+}++// Collide circles to segment shapes.+static int+circle2segment(cpShape *circleShape, cpShape *segmentShape, cpContact *con)+{+	cpCircleShape *circ = (cpCircleShape *)circleShape;+	cpSegmentShape *seg = (cpSegmentShape *)segmentShape;+	+	// Radius sum+	cpFloat rsum = circ->r + seg->r;+	+	// Calculate normal distance from segment.+	cpFloat dn = cpvdot(seg->tn, circ->tc) - cpvdot(seg->ta, seg->tn);+	cpFloat dist = cpfabs(dn) - rsum;+	if(dist > 0.0f) return 0;+	+	// Calculate tangential distance along segment.+	cpFloat dt = -cpvcross(seg->tn, circ->tc);+	cpFloat dtMin = -cpvcross(seg->tn, seg->ta);+	cpFloat dtMax = -cpvcross(seg->tn, seg->tb);+	+	// Decision tree to decide which feature of the segment to collide with.+	if(dt < dtMin){+		if(dt < (dtMin - rsum)){+			return 0;+		} else {+			return circle2circleQuery(circ->tc, seg->ta, circ->r, seg->r, con);+		}+	} else {+		if(dt < dtMax){+			cpVect n = (dn < 0.0f) ? seg->tn : cpvneg(seg->tn);+			cpContactInit(+				con,+				cpvadd(circ->tc, cpvmult(n, circ->r + dist*0.5f)),+				n,+				dist,+				0				 +			);+			return 1;+		} else {+			if(dt < (dtMax + rsum)) {+				return circle2circleQuery(circ->tc, seg->tb, circ->r, seg->r, con);+			} else {+				return 0;+			}+		}+	}+	+	return 1;+}++// Helper function for working with contact buffers+// This used to malloc/realloc memory on the fly but was repurposed.+static cpContact *+nextContactPoint(cpContact *arr, int *numPtr)+{+	int num = *numPtr;+	+	if(num <= CP_MAX_CONTACTS_PER_ARBITER)+		(*numPtr) = num + 1;+	+	return &arr[num];+}++// Find the minimum separating axis for the give poly and axis list.+static inline int+findMSA(cpPolyShape *poly, cpPolyShapeAxis *axes, int num, cpFloat *min_out)+{+	int min_index = 0;+	cpFloat min = cpPolyShapeValueOnAxis(poly, axes->n, axes->d);+	if(min > 0.0f) return -1;+	+	for(int i=1; i<num; i++){+		cpFloat dist = cpPolyShapeValueOnAxis(poly, axes[i].n, axes[i].d);+		if(dist > 0.0f) {+			return -1;+		} else if(dist > min){+			min = dist;+			min_index = i;+		}+	}+	+	(*min_out) = min;+	return min_index;+}++// Add contacts for penetrating vertexes.+static inline int+findVerts(cpContact *arr, cpPolyShape *poly1, cpPolyShape *poly2, cpVect n, cpFloat dist)+{+	int num = 0;+	+	for(int i=0; i<poly1->numVerts; i++){+		cpVect v = poly1->tVerts[i];+		if(cpPolyShapeContainsVertPartial(poly2, v, cpvneg(n)))+			cpContactInit(nextContactPoint(arr, &num), v, n, dist, CP_HASH_PAIR(poly1->shape.hashid, i));+	}+	+	for(int i=0; i<poly2->numVerts; i++){+		cpVect v = poly2->tVerts[i];+		if(cpPolyShapeContainsVertPartial(poly1, v, n))+			cpContactInit(nextContactPoint(arr, &num), v, n, dist, CP_HASH_PAIR(poly2->shape.hashid, i));+	}+	+	//	if(!num)+	//		addContactPoint(arr, &size, &num, cpContactNew(shape1->body->p, n, dist, 0));++	return num;+}++// Collide poly shapes together.+static int+poly2poly(cpShape *shape1, cpShape *shape2, cpContact *arr)+{+	cpPolyShape *poly1 = (cpPolyShape *)shape1;+	cpPolyShape *poly2 = (cpPolyShape *)shape2;+	+	cpFloat min1;+	int mini1 = findMSA(poly2, poly1->tAxes, poly1->numVerts, &min1);+	if(mini1 == -1) return 0;+	+	cpFloat min2;+	int mini2 = findMSA(poly1, poly2->tAxes, poly2->numVerts, &min2);+	if(mini2 == -1) return 0;+	+	// There is overlap, find the penetrating verts+	if(min1 > min2)+		return findVerts(arr, poly1, poly2, poly1->tAxes[mini1].n, min1);+	else+		return findVerts(arr, poly1, poly2, cpvneg(poly2->tAxes[mini2].n), min2);+}++// Like cpPolyValueOnAxis(), but for segments.+static inline cpFloat+segValueOnAxis(cpSegmentShape *seg, cpVect n, cpFloat d)+{+	cpFloat a = cpvdot(n, seg->ta) - seg->r;+	cpFloat b = cpvdot(n, seg->tb) - seg->r;+	return cpfmin(a, b) - d;+}++// Identify vertexes that have penetrated the segment.+static inline void+findPointsBehindSeg(cpContact *arr, int *num, cpSegmentShape *seg, cpPolyShape *poly, cpFloat pDist, cpFloat coef) +{+	cpFloat dta = cpvcross(seg->tn, seg->ta);+	cpFloat dtb = cpvcross(seg->tn, seg->tb);+	cpVect n = cpvmult(seg->tn, coef);+	+	for(int i=0; i<poly->numVerts; i++){+		cpVect v = poly->tVerts[i];+		if(cpvdot(v, n) < cpvdot(seg->tn, seg->ta)*coef + seg->r){+			cpFloat dt = cpvcross(seg->tn, v);+			if(dta >= dt && dt >= dtb){+				cpContactInit(nextContactPoint(arr, num), v, n, pDist, CP_HASH_PAIR(poly->shape.hashid, i));+			}+		}+	}+}++// This one is complicated and gross. Just don't go there...+// TODO: Comment me!+static int+seg2poly(cpShape *shape1, cpShape *shape2, cpContact *arr)+{+	cpSegmentShape *seg = (cpSegmentShape *)shape1;+	cpPolyShape *poly = (cpPolyShape *)shape2;+	cpPolyShapeAxis *axes = poly->tAxes;+	+	cpFloat segD = cpvdot(seg->tn, seg->ta);+	cpFloat minNorm = cpPolyShapeValueOnAxis(poly, seg->tn, segD) - seg->r;+	cpFloat minNeg = cpPolyShapeValueOnAxis(poly, cpvneg(seg->tn), -segD) - seg->r;+	if(minNeg > 0.0f || minNorm > 0.0f) return 0;+	+	int mini = 0;+	cpFloat poly_min = segValueOnAxis(seg, axes->n, axes->d);+	if(poly_min > 0.0f) return 0;+	for(int i=0; i<poly->numVerts; i++){+		cpFloat dist = segValueOnAxis(seg, axes[i].n, axes[i].d);+		if(dist > 0.0f){+			return 0;+		} else if(dist > poly_min){+			poly_min = dist;+			mini = i;+		}+	}+	+	int num = 0;+	+	cpVect poly_n = cpvneg(axes[mini].n);+	+	cpVect va = cpvadd(seg->ta, cpvmult(poly_n, seg->r));+	cpVect vb = cpvadd(seg->tb, cpvmult(poly_n, seg->r));+	if(cpPolyShapeContainsVert(poly, va))+		cpContactInit(nextContactPoint(arr, &num), va, poly_n, poly_min, CP_HASH_PAIR(seg->shape.hashid, 0));+	if(cpPolyShapeContainsVert(poly, vb))+		cpContactInit(nextContactPoint(arr, &num), vb, poly_n, poly_min, CP_HASH_PAIR(seg->shape.hashid, 1));++	// Floating point precision problems here.+	// This will have to do for now.+	poly_min -= cp_collision_slop;+	if(minNorm >= poly_min || minNeg >= poly_min) {+		if(minNorm > minNeg)+			findPointsBehindSeg(arr, &num, seg, poly, minNorm, 1.0f);+		else+			findPointsBehindSeg(arr, &num, seg, poly, minNeg, -1.0f);+	}+	+	// If no other collision points are found, try colliding endpoints.+	if(num == 0){+		cpVect poly_a = poly->tVerts[mini];+		cpVect poly_b = poly->tVerts[(mini + 1)%poly->numVerts];+		+		if(circle2circleQuery(seg->ta, poly_a, seg->r, 0.0f, arr))+			return 1;+			+		if(circle2circleQuery(seg->tb, poly_a, seg->r, 0.0f, arr))+			return 1;+			+		if(circle2circleQuery(seg->ta, poly_b, seg->r, 0.0f, arr))+			return 1;+			+		if(circle2circleQuery(seg->tb, poly_b, seg->r, 0.0f, arr))+			return 1;+	}++	return num;+}++// This one is less gross, but still gross.+// TODO: Comment me!+static int+circle2poly(cpShape *shape1, cpShape *shape2, cpContact *con)+{+	cpCircleShape *circ = (cpCircleShape *)shape1;+	cpPolyShape *poly = (cpPolyShape *)shape2;+	cpPolyShapeAxis *axes = poly->tAxes;+	+	int mini = 0;+	cpFloat min = cpvdot(axes->n, circ->tc) - axes->d - circ->r;+	for(int i=0; i<poly->numVerts; i++){+		cpFloat dist = cpvdot(axes[i].n, circ->tc) - axes[i].d - circ->r;+		if(dist > 0.0f){+			return 0;+		} else if(dist > min) {+			min = dist;+			mini = i;+		}+	}+	+	cpVect n = axes[mini].n;+	cpVect a = poly->tVerts[mini];+	cpVect b = poly->tVerts[(mini + 1)%poly->numVerts];+	cpFloat dta = cpvcross(n, a);+	cpFloat dtb = cpvcross(n, b);+	cpFloat dt = cpvcross(n, circ->tc);+		+	if(dt < dtb){+		return circle2circleQuery(circ->tc, b, circ->r, 0.0f, con);+	} else if(dt < dta) {+		cpContactInit(+			con,+			cpvsub(circ->tc, cpvmult(n, circ->r + min/2.0f)),+			cpvneg(n),+			min,+			0				 +		);+	+		return 1;+	} else {+		return circle2circleQuery(circ->tc, a, circ->r, 0.0f, con);+	}+}++//static const collisionFunc builtinCollisionFuncs[9] = {+//	circle2circle,+//	NULL,+//	NULL,+//	circle2segment,+//	NULL,+//	NULL,+//	circle2poly,+//	seg2poly,+//	poly2poly,+//};+//static const collisionFunc *colfuncs = builtinCollisionFuncs;++static collisionFunc *colfuncs = NULL;++static void+addColFunc(cpShapeType a, cpShapeType b, collisionFunc func)+{+	colfuncs[a + b*CP_NUM_SHAPES] = func;+}++#ifdef __cplusplus+extern "C" {+#endif+	void cpInitCollisionFuncs(void);+	+	// Initializes the array of collision functions.+	// Called by cpInitChipmunk().+	void+	cpInitCollisionFuncs(void)+	{+		if(!colfuncs)+			colfuncs = (collisionFunc *)cpcalloc(CP_NUM_SHAPES*CP_NUM_SHAPES, sizeof(collisionFunc));+		+		addColFunc(CP_CIRCLE_SHAPE,  CP_CIRCLE_SHAPE,  circle2circle);+		addColFunc(CP_CIRCLE_SHAPE,  CP_SEGMENT_SHAPE, circle2segment);+		addColFunc(CP_SEGMENT_SHAPE, CP_POLY_SHAPE,    seg2poly);+		addColFunc(CP_CIRCLE_SHAPE,  CP_POLY_SHAPE,    circle2poly);+		addColFunc(CP_POLY_SHAPE,    CP_POLY_SHAPE,    poly2poly);+	}	+#ifdef __cplusplus+}+#endif++int+cpCollideShapes(cpShape *a, cpShape *b, cpContact *arr)+{+	// Their shape types must be in order.+	cpAssert(a->klass->type <= b->klass->type, "Collision shapes passed to cpCollideShapes() are not sorted.");+	+	collisionFunc cfunc = colfuncs[a->klass->type + b->klass->type*CP_NUM_SHAPES];+	return (cfunc) ? cfunc(a, b, arr) : 0;+}
+ chipmunk-r402/src/cpHashSet.c view
@@ -0,0 +1,253 @@+/* Copyright (c) 2007 Scott Lembcke+ * + * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ * + * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+ * SOFTWARE.+ */+ +#include <stdlib.h>+#include <assert.h>++#include "chipmunk.h"+#include "prime.h"++static void freeWrap(void *ptr, void *unused){cpfree(ptr);}++void+cpHashSetDestroy(cpHashSet *set)+{+	// Free the table.+	cpfree(set->table);+	+	cpArrayEach(set->allocatedBuffers, freeWrap, NULL);+	cpArrayFree(set->allocatedBuffers);+}++void+cpHashSetFree(cpHashSet *set)+{+	if(set){+		cpHashSetDestroy(set);+		cpfree(set);+	}+}++cpHashSet *+cpHashSetAlloc(void)+{+	return (cpHashSet *)cpcalloc(1, sizeof(cpHashSet));+}++cpHashSet *+cpHashSetInit(cpHashSet *set, int size, cpHashSetEqlFunc eqlFunc, cpHashSetTransFunc trans)+{+	set->size = next_prime(size);+	set->entries = 0;+	+	set->eql = eqlFunc;+	set->trans = trans;+	+	set->default_value = NULL;+	+	set->table = (cpHashSetBin **)cpcalloc(set->size, sizeof(cpHashSetBin *));+	set->pooledBins = NULL;+	+	set->allocatedBuffers = cpArrayNew(0);+	+	return set;+}++cpHashSet *+cpHashSetNew(int size, cpHashSetEqlFunc eqlFunc, cpHashSetTransFunc trans)+{+	return cpHashSetInit(cpHashSetAlloc(), size, eqlFunc, trans);+}++static int+setIsFull(cpHashSet *set)+{+	return (set->entries >= set->size);+}++static void+cpHashSetResize(cpHashSet *set)+{+	// Get the next approximate doubled prime.+	int newSize = next_prime(set->size + 1);+	// Allocate a new table.+	cpHashSetBin **newTable = (cpHashSetBin **)cpcalloc(newSize, sizeof(cpHashSetBin *));+	+	// Iterate over the chains.+	for(int i=0; i<set->size; i++){+		// Rehash the bins into the new table.+		cpHashSetBin *bin = set->table[i];+		while(bin){+			cpHashSetBin *next = bin->next;+			+			int idx = bin->hash%newSize;+			bin->next = newTable[idx];+			newTable[idx] = bin;+			+			bin = next;+		}+	}+	+	cpfree(set->table);+	+	set->table = newTable;+	set->size = newSize;+}++static inline void+recycleBin(cpHashSet *set, cpHashSetBin *bin)+{+	bin->next = set->pooledBins;+	set->pooledBins = bin;+	bin->elt = NULL;+}++static cpHashSetBin *+getUnusedBin(cpHashSet *set)+{+	cpHashSetBin *bin = set->pooledBins;+	+	if(bin){+		set->pooledBins = bin->next;+		return bin;+	} else {+		// Pool is exhausted, make more+		int count = CP_BUFFER_BYTES/sizeof(cpHashSetBin);+		cpAssert(count, "Buffer size is too small.");+		+		cpHashSetBin *buffer = (cpHashSetBin *)cpmalloc(CP_BUFFER_BYTES);+		cpArrayPush(set->allocatedBuffers, buffer);+		+		// push all but the first one, return the first instead+		for(int i=1; i<count; i++) recycleBin(set, buffer + i);+		return buffer;+	}+}++void *+cpHashSetInsert(cpHashSet *set, cpHashValue hash, void *ptr, void *data)+{+	int idx = hash%set->size;+	+	// Find the bin with the matching element.+	cpHashSetBin *bin = set->table[idx];+	while(bin && !set->eql(ptr, bin->elt))+		bin = bin->next;+	+	// Create it necessary.+	if(!bin){+		bin = getUnusedBin(set);+		bin->hash = hash;+		bin->elt = set->trans(ptr, data); // Transform the pointer.+		+		bin->next = set->table[idx];+		set->table[idx] = bin;+		+		set->entries++;+		+		// Resize the set if it's full.+		if(setIsFull(set))+			cpHashSetResize(set);+	}+	+	return bin->elt;+}++void *+cpHashSetRemove(cpHashSet *set, cpHashValue hash, void *ptr)+{+	int idx = hash%set->size;+	+	// Pointer to the previous bin pointer.+	cpHashSetBin **prev_ptr = &set->table[idx];+	// Pointer the the current bin.+	cpHashSetBin *bin = set->table[idx];+	+	// Find the bin+	while(bin && !set->eql(ptr, bin->elt)){+		prev_ptr = &bin->next;+		bin = bin->next;+	}+	+	// Remove it if it exists.+	if(bin){+		// Update the previous bin pointer to point to the next bin.+		(*prev_ptr) = bin->next;+		set->entries--;+		+		void *return_value = bin->elt;+		+		recycleBin(set, bin);+		+		return return_value;+	}+	+	return NULL;+}++void *+cpHashSetFind(cpHashSet *set, cpHashValue hash, void *ptr)+{	+	int idx = hash%set->size;+	cpHashSetBin *bin = set->table[idx];+	while(bin && !set->eql(ptr, bin->elt))+		bin = bin->next;+		+	return (bin ? bin->elt : set->default_value);+}++void+cpHashSetEach(cpHashSet *set, cpHashSetIterFunc func, void *data)+{+	for(int i=0; i<set->size; i++){+		cpHashSetBin *bin = set->table[i];+		while(bin){+			cpHashSetBin *next = bin->next;+			func(bin->elt, data);+			bin = next;+		}+	}+}++void+cpHashSetFilter(cpHashSet *set, cpHashSetFilterFunc func, void *data)+{+	// Iterate over all the chains.+	for(int i=0; i<set->size; i++){+		// The rest works similarly to cpHashSetRemove() above.+		cpHashSetBin **prev_ptr = &set->table[i];+		cpHashSetBin *bin = set->table[i];+		while(bin){+			cpHashSetBin *next = bin->next;+			+			if(func(bin->elt, data)){+				prev_ptr = &bin->next;+			} else {+				(*prev_ptr) = next;++				set->entries--;+				recycleBin(set, bin);+			}+			+			bin = next;+		}+	}+}
+ chipmunk-r402/src/cpPolyShape.c view
@@ -0,0 +1,219 @@+/* Copyright (c) 2007 Scott Lembcke+ * + * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ * + * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+ * SOFTWARE.+ */+ +#include <stdlib.h>+#include <stdio.h>++#include "chipmunk.h"+#include "chipmunk_unsafe.h"++cpPolyShape *+cpPolyShapeAlloc(void)+{+	return (cpPolyShape *)cpcalloc(1, sizeof(cpPolyShape));+}++static void+cpPolyShapeTransformVerts(cpPolyShape *poly, cpVect p, cpVect rot)+{+	cpVect *src = poly->verts;+	cpVect *dst = poly->tVerts;+	+	for(int i=0; i<poly->numVerts; i++)+		dst[i] = cpvadd(p, cpvrotate(src[i], rot));+}++static void+cpPolyShapeTransformAxes(cpPolyShape *poly, cpVect p, cpVect rot)+{+	cpPolyShapeAxis *src = poly->axes;+	cpPolyShapeAxis *dst = poly->tAxes;+	+	for(int i=0; i<poly->numVerts; i++){+		cpVect n = cpvrotate(src[i].n, rot);+		dst[i].n = n;+		dst[i].d = cpvdot(p, n) + src[i].d;+	}+}++static cpBB+cpPolyShapeCacheData(cpShape *shape, cpVect p, cpVect rot)+{+	cpPolyShape *poly = (cpPolyShape *)shape;+	+	cpFloat l, b, r, t;+	+	cpPolyShapeTransformAxes(poly, p, rot);+	cpPolyShapeTransformVerts(poly, p, rot);+	+	cpVect *verts = poly->tVerts;+	l = r = verts[0].x;+	b = t = verts[0].y;+	+	// TODO do as part of cpPolyShapeTransformVerts?+	for(int i=1; i<poly->numVerts; i++){+		cpVect v = verts[i];+		+		l = cpfmin(l, v.x);+		r = cpfmax(r, v.x);+		+		b = cpfmin(b, v.y);+		t = cpfmax(t, v.y);+	}+	+	return cpBBNew(l, b, r, t);+}++static void+cpPolyShapeDestroy(cpShape *shape)+{+	cpPolyShape *poly = (cpPolyShape *)shape;+	+	cpfree(poly->verts);+	cpfree(poly->tVerts);+	+	cpfree(poly->axes);+	cpfree(poly->tAxes);+}++static int+cpPolyShapePointQuery(cpShape *shape, cpVect p){+	return cpBBcontainsVect(shape->bb, p) && cpPolyShapeContainsVert((cpPolyShape *)shape, p);+}++static void+cpPolyShapeSegmentQuery(cpShape *shape, cpVect a, cpVect b, cpSegmentQueryInfo *info)+{+	cpPolyShape *poly = (cpPolyShape *)shape;+	cpPolyShapeAxis *axes = poly->tAxes;+	cpVect *verts = poly->tVerts;+	int numVerts = poly->numVerts;+	+	for(int i=0; i<numVerts; i++){+		cpVect n = axes[i].n;+		cpFloat an = cpvdot(a, n);+		if(axes[i].d > an) continue;+		+		cpFloat bn = cpvdot(b, n);+		cpFloat t = (axes[i].d - an)/(bn - an);+		if(t < 0.0f || 1.0f < t) continue;+		+		cpVect point = cpvlerp(a, b, t);+		cpFloat dt = -cpvcross(n, point);+		cpFloat dtMin = -cpvcross(n, verts[i]);+		cpFloat dtMax = -cpvcross(n, verts[(i+1)%numVerts]);+		+		if(dtMin <= dt && dt <= dtMax){+			info->shape = shape;+			info->t = t;+			info->n = n;+		}+	}+}++static const cpShapeClass polyClass = {+	CP_POLY_SHAPE,+	cpPolyShapeCacheData,+	cpPolyShapeDestroy,+	cpPolyShapePointQuery,+	cpPolyShapeSegmentQuery,+};++int+cpPolyValidate(cpVect *verts, int numVerts)+{+	for(int i=0; i<numVerts; i++){+		cpVect a = verts[i];+		cpVect b = verts[(i+1)%numVerts];+		cpVect c = verts[(i+2)%numVerts];+		+		if(cpvcross(cpvsub(b, a), cpvsub(c, b)) > 0.0f)+			return 0;+	}+	+	return 1;+}++int+cpPolyShapeGetNumVerts(cpShape *shape)+{+	cpAssert(shape->klass == &polyClass, "Shape is not a poly shape.");+	return ((cpPolyShape *)shape)->numVerts;+}++cpVect+cpPolyShapeGetVert(cpShape *shape, int idx)+{+	cpAssert(shape->klass == &polyClass, "Shape is not a poly shape.");+	cpAssert(0 <= idx && idx < cpPolyShapeGetNumVerts(shape), "Index out of range.");+	+	return ((cpPolyShape *)shape)->verts[idx];+}+++static void+setUpVerts(cpPolyShape *poly, int numVerts, cpVect *verts, cpVect offset)+{+	poly->numVerts = numVerts;++	poly->verts = (cpVect *)cpcalloc(numVerts, sizeof(cpVect));+	poly->tVerts = (cpVect *)cpcalloc(numVerts, sizeof(cpVect));+	poly->axes = (cpPolyShapeAxis *)cpcalloc(numVerts, sizeof(cpPolyShapeAxis));+	poly->tAxes = (cpPolyShapeAxis *)cpcalloc(numVerts, sizeof(cpPolyShapeAxis));+	+	for(int i=0; i<numVerts; i++){+		cpVect a = cpvadd(offset, verts[i]);+		cpVect b = cpvadd(offset, verts[(i+1)%numVerts]);+		cpVect n = cpvnormalize(cpvperp(cpvsub(b, a)));++		poly->verts[i] = a;+		poly->axes[i].n = n;+		poly->axes[i].d = cpvdot(n, a);+	}+}++cpPolyShape *+cpPolyShapeInit(cpPolyShape *poly, cpBody *body, int numVerts, cpVect *verts, cpVect offset)+{+	// Fail if the user attempts to pass a concave poly, or a bad winding.+	cpAssert(cpPolyValidate(verts, numVerts), "Polygon is concave or has a reversed winding.");+	+	setUpVerts(poly, numVerts, verts, offset);+	cpShapeInit((cpShape *)poly, &polyClass, body);++	return poly;+}++cpShape *+cpPolyShapeNew(cpBody *body, int numVerts, cpVect *verts, cpVect offset)+{+	return (cpShape *)cpPolyShapeInit(cpPolyShapeAlloc(), body, numVerts, verts, offset);+}++// Unsafe API (chipmunk_unsafe.h)++void+cpPolyShapeSetVerts(cpShape *shape, int numVerts, cpVect *verts, cpVect offset)+{+	cpAssert(shape->klass == &polyClass, "Shape is not a poly shape.");+	cpPolyShapeDestroy(shape);+	setUpVerts((cpPolyShape *)shape, numVerts, verts, offset);+}
+ chipmunk-r402/src/cpShape.c view
@@ -0,0 +1,400 @@+/* Copyright (c) 2007 Scott Lembcke+ * + * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ * + * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+ * SOFTWARE.+ */+ +#include <stdlib.h>+#include <stdio.h>+#include <math.h>++#include "chipmunk.h"+#include "chipmunk_unsafe.h"++#define CP_DefineShapeGetter(struct, type, member, name) \+CP_DeclareShapeGetter(struct, type, name){ \+	cpAssert(shape->klass == &struct##Class, "shape is not a "#struct); \+	return ((struct *)shape)->member; \+}+cpHashValue SHAPE_ID_COUNTER = 0;++void+cpResetShapeIdCounter(void)+{+	SHAPE_ID_COUNTER = 0;+}+++cpShape*+cpShapeInit(cpShape *shape, const cpShapeClass *klass, cpBody *body)+{+	shape->klass = klass;+	+	shape->hashid = SHAPE_ID_COUNTER;+	SHAPE_ID_COUNTER++;+	+	shape->body = body;+	shape->sensor = 0;+	+	shape->e = 0.0f;+	shape->u = 0.0f;+	shape->surface_v = cpvzero;+	+	shape->collision_type = 0;+	shape->group = CP_NO_GROUP;+	shape->layers = CP_ALL_LAYERS;+	+	shape->data = NULL;+	+	cpShapeCacheBB(shape);+	+	return shape;+}++void+cpShapeDestroy(cpShape *shape)+{+	if(shape->klass->destroy) shape->klass->destroy(shape);+}++void+cpShapeFree(cpShape *shape)+{+	if(shape){+		cpShapeDestroy(shape);+		cpfree(shape);+	}+}++cpBB+cpShapeCacheBB(cpShape *shape)+{+	cpBody *body = shape->body;+	+	shape->bb = shape->klass->cacheData(shape, body->p, body->rot);+	return shape->bb;+}++int+cpShapePointQuery(cpShape *shape, cpVect p){+	return shape->klass->pointQuery(shape, p);+}++int+cpShapeSegmentQuery(cpShape *shape, cpVect a, cpVect b, cpSegmentQueryInfo *info){+	cpSegmentQueryInfo blank = {NULL, 0.0f, cpvzero};+	(*info) = blank;+	+	shape->klass->segmentQuery(shape, a, b, info);+	return (info->shape != NULL);+}++void+cpSegmentQueryInfoPrint(cpSegmentQueryInfo *info)+{+	printf("Segment Query:\n");+	printf("\tt: %f\n", info->t);+//	printf("\tdist: %f\n", info->dist);+//	printf("\tpoint: %s\n", cpvstr(info->point));+	printf("\tn: %s\n", cpvstr(info->n));+}+++++cpCircleShape *+cpCircleShapeAlloc(void)+{+	return (cpCircleShape *)cpcalloc(1, sizeof(cpCircleShape));+}++static inline cpBB+bbFromCircle(const cpVect c, const cpFloat r)+{+	return cpBBNew(c.x-r, c.y-r, c.x+r, c.y+r);+}++static cpBB+cpCircleShapeCacheData(cpShape *shape, cpVect p, cpVect rot)+{+	cpCircleShape *circle = (cpCircleShape *)shape;+	+	circle->tc = cpvadd(p, cpvrotate(circle->c, rot));+	return bbFromCircle(circle->tc, circle->r);+}++static int+cpCircleShapePointQuery(cpShape *shape, cpVect p){+	cpCircleShape *circle = (cpCircleShape *)shape;+	return cpvnear(circle->tc, p, circle->r);+}++static void+circleSegmentQuery(cpShape *shape, cpVect center, cpFloat r, cpVect a, cpVect b, cpSegmentQueryInfo *info)+{+	// umm... gross I normally frown upon such things+	a = cpvsub(a, center);+	b = cpvsub(b, center);+	+	cpFloat qa = cpvdot(a, a) - 2.0f*cpvdot(a, b) + cpvdot(b, b);+	cpFloat qb = -2.0f*cpvdot(a, a) + 2.0f*cpvdot(a, b);+	cpFloat qc = cpvdot(a, a) - r*r;+	+	cpFloat det = qb*qb - 4.0f*qa*qc;+	+	if(det >= 0.0f){+		cpFloat t = (-qb - cpfsqrt(det))/(2.0f*qa);+		if(0.0f<= t && t <= 1.0f){+			info->shape = shape;+			info->t = t;+			info->n = cpvnormalize(cpvlerp(a, b, t));+		}+	}+}++static void+cpCircleShapeSegmentQuery(cpShape *shape, cpVect a, cpVect b, cpSegmentQueryInfo *info)+{+	cpCircleShape *circle = (cpCircleShape *)shape;+	circleSegmentQuery(shape, circle->tc, circle->r, a, b, info);+}++static const cpShapeClass cpCircleShapeClass = {+	CP_CIRCLE_SHAPE,+	cpCircleShapeCacheData,+	NULL,+	cpCircleShapePointQuery,+	cpCircleShapeSegmentQuery,+};++cpCircleShape *+cpCircleShapeInit(cpCircleShape *circle, cpBody *body, cpFloat radius, cpVect offset)+{+	circle->c = offset;+	circle->r = radius;+	+	cpShapeInit((cpShape *)circle, &cpCircleShapeClass, body);+	+	return circle;+}++cpShape *+cpCircleShapeNew(cpBody *body, cpFloat radius, cpVect offset)+{+	return (cpShape *)cpCircleShapeInit(cpCircleShapeAlloc(), body, radius, offset);+}++CP_DefineShapeGetter(cpCircleShape, cpVect, c, Offset)+CP_DefineShapeGetter(cpCircleShape, cpFloat, r, Radius)++cpSegmentShape *+cpSegmentShapeAlloc(void)+{+	return (cpSegmentShape *)cpcalloc(1, sizeof(cpSegmentShape));+}++static cpBB+cpSegmentShapeCacheData(cpShape *shape, cpVect p, cpVect rot)+{+	cpSegmentShape *seg = (cpSegmentShape *)shape;+	+	seg->ta = cpvadd(p, cpvrotate(seg->a, rot));+	seg->tb = cpvadd(p, cpvrotate(seg->b, rot));+	seg->tn = cpvrotate(seg->n, rot);+	+	cpFloat l,r,s,t;+	+	if(seg->ta.x < seg->tb.x){+		l = seg->ta.x;+		r = seg->tb.x;+	} else {+		l = seg->tb.x;+		r = seg->ta.x;+	}+	+	if(seg->ta.y < seg->tb.y){+		s = seg->ta.y;+		t = seg->tb.y;+	} else {+		s = seg->tb.y;+		t = seg->ta.y;+	}+	+	cpFloat rad = seg->r;+	return cpBBNew(l - rad, s - rad, r + rad, t + rad);+}++static int+cpSegmentShapePointQuery(cpShape *shape, cpVect p){+	if(!cpBBcontainsVect(shape->bb, p)) return 0;+	+	cpSegmentShape *seg = (cpSegmentShape *)shape;+	+	// Calculate normal distance from segment.+	cpFloat dn = cpvdot(seg->tn, p) - cpvdot(seg->ta, seg->tn);+	cpFloat dist = cpfabs(dn) - seg->r;+	if(dist > 0.0f) return 0;+	+	// Calculate tangential distance along segment.+	cpFloat dt = -cpvcross(seg->tn, p);+	cpFloat dtMin = -cpvcross(seg->tn, seg->ta);+	cpFloat dtMax = -cpvcross(seg->tn, seg->tb);+	+	// Decision tree to decide which feature of the segment to collide with.+	if(dt <= dtMin){+		if(dt < (dtMin - seg->r)){+			return 0;+		} else {+			return cpvlengthsq(cpvsub(seg->ta, p)) < (seg->r*seg->r);+		}+	} else {+		if(dt < dtMax){+			return 1;+		} else {+			if(dt < (dtMax + seg->r)) {+				return cpvlengthsq(cpvsub(seg->tb, p)) < (seg->r*seg->r);+			} else {+				return 0;+			}+		}+	}+	+	return 1;	+}++static void+cpSegmentShapeSegmentQuery(cpShape *shape, cpVect a, cpVect b, cpSegmentQueryInfo *info)+{+	cpSegmentShape *seg = (cpSegmentShape *)shape;+	cpVect n = seg->tn;+	// flip n if a is behind the axis+	if(cpvdot(a, n) < cpvdot(seg->ta, n))+		n = cpvneg(n);+	+	cpFloat an = cpvdot(a, n);+	cpFloat bn = cpvdot(b, n);+	cpFloat d = cpvdot(seg->ta, n) + seg->r;+	+	cpFloat t = (d - an)/(bn - an);+	if(0.0f < t && t < 1.0f){+		cpVect point = cpvlerp(a, b, t);+		cpFloat dt = -cpvcross(seg->tn, point);+		cpFloat dtMin = -cpvcross(seg->tn, seg->ta);+		cpFloat dtMax = -cpvcross(seg->tn, seg->tb);+		+		if(dtMin < dt && dt < dtMax){+			info->shape = shape;+			info->t = t;+			info->n = n;+			+			return; // don't continue on and check endcaps+		}+	}+	+	if(seg->r) {+		cpSegmentQueryInfo info1; info1.shape = NULL;+		cpSegmentQueryInfo info2; info2.shape = NULL;+		circleSegmentQuery(shape, seg->ta, seg->r, a, b, &info1);+		circleSegmentQuery(shape, seg->tb, seg->r, a, b, &info2);+		+		if(info1.shape && !info2.shape){+			(*info) = info1;+		} else if(info2.shape && !info1.shape){+			(*info) = info2;+		} else if(info1.shape && info2.shape){+			if(info1.t < info2.t){+				(*info) = info1;+			} else {+				(*info) = info2;+			}+		}+	}+}++static const cpShapeClass cpSegmentShapeClass = {+	CP_SEGMENT_SHAPE,+	cpSegmentShapeCacheData,+	NULL,+	cpSegmentShapePointQuery,+	cpSegmentShapeSegmentQuery,+};++cpSegmentShape *+cpSegmentShapeInit(cpSegmentShape *seg, cpBody *body, cpVect a, cpVect b, cpFloat r)+{+	seg->a = a;+	seg->b = b;+	seg->n = cpvperp(cpvnormalize(cpvsub(b, a)));+	+	seg->r = r;+	+	cpShapeInit((cpShape *)seg, &cpSegmentShapeClass, body);+	+	return seg;+}++cpShape*+cpSegmentShapeNew(cpBody *body, cpVect a, cpVect b, cpFloat r)+{+	return (cpShape *)cpSegmentShapeInit(cpSegmentShapeAlloc(), body, a, b, r);+}++CP_DefineShapeGetter(cpSegmentShape, cpVect, a, A)+CP_DefineShapeGetter(cpSegmentShape, cpVect, b, B)+CP_DefineShapeGetter(cpSegmentShape, cpVect, n, Normal)+CP_DefineShapeGetter(cpSegmentShape, cpFloat, r, Radius)++// Unsafe API (chipmunk_unsafe.h)++void+cpCircleShapeSetRadius(cpShape *shape, cpFloat radius)+{+	cpAssert(shape->klass == &cpCircleShapeClass, "Shape is not a circle shape.");+	cpCircleShape *circle = (cpCircleShape *)shape;+	+	circle->r = radius;+}++void+cpCircleShapeSetOffset(cpShape *shape, cpVect offset)+{+	cpAssert(shape->klass == &cpCircleShapeClass, "Shape is not a circle shape.");+	cpCircleShape *circle = (cpCircleShape *)shape;+	+	circle->c = offset;+}++void+cpSegmentShapeSetEndpoints(cpShape *shape, cpVect a, cpVect b)+{+	cpAssert(shape->klass == &cpSegmentShapeClass, "Shape is not a segment shape.");+	cpSegmentShape *seg = (cpSegmentShape *)shape;+	+	seg->a = a;+	seg->b = b;+	seg->n = cpvperp(cpvnormalize(cpvsub(b, a)));+}++void+cpSegmentShapeSetRadius(cpShape *shape, cpFloat radius)+{+	cpAssert(shape->klass == &cpSegmentShapeClass, "Shape is not a segment shape.");+	cpSegmentShape *seg = (cpSegmentShape *)shape;+	+	seg->r = radius;+}
+ chipmunk-r402/src/cpSpace.c view
@@ -0,0 +1,887 @@+/* Copyright (c) 2007 Scott Lembcke+ * + * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ * + * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+ * SOFTWARE.+ */+ +#include <stdlib.h>+#include <stdio.h>+#include <string.h>+#include <math.h>++#include "chipmunk.h"++int cp_contact_persistence = 1;++#pragma mark Contact Set Helpers++// Equal function for contactSet.+static int+contactSetEql(cpShape **shapes, cpArbiter *arb)+{+	cpShape *a = shapes[0];+	cpShape *b = shapes[1];+	+	return ((a == arb->private_a && b == arb->private_b) || (b == arb->private_a && a == arb->private_b));+}++// Transformation function for contactSet.+static void *+contactSetTrans(cpShape **shapes, cpSpace *space)+{+	if(space->pooledArbiters->num == 0){+		// arbiter pool is exhausted, make more+		int count = CP_BUFFER_BYTES/sizeof(cpArbiter);+		cpAssert(count, "Buffer size too small.");+		+		cpArbiter *buffer = (cpArbiter *)cpmalloc(CP_BUFFER_BYTES);+		cpArrayPush(space->allocatedBuffers, buffer);+		+		for(int i=0; i<count; i++) cpArrayPush(space->pooledArbiters, buffer + i);+	}+	+	return cpArbiterInit(cpArrayPop(space->pooledArbiters), shapes[0], shapes[1]);+}++#pragma mark Collision Pair Function Helpers++// Equals function for collFuncSet.+static int+collFuncSetEql(cpCollisionHandler *check, cpCollisionHandler *pair)+{+	return ((check->a == pair->a && check->b == pair->b) || (check->b == pair->a && check->a == pair->b));+}++// Transformation function for collFuncSet.+static void *+collFuncSetTrans(cpCollisionHandler *handler, void *unused)+{+	cpCollisionHandler *copy = (cpCollisionHandler *)cpmalloc(sizeof(cpCollisionHandler));+	(*copy) = (*handler);+	+	return copy;+}++#pragma mark Post Step Function Helpers++typedef struct postStepCallback {+	cpPostStepFunc func;+	void *obj;+	void *data;+} postStepCallback;++static int+postStepFuncSetEql(postStepCallback *a, postStepCallback *b){+	return a->obj == b->obj;+}++static void *+postStepFuncSetTrans(postStepCallback *callback, void *ignored)+{+	postStepCallback *value = (postStepCallback *)cpmalloc(sizeof(postStepCallback));+	(*value) = (*callback);+	+	return value;+}++#pragma mark Misc Helper Funcs++// Default collision functions.+static int alwaysCollide(cpArbiter *arb, cpSpace *space, void *data){return 1;}+static void nothing(cpArbiter *arb, cpSpace *space, void *data){}++// BBfunc callback for the spatial hash.+static cpBB shapeBBFunc(cpShape *shape){return shape->bb;}++// Iterator functions for destructors.+static void             freeWrap(void         *ptr, void *unused){            cpfree(ptr);}+static void        shapeFreeWrap(cpShape      *ptr, void *unused){     cpShapeFree(ptr);}+static void         bodyFreeWrap(cpBody       *ptr, void *unused){      cpBodyFree(ptr);}+static void   constraintFreeWrap(cpConstraint *ptr, void *unused){cpConstraintFree(ptr);}++#pragma mark Memory Management Functions++static cpContactBuffer *+cpSpaceAllocContactBuffer(cpSpace *space)+{+	cpContactBuffer *buffer = (cpContactBuffer *)malloc(sizeof(cpContactBuffer));+	cpArrayPush(space->allocatedBuffers, buffer);+	return buffer;+}++static cpContactBuffer *+cpContactBufferInit(cpContactBuffer *buffer, cpSpace *space)+{+	buffer->stamp = space->stamp;+	buffer->next = space->contactBuffersTail;+	buffer->numContacts = 0;+	+	return buffer;+}++cpSpace *+cpSpaceAlloc(void)+{+	return (cpSpace *)cpcalloc(1, sizeof(cpSpace));+}++#define DEFAULT_DIM_SIZE 100.0f+#define DEFAULT_COUNT 1000+#define DEFAULT_ITERATIONS 10+#define DEFAULT_ELASTIC_ITERATIONS 0++#define MAX_CONTACTS 10000++cpCollisionHandler defaultHandler = {0, 0, alwaysCollide, alwaysCollide, nothing, nothing, NULL};++cpSpace*+cpSpaceInit(cpSpace *space)+{+	space->iterations = DEFAULT_ITERATIONS;+	space->elasticIterations = DEFAULT_ELASTIC_ITERATIONS;+//	space->sleepTicks = 300;+	+	space->gravity = cpvzero;+	space->damping = 1.0f;+	+	space->locked = 0;+	space->stamp = 0;++	space->staticShapes = cpSpaceHashNew(DEFAULT_DIM_SIZE, DEFAULT_COUNT, (cpSpaceHashBBFunc)shapeBBFunc);+	space->activeShapes = cpSpaceHashNew(DEFAULT_DIM_SIZE, DEFAULT_COUNT, (cpSpaceHashBBFunc)shapeBBFunc);+	+	space->allocatedBuffers = cpArrayNew(0);+	+	space->bodies = cpArrayNew(0);+	space->arbiters = cpArrayNew(0);+	space->pooledArbiters = cpArrayNew(0);+	+	cpContactBuffer *buffer = cpContactBufferInit(cpSpaceAllocContactBuffer(space), space);+	space->contactBuffersHead = buffer;+	space->contactBuffersTail = buffer;+	buffer->next = buffer; // Buffers will form a ring, start the ring explicitly+	+	space->contactSet = cpHashSetNew(0, (cpHashSetEqlFunc)contactSetEql, (cpHashSetTransFunc)contactSetTrans);+	+	space->constraints = cpArrayNew(0);+	+	space->defaultHandler = defaultHandler;+	space->collFuncSet = cpHashSetNew(0, (cpHashSetEqlFunc)collFuncSetEql, (cpHashSetTransFunc)collFuncSetTrans);+	space->collFuncSet->default_value = &space->defaultHandler;+	+	space->postStepCallbacks = cpHashSetNew(0, (cpHashSetEqlFunc)postStepFuncSetEql, (cpHashSetTransFunc)postStepFuncSetTrans);+	+	return space;+}++cpSpace*+cpSpaceNew(void)+{+	return cpSpaceInit(cpSpaceAlloc());+}++void+cpSpaceDestroy(cpSpace *space)+{+	cpSpaceHashFree(space->staticShapes);+	cpSpaceHashFree(space->activeShapes);+	+	cpArrayFree(space->bodies);+	+	cpArrayFree(space->constraints);+	+	cpHashSetFree(space->contactSet);+	+	cpArrayFree(space->arbiters);+	cpArrayFree(space->pooledArbiters);+	+	if(space->allocatedBuffers){+		cpArrayEach(space->allocatedBuffers, freeWrap, NULL);+		cpArrayFree(space->allocatedBuffers);+	}+	+	if(space->postStepCallbacks){+		cpHashSetEach(space->postStepCallbacks, freeWrap, NULL);+		cpHashSetFree(space->postStepCallbacks);+	}+	+	if(space->collFuncSet){+		cpHashSetEach(space->collFuncSet, freeWrap, NULL);+		cpHashSetFree(space->collFuncSet);+	}+}++void+cpSpaceFree(cpSpace *space)+{+	if(space){+		cpSpaceDestroy(space);+		cpfree(space);+	}+}++void+cpSpaceFreeChildren(cpSpace *space)+{+	cpSpaceHashEach(space->staticShapes, (cpSpaceHashIterator)&shapeFreeWrap, NULL);+	cpSpaceHashEach(space->activeShapes, (cpSpaceHashIterator)&shapeFreeWrap, NULL);+	cpArrayEach(space->bodies,           (cpArrayIter)&bodyFreeWrap,          NULL);+	cpArrayEach(space->constraints,      (cpArrayIter)&constraintFreeWrap,    NULL);+}++#pragma mark Collision Handler Function Management++void+cpSpaceAddCollisionHandler(+	cpSpace *space,+	cpCollisionType a, cpCollisionType b,+	cpCollisionBeginFunc begin,+	cpCollisionPreSolveFunc preSolve,+	cpCollisionPostSolveFunc postSolve,+	cpCollisionSeparateFunc separate,+	void *data+){+	// Remove any old function so the new one will get added.+	cpSpaceRemoveCollisionHandler(space, a, b);+	+	cpCollisionHandler handler = {+		a, b,+		begin ? begin : alwaysCollide,+		preSolve ? preSolve : alwaysCollide,+		postSolve ? postSolve : nothing,+		separate ? separate : nothing,+		data+	};+	+	cpHashSetInsert(space->collFuncSet, CP_HASH_PAIR(a, b), &handler, NULL);+}++void+cpSpaceRemoveCollisionHandler(cpSpace *space, cpCollisionType a, cpCollisionType b)+{+	struct{cpCollisionType a, b;} ids = {a, b};+	cpCollisionHandler *old_handler = cpHashSetRemove(space->collFuncSet, CP_HASH_PAIR(a, b), &ids);+	cpfree(old_handler);+}++void+cpSpaceSetDefaultCollisionHandler(+	cpSpace *space,+	cpCollisionBeginFunc begin,+	cpCollisionPreSolveFunc preSolve,+	cpCollisionPostSolveFunc postSolve,+	cpCollisionSeparateFunc separate,+	void *data+){+	cpCollisionHandler handler = {+		0, 0,+		begin ? begin : alwaysCollide,+		preSolve ? preSolve : alwaysCollide,+		postSolve ? postSolve : nothing,+		separate ? separate : nothing,+		data+	};+	+	space->defaultHandler = handler;+}++#pragma mark Body, Shape, and Joint Management++#define cpAssertSpaceUnlocked(space) \+	cpAssert(!space->locked, \+		"Cannot safely add or remove objects from a space during a call to cpSpaceStep(). " \+		"Put these calls into a Post Step Callback." \+	);++cpShape *+cpSpaceAddShape(cpSpace *space, cpShape *shape)+{+	cpAssert(shape->body, "Cannot add a shape with a NULL body.");+	cpAssert(!cpHashSetFind(space->activeShapes->handleSet, shape->hashid, shape), "Cannot add the same shape more than once.");+	cpAssertSpaceUnlocked(space);+	+	cpSpaceHashInsert(space->activeShapes, shape, shape->hashid, shape->bb);+	return shape;+}++cpShape *+cpSpaceAddStaticShape(cpSpace *space, cpShape *shape)+{+	cpAssert(shape->body, "Cannot add a static shape with a NULL body.");+	cpAssert(!cpHashSetFind(space->staticShapes->handleSet, shape->hashid, shape), "Cannot add the same static shape more than once.");+	cpAssertSpaceUnlocked(space);+	+	cpShapeCacheBB(shape);+	cpSpaceHashInsert(space->staticShapes, shape, shape->hashid, shape->bb);+	+	return shape;+}++cpBody *+cpSpaceAddBody(cpSpace *space, cpBody *body)+{+	cpAssert(!cpArrayContains(space->bodies, body), "Cannot add the same body more than once.");+	cpAssertSpaceUnlocked(space);+	+	cpArrayPush(space->bodies, body);+	+	return body;+}++cpConstraint *+cpSpaceAddConstraint(cpSpace *space, cpConstraint *constraint)+{+	cpAssert(!cpArrayContains(space->constraints, constraint), "Cannot add the same constraint more than once.");+	cpAssertSpaceUnlocked(space);+	+	cpArrayPush(space->constraints, constraint);+	+	return constraint;+}++typedef struct removalContext {+	cpSpace *space;+	cpShape *shape;+} removalContext;++// Hashset filter func to throw away old arbiters.+static int+contactSetFilterRemovedShape(cpArbiter *arb, removalContext *context)+{+	if(context->shape == arb->private_a || context->shape == arb->private_b){+		arb->handler->separate(arb, context->space, arb->handler->data);+		cpArrayPush(context->space->pooledArbiters, arb);+		return 0;+	}+	+	return 1;+}++void+cpSpaceRemoveShape(cpSpace *space, cpShape *shape)+{+	cpAssert(cpHashSetFind(space->activeShapes->handleSet, shape->hashid, shape), "Cannot remove a shape that was never added to the space.");+	cpAssertSpaceUnlocked(space);+	+	removalContext context = {space, shape};+	cpHashSetFilter(space->contactSet, (cpHashSetFilterFunc)contactSetFilterRemovedShape, &context);+	cpSpaceHashRemove(space->activeShapes, shape, shape->hashid);+}++void+cpSpaceRemoveStaticShape(cpSpace *space, cpShape *shape)+{+	cpAssert(cpHashSetFind(space->staticShapes->handleSet, shape->hashid, shape), "Cannot remove a static shape that was never added to the space.");+	cpAssertSpaceUnlocked(space);+	+	removalContext context = {space, shape};+	cpHashSetFilter(space->contactSet, (cpHashSetFilterFunc)contactSetFilterRemovedShape, &context);+	cpSpaceHashRemove(space->staticShapes, shape, shape->hashid);+}++void+cpSpaceRemoveBody(cpSpace *space, cpBody *body)+{+	cpAssert(cpArrayContains(space->bodies, body), "Cannot remove a body that was never added to the space.");+	cpAssertSpaceUnlocked(space);+	+	cpArrayDeleteObj(space->bodies, body);+}++void+cpSpaceRemoveConstraint(cpSpace *space, cpConstraint *constraint)+{+	cpAssert(cpArrayContains(space->constraints, constraint), "Cannot remove a constraint that was never added to the space.");+	cpAssertSpaceUnlocked(space);+	+	cpArrayDeleteObj(space->constraints, constraint);+}++#pragma mark Post Step Functions++void+cpSpaceAddPostStepCallback(cpSpace *space, cpPostStepFunc func, void *obj, void *data)+{+	postStepCallback callback = {func, obj, data};+	cpHashSetInsert(space->postStepCallbacks, (cpHashValue)(size_t)obj, &callback, NULL);+}++static void+removeAndFreeShapeAndBody(cpShape *shape, cpSpace *space)+{+	cpSpaceRemoveShape(space, shape);+	cpShapeFree(shape);+}++void+cpSpacePostStepRemoveAndFreeShapeAndBody(cpSpace *space, cpShape *shape)+{+	cpSpaceAddPostStepCallback(space, (cpPostStepFunc)removeAndFreeShapeAndBody, shape, space);+}++#pragma mark Point Query Functions++typedef struct pointQueryContext {+	cpLayers layers;+	cpGroup group;+	cpSpacePointQueryFunc func;+	void *data;+} pointQueryContext;++static void +pointQueryHelper(cpVect *point, cpShape *shape, pointQueryContext *context)+{+	if(+		!(shape->group && context->group == shape->group) && (context->layers&shape->layers) &&+		cpShapePointQuery(shape, *point)+	){+		context->func(shape, context->data);+	}+}++void+cpSpacePointQuery(cpSpace *space, cpVect point, cpLayers layers, cpGroup group, cpSpacePointQueryFunc func, void *data)+{+	pointQueryContext context = {layers, group, func, data};+	cpSpaceHashPointQuery(space->activeShapes, point, (cpSpaceHashQueryFunc)pointQueryHelper, &context);+	cpSpaceHashPointQuery(space->staticShapes, point, (cpSpaceHashQueryFunc)pointQueryHelper, &context);+}++static void+rememberLastPointQuery(cpShape *shape, cpShape **outShape)+{+	(*outShape) = shape;+}++cpShape *+cpSpacePointQueryFirst(cpSpace *space, cpVect point, cpLayers layers, cpGroup group)+{+	cpShape *shape = NULL;+	cpSpacePointQuery(space, point, layers, group, (cpSpacePointQueryFunc)rememberLastPointQuery, &shape);+	+	return shape;+}++void+cpSpaceEachBody(cpSpace *space, cpSpaceBodyIterator func, void *data)+{+	cpArray *bodies = space->bodies;+	+	for(int i=0; i<bodies->num; i++)+		func((cpBody *)bodies->arr[i], data);+}++#pragma mark Segment Query Functions++typedef struct segQueryContext {+	cpVect start, end;+	cpLayers layers;+	cpGroup group;+	cpSpaceSegmentQueryFunc func;+	int anyCollision;+} segQueryContext;++static cpFloat+segQueryFunc(segQueryContext *context, cpShape *shape, void *data)+{+	cpSegmentQueryInfo info;+	+	if(+		!(shape->group && context->group == shape->group) && (context->layers&shape->layers) &&+		cpShapeSegmentQuery(shape, context->start, context->end, &info)+	){+		if(context->func){+			context->func(shape, info.t, info.n, data);+		}+		+		context->anyCollision = 1;+	}+	+	return 1.0f;+}++int+cpSpaceSegmentQuery(cpSpace *space, cpVect start, cpVect end, cpLayers layers, cpGroup group, cpSpaceSegmentQueryFunc func, void *data)+{+	segQueryContext context = {+		start, end,+		layers, group,+		func,+		0,+	};+	+	cpSpaceHashSegmentQuery(space->staticShapes, &context, start, end, 1.0f, (cpSpaceHashSegmentQueryFunc)segQueryFunc, data);+	cpSpaceHashSegmentQuery(space->activeShapes, &context, start, end, 1.0f, (cpSpaceHashSegmentQueryFunc)segQueryFunc, data);+	+	return context.anyCollision;+}++typedef struct segQueryFirstContext {+	cpVect start, end;+	cpLayers layers;+	cpGroup group;+} segQueryFirstContext;++static cpFloat+segQueryFirst(segQueryFirstContext *context, cpShape *shape, cpSegmentQueryInfo *out)+{+	cpSegmentQueryInfo info;// = {NULL, 1.0f, cpvzero};+	if(+		!(shape->group && context->group == shape->group) && (context->layers&shape->layers) &&+		cpShapeSegmentQuery(shape, context->start, context->end, &info)+	){+		if(info.t < out->t){+			out->shape = info.shape;+			out->t = info.t;+			out->n = info.n;+		}+		+		return info.t;+	}+	+	return 1.0f;+}++cpShape *+cpSpaceSegmentQueryFirst(cpSpace *space, cpVect start, cpVect end, cpLayers layers, cpGroup group, cpSegmentQueryInfo *out)+{+	cpSegmentQueryInfo info = {NULL, 1.0f, cpvzero};+	if(out){+		(*out) = info;+  } else {+		out = &info;+	}+	+	out->t = 1.0f;+	+	segQueryFirstContext context = {+		start, end,+		layers, group+	};+	+	cpSpaceHashSegmentQuery(space->staticShapes, &context, start, end, 1.0f, (cpSpaceHashSegmentQueryFunc)segQueryFirst, out);+	cpSpaceHashSegmentQuery(space->activeShapes, &context, start, end, out->t, (cpSpaceHashSegmentQueryFunc)segQueryFirst, out);+	+	return out->shape;+}++#pragma mark BB Query functions++typedef struct bbQueryContext {+	cpLayers layers;+	cpGroup group;+	cpSpaceBBQueryFunc func;+	void *data;+} bbQueryContext;++static void +bbQueryHelper(cpBB *bb, cpShape *shape, bbQueryContext *context)+{+	if(+		!(shape->group && context->group == shape->group) && (context->layers&shape->layers) &&+		cpBBintersects(*bb, shape->bb)+	){+		context->func(shape, context->data);+	}+}++void+cpSpaceBBQuery(cpSpace *space, cpBB bb, cpLayers layers, cpGroup group, cpSpaceBBQueryFunc func, void *data)+{+	bbQueryContext context = {layers, group, func, data};+	cpSpaceHashQuery(space->activeShapes, &bb, bb, (cpSpaceHashQueryFunc)bbQueryHelper, &context);+	cpSpaceHashQuery(space->staticShapes, &bb, bb, (cpSpaceHashQueryFunc)bbQueryHelper, &context);+}++#pragma mark Spatial Hash Management++// Iterator function used for updating shape BBoxes.+static void+updateBBCache(cpShape *shape, void *unused)+{+	cpShapeCacheBB(shape);+}++void+cpSpaceResizeStaticHash(cpSpace *space, cpFloat dim, int count)+{+	cpSpaceHashResize(space->staticShapes, dim, count);+	cpSpaceHashRehash(space->staticShapes);+}++void+cpSpaceResizeActiveHash(cpSpace *space, cpFloat dim, int count)+{+	cpSpaceHashResize(space->activeShapes, dim, count);+}++void +cpSpaceRehashStatic(cpSpace *space)+{+	cpSpaceHashEach(space->staticShapes, (cpSpaceHashIterator)&updateBBCache, NULL);+	cpSpaceHashRehash(space->staticShapes);+}++#pragma mark Collision Detection Functions++static cpContactBuffer *+cpSpaceGetFreeContactBuffer(cpSpace *space)+{+	if(space->stamp - space->contactBuffersTail->stamp > cp_contact_persistence){+		cpContactBuffer *buffer = space->contactBuffersTail;+		space->contactBuffersTail = buffer->next;+		+		return cpContactBufferInit(buffer, space);+	} else {+		cpContactBuffer *buffer = cpSpaceAllocContactBuffer(space);+		return cpContactBufferInit(buffer, space);+	}+}++static void+cpSpacePushNewContactBuffer(cpSpace *space)+{+//	for(cpContactBuffer *buffer = space->contactBuffersTail; buffer != space->contactBuffersHead; buffer = buffer->next){+//		printf("%p -> ", buffer);+//	}+//	printf("%p (head)\n", space->contactBuffersHead);+	+	cpContactBuffer *buffer = cpSpaceGetFreeContactBuffer(space);+	space->contactBuffersHead->next = buffer;+	space->contactBuffersHead = buffer;+}++static inline int+queryReject(cpShape *a, cpShape *b)+{+	return+		// BBoxes must overlap+		!cpBBintersects(a->bb, b->bb)+		// Don't collide shapes attached to the same body.+		|| a->body == b->body+		// Don't collide objects in the same non-zero group+		|| (a->group && b->group && a->group == b->group)+		// Don't collide objects that don't share at least on layer.+		|| !(a->layers & b->layers);+}++// Callback from the spatial hash.+static void+queryFunc(cpShape *a, cpShape *b, cpSpace *space)+{+	// Reject any of the simple cases+	if(queryReject(a,b)) return;+	+	// Find the collision pair function for the shapes.+	struct{cpCollisionType a, b;} ids = {a->collision_type, b->collision_type};+	cpHashValue collHashID = CP_HASH_PAIR(a->collision_type, b->collision_type);+	cpCollisionHandler *handler = (cpCollisionHandler *)cpHashSetFind(space->collFuncSet, collHashID, &ids);+	+	int sensor = a->sensor || b->sensor;+	if(sensor && handler == &space->defaultHandler) return;+	+	// Shape 'a' should have the lower shape type. (required by cpCollideShapes() )+	if(a->klass->type > b->klass->type){+		cpShape *temp = a;+		a = b;+		b = temp;+	}+	+	if(space->contactBuffersHead->numContacts + CP_MAX_CONTACTS_PER_ARBITER > CP_CONTACTS_BUFFER_SIZE){+		// contact buffer could overflow on the next collision, push a fresh one.+		cpSpacePushNewContactBuffer(space);+	}+	+	// Narrow-phase collision detection.+	cpContact *contacts = space->contactBuffersHead->contacts + space->contactBuffersHead->numContacts;+	int numContacts = cpCollideShapes(a, b, contacts);+	if(!numContacts) return; // Shapes are not colliding.+	space->contactBuffersHead->numContacts += numContacts;+	+	// Get an arbiter from space->contactSet for the two shapes.+	// This is where the persistant contact magic comes from.+	cpShape *shape_pair[] = {a, b};+	cpHashValue arbHashID = CP_HASH_PAIR((size_t)a, (size_t)b);+	cpArbiter *arb = (cpArbiter *)cpHashSetInsert(space->contactSet, arbHashID, shape_pair, space);+	cpArbiterUpdate(arb, contacts, numContacts, handler, a, b); // retains the contacts array+	+	// Call the begin function first if it's the first step+	if(arb->stamp == -1 && !handler->begin(arb, space, handler->data)){+		cpArbiterIgnore(arb); // permanently ignore the collision until separation+	}+	+	if(+		// Ignore the arbiter if it has been flagged+		(arb->state != cpArbiterStateIgnore) && +		// Call preSolve+		handler->preSolve(arb, space, handler->data) &&+		// Process, but don't add collisions for sensors.+		!sensor+	){+		cpArrayPush(space->arbiters, arb);+	} else {+//		cpfree(arb->contacts);+		space->contactBuffersHead->numContacts -= numContacts;+		arb->contacts = NULL;+		arb->numContacts = 0;+	}+	+	// Time stamp the arbiter so we know it was used recently.+	arb->stamp = space->stamp;+}++// Iterator for active/static hash collisions.+static void+active2staticIter(cpShape *shape, cpSpace *space)+{+	cpSpaceHashQuery(space->staticShapes, shape, shape->bb, (cpSpaceHashQueryFunc)queryFunc, space);+}++// Hashset filter func to throw away old arbiters.+static int+contactSetFilter(cpArbiter *arb, cpSpace *space)+{+	int ticks = space->stamp - arb->stamp;+	+	// was used last frame, but not this one+	if(ticks == 1){+		arb->handler->separate(arb, space, arb->handler->data);+		arb->stamp = -1; // mark it as a new pair again.+	}+	+	if(ticks >= cp_contact_persistence){+		cpArrayPush(space->pooledArbiters, arb);+		return 0;+	}+	+	return 1;+}++// Hashset filter func to call and throw away post step callbacks.+static int+postStepCallbackSetFilter(postStepCallback *callback, cpSpace *space)+{+	callback->func(space, callback->obj, callback->data);+	cpfree(callback);+	+	return 0;+}++#pragma mark All Important cpSpaceStep() Function++void+cpSpaceStep(cpSpace *space, cpFloat dt)+{+	if(!dt) return; // don't step if the timestep is 0!+	+	cpFloat dt_inv = 1.0f/dt;++	cpArray *bodies = space->bodies;+	cpArray *constraints = space->constraints;+	+	space->locked = 1;+	+	// Empty the arbiter list.+	space->arbiters->num = 0;++	// Integrate positions.+	for(int i=0; i<bodies->num; i++){+		cpBody *body = (cpBody *)bodies->arr[i];+		body->position_func(body, dt);+	}+	+	// Pre-cache BBoxes and shape data.+	cpSpaceHashEach(space->activeShapes, (cpSpaceHashIterator)updateBBCache, NULL);+	+	// Collide!+	cpSpacePushNewContactBuffer(space);+	cpSpaceHashEach(space->activeShapes, (cpSpaceHashIterator)active2staticIter, space);+	cpSpaceHashQueryRehash(space->activeShapes, (cpSpaceHashQueryFunc)queryFunc, space);+	+	// Clear out old cached arbiters and dispatch untouch functions+	cpHashSetFilter(space->contactSet, (cpHashSetFilterFunc)contactSetFilter, space);++	// Prestep the arbiters.+	cpArray *arbiters = space->arbiters;+	for(int i=0; i<arbiters->num; i++)+		cpArbiterPreStep((cpArbiter *)arbiters->arr[i], dt_inv);++	// Prestep the constraints.+	for(int i=0; i<constraints->num; i++){+		cpConstraint *constraint = (cpConstraint *)constraints->arr[i];+		constraint->klass->preStep(constraint, dt, dt_inv);+	}++	for(int i=0; i<space->elasticIterations; i++){+		for(int j=0; j<arbiters->num; j++)+			cpArbiterApplyImpulse((cpArbiter *)arbiters->arr[j], 1.0f);+			+		for(int j=0; j<constraints->num; j++){+			cpConstraint *constraint = (cpConstraint *)constraints->arr[j];+			constraint->klass->applyImpulse(constraint);+		}+	}++	// Integrate velocities.+	cpFloat damping = cpfpow(1.0f/space->damping, -dt);+	for(int i=0; i<bodies->num; i++){+		cpBody *body = (cpBody *)bodies->arr[i];+		body->velocity_func(body, space->gravity, damping, dt);+	}++	for(int i=0; i<arbiters->num; i++)+		cpArbiterApplyCachedImpulse((cpArbiter *)arbiters->arr[i]);+	+	// run the old-style elastic solver if elastic iterations are disabled+	cpFloat elasticCoef = (space->elasticIterations ? 0.0f : 1.0f);+	+	// Run the impulse solver.+	for(int i=0; i<space->iterations; i++){+		for(int j=0; j<arbiters->num; j++)+			cpArbiterApplyImpulse((cpArbiter *)arbiters->arr[j], elasticCoef);+			+		for(int j=0; j<constraints->num; j++){+			cpConstraint *constraint = (cpConstraint *)constraints->arr[j];+			constraint->klass->applyImpulse(constraint);+		}+	}+	+	space->locked = 0;+	+	// run the post solve callbacks+	for(int i=0; i<arbiters->num; i++){+		cpArbiter *arb = arbiters->arr[i];+		+		cpCollisionHandler *handler = arb->handler;+		handler->postSolve(arb, space, handler->data);+		+		arb->state = cpArbiterStateNormal;+	}+	+	// Run the post step callbacks+	// Use filter as an easy way to clear out the queue as it runs+	cpHashSetFilter(space->postStepCallbacks, (cpHashSetFilterFunc)postStepCallbackSetFilter, space);+	+//	cpFloat dvsq = cpvdot(space->gravity, space->gravity);+//	dvsq *= dt*dt * space->damping*space->damping;+//	for(int i=0; i<bodies->num; i++)+//		cpBodyMarkLowEnergy(bodies->arr[i], dvsq, space->sleepTicks);+	+	// Increment the stamp.+	space->stamp++;+}
+ chipmunk-r402/src/cpSpaceHash.c view
@@ -0,0 +1,541 @@+/* Copyright (c) 2007 Scott Lembcke+ * + * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ * + * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+ * SOFTWARE.+ */++#include <math.h>+#include <stdlib.h>+#include <stdio.h>++#include "chipmunk.h"+#include "prime.h"++static cpHandle*+cpHandleInit(cpHandle *hand, void *obj)+{+	hand->obj = obj;+	hand->retain = 0;+	hand->stamp = 0;+	+	return hand;+}++static inline void+cpHandleRetain(cpHandle *hand)+{+	hand->retain++;+}++static inline void+cpHandleRelease(cpHandle *hand, cpArray *pooledHandles)+{+	hand->retain--;+	if(hand->retain == 0) cpArrayPush(pooledHandles, hand);+}++cpSpaceHash*+cpSpaceHashAlloc(void)+{+	return (cpSpaceHash *)cpcalloc(1, sizeof(cpSpaceHash));+}++// Frees the old table, and allocates a new one.+static void+cpSpaceHashAllocTable(cpSpaceHash *hash, int numcells)+{+	cpfree(hash->table);+	+	hash->numcells = numcells;+	hash->table = (cpSpaceHashBin **)cpcalloc(numcells, sizeof(cpSpaceHashBin *));+}++// Equality function for the handleset.+static int+handleSetEql(void *obj, void *elt)+{+	cpHandle *hand = (cpHandle *)elt;+	return (obj == hand->obj);+}++// Transformation function for the handleset.+static void *+handleSetTrans(void *obj, cpSpaceHash *hash)+{+	if(hash->pooledHandles->num == 0){+		// handle pool is exhausted, make more+		int count = CP_BUFFER_BYTES/sizeof(cpHandle);+		cpAssert(count, "Buffer size is too small.");+		+		cpHandle *buffer = (cpHandle *)cpmalloc(CP_BUFFER_BYTES);+		cpArrayPush(hash->allocatedBuffers, buffer);+		+		for(int i=0; i<count; i++) cpArrayPush(hash->pooledHandles, buffer + i);+	}+	+	cpHandle *hand = cpHandleInit(cpArrayPop(hash->pooledHandles), obj);+	cpHandleRetain(hand);+	+	return hand;+}++cpSpaceHash*+cpSpaceHashInit(cpSpaceHash *hash, cpFloat celldim, int numcells, cpSpaceHashBBFunc bbfunc)+{+	cpSpaceHashAllocTable(hash, next_prime(numcells));+	hash->celldim = celldim;+	hash->bbfunc = bbfunc;+	+	hash->handleSet = cpHashSetNew(0, handleSetEql, (cpHashSetTransFunc)handleSetTrans);+	hash->pooledHandles = cpArrayNew(0);+	+	hash->pooledBins = NULL;+	hash->allocatedBuffers = cpArrayNew(0);+	+	hash->stamp = 1;+	+	return hash;+}++cpSpaceHash*+cpSpaceHashNew(cpFloat celldim, int cells, cpSpaceHashBBFunc bbfunc)+{+	return cpSpaceHashInit(cpSpaceHashAlloc(), celldim, cells, bbfunc);+}++static inline void+recycleBin(cpSpaceHash *hash, cpSpaceHashBin *bin)+{+	bin->next = hash->pooledBins;+	hash->pooledBins = bin;+}++static inline void+clearHashCell(cpSpaceHash *hash, int idx)+{+	cpSpaceHashBin *bin = hash->table[idx];+	while(bin){+		cpSpaceHashBin *next = bin->next;+		+		// Release the lock on the handle.+		cpHandleRelease(bin->handle, hash->pooledHandles);+		recycleBin(hash, bin);+		+		bin = next;+	}+	+	hash->table[idx] = NULL;+}++// Clear all cells in the hashtable.+static void+clearHash(cpSpaceHash *hash)+{+	for(int i=0; i<hash->numcells; i++)+		clearHashCell(hash, i);+}++static void freeWrap(void *ptr, void *unused){cpfree(ptr);}++void+cpSpaceHashDestroy(cpSpaceHash *hash)+{+	clearHash(hash);+	+	cpHashSetFree(hash->handleSet);+	+	cpArrayEach(hash->allocatedBuffers, freeWrap, NULL);+	cpArrayFree(hash->allocatedBuffers);+	cpArrayFree(hash->pooledHandles);+	+	cpfree(hash->table);+}++void+cpSpaceHashFree(cpSpaceHash *hash)+{+	if(hash){+		cpSpaceHashDestroy(hash);+		cpfree(hash);+	}+}++void+cpSpaceHashResize(cpSpaceHash *hash, cpFloat celldim, int numcells)+{+	// Clear the hash to release the old handle locks.+	clearHash(hash);+	+	hash->celldim = celldim;+	cpSpaceHashAllocTable(hash, next_prime(numcells));+}++// Return true if the chain contains the handle.+static inline int+containsHandle(cpSpaceHashBin *bin, cpHandle *hand)+{+	while(bin){+		if(bin->handle == hand) return 1;+		bin = bin->next;+	}+	+	return 0;+}++// Get a recycled or new bin.+static inline cpSpaceHashBin *+getEmptyBin(cpSpaceHash *hash)+{+	cpSpaceHashBin *bin = hash->pooledBins;+	+	if(bin){+		hash->pooledBins = bin->next;+		return bin;+	} else {+		// Pool is exhausted, make more+		int count = CP_BUFFER_BYTES/sizeof(cpSpaceHashBin);+		cpAssert(count, "Buffer size is too small.");+		+		cpSpaceHashBin *buffer = (cpSpaceHashBin *)cpmalloc(CP_BUFFER_BYTES);+		cpArrayPush(hash->allocatedBuffers, buffer);+		+		// push all but the first one, return the first instead+		for(int i=1; i<count; i++) recycleBin(hash, buffer + i);+		return buffer;+	}+}++// The hash function itself.+static inline cpHashValue+hash_func(cpHashValue x, cpHashValue y, cpHashValue n)+{+	return (x*1640531513ul ^ y*2654435789ul) % n;+}++// Much faster than (int)floor(f)+// Profiling showed floor() to be a sizable performance hog+static inline int+floor_int(cpFloat f)+{+	int i = (int)f;+	return (f < 0.0f && f != i ? i - 1 : i);+}++static inline void+hashHandle(cpSpaceHash *hash, cpHandle *hand, cpBB bb)+{+	// Find the dimensions in cell coordinates.+	cpFloat dim = hash->celldim;+	int l = floor_int(bb.l/dim); // Fix by ShiftZ+	int r = floor_int(bb.r/dim);+	int b = floor_int(bb.b/dim);+	int t = floor_int(bb.t/dim);+	+	int n = hash->numcells;+	for(int i=l; i<=r; i++){+		for(int j=b; j<=t; j++){+			int idx = hash_func(i,j,n);+			cpSpaceHashBin *bin = hash->table[idx];+			+			// Don't add an object twice to the same cell.+			if(containsHandle(bin, hand)) continue;++			cpHandleRetain(hand);+			// Insert a new bin for the handle in this cell.+			cpSpaceHashBin *newBin = getEmptyBin(hash);+			newBin->handle = hand;+			newBin->next = bin;+			hash->table[idx] = newBin;+		}+	}+}++void+cpSpaceHashInsert(cpSpaceHash *hash, void *obj, cpHashValue hashid, cpBB bb)+{+	cpHandle *hand = (cpHandle *)cpHashSetInsert(hash->handleSet, hashid, obj, hash);+	hashHandle(hash, hand, bb);+}++void+cpSpaceHashRehashObject(cpSpaceHash *hash, void *obj, cpHashValue hashid)+{+	cpHandle *hand = (cpHandle *)cpHashSetFind(hash->handleSet, hashid, obj);+	hashHandle(hash, hand, hash->bbfunc(obj));+}++// Hashset iterator function for rehashing the spatial hash. (hash hash hash hash?)+static void+handleRehashHelper(void *elt, void *data)+{+	cpHandle *hand = (cpHandle *)elt;+	cpSpaceHash *hash = (cpSpaceHash *)data;+	+	hashHandle(hash, hand, hash->bbfunc(hand->obj));+}++void+cpSpaceHashRehash(cpSpaceHash *hash)+{+	clearHash(hash);+	+	// Rehash all of the handles.+	cpHashSetEach(hash->handleSet, &handleRehashHelper, hash);+}++void+cpSpaceHashRemove(cpSpaceHash *hash, void *obj, cpHashValue hashid)+{+	cpHandle *hand = (cpHandle *)cpHashSetRemove(hash->handleSet, hashid, obj);+	+	if(hand){+		hand->obj = NULL;+		cpHandleRelease(hand, hash->pooledHandles);+	}+}++// Used by the cpSpaceHashEach() iterator.+typedef struct eachPair {+	cpSpaceHashIterator func;+	void *data;+} eachPair;++// Calls the user iterator function. (Gross I know.)+static void+eachHelper(void *elt, void *data)+{+	cpHandle *hand = (cpHandle *)elt;+	eachPair *pair = (eachPair *)data;+	+	pair->func(hand->obj, pair->data);+}++// Iterate over the objects in the spatial hash.+void+cpSpaceHashEach(cpSpaceHash *hash, cpSpaceHashIterator func, void *data)+{+	// Bundle the callback up to send to the hashset iterator.+	eachPair pair = {func, data};+	+	cpHashSetEach(hash->handleSet, &eachHelper, &pair);+}++// Calls the callback function for the objects in a given chain.+static inline void+query(cpSpaceHash *hash, cpSpaceHashBin *bin, void *obj, cpSpaceHashQueryFunc func, void *data)+{+	for(; bin; bin = bin->next){+		cpHandle *hand = bin->handle;+		void *other = hand->obj;+		+		// Skip over certain conditions+		if(+			// Have we already tried this pair in this query?+			hand->stamp == hash->stamp+			// Is obj the same as other?+			|| obj == other +			// Has other been removed since the last rehash?+			|| !other+			) continue;+		+		func(obj, other, data);++		// Stamp that the handle was checked already against this object.+		hand->stamp = hash->stamp;+	}+}++void+cpSpaceHashPointQuery(cpSpaceHash *hash, cpVect point, cpSpaceHashQueryFunc func, void *data)+{+	cpFloat dim = hash->celldim;+	int idx = hash_func(floor_int(point.x/dim), floor_int(point.y/dim), hash->numcells);  // Fix by ShiftZ+	+	query(hash, hash->table[idx], &point, func, data);++	// Increment the stamp.+	// Only one cell is checked, but query() requires it anyway.+	hash->stamp++;+}++void+cpSpaceHashQuery(cpSpaceHash *hash, void *obj, cpBB bb, cpSpaceHashQueryFunc func, void *data)+{+	// Get the dimensions in cell coordinates.+	cpFloat dim = hash->celldim;+	int l = floor_int(bb.l/dim);  // Fix by ShiftZ+	int r = floor_int(bb.r/dim);+	int b = floor_int(bb.b/dim);+	int t = floor_int(bb.t/dim);+	+	int n = hash->numcells;+	+	// Iterate over the cells and query them.+	for(int i=l; i<=r; i++){+		for(int j=b; j<=t; j++){+			int idx = hash_func(i,j,n);+			query(hash, hash->table[idx], obj, func, data);+		}+	}+	+	// Increment the stamp.+	hash->stamp++;+}++// Similar to struct eachPair above.+typedef struct queryRehashPair {+	cpSpaceHash *hash;+	cpSpaceHashQueryFunc func;+	void *data;+} queryRehashPair;++// Hashset iterator func used with cpSpaceHashQueryRehash().+static void+handleQueryRehashHelper(void *elt, void *data)+{+	cpHandle *hand = (cpHandle *)elt;+	+	// Unpack the user callback data.+	queryRehashPair *pair = (queryRehashPair *)data;+	cpSpaceHash *hash = pair->hash;+	cpSpaceHashQueryFunc func = pair->func;++	cpFloat dim = hash->celldim;+	int n = hash->numcells;++	void *obj = hand->obj;+	cpBB bb = hash->bbfunc(obj);++	int l = floor_int(bb.l/dim);+	int r = floor_int(bb.r/dim);+	int b = floor_int(bb.b/dim);+	int t = floor_int(bb.t/dim);++	for(int i=l; i<=r; i++){+		for(int j=b; j<=t; j++){+//			// exit the loops if the object has been deleted in func().+//			if(!hand->obj) goto break_out;+			+			int idx = hash_func(i,j,n);+			cpSpaceHashBin *bin = hash->table[idx];+			+			if(containsHandle(bin, hand)) continue;+			+			cpHandleRetain(hand); // this MUST be done first in case the object is removed in func()+			query(hash, bin, obj, func, pair->data);+			+			cpSpaceHashBin *newBin = getEmptyBin(hash);+			newBin->handle = hand;+			newBin->next = bin;+			hash->table[idx] = newBin;+		}+	}+	+//	break_out:+	// Increment the stamp for each object we hash.+	hash->stamp++;+}++void+cpSpaceHashQueryRehash(cpSpaceHash *hash, cpSpaceHashQueryFunc func, void *data)+{+	clearHash(hash);+	+	queryRehashPair pair = {hash, func, data};+	cpHashSetEach(hash->handleSet, &handleQueryRehashHelper, &pair);+}++static inline cpFloat+segmentQuery(cpSpaceHash *hash, cpSpaceHashBin *bin, void *obj, cpSpaceHashSegmentQueryFunc func, void *data)+{+	cpFloat t = 1.0f;+	 +	for(; bin; bin = bin->next){+		cpHandle *hand = bin->handle;+		void *other = hand->obj;+		+		// Skip over certain conditions+		if(+			// Have we already tried this pair in this query?+			hand->stamp == hash->stamp+			// Has other been removed since the last rehash?+			|| !other+			) continue;+		+		// Stamp that the handle was checked already against this object.+		hand->stamp = hash->stamp;+		+		t = cpfmin(t, func(obj, other, data));+	}+	+	return t;+}++// modified from http://playtechs.blogspot.com/2007/03/raytracing-on-grid.html+void cpSpaceHashSegmentQuery(cpSpaceHash *hash, void *obj, cpVect a, cpVect b, cpFloat t_exit, cpSpaceHashSegmentQueryFunc func, void *data)+{+	a = cpvmult(a, 1.0f/hash->celldim);+	b = cpvmult(b, 1.0f/hash->celldim);+	+	cpFloat dt_dx = 1.0f/cpfabs(b.x - a.x), dt_dy = 1.0f/cpfabs(b.y - a.y);+	+	int cell_x = floor_int(a.x), cell_y = floor_int(a.y);++	cpFloat t = 0;++	int x_inc, y_inc;+	cpFloat temp_v, temp_h;++	if (b.x > a.x){+		x_inc = 1;+		temp_h = (cpffloor(a.x + 1.0f) - a.x);+	} else {+		x_inc = -1;+		temp_h = (a.x - cpffloor(a.x));+	}++	if (b.y > a.y){+		y_inc = 1;+		temp_v = (cpffloor(a.y + 1.0f) - a.y);+	} else {+		y_inc = -1;+		temp_v = (a.y - cpffloor(a.y));+	}+	+	// fix NANs in horizontal directions+	cpFloat next_h = (temp_h ? temp_h*dt_dx : dt_dx);+	cpFloat next_v = (temp_v ? temp_v*dt_dy : dt_dy);++	int n = hash->numcells;+	while(t < t_exit){+		int idx = hash_func(cell_x, cell_y, n);+		t_exit = cpfmin(t_exit, segmentQuery(hash, hash->table[idx], obj, func, data));++		if (next_v < next_h){+			cell_y += y_inc;+			t = next_v;+			next_v += dt_dy;+		} else {+			cell_x += x_inc;+			t = next_h;+			next_h += dt_dx;+		}+	}+	+	hash->stamp++;+}
+ chipmunk-r402/src/cpVect.c view
@@ -0,0 +1,71 @@+/* Copyright (c) 2007 Scott Lembcke+ * + * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ * + * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+ * SOFTWARE.+ */+ +#include <stdio.h>+#include <math.h>++#include "chipmunk.h"++cpFloat+cpvlength(const cpVect v)+{+	return cpfsqrt( cpvdot(v, v) );+}++inline cpVect+cpvslerp(const cpVect v1, const cpVect v2, const cpFloat t)+{+	cpFloat omega = cpfacos(cpvdot(v1, v2));+	+	if(omega){+		cpFloat denom = 1.0f/cpfsin(omega);+		return cpvadd(cpvmult(v1, cpfsin((1.0f - t)*omega)*denom), cpvmult(v2, cpfsin(t*omega)*denom));+	} else {+		return v1;+	}+}++cpVect+cpvslerpconst(const cpVect v1, const cpVect v2, const cpFloat a)+{+	cpFloat angle = cpfacos(cpvdot(v1, v2));+	return cpvslerp(v1, v2, cpfmin(a, angle)/angle);+}++cpVect+cpvforangle(const cpFloat a)+{+	return cpv(cpfcos(a), cpfsin(a));+}++cpFloat+cpvtoangle(const cpVect v)+{+	return cpfatan2(v.y, v.x);+}++char*+cpvstr(const cpVect v)+{+	static char str[256];+	sprintf(str, "(% .3f, % .3f)", v.x, v.y);+	return str;+}
+ chipmunk-r402/src/prime.h view
@@ -0,0 +1,68 @@+/* Copyright (c) 2007 Scott Lembcke+ * + * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ * + * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+ * SOFTWARE.+ */+ +// Used for resizing hash tables.+// Values approximately double.+// http://planetmath.org/encyclopedia/GoodHashTablePrimes.html+static int primes[] = {+	5,+	13,+	23,+	47,+	97,+	193,+	389,+	769,+	1543,+	3079,+	6151,+	12289,+	24593,+	49157,+	98317,+	196613,+	393241,+	786433,+	1572869,+	3145739,+	6291469,+	12582917,+	25165843,+	50331653,+	100663319,+	201326611,+	402653189,+	805306457,+	1610612741,+	0,+};++static inline int+next_prime(int n)+{+	int i = 0;+	while(n > primes[i]){+		i++;+		cpAssert(primes[i], "Tried to resize a hash table to a size greater than 1610612741 O_o"); // realistically this should never happen+	}+	+	return primes[i];+}