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"
// Chipmunk 6.1.1
// Chipmunk 6.1.2
#define CP_VERSION_MAJOR 6
#define CP_VERSION_MINOR 1
#define CP_VERSION_RELEASE 1
#define CP_VERSION_RELEASE 2
/// Version string.
extern const char *cpVersionString;
@ -117,6 +117,10 @@ extern const char *cpVersionString;
/// @deprecated
void cpInitChipmunk(void);
/// Enables segment to segment shape collisions.
void cpEnableSegmentToSegmentCollisions(void);
/// 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.
cpFloat cpMomentForCircle(cpFloat m, cpFloat r1, cpFloat r2, cpVect offset);

View File

@ -14,7 +14,7 @@
#endif
#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(cpveql);

View File

@ -188,7 +188,13 @@ void cpSpacePushFreshContactBuffer(cpSpace *space);
cpContact *cpContactBufferGetArray(cpSpace *space);
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);
void cpSpaceFilterArbiters(cpSpace *space, cpBody *body, cpShape *filter);

View File

@ -1,11 +1,7 @@
#include <math.h>
#ifndef WIN32
#include <stdint.h>
#endif
#ifdef __APPLE__
#import "TargetConditionals.h"
#include "TargetConditionals.h"
#endif
#if (TARGET_OS_IPHONE == 1) || (TARGET_OS_MAC == 1) && (!defined CP_USE_CGPOINTS)
@ -16,7 +12,7 @@
#if TARGET_OS_IPHONE
#import <CoreGraphics/CGGeometry.h>
#elif TARGET_OS_MAC
#import <ApplicationServices/ApplicationServices.h>
#include <ApplicationServices/ApplicationServices.h>
#endif
#if defined(__LP64__) && __LP64__
@ -213,4 +209,7 @@ typedef uintptr_t cpHashValue;
typedef struct cpVect{cpFloat x,y;} cpVect;
#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 (*cpConstraintApplyCachedImpulseImpl)(cpConstraint *constraint, cpFloat dt_coef);
typedef void (*cpConstraintApplyImpulseImpl)(cpConstraint *constraint);
typedef void (*cpConstraintApplyImpulseImpl)(cpConstraint *constraint, cpFloat dt);
typedef cpFloat (*cpConstraintGetImpulseImpl)(cpConstraint *constraint);
/// @private
@ -110,16 +110,16 @@ static inline void cpConstraint##Set##name(cpConstraint *constraint, type value)
CP_DefineConstraintStructGetter(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*, b, B);
CP_DefineConstraintStructProperty(cpFloat, maxForce, MaxForce);
CP_DefineConstraintStructProperty(cpFloat, errorBias, ErrorBias);
CP_DefineConstraintStructProperty(cpFloat, maxBias, MaxBias);
CP_DefineConstraintStructProperty(cpConstraintPreSolveFunc, preSolve, PreSolveFunc);
CP_DefineConstraintStructProperty(cpConstraintPostSolveFunc, postSolve, PostSolveFunc);
CP_DefineConstraintStructProperty(cpDataPointer, data, UserData);
CP_DefineConstraintStructGetter(cpBody*, a, A)
CP_DefineConstraintStructGetter(cpBody*, b, B)
CP_DefineConstraintStructProperty(cpFloat, maxForce, MaxForce)
CP_DefineConstraintStructProperty(cpFloat, errorBias, ErrorBias)
CP_DefineConstraintStructProperty(cpFloat, maxBias, MaxBias)
CP_DefineConstraintStructProperty(cpConstraintPreSolveFunc, preSolve, PreSolveFunc)
CP_DefineConstraintStructProperty(cpConstraintPostSolveFunc, postSolve, PostSolveFunc)
CP_DefineConstraintStructProperty(cpDataPointer, data, UserData)
// Get the last impulse applied by this 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.
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);
CP_DefineConstraintProperty(cpDampedRotarySpring, cpFloat, restAngle, RestAngle)
CP_DefineConstraintProperty(cpDampedRotarySpring, cpFloat, stiffness, Stiffness)
CP_DefineConstraintProperty(cpDampedRotarySpring, cpFloat, damping, Damping)
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.
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);
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)
/// @}

