issue #1564: Updated Chipmunk to v6.1.2.

This commit is contained in:
James Chen 2012-11-20 16:15:21 +08:00
parent af36ada6e4
commit 3d275dc8cf
45 changed files with 334 additions and 274 deletions

View File

@ -106,10 +106,10 @@ typedef struct cpSpace cpSpace;
#include "cpSpace.h" #include "cpSpace.h"
// Chipmunk 6.1.1 // Chipmunk 6.1.2
#define CP_VERSION_MAJOR 6 #define CP_VERSION_MAJOR 6
#define CP_VERSION_MINOR 1 #define CP_VERSION_MINOR 1
#define CP_VERSION_RELEASE 1 #define CP_VERSION_RELEASE 2
/// Version string. /// Version string.
extern const char *cpVersionString; extern const char *cpVersionString;
@ -117,6 +117,10 @@ extern const char *cpVersionString;
/// @deprecated /// @deprecated
void cpInitChipmunk(void); void cpInitChipmunk(void);
/// Enables segment to segment shape collisions.
void cpEnableSegmentToSegmentCollisions(void);
/// Calculate the moment of inertia for a circle. /// Calculate the moment of inertia for a circle.
/// @c r1 and @c r2 are the inner and outer diameters. A solid circle has an inner diameter of 0. /// @c r1 and @c 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); cpFloat cpMomentForCircle(cpFloat m, cpFloat r1, cpFloat r2, cpVect offset);

View File

@ -14,7 +14,7 @@
#endif #endif
#define MAKE_PROPERTIES_REF(struct, property) \ #define MAKE_PROPERTIES_REF(struct, property) \
MAKE_REF(struct##Get##property); MAKE_REF(struct##Set##property); MAKE_REF(struct##Get##property); MAKE_REF(struct##Set##property)
MAKE_REF(cpv); // makes a variable named _cpv that contains the function pointer for cpv() MAKE_REF(cpv); // makes a variable named _cpv that contains the function pointer for cpv()
MAKE_REF(cpveql); MAKE_REF(cpveql);

View File

@ -188,7 +188,13 @@ void cpSpacePushFreshContactBuffer(cpSpace *space);
cpContact *cpContactBufferGetArray(cpSpace *space); cpContact *cpContactBufferGetArray(cpSpace *space);
void cpSpacePushContacts(cpSpace *space, int count); void cpSpacePushContacts(cpSpace *space, int count);
void *cpSpaceGetPostStepData(cpSpace *space, void *key); typedef struct cpPostStepCallback {
cpPostStepFunc func;
void *key;
void *data;
} cpPostStepCallback;
cpPostStepCallback *cpSpaceGetPostStepCallback(cpSpace *space, void *key);
cpBool cpSpaceArbiterSetFilter(cpArbiter *arb, cpSpace *space); cpBool cpSpaceArbiterSetFilter(cpArbiter *arb, cpSpace *space);
void cpSpaceFilterArbiters(cpSpace *space, cpBody *body, cpShape *filter); void cpSpaceFilterArbiters(cpSpace *space, cpBody *body, cpShape *filter);

View File

@ -1,11 +1,7 @@
#include <math.h>
#ifndef WIN32
#include <stdint.h> #include <stdint.h>
#endif
#ifdef __APPLE__ #ifdef __APPLE__
#import "TargetConditionals.h" #include "TargetConditionals.h"
#endif #endif
#if (TARGET_OS_IPHONE == 1) || (TARGET_OS_MAC == 1) && (!defined CP_USE_CGPOINTS) #if (TARGET_OS_IPHONE == 1) || (TARGET_OS_MAC == 1) && (!defined CP_USE_CGPOINTS)
@ -16,7 +12,7 @@
#if TARGET_OS_IPHONE #if TARGET_OS_IPHONE
#import <CoreGraphics/CGGeometry.h> #import <CoreGraphics/CGGeometry.h>
#elif TARGET_OS_MAC #elif TARGET_OS_MAC
#import <ApplicationServices/ApplicationServices.h> #include <ApplicationServices/ApplicationServices.h>
#endif #endif
#if defined(__LP64__) && __LP64__ #if defined(__LP64__) && __LP64__
@ -213,4 +209,7 @@ typedef uintptr_t cpHashValue;
typedef struct cpVect{cpFloat x,y;} cpVect; typedef struct cpVect{cpFloat x,y;} cpVect;
#endif #endif
typedef struct cpMat2x2 {
// Row major [[a, b][c d]]
cpFloat a, b, c, d;
} cpMat2x2;

View File

@ -26,7 +26,7 @@ typedef struct cpConstraintClass cpConstraintClass;
typedef void (*cpConstraintPreStepImpl)(cpConstraint *constraint, cpFloat dt); typedef void (*cpConstraintPreStepImpl)(cpConstraint *constraint, cpFloat dt);
typedef void (*cpConstraintApplyCachedImpulseImpl)(cpConstraint *constraint, cpFloat dt_coef); typedef void (*cpConstraintApplyCachedImpulseImpl)(cpConstraint *constraint, cpFloat dt_coef);
typedef void (*cpConstraintApplyImpulseImpl)(cpConstraint *constraint); typedef void (*cpConstraintApplyImpulseImpl)(cpConstraint *constraint, cpFloat dt);
typedef cpFloat (*cpConstraintGetImpulseImpl)(cpConstraint *constraint); typedef cpFloat (*cpConstraintGetImpulseImpl)(cpConstraint *constraint);
/// @private /// @private
@ -110,16 +110,16 @@ static inline void cpConstraint##Set##name(cpConstraint *constraint, type value)
CP_DefineConstraintStructGetter(type, member, name) \ CP_DefineConstraintStructGetter(type, member, name) \
CP_DefineConstraintStructSetter(type, member, name) CP_DefineConstraintStructSetter(type, member, name)
CP_DefineConstraintStructGetter(cpSpace*, CP_PRIVATE(space), Space); CP_DefineConstraintStructGetter(cpSpace*, CP_PRIVATE(space), Space)
CP_DefineConstraintStructGetter(cpBody*, a, A); CP_DefineConstraintStructGetter(cpBody*, a, A)
CP_DefineConstraintStructGetter(cpBody*, b, B); CP_DefineConstraintStructGetter(cpBody*, b, B)
CP_DefineConstraintStructProperty(cpFloat, maxForce, MaxForce); CP_DefineConstraintStructProperty(cpFloat, maxForce, MaxForce)
CP_DefineConstraintStructProperty(cpFloat, errorBias, ErrorBias); CP_DefineConstraintStructProperty(cpFloat, errorBias, ErrorBias)
CP_DefineConstraintStructProperty(cpFloat, maxBias, MaxBias); CP_DefineConstraintStructProperty(cpFloat, maxBias, MaxBias)
CP_DefineConstraintStructProperty(cpConstraintPreSolveFunc, preSolve, PreSolveFunc); CP_DefineConstraintStructProperty(cpConstraintPreSolveFunc, preSolve, PreSolveFunc)
CP_DefineConstraintStructProperty(cpConstraintPostSolveFunc, postSolve, PostSolveFunc); CP_DefineConstraintStructProperty(cpConstraintPostSolveFunc, postSolve, PostSolveFunc)
CP_DefineConstraintStructProperty(cpDataPointer, data, UserData); CP_DefineConstraintStructProperty(cpDataPointer, data, UserData)
// Get the last impulse applied by this constraint. // Get the last impulse applied by this constraint.
static inline cpFloat cpConstraintGetImpulse(cpConstraint *constraint) static inline cpFloat cpConstraintGetImpulse(cpConstraint *constraint)

View File

@ -47,9 +47,9 @@ cpDampedRotarySpring* cpDampedRotarySpringInit(cpDampedRotarySpring *joint, cpBo
/// Allocate and initialize a damped rotary spring. /// Allocate and initialize a damped rotary spring.
cpConstraint* cpDampedRotarySpringNew(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, restAngle, RestAngle)
CP_DefineConstraintProperty(cpDampedRotarySpring, cpFloat, stiffness, Stiffness); CP_DefineConstraintProperty(cpDampedRotarySpring, cpFloat, stiffness, Stiffness)
CP_DefineConstraintProperty(cpDampedRotarySpring, cpFloat, damping, Damping); CP_DefineConstraintProperty(cpDampedRotarySpring, cpFloat, damping, Damping)
CP_DefineConstraintProperty(cpDampedRotarySpring, cpDampedRotarySpringTorqueFunc, springTorqueFunc, SpringTorqueFunc); CP_DefineConstraintProperty(cpDampedRotarySpring, cpDampedRotarySpringTorqueFunc, springTorqueFunc, SpringTorqueFunc)
/// @} /// @}

View File

@ -52,11 +52,11 @@ cpDampedSpring* cpDampedSpringInit(cpDampedSpring *joint, cpBody *a, cpBody *b,
/// Allocate and initialize a damped spring. /// Allocate and initialize a damped spring.
cpConstraint* cpDampedSpringNew(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, anchr1, Anchr1)
CP_DefineConstraintProperty(cpDampedSpring, cpVect, anchr2, Anchr2); CP_DefineConstraintProperty(cpDampedSpring, cpVect, anchr2, Anchr2)
CP_DefineConstraintProperty(cpDampedSpring, cpFloat, restLength, RestLength); CP_DefineConstraintProperty(cpDampedSpring, cpFloat, restLength, RestLength)
CP_DefineConstraintProperty(cpDampedSpring, cpFloat, stiffness, Stiffness); CP_DefineConstraintProperty(cpDampedSpring, cpFloat, stiffness, Stiffness)
CP_DefineConstraintProperty(cpDampedSpring, cpFloat, damping, Damping); CP_DefineConstraintProperty(cpDampedSpring, cpFloat, damping, Damping)
CP_DefineConstraintProperty(cpDampedSpring, cpDampedSpringForceFunc, springForceFunc, SpringForceFunc); CP_DefineConstraintProperty(cpDampedSpring, cpDampedSpringForceFunc, springForceFunc, SpringForceFunc)
/// @} /// @}

View File

@ -33,7 +33,7 @@ typedef struct cpGearJoint {
cpFloat iSum; cpFloat iSum;
cpFloat bias; cpFloat bias;
cpFloat jAcc, jMax; cpFloat jAcc;
} cpGearJoint; } cpGearJoint;
/// Allocate a gear joint. /// Allocate a gear joint.
@ -43,8 +43,8 @@ cpGearJoint* cpGearJointInit(cpGearJoint *joint, cpBody *a, cpBody *b, cpFloat p
/// Allocate and initialize a gear joint. /// Allocate and initialize a gear joint.
cpConstraint* cpGearJointNew(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, phase, Phase)
CP_DefineConstraintGetter(cpGearJoint, cpFloat, ratio, Ratio); CP_DefineConstraintGetter(cpGearJoint, cpFloat, ratio, Ratio)
/// Set the ratio of a gear joint. /// Set the ratio of a gear joint.
void cpGearJointSetRatio(cpConstraint *constraint, cpFloat value); void cpGearJointSetRatio(cpConstraint *constraint, cpFloat value);

View File

@ -33,10 +33,9 @@ typedef struct cpGrooveJoint {
cpVect grv_tn; cpVect grv_tn;
cpFloat clamp; cpFloat clamp;
cpVect r1, r2; cpVect r1, r2;
cpVect k1, k2; cpMat2x2 k;
cpVect jAcc; cpVect jAcc;
cpFloat jMaxLen;
cpVect bias; cpVect bias;
} cpGrooveJoint; } cpGrooveJoint;
@ -47,12 +46,12 @@ cpGrooveJoint* cpGrooveJointInit(cpGrooveJoint *joint, cpBody *a, cpBody *b, cpV
/// Allocate and initialize a groove joint. /// Allocate and initialize a groove joint.
cpConstraint* cpGrooveJointNew(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);
CP_DefineConstraintGetter(cpGrooveJoint, cpVect, grv_a, GrooveA); CP_DefineConstraintGetter(cpGrooveJoint, cpVect, grv_a, GrooveA)
/// Set endpoint a of a groove joint's groove /// Set endpoint a of a groove joint's groove
void cpGrooveJointSetGrooveA(cpConstraint *constraint, cpVect value); void cpGrooveJointSetGrooveA(cpConstraint *constraint, cpVect value);
CP_DefineConstraintGetter(cpGrooveJoint, cpVect, grv_b, GrooveB); CP_DefineConstraintGetter(cpGrooveJoint, cpVect, grv_b, GrooveB)
/// Set endpoint b of a groove joint's groove /// Set endpoint b of a groove joint's groove
void cpGrooveJointSetGrooveB(cpConstraint *constraint, cpVect value); void cpGrooveJointSetGrooveB(cpConstraint *constraint, cpVect value);
CP_DefineConstraintProperty(cpGrooveJoint, cpVect, anchr2, Anchr2); CP_DefineConstraintProperty(cpGrooveJoint, cpVect, anchr2, Anchr2)
/// @} /// @}

View File

@ -34,7 +34,7 @@ typedef struct cpPinJoint {
cpVect n; cpVect n;
cpFloat nMass; cpFloat nMass;
cpFloat jnAcc, jnMax; cpFloat jnAcc;
cpFloat bias; cpFloat bias;
} cpPinJoint; } cpPinJoint;
@ -45,8 +45,8 @@ cpPinJoint* cpPinJointInit(cpPinJoint *joint, cpBody *a, cpBody *b, cpVect anchr
/// Allocate and initialize a pin joint. /// Allocate and initialize a pin joint.
cpConstraint* cpPinJointNew(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, anchr1, Anchr1)
CP_DefineConstraintProperty(cpPinJoint, cpVect, anchr2, Anchr2); CP_DefineConstraintProperty(cpPinJoint, cpVect, anchr2, Anchr2)
CP_DefineConstraintProperty(cpPinJoint, cpFloat, dist, Dist); CP_DefineConstraintProperty(cpPinJoint, cpFloat, dist, Dist)
///@} ///@}

View File

@ -30,10 +30,9 @@ typedef struct cpPivotJoint {
cpVect anchr1, anchr2; cpVect anchr1, anchr2;
cpVect r1, r2; cpVect r1, r2;
cpVect k1, k2; cpMat2x2 k;
cpVect jAcc; cpVect jAcc;
cpFloat jMaxLen;
cpVect bias; cpVect bias;
} cpPivotJoint; } cpPivotJoint;
@ -46,7 +45,7 @@ cpConstraint* cpPivotJointNew(cpBody *a, cpBody *b, cpVect pivot);
/// Allocate and initialize a pivot joint with specific anchors. /// Allocate and initialize a pivot joint with specific anchors.
cpConstraint* cpPivotJointNew2(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2); cpConstraint* cpPivotJointNew2(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2);
CP_DefineConstraintProperty(cpPivotJoint, cpVect, anchr1, Anchr1); CP_DefineConstraintProperty(cpPivotJoint, cpVect, anchr1, Anchr1)
CP_DefineConstraintProperty(cpPivotJoint, cpVect, anchr2, Anchr2); CP_DefineConstraintProperty(cpPivotJoint, cpVect, anchr2, Anchr2)
/// @} /// @}

View File

@ -32,7 +32,7 @@ typedef struct cpRatchetJoint {
cpFloat iSum; cpFloat iSum;
cpFloat bias; cpFloat bias;
cpFloat jAcc, jMax; cpFloat jAcc;
} cpRatchetJoint; } cpRatchetJoint;
/// Allocate a ratchet joint. /// Allocate a ratchet joint.
@ -42,8 +42,8 @@ cpRatchetJoint* cpRatchetJointInit(cpRatchetJoint *joint, cpBody *a, cpBody *b,
/// Allocate and initialize a ratchet joint. /// Allocate and initialize a ratchet joint.
cpConstraint* cpRatchetJointNew(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, angle, Angle)
CP_DefineConstraintProperty(cpRatchetJoint, cpFloat, phase, Phase); CP_DefineConstraintProperty(cpRatchetJoint, cpFloat, phase, Phase)
CP_DefineConstraintProperty(cpRatchetJoint, cpFloat, ratchet, Ratchet); CP_DefineConstraintProperty(cpRatchetJoint, cpFloat, ratchet, Ratchet)
/// @} /// @}

View File

@ -32,7 +32,7 @@ typedef struct cpRotaryLimitJoint {
cpFloat iSum; cpFloat iSum;
cpFloat bias; cpFloat bias;
cpFloat jAcc, jMax; cpFloat jAcc;
} cpRotaryLimitJoint; } cpRotaryLimitJoint;
/// Allocate a damped rotary limit joint. /// Allocate a damped rotary limit joint.
@ -42,7 +42,7 @@ cpRotaryLimitJoint* cpRotaryLimitJointInit(cpRotaryLimitJoint *joint, cpBody *a,
/// Allocate and initialize a damped rotary limit joint. /// Allocate and initialize a damped rotary limit joint.
cpConstraint* cpRotaryLimitJointNew(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, min, Min)
CP_DefineConstraintProperty(cpRotaryLimitJoint, cpFloat, max, Max); CP_DefineConstraintProperty(cpRotaryLimitJoint, cpFloat, max, Max)
/// @} /// @}

View File

@ -31,7 +31,7 @@ typedef struct cpSimpleMotor {
cpFloat iSum; cpFloat iSum;
cpFloat jAcc, jMax; cpFloat jAcc;
} cpSimpleMotor; } cpSimpleMotor;
/// Allocate a simple motor. /// Allocate a simple motor.
@ -41,6 +41,6 @@ cpSimpleMotor* cpSimpleMotorInit(cpSimpleMotor *joint, cpBody *a, cpBody *b, cpF
/// Allocate and initialize a simple motor. /// Allocate and initialize a simple motor.
cpConstraint* cpSimpleMotorNew(cpBody *a, cpBody *b, cpFloat rate); cpConstraint* cpSimpleMotorNew(cpBody *a, cpBody *b, cpFloat rate);
CP_DefineConstraintProperty(cpSimpleMotor, cpFloat, rate, Rate); CP_DefineConstraintProperty(cpSimpleMotor, cpFloat, rate, Rate)
/// @} /// @}

View File

@ -34,7 +34,7 @@ typedef struct cpSlideJoint {
cpVect n; cpVect n;
cpFloat nMass; cpFloat nMass;
cpFloat jnAcc, jnMax; cpFloat jnAcc;
cpFloat bias; cpFloat bias;
} cpSlideJoint; } cpSlideJoint;
@ -45,9 +45,9 @@ cpSlideJoint* cpSlideJointInit(cpSlideJoint *joint, cpBody *a, cpBody *b, cpVect
/// Allocate and initialize a slide joint. /// Allocate and initialize a slide joint.
cpConstraint* cpSlideJointNew(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, anchr1, Anchr1)
CP_DefineConstraintProperty(cpSlideJoint, cpVect, anchr2, Anchr2); CP_DefineConstraintProperty(cpSlideJoint, cpVect, anchr2, Anchr2)
CP_DefineConstraintProperty(cpSlideJoint, cpFloat, min, Min); CP_DefineConstraintProperty(cpSlideJoint, cpFloat, min, Min)
CP_DefineConstraintProperty(cpSlideJoint, cpFloat, max, Max); CP_DefineConstraintProperty(cpSlideJoint, cpFloat, max, Max)
/// @} /// @}

View File

@ -27,8 +27,6 @@
void cpConstraintInit(cpConstraint *constraint, const cpConstraintClass *klass, cpBody *a, cpBody *b); void cpConstraintInit(cpConstraint *constraint, const cpConstraintClass *klass, cpBody *a, cpBody *b);
#define J_MAX(constraint, dt) (((cpConstraint *)constraint)->maxForce*(dt))
static inline cpVect static inline cpVect
relative_velocity(cpBody *a, cpBody *b, cpVect r1, cpVect r2){ relative_velocity(cpBody *a, cpBody *b, cpVect r1, cpVect r2){
cpVect v1_sum = cpvadd(a->v, cpvmult(cpvperp(r1), a->w)); cpVect v1_sum = cpvadd(a->v, cpvmult(cpvperp(r1), a->w));
@ -85,17 +83,14 @@ k_scalar(cpBody *a, cpBody *b, cpVect r1, cpVect r2, cpVect n)
return value; return value;
} }
static inline void static inline cpMat2x2
k_tensor(cpBody *a, cpBody *b, cpVect r1, cpVect r2, cpVect *k1, cpVect *k2) k_tensor(cpBody *a, cpBody *b, cpVect r1, cpVect r2)
{ {
// 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; cpFloat m_sum = a->m_inv + b->m_inv;
// start with I*m_sum // start with Identity*m_sum
k11 = m_sum; k12 = 0.0f; cpFloat k11 = m_sum, k12 = 0.0f;
k21 = 0.0f; k22 = m_sum; cpFloat k21 = 0.0f, k22 = m_sum;
// add the influence from r1 // add the influence from r1
cpFloat a_i_inv = a->i_inv; cpFloat a_i_inv = a->i_inv;
@ -114,18 +109,14 @@ k_tensor(cpBody *a, cpBody *b, cpVect r1, cpVect r2, cpVect *k1, cpVect *k2)
k21 += r2nxy; k22 += r2xsq; k21 += r2nxy; k22 += r2xsq;
// invert // invert
cpFloat determinant = k11*k22 - k12*k21; cpFloat det = k11*k22 - k12*k21;
cpAssertSoft(determinant != 0.0, "Unsolvable constraint."); cpAssertSoft(det != 0.0, "Unsolvable constraint.");
cpFloat det_inv = 1.0f/determinant; cpFloat det_inv = 1.0f/det;
*k1 = cpv( k22*det_inv, -k12*det_inv); return cpMat2x2New(
*k2 = cpv(-k21*det_inv, k11*det_inv); k22*det_inv, -k12*det_inv,
} -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));
} }
static inline cpFloat static inline cpFloat