View File

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

View File

@ -33,10 +33,9 @@ typedef struct cpGrooveJoint {
cpVect grv_tn;
cpFloat clamp;
cpVect r1, r2;
cpVect k1, k2;
cpMat2x2 k;
cpVect jAcc;
cpFloat jMaxLen;
cpVect bias;
} cpGrooveJoint;
@ -47,12 +46,12 @@ cpGrooveJoint* cpGrooveJointInit(cpGrooveJoint *joint, cpBody *a, cpBody *b, cpV
/// Allocate and initialize a groove joint.
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
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
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;
cpFloat nMass;
cpFloat jnAcc, jnMax;
cpFloat jnAcc;
cpFloat bias;
} cpPinJoint;
@ -45,8 +45,8 @@ cpPinJoint* cpPinJointInit(cpPinJoint *joint, cpBody *a, cpBody *b, cpVect anchr
/// Allocate and initialize a pin joint.
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);
CP_DefineConstraintProperty(cpPinJoint, cpVect, anchr1, Anchr1)
CP_DefineConstraintProperty(cpPinJoint, cpVect, anchr2, Anchr2)
CP_DefineConstraintProperty(cpPinJoint, cpFloat, dist, Dist)
///@}

View File

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

View File

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

View File

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

View File

@ -31,7 +31,7 @@ typedef struct cpSimpleMotor {
cpFloat iSum;
cpFloat jAcc, jMax;
cpFloat jAcc;
} cpSimpleMotor;
/// Allocate a simple motor.
@ -41,6 +41,6 @@ cpSimpleMotor* cpSimpleMotorInit(cpSimpleMotor *joint, cpBody *a, cpBody *b, cpF
/// Allocate and initialize a simple motor.
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;
cpFloat nMass;
cpFloat jnAcc, jnMax;
cpFloat jnAcc;
cpFloat bias;
} cpSlideJoint;
@ -45,9 +45,9 @@ cpSlideJoint* cpSlideJointInit(cpSlideJoint *joint, cpBody *a, cpBody *b, cpVect
/// Allocate and initialize a slide joint.
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);
CP_DefineConstraintProperty(cpSlideJoint, cpVect, anchr1, Anchr1)
CP_DefineConstraintProperty(cpSlideJoint, cpVect, anchr2, Anchr2)
CP_DefineConstraintProperty(cpSlideJoint, cpFloat, min, Min)
CP_DefineConstraintProperty(cpSlideJoint, cpFloat, max, Max)
/// @}

View File

@ -27,8 +27,6 @@
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));
@ -85,17 +83,14 @@ k_scalar(cpBody *a, cpBody *b, cpVect r1, cpVect r2, cpVect n)
return value;
}
static inline void
k_tensor(cpBody *a, cpBody *b, cpVect r1, cpVect r2, cpVect *k1, cpVect *k2)
static inline cpMat2x2
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;
// start with I*m_sum
k11 = m_sum; k12 = 0.0f;
k21 = 0.0f; k22 = m_sum;
// start with Identity*m_sum
cpFloat k11 = m_sum, k12 = 0.0f;
cpFloat k21 = 0.0f, k22 = m_sum;
// add the influence from r1
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;
// invert
cpFloat determinant = k11*k22 - k12*k21;
cpAssertSoft(determinant != 0.0, "Unsolvable constraint.");
cpFloat det = k11*k22 - k12*k21;
cpAssertSoft(det != 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));
cpFloat det_inv = 1.0f/det;
return cpMat2x2New(
k22*det_inv, -k12*det_inv,
-k21*det_inv, k11*det_inv
);
}
static inline cpFloat

View File

@ -83,6 +83,11 @@ struct cpArbiter {
/// Override in a pre-solve collision handler for custom behavior.
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 *b);
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_DefineArbiterStructSetter(type, member, name)
CP_DefineArbiterStructProperty(cpFloat, e, Elasticity);
CP_DefineArbiterStructProperty(cpFloat, u, Friction);
CP_DefineArbiterStructProperty(cpVect, surface_vr, SurfaceVelocity);
CP_DefineArbiterStructProperty(cpFloat, e, Elasticity)
CP_DefineArbiterStructProperty(cpFloat, u, Friction)
CP_DefineArbiterStructProperty(cpVect, surface_vr, SurfaceVelocity)
CP_DefineArbiterStructProperty(cpDataPointer, data, UserData)
/// 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.

View File

@ -123,7 +123,11 @@ static inline cpBool cpBBIntersectsSegment(cpBB bb, cpVect a, cpVect b)
}
/// 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
/// 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) \
static inline void cpBodySet##name(cpBody *body, const type value){ \
cpBodyActivate(body); \
cpBodyAssertSane(body); \
body->member = value; \
cpBodyAssertSane(body); \
}
#define CP_DefineBodyStructProperty(type, member, name) \
@ -169,30 +169,30 @@ CP_DefineBodyStructGetter(type, member, name) \
CP_DefineBodyStructSetter(type, member, name)
// 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.
void cpBodySetMass(cpBody *body, cpFloat m);
CP_DefineBodyStructGetter(cpFloat, i, Moment);
CP_DefineBodyStructGetter(cpFloat, i, Moment)
/// Set the moment of a body.
void cpBodySetMoment(cpBody *body, cpFloat i);
CP_DefineBodyStructGetter(cpVect, p, Pos);
CP_DefineBodyStructGetter(cpVect, p, Pos)
/// Set the position of a body.
void cpBodySetPos(cpBody *body, cpVect pos);
CP_DefineBodyStructProperty(cpVect, v, Vel);
CP_DefineBodyStructProperty(cpVect, f, Force);
CP_DefineBodyStructGetter(cpFloat, a, Angle);
CP_DefineBodyStructProperty(cpVect, v, Vel)
CP_DefineBodyStructProperty(cpVect, f, Force)
CP_DefineBodyStructGetter(cpFloat, a, Angle)
/// Set the angle of a body.
void cpBodySetAngle(cpBody *body, cpFloat a);
CP_DefineBodyStructProperty(cpFloat, w, AngVel);
CP_DefineBodyStructProperty(cpFloat, t, Torque);
CP_DefineBodyStructGetter(cpVect, rot, Rot);
CP_DefineBodyStructProperty(cpFloat, v_limit, VelLimit);
CP_DefineBodyStructProperty(cpFloat, w_limit, AngVelLimit);
CP_DefineBodyStructProperty(cpDataPointer, data, UserData);
CP_DefineBodyStructProperty(cpFloat, w, AngVel)
CP_DefineBodyStructProperty(cpFloat, t, Torque)
CP_DefineBodyStructGetter(cpVect, rot, Rot)
CP_DefineBodyStructProperty(cpFloat, v_limit, VelLimit)
CP_DefineBodyStructProperty(cpFloat, w_limit, AngVelLimit)
CP_DefineBodyStructProperty(cpDataPointer, data, UserData)
/// Default Integration functions.
void cpBodyUpdateVelocity(cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt);

View File