View File

@ -83,6 +83,11 @@ struct cpArbiter {
/// Override in a pre-solve collision handler for custom behavior. /// Override in a pre-solve collision handler for custom behavior.
cpVect surface_vr; cpVect surface_vr;
/// User definable data pointer.
/// The value will persist for the pair of shapes until the separate() callback is called.
/// NOTE: If you need to clean up this pointer, you should implement the separate() callback to do it.
cpDataPointer data;
CP_PRIVATE(cpShape *a); CP_PRIVATE(cpShape *a);
CP_PRIVATE(cpShape *b); CP_PRIVATE(cpShape *b);
CP_PRIVATE(cpBody *body_a); CP_PRIVATE(cpBody *body_a);
@ -110,9 +115,10 @@ static inline void cpArbiterSet##name(cpArbiter *arb, type value){arb->member =
CP_DefineArbiterStructGetter(type, member, name) \ CP_DefineArbiterStructGetter(type, member, name) \
CP_DefineArbiterStructSetter(type, member, name) CP_DefineArbiterStructSetter(type, member, name)
CP_DefineArbiterStructProperty(cpFloat, e, Elasticity); CP_DefineArbiterStructProperty(cpFloat, e, Elasticity)
CP_DefineArbiterStructProperty(cpFloat, u, Friction); CP_DefineArbiterStructProperty(cpFloat, u, Friction)
CP_DefineArbiterStructProperty(cpVect, surface_vr, SurfaceVelocity); CP_DefineArbiterStructProperty(cpVect, surface_vr, SurfaceVelocity)
CP_DefineArbiterStructProperty(cpDataPointer, data, UserData)
/// Calculate the total impulse that was applied by this arbiter. /// Calculate the total impulse that was applied by this arbiter.
/// This function should only be called from a post-solve, post-step or cpBodyEachArbiter callback. /// This function should only be called from a post-solve, post-step or cpBodyEachArbiter callback.

View File

@ -123,7 +123,11 @@ static inline cpBool cpBBIntersectsSegment(cpBB bb, cpVect a, cpVect b)
} }
/// Clamp a vector to a bounding box. /// Clamp a vector to a bounding box.
cpVect cpBBClampVect(const cpBB bb, const cpVect v); // clamps the vector to lie within the bbox static inline cpVect
cpBBClampVect(const cpBB bb, const cpVect v)
{
return cpv(cpfclamp(v.x, bb.l, bb.r), cpfclamp(v.y, bb.b, bb.t));
}
// TODO edge case issue // TODO edge case issue
/// Wrap a vector to a bounding box. /// Wrap a vector to a bounding box.

View File

@ -160,8 +160,8 @@ static inline type cpBodyGet##name(const cpBody *body){return body->member;}
#define CP_DefineBodyStructSetter(type, member, name) \ #define CP_DefineBodyStructSetter(type, member, name) \
static inline void cpBodySet##name(cpBody *body, const type value){ \ static inline void cpBodySet##name(cpBody *body, const type value){ \
cpBodyActivate(body); \ cpBodyActivate(body); \
cpBodyAssertSane(body); \
body->member = value; \ body->member = value; \
cpBodyAssertSane(body); \
} }
#define CP_DefineBodyStructProperty(type, member, name) \ #define CP_DefineBodyStructProperty(type, member, name) \
@ -169,30 +169,30 @@ CP_DefineBodyStructGetter(type, member, name) \
CP_DefineBodyStructSetter(type, member, name) CP_DefineBodyStructSetter(type, member, name)
// TODO add to docs // TODO add to docs
CP_DefineBodyStructGetter(cpSpace*, CP_PRIVATE(space), Space); CP_DefineBodyStructGetter(cpSpace*, CP_PRIVATE(space), Space)
CP_DefineBodyStructGetter(cpFloat, m, Mass); CP_DefineBodyStructGetter(cpFloat, m, Mass)
/// Set the mass of a body. /// Set the mass of a body.
void cpBodySetMass(cpBody *body, cpFloat m); void cpBodySetMass(cpBody *body, cpFloat m);
CP_DefineBodyStructGetter(cpFloat, i, Moment); CP_DefineBodyStructGetter(cpFloat, i, Moment)
/// Set the moment of a body. /// Set the moment of a body.
void cpBodySetMoment(cpBody *body, cpFloat i); void cpBodySetMoment(cpBody *body, cpFloat i);
CP_DefineBodyStructGetter(cpVect, p, Pos); CP_DefineBodyStructGetter(cpVect, p, Pos)
/// Set the position of a body. /// Set the position of a body.
void cpBodySetPos(cpBody *body, cpVect pos); void cpBodySetPos(cpBody *body, cpVect pos);
CP_DefineBodyStructProperty(cpVect, v, Vel); CP_DefineBodyStructProperty(cpVect, v, Vel)
CP_DefineBodyStructProperty(cpVect, f, Force); CP_DefineBodyStructProperty(cpVect, f, Force)
CP_DefineBodyStructGetter(cpFloat, a, Angle); CP_DefineBodyStructGetter(cpFloat, a, Angle)
/// Set the angle of a body. /// Set the angle of a body.
void cpBodySetAngle(cpBody *body, cpFloat a); void cpBodySetAngle(cpBody *body, cpFloat a);
CP_DefineBodyStructProperty(cpFloat, w, AngVel); CP_DefineBodyStructProperty(cpFloat, w, AngVel)
CP_DefineBodyStructProperty(cpFloat, t, Torque); CP_DefineBodyStructProperty(cpFloat, t, Torque)
CP_DefineBodyStructGetter(cpVect, rot, Rot); CP_DefineBodyStructGetter(cpVect, rot, Rot)
CP_DefineBodyStructProperty(cpFloat, v_limit, VelLimit); CP_DefineBodyStructProperty(cpFloat, v_limit, VelLimit)
CP_DefineBodyStructProperty(cpFloat, w_limit, AngVelLimit); CP_DefineBodyStructProperty(cpFloat, w_limit, AngVelLimit)
CP_DefineBodyStructProperty(cpDataPointer, data, UserData); CP_DefineBodyStructProperty(cpDataPointer, data, UserData)
/// Default Integration functions. /// Default Integration functions.
void cpBodyUpdateVelocity(cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt); void cpBodyUpdateVelocity(cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt);

View File