@ -41,7 +41,7 @@ typedef struct cpPolyShape {
cpPolyShape* cpPolyShapeAlloc(void);
/// Initialize a polygon shape.
/// 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.
/// A convex hull will be created from the vertexes.
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_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);
CP_DefineShapeStructGetter(cpBB, bb, BB);
CP_DefineShapeStructProperty(cpBool, sensor, Sensor, cpTrue);
CP_DefineShapeStructProperty(cpFloat, e, Elasticity, cpFalse);
CP_DefineShapeStructProperty(cpFloat, u, Friction, cpTrue);
CP_DefineShapeStructProperty(cpVect, surface_v, SurfaceVelocity, cpTrue);
CP_DefineShapeStructProperty(cpDataPointer, data, UserData, cpFalse);
CP_DefineShapeStructProperty(cpCollisionType, collision_type, CollisionType, cpTrue);
CP_DefineShapeStructProperty(cpGroup, group, Group, cpTrue);
CP_DefineShapeStructProperty(cpLayers, layers, Layers, cpTrue);
CP_DefineShapeStructGetter(cpBB, bb, BB)
CP_DefineShapeStructProperty(cpBool, sensor, Sensor, cpTrue)
CP_DefineShapeStructProperty(cpFloat, e, Elasticity, cpFalse)
CP_DefineShapeStructProperty(cpFloat, u, Friction, cpTrue)
CP_DefineShapeStructProperty(cpVect, surface_v, SurfaceVelocity, cpTrue)
CP_DefineShapeStructProperty(cpDataPointer, data, UserData, cpFalse)
CP_DefineShapeStructProperty(cpCollisionType, collision_type, CollisionType, cpTrue)
CP_DefineShapeStructProperty(cpGroup, group, Group, cpTrue)
CP_DefineShapeStructProperty(cpLayers, layers, Layers, cpTrue)
/// 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

View File

@ -127,18 +127,18 @@ static inline void cpSpaceSet##name(cpSpace *space, type value){space->member =
CP_DefineSpaceStructGetter(type, member, name) \
CP_DefineSpaceStructSetter(type, member, name)
CP_DefineSpaceStructProperty(int, iterations, Iterations);
CP_DefineSpaceStructProperty(cpVect, gravity, Gravity);
CP_DefineSpaceStructProperty(cpFloat, damping, Damping);
CP_DefineSpaceStructProperty(cpFloat, idleSpeedThreshold, IdleSpeedThreshold);
CP_DefineSpaceStructProperty(cpFloat, sleepTimeThreshold, SleepTimeThreshold);
CP_DefineSpaceStructProperty(cpFloat, collisionSlop, CollisionSlop);
CP_DefineSpaceStructProperty(cpFloat, collisionBias, CollisionBias);
CP_DefineSpaceStructProperty(cpTimestamp, collisionPersistence, CollisionPersistence);
CP_DefineSpaceStructProperty(cpBool, enableContactGraph, EnableContactGraph);
CP_DefineSpaceStructProperty(cpDataPointer, data, UserData);
CP_DefineSpaceStructGetter(cpBody*, staticBody, StaticBody);
CP_DefineSpaceStructGetter(cpFloat, CP_PRIVATE(curr_dt), CurrentTimeStep);
CP_DefineSpaceStructProperty(int, iterations, Iterations)
CP_DefineSpaceStructProperty(cpVect, gravity, Gravity)
CP_DefineSpaceStructProperty(cpFloat, damping, Damping)
CP_DefineSpaceStructProperty(cpFloat, idleSpeedThreshold, IdleSpeedThreshold)
CP_DefineSpaceStructProperty(cpFloat, sleepTimeThreshold, SleepTimeThreshold)
CP_DefineSpaceStructProperty(cpFloat, collisionSlop, CollisionSlop)
CP_DefineSpaceStructProperty(cpFloat, collisionBias, CollisionBias)
CP_DefineSpaceStructProperty(cpTimestamp, collisionPersistence, CollisionPersistence)
CP_DefineSpaceStructProperty(cpBool, enableContactGraph, EnableContactGraph)
CP_DefineSpaceStructProperty(cpDataPointer, data, UserData)
CP_DefineSpaceStructGetter(cpBody*, staticBody, StaticBody)
CP_DefineSpaceStructGetter(cpFloat, CP_PRIVATE(curr_dt), CurrentTimeStep)
/// returns true from inside a callback and objects cannot be added/removed.
static inline cpBool
@ -202,10 +202,12 @@ cpBool cpSpaceContainsBody(cpSpace *space, cpBody *body);
cpBool cpSpaceContainsConstraint(cpSpace *space, cpConstraint *constraint);
/// 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.
/// 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.
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;
}
/// Returns the length of v.
cpFloat cpvlength(const cpVect v);
/// Spherical linearly interpolate between v1 and v2.
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
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.
/// @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.
@ -115,6 +106,18 @@ static inline cpVect cpvproject(const cpVect v1, const cpVect 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.
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);
}
/// Returns the length of v.
static inline cpFloat cpvlength(const cpVect v)
{
return cpfsqrt(cpvdot(v, v));
}
/// Linearly interpolate between v1 and v2.
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;
}
/// @}
/// @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}
)
# 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)
endif(BUILD_SHARED)

View File

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

View File

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

View File

@ -54,10 +54,7 @@ preStep(cpGrooveJoint *joint, cpFloat dt)
}
// Calculate mass tensor
k_tensor(a, b, joint->r1, joint->r2, &joint->k1, &joint->k2);
// compute max impulse
joint->jMaxLen = J_MAX(joint, dt);
joint->k = k_tensor(a, b, joint->r1, joint->r2);
// calculate bias velocity
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
grooveConstrain(cpGrooveJoint *joint, cpVect j){
grooveConstrain(cpGrooveJoint *joint, cpVect j, cpFloat dt){
cpVect n = joint->grv_tn;
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
applyImpulse(cpGrooveJoint *joint)
applyImpulse(cpGrooveJoint *joint, cpFloat dt)
{
cpBody *a = joint->constraint.a;
cpBody *b = joint->constraint.b;
@ -92,9 +89,9 @@ applyImpulse(cpGrooveJoint *joint)
// compute impulse
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;
joint->jAcc = grooveConstrain(joint, cpvadd(jOld, j));
joint->jAcc = grooveConstrain(joint, cpvadd(jOld, j), dt);
j = cpvsub(joint->jAcc, jOld);
// apply impulse

View File

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

View File

@ -32,10 +32,7 @@ preStep(cpPivotJoint *joint, cpFloat dt)
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);
joint-> k = k_tensor(a, b, joint->r1, joint->r2);
// calculate bias velocity
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
applyImpulse(cpPivotJoint *joint)
applyImpulse(cpPivotJoint *joint, cpFloat dt)
{
cpBody *a = joint->constraint.a;
cpBody *b = joint->constraint.b;
@ -64,9 +61,9 @@ applyImpulse(cpPivotJoint *joint)
cpVect vr = relative_velocity(a, b, r1, r2);
// 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;
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);
// apply impulse

View File

@ -48,9 +48,6 @@ preStep(cpRatchetJoint *joint, cpFloat dt)
// calculate bias velocity
cpFloat maxBias = joint->constraint.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(!joint->bias) joint->jAcc = 0.0f;
@ -68,7 +65,7 @@ applyCachedImpulse(cpRatchetJoint *joint, cpFloat dt_coef)
}
static void
applyImpulse(cpRatchetJoint *joint)
applyImpulse(cpRatchetJoint *joint, cpFloat dt)
{
if(!joint->bias) return; // early exit
@ -79,10 +76,12 @@ applyImpulse(cpRatchetJoint *joint)
cpFloat wr = b->w - a->w;
cpFloat ratchet = joint->ratchet;
cpFloat jMax = joint->constraint.maxForce*dt;
// 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;
joint->jAcc = cpfclamp((jOld + j)*ratchet, 0.0f, jMax*cpfabs(ratchet))/ratchet;
j = joint->jAcc - jOld;
// apply impulse

View File

@ -42,9 +42,6 @@ preStep(cpRotaryLimitJoint *joint, cpFloat dt)
// calculate bias velocity
cpFloat maxBias = joint->constraint.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(!joint->bias) joint->jAcc = 0.0f;
@ -62,7 +59,7 @@ applyCachedImpulse(cpRotaryLimitJoint *joint, cpFloat dt_coef)
}
static void
applyImpulse(cpRotaryLimitJoint *joint)
applyImpulse(cpRotaryLimitJoint *joint, cpFloat dt)
{
if(!joint->bias) return; // early exit
@ -72,13 +69,15 @@ applyImpulse(cpRotaryLimitJoint *joint)
// compute relative rotational velocity
cpFloat wr = b->w - a->w;
cpFloat jMax = joint->constraint.maxForce*dt;
// 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);
joint->jAcc = cpfclamp(jOld + j, 0.0f, jMax);
} else {
joint->jAcc = cpfclamp(jOld + j, -joint->jMax, 0.0f);
joint->jAcc = cpfclamp(jOld + j, -jMax, 0.0f);
}
j = joint->jAcc - jOld;

View File

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

View File

@ -51,9 +51,6 @@ preStep(cpSlideJoint *joint, cpFloat dt)
// calculate bias velocity
cpFloat maxBias = joint->constraint.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
@ -67,7 +64,7 @@ applyCachedImpulse(cpSlideJoint *joint, cpFloat dt_coef)
}
static void
applyImpulse(cpSlideJoint *joint)
applyImpulse(cpSlideJoint *joint, cpFloat dt)
{
if(cpveql(joint->n, cpvzero)) return; // early exit
@ -85,7 +82,7 @@ applyImpulse(cpSlideJoint *joint)
// compute normal impulse
cpFloat jn = (joint->bias - vrn)*joint->nMass;
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;
// apply impulse

View File

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

View File

@ -21,14 +21,6 @@
#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
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);
}
static inline cpTimestamp
GetStamp(cpBBTree *tree)
static inline cpBBTree *
GetMasterTree(cpBBTree *tree)
{
cpBBTree *dynamicTree = GetTree(tree->spatialIndex.dynamicIndex);
return (dynamicTree ? dynamicTree->stamp : tree->stamp);
return (dynamicTree ? dynamicTree : tree);
}
static inline void
@ -128,6 +128,10 @@ IncrementStamp(cpBBTree *tree)
static void
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;
tree->pooledPairs = pair;
}
@ -135,6 +139,10 @@ PairRecycle(cpBBTree *tree, Pair *pair)
static Pair *
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;
if(pair){
@ -433,7 +441,7 @@ static void
MarkLeaf(Node *leaf, MarkContext *context)
{
cpBBTree *tree = context->tree;
if(leaf->STAMP == GetStamp(tree)){
if(leaf->STAMP == GetMasterTree(tree)->stamp){
Node *staticRoot = context->staticRoot;
if(staticRoot) MarkLeafQuery(staticRoot, leaf, cpFalse, context);
@ -497,7 +505,7 @@ LeafUpdate(Node *leaf, cpBBTree *tree)
tree->root = SubtreeInsert(root, leaf, tree);
PairsClear(leaf, tree);
leaf->STAMP = GetStamp(tree);
leaf->STAMP = GetMasterTree(tree)->stamp;
return cpTrue;
}
@ -599,7 +607,7 @@ cpBBTreeInsert(cpBBTree *tree, void *obj, cpHashValue hashid)
Node *root = tree->root;
tree->root = SubtreeInsert(root, leaf, tree);
leaf->STAMP = GetStamp(tree);
leaf->STAMP = GetMasterTree(tree)->stamp;
LeafAddPairs(leaf, tree);
IncrementStamp(tree);
}

View File

@ -142,6 +142,7 @@ cpBodySetMass(cpBody *body, cpFloat mass)
cpBodyActivate(body);
body->m = mass;
body->m_inv = 1.0f/mass;
cpBodyAssertSane(body);
}
void
@ -152,6 +153,7 @@ cpBodySetMoment(cpBody *body, cpFloat moment)
cpBodyActivate(body);
body->i = moment;
body->i_inv = 1.0f/moment;
cpBodyAssertSane(body);
}
void
@ -208,8 +210,8 @@ void
cpBodySetPos(cpBody *body, cpVect pos)
{
cpBodyActivate(body);
cpBodyAssertSane(body);
body->p = pos;
cpBodyAssertSane(body);
}
static inline void
@ -217,13 +219,13 @@ setAngle(cpBody *body, cpFloat angle)
{
body->a = angle;//fmod(a, (cpFloat)M_PI*2.0f);
body->rot = cpvforangle(angle);
cpBodyAssertSane(body);
}
void
cpBodySetAngle(cpBody *body, cpFloat angle)
{
cpBodyActivate(body);
cpBodyAssertSane(body);
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] = {
circle2circle,
NULL,
@ -335,36 +393,23 @@ static const collisionFunc builtinCollisionFuncs[9] = {
};
static const collisionFunc *colfuncs = builtinCollisionFuncs;
//static collisionFunc *colfuncs = NULL;
//
//static void
//addColFunc(const cpShapeType a, const cpShapeType b, const 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
static const collisionFunc segmentCollisions[9] = {
circle2circle,
NULL,
NULL,
(collisionFunc)circle2segment,
seg2seg,
NULL,
circle2poly,
seg2poly,
poly2poly,
};
void
cpEnableSegmentToSegmentCollisions(void)
{
colfuncs = segmentCollisions;
}
int
cpCollideShapes(const cpShape *a, const cpShape *b, cpContact *arr)

View File

@ -181,7 +181,7 @@ cpPolyShapeGetVert(cpShape *shape, int idx)
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.
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 *
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);
cpShapeInit((cpShape *)poly, &polyClass, body);