@ -41,7 +41,7 @@ typedef struct cpPolyShape {
cpPolyShape* cpPolyShapeAlloc(void); cpPolyShape* cpPolyShapeAlloc(void);
/// Initialize a polygon shape. /// Initialize a polygon shape.
/// A convex hull will be created from the vertexes. /// A convex hull will be created from the vertexes.
cpPolyShape* cpPolyShapeInit(cpPolyShape *poly, cpBody *body, int numVerts, cpVect *verts, cpVect offset); cpPolyShape* cpPolyShapeInit(cpPolyShape *poly, cpBody *body, int numVerts, const cpVect *verts, cpVect offset);
/// Allocate and initialize a polygon shape. /// Allocate and initialize a polygon shape.
/// A convex hull will be created from the vertexes. /// A convex hull will be created from the vertexes.
cpShape* cpPolyShapeNew(cpBody *body, int numVerts, cpVect *verts, cpVect offset); cpShape* cpPolyShapeNew(cpBody *body, int numVerts, cpVect *verts, cpVect offset);

View File

@ -154,20 +154,20 @@ static inline void cpShapeSet##name(cpShape *shape, type value){ \
CP_DefineShapeStructGetter(type, member, name) \ CP_DefineShapeStructGetter(type, member, name) \
CP_DefineShapeStructSetter(type, member, name, activates) CP_DefineShapeStructSetter(type, member, name, activates)
CP_DefineShapeStructGetter(cpSpace*, CP_PRIVATE(space), Space); CP_DefineShapeStructGetter(cpSpace*, CP_PRIVATE(space), Space)
CP_DefineShapeStructGetter(cpBody*, body, Body); CP_DefineShapeStructGetter(cpBody*, body, Body)
void cpShapeSetBody(cpShape *shape, cpBody *body); void cpShapeSetBody(cpShape *shape, cpBody *body);
CP_DefineShapeStructGetter(cpBB, bb, BB); CP_DefineShapeStructGetter(cpBB, bb, BB)
CP_DefineShapeStructProperty(cpBool, sensor, Sensor, cpTrue); CP_DefineShapeStructProperty(cpBool, sensor, Sensor, cpTrue)
CP_DefineShapeStructProperty(cpFloat, e, Elasticity, cpFalse); CP_DefineShapeStructProperty(cpFloat, e, Elasticity, cpFalse)
CP_DefineShapeStructProperty(cpFloat, u, Friction, cpTrue); CP_DefineShapeStructProperty(cpFloat, u, Friction, cpTrue)
CP_DefineShapeStructProperty(cpVect, surface_v, SurfaceVelocity, cpTrue); CP_DefineShapeStructProperty(cpVect, surface_v, SurfaceVelocity, cpTrue)
CP_DefineShapeStructProperty(cpDataPointer, data, UserData, cpFalse); CP_DefineShapeStructProperty(cpDataPointer, data, UserData, cpFalse)
CP_DefineShapeStructProperty(cpCollisionType, collision_type, CollisionType, cpTrue); CP_DefineShapeStructProperty(cpCollisionType, collision_type, CollisionType, cpTrue)
CP_DefineShapeStructProperty(cpGroup, group, Group, cpTrue); CP_DefineShapeStructProperty(cpGroup, group, Group, cpTrue)
CP_DefineShapeStructProperty(cpLayers, layers, Layers, cpTrue); CP_DefineShapeStructProperty(cpLayers, layers, Layers, cpTrue)
/// When initializing a shape, it's hash value comes from a counter. /// When initializing a shape, it's hash value comes from a counter.
/// Because the hash value may affect iteration order, you can reset the shape ID counter /// Because the hash value may affect iteration order, you can reset the shape ID counter

View File

@ -127,18 +127,18 @@ static inline void cpSpaceSet##name(cpSpace *space, type value){space->member =
CP_DefineSpaceStructGetter(type, member, name) \ CP_DefineSpaceStructGetter(type, member, name) \
CP_DefineSpaceStructSetter(type, member, name) CP_DefineSpaceStructSetter(type, member, name)
CP_DefineSpaceStructProperty(int, iterations, Iterations); CP_DefineSpaceStructProperty(int, iterations, Iterations)
CP_DefineSpaceStructProperty(cpVect, gravity, Gravity); CP_DefineSpaceStructProperty(cpVect, gravity, Gravity)
CP_DefineSpaceStructProperty(cpFloat, damping, Damping); CP_DefineSpaceStructProperty(cpFloat, damping, Damping)
CP_DefineSpaceStructProperty(cpFloat, idleSpeedThreshold, IdleSpeedThreshold); CP_DefineSpaceStructProperty(cpFloat, idleSpeedThreshold, IdleSpeedThreshold)
CP_DefineSpaceStructProperty(cpFloat, sleepTimeThreshold, SleepTimeThreshold); CP_DefineSpaceStructProperty(cpFloat, sleepTimeThreshold, SleepTimeThreshold)
CP_DefineSpaceStructProperty(cpFloat, collisionSlop, CollisionSlop); CP_DefineSpaceStructProperty(cpFloat, collisionSlop, CollisionSlop)
CP_DefineSpaceStructProperty(cpFloat, collisionBias, CollisionBias); CP_DefineSpaceStructProperty(cpFloat, collisionBias, CollisionBias)
CP_DefineSpaceStructProperty(cpTimestamp, collisionPersistence, CollisionPersistence); CP_DefineSpaceStructProperty(cpTimestamp, collisionPersistence, CollisionPersistence)
CP_DefineSpaceStructProperty(cpBool, enableContactGraph, EnableContactGraph); CP_DefineSpaceStructProperty(cpBool, enableContactGraph, EnableContactGraph)
CP_DefineSpaceStructProperty(cpDataPointer, data, UserData); CP_DefineSpaceStructProperty(cpDataPointer, data, UserData)
CP_DefineSpaceStructGetter(cpBody*, staticBody, StaticBody); CP_DefineSpaceStructGetter(cpBody*, staticBody, StaticBody)
CP_DefineSpaceStructGetter(cpFloat, CP_PRIVATE(curr_dt), CurrentTimeStep); CP_DefineSpaceStructGetter(cpFloat, CP_PRIVATE(curr_dt), CurrentTimeStep)
/// returns true from inside a callback and objects cannot be added/removed. /// returns true from inside a callback and objects cannot be added/removed.
static inline cpBool static inline cpBool
@ -202,10 +202,12 @@ cpBool cpSpaceContainsBody(cpSpace *space, cpBody *body);
cpBool cpSpaceContainsConstraint(cpSpace *space, cpConstraint *constraint); cpBool cpSpaceContainsConstraint(cpSpace *space, cpConstraint *constraint);
/// Post Step callback function type. /// Post Step callback function type.
typedef void (*cpPostStepFunc)(cpSpace *space, void *obj, void *data); typedef void (*cpPostStepFunc)(cpSpace *space, void *key, void *data);
/// Schedule a post-step callback to be called when cpSpaceStep() finishes. /// Schedule a post-step callback to be called when cpSpaceStep() finishes.
/// You can only register one callback per unique value for @c key. /// You can only register one callback per unique value for @c key.
void cpSpaceAddPostStepCallback(cpSpace *space, cpPostStepFunc func, void *key, void *data); /// Returns true only if @c key has never been scheduled before.
/// It's possible to pass @c NULL for @c func if you only want to mark @c key as being used.
cpBool cpSpaceAddPostStepCallback(cpSpace *space, cpPostStepFunc func, void *key, void *data);
/// Point query callback function type. /// Point query callback function type.
typedef void (*cpSpacePointQueryFunc)(cpShape *shape, void *data); typedef void (*cpSpacePointQueryFunc)(cpShape *shape, void *data);

View File

@ -33,21 +33,12 @@ static inline cpVect cpv(const cpFloat x, const cpFloat y)
return v; return v;
} }
/// Returns the length of v.
cpFloat cpvlength(const cpVect v);
/// Spherical linearly interpolate between v1 and v2. /// Spherical linearly interpolate between v1 and v2.
cpVect cpvslerp(const cpVect v1, const cpVect v2, const cpFloat t); cpVect cpvslerp(const cpVect v1, const cpVect v2, const cpFloat t);
/// Spherical linearly interpolate between v1 towards v2 by no more than angle a radians /// Spherical linearly interpolate between v1 towards v2 by no more than angle a radians
cpVect cpvslerpconst(const cpVect v1, const cpVect v2, const cpFloat a); cpVect cpvslerpconst(const cpVect v1, const cpVect v2, const cpFloat a);
/// Returns the unit length vector for the given angle (in radians).
cpVect cpvforangle(const cpFloat a);
/// Returns the angular direction v is pointing in (in radians).
cpFloat cpvtoangle(const cpVect v);
/// Returns a string representation of v. Intended mostly for debugging purposes and not production use. /// Returns a string representation of v. Intended mostly for debugging purposes and not production use.
/// @attention The string points to a static local and is reset every time the function is called. /// @attention The string points to a static local and is reset every time the function is called.
/// If you want to print more than one vector you will have to split up your printing onto separate lines. /// If you want to print more than one vector you will have to split up your printing onto separate lines.
@ -115,6 +106,18 @@ static inline cpVect cpvproject(const cpVect v1, const cpVect v2)
return cpvmult(v2, cpvdot(v1, v2)/cpvdot(v2, v2)); return cpvmult(v2, cpvdot(v1, v2)/cpvdot(v2, v2));
} }
/// Returns the unit length vector for the given angle (in radians).
static inline cpVect cpvforangle(const cpFloat a)
{
return cpv(cpfcos(a), cpfsin(a));
}
/// Returns the angular direction v is pointing in (in radians).
static inline cpFloat cpvtoangle(const cpVect v)
{
return cpfatan2(v.y, v.x);
}
/// Uses complex number multiplication to rotate v1 by v2. Scaling will occur if v1 is not a unit vector. /// Uses complex number multiplication to rotate v1 by v2. Scaling will occur if v1 is not a unit vector.
static inline cpVect cpvrotate(const cpVect v1, const cpVect v2) static inline cpVect cpvrotate(const cpVect v1, const cpVect v2)
{ {
@ -133,6 +136,12 @@ static inline cpFloat cpvlengthsq(const cpVect v)
return cpvdot(v, v); return cpvdot(v, v);
} }
/// Returns the length of v.
static inline cpFloat cpvlength(const cpVect v)
{
return cpfsqrt(cpvdot(v, v));
}
/// Linearly interpolate between v1 and v2. /// Linearly interpolate between v1 and v2.
static inline cpVect cpvlerp(const cpVect v1, const cpVect v2, const cpFloat t) static inline cpVect cpvlerp(const cpVect v1, const cpVect v2, const cpFloat t)
{ {
@ -180,4 +189,24 @@ static inline cpBool cpvnear(const cpVect v1, const cpVect v2, const cpFloat dis
{ {
return cpvdistsq(v1, v2) < dist*dist; return cpvdistsq(v1, v2) < dist*dist;
} }
/// @} /// @}
/// @defgroup cpMat2x2 cpMat2x2
/// 2x2 matrix type used for tensors and such.
/// @{
static inline cpMat2x2
cpMat2x2New(cpFloat a, cpFloat b, cpFloat c, cpFloat d)
{
cpMat2x2 m = {a, b, c, d};
return m;
}
static inline cpVect
cpMat2x2Transform(cpMat2x2 m, cpVect v)
{
return cpv(v.x*m.a + v.y*m.b, v.x*m.c + v.y*m.d);
}
///@}

View File

@ -9,7 +9,7 @@ if(BUILD_SHARED)
${chipmunk_source_files} ${chipmunk_source_files}
) )
# set the lib's version number # set the lib's version number
set_target_properties(chipmunk PROPERTIES VERSION 6.1.1) set_target_properties(chipmunk PROPERTIES VERSION 6.1.2)
install(TARGETS chipmunk RUNTIME DESTINATION lib LIBRARY DESTINATION lib) install(TARGETS chipmunk RUNTIME DESTINATION lib LIBRARY DESTINATION lib)
endif(BUILD_SHARED) endif(BUILD_SHARED)

View File

@ -49,7 +49,7 @@ preStep(cpDampedRotarySpring *spring, cpFloat dt)
static void applyCachedImpulse(cpDampedRotarySpring *spring, cpFloat dt_coef){} static void applyCachedImpulse(cpDampedRotarySpring *spring, cpFloat dt_coef){}
static void static void
applyImpulse(cpDampedRotarySpring *spring) applyImpulse(cpDampedRotarySpring *spring, cpFloat dt)
{ {
cpBody *a = spring->constraint.a; cpBody *a = spring->constraint.a;
cpBody *b = spring->constraint.b; cpBody *b = spring->constraint.b;

View File

@ -55,7 +55,7 @@ preStep(cpDampedSpring *spring, cpFloat dt)
static void applyCachedImpulse(cpDampedSpring *spring, cpFloat dt_coef){} static void applyCachedImpulse(cpDampedSpring *spring, cpFloat dt_coef){}
static void static void
applyImpulse(cpDampedSpring *spring) applyImpulse(cpDampedSpring *spring, cpFloat dt)
{ {
cpBody *a = spring->constraint.a; cpBody *a = spring->constraint.a;
cpBody *b = spring->constraint.b; cpBody *b = spring->constraint.b;

View File

@ -34,9 +34,6 @@ preStep(cpGearJoint *joint, cpFloat dt)
// calculate bias velocity // calculate bias velocity
cpFloat maxBias = joint->constraint.maxBias; cpFloat maxBias = joint->constraint.maxBias;
joint->bias = cpfclamp(-bias_coef(joint->constraint.errorBias, dt)*(b->a*joint->ratio - a->a - joint->phase)/dt, -maxBias, maxBias); joint->bias = cpfclamp(-bias_coef(joint->constraint.errorBias, dt)*(b->a*joint->ratio - a->a - joint->phase)/dt, -maxBias, maxBias);
// compute max impulse
joint->jMax = J_MAX(joint, dt);
} }
static void static void
@ -51,7 +48,7 @@ applyCachedImpulse(cpGearJoint *joint, cpFloat dt_coef)
} }
static void static void
applyImpulse(cpGearJoint *joint) applyImpulse(cpGearJoint *joint, cpFloat dt)
{ {
cpBody *a = joint->constraint.a; cpBody *a = joint->constraint.a;
cpBody *b = joint->constraint.b; cpBody *b = joint->constraint.b;
@ -59,10 +56,12 @@ applyImpulse(cpGearJoint *joint)
// compute relative rotational velocity // compute relative rotational velocity
cpFloat wr = b->w*joint->ratio - a->w; cpFloat wr = b->w*joint->ratio - a->w;
cpFloat jMax = joint->constraint.maxForce*dt;
// compute normal impulse // compute normal impulse
cpFloat j = (joint->bias - wr)*joint->iSum; cpFloat j = (joint->bias - wr)*joint->iSum;
cpFloat jOld = joint->jAcc; cpFloat jOld = joint->jAcc;
joint->jAcc = cpfclamp(jOld + j, -joint->jMax, joint->jMax); joint->jAcc = cpfclamp(jOld + j, -jMax, jMax);
j = joint->jAcc - jOld; j = joint->jAcc - jOld;
// apply impulse // apply impulse

View File

@ -54,10 +54,7 @@ preStep(cpGrooveJoint *joint, cpFloat dt)
} }
// Calculate mass tensor // Calculate mass tensor
k_tensor(a, b, joint->r1, joint->r2, &joint->k1, &joint->k2); joint->k = k_tensor(a, b, joint->r1, joint->r2);
// compute max impulse
joint->jMaxLen = J_MAX(joint, dt);
// calculate bias velocity // calculate bias velocity
cpVect delta = cpvsub(cpvadd(b->p, joint->r2), cpvadd(a->p, joint->r1)); cpVect delta = cpvsub(cpvadd(b->p, joint->r2), cpvadd(a->p, joint->r1));
@ -74,14 +71,14 @@ applyCachedImpulse(cpGrooveJoint *joint, cpFloat dt_coef)
} }
static inline cpVect static inline cpVect
grooveConstrain(cpGrooveJoint *joint, cpVect j){ grooveConstrain(cpGrooveJoint *joint, cpVect j, cpFloat dt){
cpVect n = joint->grv_tn; cpVect n = joint->grv_tn;
cpVect jClamp = (joint->clamp*cpvcross(j, n) > 0.0f) ? j : cpvproject(j, n); cpVect jClamp = (joint->clamp*cpvcross(j, n) > 0.0f) ? j : cpvproject(j, n);
return cpvclamp(jClamp, joint->jMaxLen); return cpvclamp(jClamp, joint->constraint.maxForce*dt);
} }
static void static void
applyImpulse(cpGrooveJoint *joint) applyImpulse(cpGrooveJoint *joint, cpFloat dt)
{ {
cpBody *a = joint->constraint.a; cpBody *a = joint->constraint.a;
cpBody *b = joint->constraint.b; cpBody *b = joint->constraint.b;
@ -92,9 +89,9 @@ applyImpulse(cpGrooveJoint *joint)
// compute impulse // compute impulse
cpVect vr = relative_velocity(a, b, r1, r2); cpVect vr = relative_velocity(a, b, r1, r2);
cpVect j = mult_k(cpvsub(joint->bias, vr), joint->k1, joint->k2); cpVect j = cpMat2x2Transform(joint->k, cpvsub(joint->bias, vr));
cpVect jOld = joint->jAcc; cpVect jOld = joint->jAcc;
joint->jAcc = grooveConstrain(joint, cpvadd(jOld, j)); joint->jAcc = grooveConstrain(joint, cpvadd(jOld, j), dt);
j = cpvsub(joint->jAcc, jOld); j = cpvsub(joint->jAcc, jOld);
// apply impulse // apply impulse

View File

@ -41,9 +41,6 @@ preStep(cpPinJoint *joint, cpFloat dt)
// calculate bias velocity // calculate bias velocity
cpFloat maxBias = joint->constraint.maxBias; cpFloat maxBias = joint->constraint.maxBias;
joint->bias = cpfclamp(-bias_coef(joint->constraint.errorBias, dt)*(dist - joint->dist)/dt, -maxBias, maxBias); joint->bias = cpfclamp(-bias_coef(joint->constraint.errorBias, dt)*(dist - joint->dist)/dt, -maxBias, maxBias);
// compute max impulse
joint->jnMax = J_MAX(joint, dt);
} }
static void static void
@ -57,7 +54,7 @@ applyCachedImpulse(cpPinJoint *joint, cpFloat dt_coef)
} }
static void static void
applyImpulse(cpPinJoint *joint) applyImpulse(cpPinJoint *joint, cpFloat dt)
{ {
cpBody *a = joint->constraint.a; cpBody *a = joint->constraint.a;
cpBody *b = joint->constraint.b; cpBody *b = joint->constraint.b;
@ -66,10 +63,12 @@ applyImpulse(cpPinJoint *joint)
// compute relative velocity // compute relative velocity
cpFloat vrn = normal_relative_velocity(a, b, joint->r1, joint->r2, n); cpFloat vrn = normal_relative_velocity(a, b, joint->r1, joint->r2, n);
cpFloat jnMax = joint->constraint.maxForce*dt;
// compute normal impulse // compute normal impulse
cpFloat jn = (joint->bias - vrn)*joint->nMass; cpFloat jn = (joint->bias - vrn)*joint->nMass;
cpFloat jnOld = joint->jnAcc; cpFloat jnOld = joint->jnAcc;
joint->jnAcc = cpfclamp(jnOld + jn, -joint->jnMax, joint->jnMax); joint->jnAcc = cpfclamp(jnOld + jn, -jnMax, jnMax);
jn = joint->jnAcc - jnOld; jn = joint->jnAcc - jnOld;
// apply impulse // apply impulse
@ -88,7 +87,7 @@ static const cpConstraintClass klass = {
(cpConstraintApplyImpulseImpl)applyImpulse, (cpConstraintApplyImpulseImpl)applyImpulse,
(cpConstraintGetImpulseImpl)getImpulse, (cpConstraintGetImpulseImpl)getImpulse,
}; };
CP_DefineClassGetter(cpPinJoint); CP_DefineClassGetter(cpPinJoint)
cpPinJoint * cpPinJoint *

View File

@ -32,10 +32,7 @@ preStep(cpPivotJoint *joint, cpFloat dt)
joint->r2 = cpvrotate(joint->anchr2, b->rot); joint->r2 = cpvrotate(joint->anchr2, b->rot);
// Calculate mass tensor // Calculate mass tensor
k_tensor(a, b, joint->r1, joint->r2, &joint->k1, &joint->k2); joint-> k = k_tensor(a, b, joint->r1, joint->r2);
// compute max impulse
joint->jMaxLen = J_MAX(joint, dt);
// calculate bias velocity // calculate bias velocity
cpVect delta = cpvsub(cpvadd(b->p, joint->r2), cpvadd(a->p, joint->r1)); cpVect delta = cpvsub(cpvadd(b->p, joint->r2), cpvadd(a->p, joint->r1));
@ -52,7 +49,7 @@ applyCachedImpulse(cpPivotJoint *joint, cpFloat dt_coef)
} }
static void static void
applyImpulse(cpPivotJoint *joint) applyImpulse(cpPivotJoint *joint, cpFloat dt)
{ {
cpBody *a = joint->constraint.a; cpBody *a = joint->constraint.a;
cpBody *b = joint->constraint.b; cpBody *b = joint->constraint.b;
@ -64,9 +61,9 @@ applyImpulse(cpPivotJoint *joint)
cpVect vr = relative_velocity(a, b, r1, r2); cpVect vr = relative_velocity(a, b, r1, r2);
// compute normal impulse // compute normal impulse
cpVect j = mult_k(cpvsub(joint->bias, vr), joint->k1, joint->k2); cpVect j = cpMat2x2Transform(joint->k, cpvsub(joint->bias, vr));
cpVect jOld = joint->jAcc; cpVect jOld = joint->jAcc;
joint->jAcc = cpvclamp(cpvadd(joint->jAcc, j), joint->jMaxLen); joint->jAcc = cpvclamp(cpvadd(joint->jAcc, j), joint->constraint.maxForce*dt);
j = cpvsub(joint->jAcc, jOld); j = cpvsub(joint->jAcc, jOld);
// apply impulse // apply impulse

View File

@ -49,9 +49,6 @@ preStep(cpRatchetJoint *joint, cpFloat dt)
cpFloat maxBias = joint->constraint.maxBias; cpFloat maxBias = joint->constraint.maxBias;
joint->bias = cpfclamp(-bias_coef(joint->constraint.errorBias, dt)*pdist/dt, -maxBias, maxBias); joint->bias = cpfclamp(-bias_coef(joint->constraint.errorBias, dt)*pdist/dt, -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 the bias is 0, the joint is not at a limit. Reset the impulse.
if(!joint->bias) joint->jAcc = 0.0f; if(!joint->bias) joint->jAcc = 0.0f;
} }
@ -68,7 +65,7 @@ applyCachedImpulse(cpRatchetJoint *joint, cpFloat dt_coef)
} }
static void static void
applyImpulse(cpRatchetJoint *joint) applyImpulse(cpRatchetJoint *joint, cpFloat dt)
{ {
if(!joint->bias) return; // early exit if(!joint->bias) return; // early exit
@ -79,10 +76,12 @@ applyImpulse(cpRatchetJoint *joint)
cpFloat wr = b->w - a->w; cpFloat wr = b->w - a->w;
cpFloat ratchet = joint->ratchet; cpFloat ratchet = joint->ratchet;
cpFloat jMax = joint->constraint.maxForce*dt;
// compute normal impulse // compute normal impulse
cpFloat j = -(joint->bias + wr)*joint->iSum; cpFloat j = -(joint->bias + wr)*joint->iSum;
cpFloat jOld = joint->jAcc; cpFloat jOld = joint->jAcc;
joint->jAcc = cpfclamp((jOld + j)*ratchet, 0.0f, joint->jMax*cpfabs(ratchet))/ratchet; joint->jAcc = cpfclamp((jOld + j)*ratchet, 0.0f, jMax*cpfabs(ratchet))/ratchet;
j = joint->jAcc - jOld; j = joint->jAcc - jOld;
// apply impulse // apply impulse

View File

@ -43,9 +43,6 @@ preStep(cpRotaryLimitJoint *joint, cpFloat dt)
cpFloat maxBias = joint->constraint.maxBias; cpFloat maxBias = joint->constraint.maxBias;
joint->bias = cpfclamp(-bias_coef(joint->constraint.errorBias, dt)*pdist/dt, -maxBias, maxBias); joint->bias = cpfclamp(-bias_coef(joint->constraint.errorBias, dt)*pdist/dt, -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 the bias is 0, the joint is not at a limit. Reset the impulse.
if(!joint->bias) joint->jAcc = 0.0f; if(!joint->bias) joint->jAcc = 0.0f;
} }
@ -62,7 +59,7 @@ applyCachedImpulse(cpRotaryLimitJoint *joint, cpFloat dt_coef)
} }
static void static void
applyImpulse(cpRotaryLimitJoint *joint) applyImpulse(cpRotaryLimitJoint *joint, cpFloat dt)
{ {
if(!joint->bias) return; // early exit if(!joint->bias) return; // early exit
@ -72,13 +69,15 @@ applyImpulse(cpRotaryLimitJoint *joint)
// compute relative rotational velocity // compute relative rotational velocity
cpFloat wr = b->w - a->w; cpFloat wr = b->w - a->w;
cpFloat jMax = joint->constraint.maxForce*dt;
// compute normal impulse // compute normal impulse
cpFloat j = -(joint->bias + wr)*joint->iSum; cpFloat j = -(joint->bias + wr)*joint->iSum;
cpFloat jOld = joint->jAcc; cpFloat jOld = joint->jAcc;
if(joint->bias < 0.0f){ if(joint->bias < 0.0f){
joint->jAcc = cpfclamp(jOld + j, 0.0f, joint->jMax); joint->jAcc = cpfclamp(jOld + j, 0.0f, jMax);
} else { } else {
joint->jAcc = cpfclamp(jOld + j, -joint->jMax, 0.0f); joint->jAcc = cpfclamp(jOld + j, -jMax, 0.0f);
} }
j = joint->jAcc - jOld; j = joint->jAcc - jOld;

View File

@ -30,9 +30,6 @@ preStep(cpSimpleMotor *joint, cpFloat dt)
// calculate moment of inertia coefficient. // calculate moment of inertia coefficient.
joint->iSum = 1.0f/(a->i_inv + b->i_inv); joint->iSum = 1.0f/(a->i_inv + b->i_inv);
// compute max impulse
joint->jMax = J_MAX(joint, dt);
} }
static void static void
@ -47,7 +44,7 @@ applyCachedImpulse(cpSimpleMotor *joint, cpFloat dt_coef)
} }
static void static void
applyImpulse(cpSimpleMotor *joint) applyImpulse(cpSimpleMotor *joint, cpFloat dt)
{ {
cpBody *a = joint->constraint.a; cpBody *a = joint->constraint.a;
cpBody *b = joint->constraint.b; cpBody *b = joint->constraint.b;
@ -55,10 +52,12 @@ applyImpulse(cpSimpleMotor *joint)
// compute relative rotational velocity // compute relative rotational velocity
cpFloat wr = b->w - a->w + joint->rate; cpFloat wr = b->w - a->w + joint->rate;
cpFloat jMax = joint->constraint.maxForce*dt;
// compute normal impulse // compute normal impulse
cpFloat j = -wr*joint->iSum; cpFloat j = -wr*joint->iSum;
cpFloat jOld = joint->jAcc; cpFloat jOld = joint->jAcc;
joint->jAcc = cpfclamp(jOld + j, -joint->jMax, joint->jMax); joint->jAcc = cpfclamp(jOld + j, -jMax, jMax);
j = joint->jAcc - jOld; j = joint->jAcc - jOld;
// apply impulse // apply impulse

View File

@ -51,9 +51,6 @@ preStep(cpSlideJoint *joint, cpFloat dt)
// calculate bias velocity // calculate bias velocity
cpFloat maxBias = joint->constraint.maxBias; cpFloat maxBias = joint->constraint.maxBias;
joint->bias = cpfclamp(-bias_coef(joint->constraint.errorBias, dt)*pdist/dt, -maxBias, maxBias); joint->bias = cpfclamp(-bias_coef(joint->constraint.errorBias, dt)*pdist/dt, -maxBias, maxBias);
// compute max impulse
joint->jnMax = J_MAX(joint, dt);
} }
static void static void
@ -67,7 +64,7 @@ applyCachedImpulse(cpSlideJoint *joint, cpFloat dt_coef)
} }
static void static void
applyImpulse(cpSlideJoint *joint) applyImpulse(cpSlideJoint *joint, cpFloat dt)
{ {
if(cpveql(joint->n, cpvzero)) return; // early exit if(cpveql(joint->n, cpvzero)) return; // early exit
@ -85,7 +82,7 @@ applyImpulse(cpSlideJoint *joint)
// compute normal impulse // compute normal impulse
cpFloat jn = (joint->bias - vrn)*joint->nMass; cpFloat jn = (joint->bias - vrn)*joint->nMass;
cpFloat jnOld = joint->jnAcc; cpFloat jnOld = joint->jnAcc;
joint->jnAcc = cpfclamp(jnOld + jn, -joint->jnMax, 0.0f); joint->jnAcc = cpfclamp(jnOld + jn, -joint->constraint.maxForce*dt, 0.0f);
jn = joint->jnAcc - jnOld; jn = joint->jnAcc - jnOld;
// apply impulse // apply impulse

View File

@ -212,6 +212,8 @@ cpArbiterInit(cpArbiter *arb, cpShape *a, cpShape *b)
arb->stamp = 0; arb->stamp = 0;
arb->state = cpArbiterStateFirstColl; arb->state = cpArbiterStateFirstColl;
arb->data = NULL;
return arb; return arb;
} }

View File

@ -21,14 +21,6 @@
#include "chipmunk_private.h" #include "chipmunk_private.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 cpVect
cpBBWrapVect(const cpBB bb, const cpVect v) cpBBWrapVect(const cpBB bb, const cpVect v)
{ {

View File

@ -105,11 +105,11 @@ GetRootIfTree(cpSpatialIndex *index){
return (index && index->klass == Klass() ? ((cpBBTree *)index)->root : NULL); return (index && index->klass == Klass() ? ((cpBBTree *)index)->root : NULL);
} }
static inline cpTimestamp static inline cpBBTree *
GetStamp(cpBBTree *tree) GetMasterTree(cpBBTree *tree)
{ {
cpBBTree *dynamicTree = GetTree(tree->spatialIndex.dynamicIndex); cpBBTree *dynamicTree = GetTree(tree->spatialIndex.dynamicIndex);
return (dynamicTree ? dynamicTree->stamp : tree->stamp); return (dynamicTree ? dynamicTree : tree);
} }
static inline void static inline void
@ -128,6 +128,10 @@ IncrementStamp(cpBBTree *tree)
static void static void
PairRecycle(cpBBTree *tree, Pair *pair) PairRecycle(cpBBTree *tree, Pair *pair)
{ {
// Share the pool of the master tree.
// TODO would be lovely to move the pairs stuff into an external data structure.
tree = GetMasterTree(tree);
pair->a.next = tree->pooledPairs; pair->a.next = tree->pooledPairs;
tree->pooledPairs = pair; tree->pooledPairs = pair;
} }
@ -135,6 +139,10 @@ PairRecycle(cpBBTree *tree, Pair *pair)
static Pair * static Pair *
PairFromPool(cpBBTree *tree) PairFromPool(cpBBTree *tree)
{ {
// Share the pool of the master tree.
// TODO would be lovely to move the pairs stuff into an external data structure.
tree = GetMasterTree(tree);
Pair *pair = tree->pooledPairs; Pair *pair = tree->pooledPairs;
if(pair){ if(pair){
@ -433,7 +441,7 @@ static void
MarkLeaf(Node *leaf, MarkContext *context) MarkLeaf(Node *leaf, MarkContext *context)
{ {
cpBBTree *tree = context->tree; cpBBTree *tree = context->tree;
if(leaf->STAMP == GetStamp(tree)){ if(leaf->STAMP == GetMasterTree(tree)->stamp){
Node *staticRoot = context->staticRoot; Node *staticRoot = context->staticRoot;
if(staticRoot) MarkLeafQuery(staticRoot, leaf, cpFalse, context); if(staticRoot) MarkLeafQuery(staticRoot, leaf, cpFalse, context);
@ -497,7 +505,7 @@ LeafUpdate(Node *leaf, cpBBTree *tree)
tree->root = SubtreeInsert(root, leaf, tree); tree->root = SubtreeInsert(root, leaf, tree);
PairsClear(leaf, tree); PairsClear(leaf, tree);
leaf->STAMP = GetStamp(tree); leaf->STAMP = GetMasterTree(tree)->stamp;
return cpTrue; return cpTrue;
} }
@ -599,7 +607,7 @@ cpBBTreeInsert(cpBBTree *tree, void *obj, cpHashValue hashid)
Node *root = tree->root; Node *root = tree->root;
tree->root = SubtreeInsert(root, leaf, tree); tree->root = SubtreeInsert(root, leaf, tree);
leaf->STAMP = GetStamp(tree); leaf->STAMP = GetMasterTree(tree)->stamp;
LeafAddPairs(leaf, tree); LeafAddPairs(leaf, tree);
IncrementStamp(tree); IncrementStamp(tree);
} }

View File

@ -142,6 +142,7 @@ cpBodySetMass(cpBody *body, cpFloat mass)
cpBodyActivate(body); cpBodyActivate(body);
body->m = mass; body->m = mass;
body->m_inv = 1.0f/mass; body->m_inv = 1.0f/mass;
cpBodyAssertSane(body);
} }
void void
@ -152,6 +153,7 @@ cpBodySetMoment(cpBody *body, cpFloat moment)
cpBodyActivate(body); cpBodyActivate(body);
body->i = moment; body->i = moment;
body->i_inv = 1.0f/moment; body->i_inv = 1.0f/moment;
cpBodyAssertSane(body);
} }
void void
@ -208,8 +210,8 @@ void
cpBodySetPos(cpBody *body, cpVect pos) cpBodySetPos(cpBody *body, cpVect pos)
{ {
cpBodyActivate(body); cpBodyActivate(body);
cpBodyAssertSane(body);
body->p = pos; body->p = pos;
cpBodyAssertSane(body);
} }
static inline void static inline void
@ -217,13 +219,13 @@ setAngle(cpBody *body, cpFloat angle)
{ {
body->a = angle;//fmod(a, (cpFloat)M_PI*2.0f); body->a = angle;//fmod(a, (cpFloat)M_PI*2.0f);
body->rot = cpvforangle(angle); body->rot = cpvforangle(angle);
cpBodyAssertSane(body);
} }
void void
cpBodySetAngle(cpBody *body, cpFloat angle) cpBodySetAngle(cpBody *body, cpFloat angle)
{ {
cpBodyActivate(body); cpBodyActivate(body);
cpBodyAssertSane(body);
setAngle(body, angle); setAngle(body, angle);
} }

View File

@ -322,6 +322,64 @@ circle2poly(const cpShape *shape1, const cpShape *shape2, cpContact *con)
} }
} }
// Submitted by LegoCyclon
static int
seg2seg(const cpShape* shape1, const cpShape* shape2, cpContact* con)
{
cpSegmentShape* seg1 = (cpSegmentShape *)shape1;
cpSegmentShape* seg2 = (cpSegmentShape *)shape2;
cpVect v1 = cpvsub(seg1->tb, seg1->ta);
cpVect v2 = cpvsub(seg2->tb, seg2->ta);
cpFloat v1lsq = cpvlengthsq(v1);
cpFloat v2lsq = cpvlengthsq(v2);
// project seg2 onto seg1
cpVect p1a = cpvproject(cpvsub(seg2->ta, seg1->ta), v1);
cpVect p1b = cpvproject(cpvsub(seg2->tb, seg1->ta), v1);
// project seg1 onto seg2
cpVect p2a = cpvproject(cpvsub(seg1->ta, seg2->ta), v2);
cpVect p2b = cpvproject(cpvsub(seg1->tb, seg2->ta), v2);
// clamp projections to segment endcaps
if (cpvdot(p1a, v1) < 0.0f)
p1a = cpvzero;
else if (cpvdot(p1a, v1) > 0.0f && cpvlengthsq(p1a) > v1lsq)
p1a = v1;
if (cpvdot(p1b, v1) < 0.0f)
p1b = cpvzero;
else if (cpvdot(p1b, v1) > 0.0f && cpvlengthsq(p1b) > v1lsq)
p1b = v1;
if (cpvdot(p2a, v2) < 0.0f)
p2a = cpvzero;
else if (cpvdot(p2a, v2) > 0.0f && cpvlengthsq(p2a) > v2lsq)
p2a = v2;
if (cpvdot(p2b, v2) < 0.0f)
p2b = cpvzero;
else if (cpvdot(p2b, v2) > 0.0f && cpvlengthsq(p2b) > v2lsq)
p2b = v2;
p1a = cpvadd(p1a, seg1->ta);
p1b = cpvadd(p1b, seg1->ta);
p2a = cpvadd(p2a, seg2->ta);
p2b = cpvadd(p2b, seg2->ta);
int num = 0;
if (!circle2circleQuery(p1a, p2a, seg1->r, seg2->r, nextContactPoint(con, &num)))
--num;
if (!circle2circleQuery(p1b, p2b, seg1->r, seg2->r, nextContactPoint(con, &num)))
--num;
if (!circle2circleQuery(p1a, p2b, seg1->r, seg2->r, nextContactPoint(con, &num)))
--num;
if (!circle2circleQuery(p1b, p2a, seg1->r, seg2->r, nextContactPoint(con, &num)))
--num;
return num;
}
static const collisionFunc builtinCollisionFuncs[9] = { static const collisionFunc builtinCollisionFuncs[9] = {
circle2circle, circle2circle,
NULL, NULL,
@ -335,36 +393,23 @@ static const collisionFunc builtinCollisionFuncs[9] = {
}; };
static const collisionFunc *colfuncs = builtinCollisionFuncs; static const collisionFunc *colfuncs = builtinCollisionFuncs;
//static collisionFunc *colfuncs = NULL; static const collisionFunc segmentCollisions[9] = {
// circle2circle,
//static void NULL,
//addColFunc(const cpShapeType a, const cpShapeType b, const collisionFunc func) NULL,
//{ (collisionFunc)circle2segment,
// colfuncs[a + b*CP_NUM_SHAPES] = func; seg2seg,
//} NULL,
// circle2poly,
//#ifdef __cplusplus seg2poly,
//extern "C" { poly2poly,
//#endif };
// void cpInitCollisionFuncs(void);
// void
// // Initializes the array of collision functions. cpEnableSegmentToSegmentCollisions(void)
// // Called by cpInitChipmunk(). {
// void colfuncs = segmentCollisions;
// 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 int
cpCollideShapes(const cpShape *a, const cpShape *b, cpContact *arr) cpCollideShapes(const cpShape *a, const cpShape *b, cpContact *arr)

View File

@ -181,7 +181,7 @@ cpPolyShapeGetVert(cpShape *shape, int idx)
static void static void
setUpVerts(cpPolyShape *poly, int numVerts, cpVect *verts, cpVect offset) setUpVerts(cpPolyShape *poly, int numVerts, const cpVect *verts, cpVect offset)
{ {
// Fail if the user attempts to pass a concave poly, or a bad winding. // Fail if the user attempts to pass a concave poly, or a bad winding.
cpAssertHard(cpPolyValidate(verts, numVerts), "Polygon is concave or has a reversed winding. Consider using cpConvexHull() or CP_CONVEX_HULL()."); cpAssertHard(cpPolyValidate(verts, numVerts), "Polygon is concave or has a reversed winding. Consider using cpConvexHull() or CP_CONVEX_HULL().");
@ -205,7 +205,7 @@ setUpVerts(cpPolyShape *poly, int numVerts, cpVect *verts, cpVect offset)
} }
cpPolyShape * cpPolyShape *
cpPolyShapeInit(cpPolyShape *poly, cpBody *body, int numVerts, cpVect *verts, cpVect offset) cpPolyShapeInit(cpPolyShape *poly, cpBody *body, int numVerts, const cpVect *verts, cpVect offset)
{ {
setUpVerts(poly, numVerts, verts, offset); setUpVerts(poly, numVerts, verts, offset);
cpShapeInit((cpShape *)poly, &polyClass, body); cpShapeInit((cpShape *)poly, &polyClass, body);

View File

@ -103,7 +103,7 @@ cpShapeUpdate(cpShape *shape, cpVect pos, cpVect rot)
cpBool cpBool
cpShapePointQuery(cpShape *shape, cpVect p){ cpShapePointQuery(cpShape *shape, cpVect p){
cpNearestPointQueryInfo info = {}; cpNearestPointQueryInfo info = {NULL, cpvzero, INFINITY};
cpShapeNearestPointQuery(shape, p, &info); cpShapeNearestPointQuery(shape, p, &info);
return (info.d < 0.0f); return (info.d < 0.0f);

View File

@ -284,7 +284,9 @@ ShapeQuery(cpShape *a, cpShape *b, struct ShapeQueryContext *context)
context->anyCollision = !(a->sensor || b->sensor); context->anyCollision = !(a->sensor || b->sensor);
if(context->func){ if(context->func){
cpContactPointSet set = {numContacts, {}}; cpContactPointSet set;
set.count = numContacts;
for(int i=0; i<set.count; i++){ for(int i=0; i<set.count; i++){
set.points[i].point = contacts[i].p; set.points[i].point = contacts[i].p;
set.points[i].normal = contacts[i].n; set.points[i].normal = contacts[i].n;

View File

@ -23,38 +23,37 @@
//MARK: Post Step Callback Functions //MARK: Post Step Callback Functions
typedef struct cpPostStepCallback { cpPostStepCallback *
cpPostStepFunc func; cpSpaceGetPostStepCallback(cpSpace *space, void *key)
void *key;
void *data;
} cpPostStepCallback;
void *
cpSpaceGetPostStepData(cpSpace *space, void *key)
{ {
cpArray *arr = space->postStepCallbacks; cpArray *arr = space->postStepCallbacks;
for(int i=0; i<arr->num; i++){ for(int i=0; i<arr->num; i++){
cpPostStepCallback *callback = (cpPostStepCallback *)arr->arr[i]; cpPostStepCallback *callback = (cpPostStepCallback *)arr->arr[i];
if(callback->key == key) return callback->data; if(callback->key == key) return callback;
} }
return NULL; return NULL;
} }
void static void PostStepDoNothing(cpSpace *space, void *obj, void *data){}
cpBool
cpSpaceAddPostStepCallback(cpSpace *space, cpPostStepFunc func, void *key, void *data) cpSpaceAddPostStepCallback(cpSpace *space, cpPostStepFunc func, void *key, void *data)
{ {
cpAssertWarn(space->locked, cpAssertWarn(space->locked,
"Adding a post-step callback when the space is not locked is unnecessary. " "Adding a post-step callback when the space is not locked is unnecessary. "
"Post-step callbacks will not called until the end of the next call to cpSpaceStep() or the next query."); "Post-step callbacks will not called until the end of the next call to cpSpaceStep() or the next query.");
if(!cpSpaceGetPostStepData(space, key)){ if(!cpSpaceGetPostStepCallback(space, key)){
cpPostStepCallback *callback = (cpPostStepCallback *)cpcalloc(1, sizeof(cpPostStepCallback)); cpPostStepCallback *callback = (cpPostStepCallback *)cpcalloc(1, sizeof(cpPostStepCallback));
callback->func = func; callback->func = (func ? func : PostStepDoNothing);
callback->key = key; callback->key = key;
callback->data = data; callback->data = data;
cpArrayPush(space->postStepCallbacks, callback); cpArrayPush(space->postStepCallbacks, callback);
return cpTrue;
} else {
return cpFalse;
} }
} }
@ -409,7 +408,7 @@ cpSpaceStep(cpSpace *space, cpFloat dt)
for(int j=0; j<constraints->num; j++){ for(int j=0; j<constraints->num; j++){
cpConstraint *constraint = (cpConstraint *)constraints->arr[j]; cpConstraint *constraint = (cpConstraint *)constraints->arr[j];
constraint->klass->applyImpulse(constraint); constraint->klass->applyImpulse(constraint, dt);
} }
} }

View File

@ -61,7 +61,7 @@ dynamicToStaticIter(void *obj, dynamicToStaticContext *context)
void void
cpSpatialIndexCollideStatic(cpSpatialIndex *dynamicIndex, cpSpatialIndex *staticIndex, cpSpatialIndexQueryFunc func, void *data) cpSpatialIndexCollideStatic(cpSpatialIndex *dynamicIndex, cpSpatialIndex *staticIndex, cpSpatialIndexQueryFunc func, void *data)
{ {
if(cpSpatialIndexCount(staticIndex) > 0){ if(staticIndex && cpSpatialIndexCount(staticIndex) > 0){
dynamicToStaticContext context = {dynamicIndex->bbfunc, staticIndex, func, data}; dynamicToStaticContext context = {dynamicIndex->bbfunc, staticIndex, func, data};
cpSpatialIndexEach(dynamicIndex, (cpSpatialIndexIteratorFunc)dynamicToStaticIter, &context); cpSpatialIndexEach(dynamicIndex, (cpSpatialIndexIteratorFunc)dynamicToStaticIter, &context);
} }

View File

@ -23,42 +23,27 @@
#include "chipmunk_private.h" #include "chipmunk_private.h"
cpFloat
cpvlength(const cpVect v)
{
return cpfsqrt(cpvdot(v, v));
}
inline cpVect inline cpVect
cpvslerp(const cpVect v1, const cpVect v2, const cpFloat t) cpvslerp(const cpVect v1, const cpVect v2, const cpFloat t)
{ {
cpFloat omega = cpfacos(cpvdot(v1, v2)); cpFloat dot = cpvdot(cpvnormalize(v1), cpvnormalize(v2));
cpFloat omega = cpfacos(cpfclamp(dot, -1.0f, 1.0f));
if(omega){ if(omega == 0.0){
return v1;
} else {
cpFloat denom = 1.0f/cpfsin(omega); cpFloat denom = 1.0f/cpfsin(omega);
return cpvadd(cpvmult(v1, cpfsin((1.0f - t)*omega)*denom), cpvmult(v2, cpfsin(t*omega)*denom)); return cpvadd(cpvmult(v1, cpfsin((1.0f - t)*omega)*denom), cpvmult(v2, cpfsin(t*omega)*denom));
} else {
return v1;
} }
} }
cpVect cpVect
cpvslerpconst(const cpVect v1, const cpVect v2, const cpFloat a) cpvslerpconst(const cpVect v1, const cpVect v2, const cpFloat a)
{ {
cpFloat angle = cpfacos(cpvdot(v1, v2)); cpFloat dot = cpvdot(cpvnormalize(v1), cpvnormalize(v2));
return cpvslerp(v1, v2, cpfmin(a, angle)/angle); cpFloat omega = cpfacos(cpfclamp(dot, -1.0f, 1.0f));
}
cpVect return cpvslerp(v1, v2, cpfmin(a, omega)/omega);
cpvforangle(const cpFloat a)
{
return cpv(cpfcos(a), cpfsin(a));
}
cpFloat
cpvtoangle(const cpVect v)
{
return cpfatan2(v.y, v.x);
} }
char* char*