View File

@ -103,7 +103,7 @@ cpShapeUpdate(cpShape *shape, cpVect pos, cpVect rot)
cpBool
cpShapePointQuery(cpShape *shape, cpVect p){
cpNearestPointQueryInfo info = {};
cpNearestPointQueryInfo info = {NULL, cpvzero, INFINITY};
cpShapeNearestPointQuery(shape, p, &info);
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);
if(context->func){
cpContactPointSet set = {numContacts, {}};
cpContactPointSet set;
set.count = numContacts;
for(int i=0; i<set.count; i++){
set.points[i].point = contacts[i].p;
set.points[i].normal = contacts[i].n;

View File

@ -23,38 +23,37 @@
//MARK: Post Step Callback Functions
typedef struct cpPostStepCallback {
cpPostStepFunc func;
void *key;
void *data;
} cpPostStepCallback;
void *
cpSpaceGetPostStepData(cpSpace *space, void *key)
cpPostStepCallback *
cpSpaceGetPostStepCallback(cpSpace *space, void *key)
{
cpArray *arr = space->postStepCallbacks;
for(int i=0; i<arr->num; i++){
cpPostStepCallback *callback = (cpPostStepCallback *)arr->arr[i];
if(callback->key == key) return callback->data;
if(callback->key == key) return callback;
}
return NULL;
}
void
static void PostStepDoNothing(cpSpace *space, void *obj, void *data){}
cpBool
cpSpaceAddPostStepCallback(cpSpace *space, cpPostStepFunc func, void *key, void *data)
{
cpAssertWarn(space->locked,
"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.");
if(!cpSpaceGetPostStepData(space, key)){
if(!cpSpaceGetPostStepCallback(space, key)){
cpPostStepCallback *callback = (cpPostStepCallback *)cpcalloc(1, sizeof(cpPostStepCallback));
callback->func = func;
callback->func = (func ? func : PostStepDoNothing);
callback->key = key;
callback->data = data;
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++){
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
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};
cpSpatialIndexEach(dynamicIndex, (cpSpatialIndexIteratorFunc)dynamicToStaticIter, &context);
}

View File

@ -23,42 +23,27 @@
#include "chipmunk_private.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));
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);
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);
cpFloat dot = cpvdot(cpvnormalize(v1), cpvnormalize(v2));
cpFloat omega = cpfacos(cpfclamp(dot, -1.0f, 1.0f));
return cpvslerp(v1, v2, cpfmin(a, omega)/omega);
}
char*