chipmunk 5.3.4.5 → 6.1.3.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. data/ext/chipmunk/chipmunk.c +199 -28
  2. data/ext/chipmunk/chipmunk.h +123 -68
  3. data/ext/chipmunk/chipmunk_ffi.h +129 -11
  4. data/ext/chipmunk/chipmunk_private.h +232 -16
  5. data/ext/chipmunk/chipmunk_types.h +94 -30
  6. data/ext/chipmunk/chipmunk_unsafe.h +12 -3
  7. data/ext/chipmunk/constraints/cpConstraint.h +90 -34
  8. data/ext/chipmunk/{cpDampedRotarySpring.h → constraints/cpDampedRotarySpring.h} +18 -8
  9. data/ext/chipmunk/{cpDampedSpring.h → constraints/cpDampedSpring.h} +27 -16
  10. data/ext/chipmunk/constraints/cpGearJoint.h +17 -7
  11. data/ext/chipmunk/constraints/cpGrooveJoint.h +19 -10
  12. data/ext/chipmunk/constraints/cpPinJoint.h +17 -8
  13. data/ext/chipmunk/constraints/cpPivotJoint.h +18 -9
  14. data/ext/chipmunk/constraints/cpRatchetJoint.h +17 -8
  15. data/ext/chipmunk/constraints/cpRotaryLimitJoint.h +16 -7
  16. data/ext/chipmunk/{cpSimpleMotor.h → constraints/cpSimpleMotor.h} +15 -6
  17. data/ext/chipmunk/constraints/cpSlideJoint.h +18 -9
  18. data/ext/chipmunk/constraints/util.h +36 -44
  19. data/ext/chipmunk/cpArbiter.c +159 -94
  20. data/ext/chipmunk/cpArbiter.h +135 -129
  21. data/ext/chipmunk/cpArray.c +37 -56
  22. data/ext/chipmunk/cpBB.c +1 -12
  23. data/ext/chipmunk/cpBB.h +80 -18
  24. data/ext/chipmunk/cpBBTree.c +891 -0
  25. data/ext/chipmunk/cpBody.c +185 -47
  26. data/ext/chipmunk/cpBody.h +156 -124
  27. data/ext/chipmunk/cpCollision.c +126 -115
  28. data/ext/chipmunk/cpConstraint.c +10 -6
  29. data/ext/chipmunk/cpDampedRotarySpring.c +26 -17
  30. data/ext/chipmunk/cpDampedSpring.c +25 -18
  31. data/ext/chipmunk/cpGearJoint.c +23 -17
  32. data/ext/chipmunk/cpGrooveJoint.c +26 -22
  33. data/ext/chipmunk/cpHashSet.c +51 -51
  34. data/ext/chipmunk/cpPinJoint.c +26 -19
  35. data/ext/chipmunk/cpPivotJoint.c +23 -19
  36. data/ext/chipmunk/cpPolyShape.c +93 -69
  37. data/ext/chipmunk/cpPolyShape.h +33 -69
  38. data/ext/chipmunk/cpRatchetJoint.c +26 -21
  39. data/ext/chipmunk/cpRotaryLimitJoint.c +28 -22
  40. data/ext/chipmunk/cpShape.c +122 -133
  41. data/ext/chipmunk/cpShape.h +146 -95
  42. data/ext/chipmunk/cpSimpleMotor.c +24 -17
  43. data/ext/chipmunk/cpSlideJoint.c +28 -26
  44. data/ext/chipmunk/cpSpace.c +251 -196
  45. data/ext/chipmunk/cpSpace.h +173 -103
  46. data/ext/chipmunk/cpSpaceComponent.c +236 -159
  47. data/ext/chipmunk/cpSpaceHash.c +259 -159
  48. data/ext/chipmunk/cpSpaceQuery.c +127 -59
  49. data/ext/chipmunk/cpSpaceStep.c +235 -197
  50. data/ext/chipmunk/cpSpatialIndex.c +69 -0
  51. data/ext/chipmunk/cpSpatialIndex.h +227 -0
  52. data/ext/chipmunk/cpSweep1D.c +254 -0
  53. data/ext/chipmunk/cpVect.c +11 -26
  54. data/ext/chipmunk/cpVect.h +76 -71
  55. data/ext/chipmunk/extconf.rb +4 -31
  56. data/ext/chipmunk/prime.h +1 -1
  57. data/ext/chipmunk/rb_chipmunk.c +36 -45
  58. data/ext/chipmunk/rb_chipmunk.h +6 -3
  59. data/ext/chipmunk/rb_cpArbiter.c +2 -2
  60. data/ext/chipmunk/rb_cpBB.c +116 -35
  61. data/ext/chipmunk/rb_cpBody.c +5 -12
  62. data/ext/chipmunk/rb_cpConstraint.c +144 -9
  63. data/ext/chipmunk/rb_cpShape.c +69 -78
  64. data/ext/chipmunk/rb_cpSpace.c +81 -76
  65. metadata +61 -61
  66. data/LICENSE +0 -22
  67. data/README +0 -110
  68. data/Rakefile +0 -102
  69. data/ext/chipmunk/cpArray.h +0 -49
  70. data/ext/chipmunk/cpCollision.h +0 -28
  71. data/ext/chipmunk/cpHashSet.h +0 -82
  72. data/ext/chipmunk/cpSpaceHash.h +0 -110
  73. data/lib/chipmunk.rb +0 -194
@@ -19,17 +19,33 @@
19
19
  * SOFTWARE.
20
20
  */
21
21
 
22
- // Forward declarations required for defining other structs.
23
- struct cpShape;
24
- struct cpShapeClass;
25
-
22
+ /// @defgroup cpShape cpShape
23
+ /// The cpShape struct defines the shape of a rigid body.
24
+ /// @{
25
+
26
+ typedef struct cpShapeClass cpShapeClass;
27
+
28
+ /// Nearest point query info struct.
29
+ typedef struct cpNearestPointQueryInfo {
30
+ /// The nearest shape, NULL if no shape was within range.
31
+ cpShape *shape;
32
+ /// The closest point on the shape's surface. (in world space coordinates)
33
+ cpVect p;
34
+ /// The distance to the point. The distance is negative if the point is inside the shape.
35
+ cpFloat d;
36
+ } cpNearestPointQueryInfo;
37
+
38
+ /// Segment query info struct.
26
39
  typedef struct cpSegmentQueryInfo {
27
- struct cpShape *shape; // shape that was hit, NULL if no collision
28
- cpFloat t; // Distance along query segment, will always be in the range [0, 1].
29
- cpVect n; // normal of hit surface
40
+ /// The shape that was hit, NULL if no collision occured.
41
+ cpShape *shape;
42
+ /// The normalized distance along the query segment in the range [0, 1].
43
+ cpFloat t;
44
+ /// The normal of the surface hit.
45
+ cpVect n;
30
46
  } cpSegmentQueryInfo;
31
47
 
32
- // Enumeration of shape types.
48
+ /// @private
33
49
  typedef enum cpShapeType{
34
50
  CP_CIRCLE_SHAPE,
35
51
  CP_SEGMENT_SHAPE,
@@ -37,141 +53,176 @@ typedef enum cpShapeType{
37
53
  CP_NUM_SHAPES
38
54
  } cpShapeType;
39
55
 
40
- // Shape class. Holds function pointers and type data.
41
- typedef struct cpShapeClass {
56
+ typedef cpBB (*cpShapeCacheDataImpl)(cpShape *shape, cpVect p, cpVect rot);
57
+ typedef void (*cpShapeDestroyImpl)(cpShape *shape);
58
+ typedef void (*cpShapeNearestPointQueryImpl)(cpShape *shape, cpVect p, cpNearestPointQueryInfo *info);
59
+ typedef void (*cpShapeSegmentQueryImpl)(cpShape *shape, cpVect a, cpVect b, cpSegmentQueryInfo *info);
60
+
61
+ /// @private
62
+ struct cpShapeClass {
42
63
  cpShapeType type;
43
64
 
44
- // Called by cpShapeCacheBB().
45
- cpBB (*cacheData)(struct cpShape *shape, cpVect p, cpVect rot);
46
- // Called to by cpShapeDestroy().
47
- void (*destroy)(struct cpShape *shape);
48
-
49
- // called by cpShapePointQuery().
50
- cpBool (*pointQuery)(struct cpShape *shape, cpVect p);
51
-
52
- // called by cpShapeSegmentQuery()
53
- void (*segmentQuery)(struct cpShape *shape, cpVect a, cpVect b, cpSegmentQueryInfo *info);
54
- } cpShapeClass;
55
-
56
- // Basic shape struct that the others inherit from.
57
- typedef struct cpShape{
58
- // The "class" of a shape as defined above
65
+ cpShapeCacheDataImpl cacheData;
66
+ cpShapeDestroyImpl destroy;
67
+ cpShapeNearestPointQueryImpl nearestPointQuery;
68
+ cpShapeSegmentQueryImpl segmentQuery;
69
+ };
70
+
71
+ /// Opaque collision shape struct.
72
+ struct cpShape {
59
73
  CP_PRIVATE(const cpShapeClass *klass);
60
74
 
61
- // cpBody that the shape is attached to.
75
+ /// The rigid body this collision shape is attached to.
62
76
  cpBody *body;
63
77
 
64
- // Cached BBox for the shape.
78
+ /// The current bounding box of the shape.
65
79
  cpBB bb;
66
80
 
67
- // Sensors invoke callbacks, but do not generate collisions
81
+ /// Sensor flag.
82
+ /// Sensor shapes call collision callbacks but don't produce collisions.
68
83
  cpBool sensor;
69
84
 
70
- // *** Surface properties.
71
-
72
- // Coefficient of restitution. (elasticity)
85
+ /// Coefficient of restitution. (elasticity)
73
86
  cpFloat e;
74
- // Coefficient of friction.
87
+ /// Coefficient of friction.
75
88
  cpFloat u;
76
- // Surface velocity used when solving for friction.
89
+ /// Surface velocity used when solving for friction.
77
90
  cpVect surface_v;
78
91
 
79
- // *** User Definable Fields
80
-
81
- // User defined data pointer for the shape.
92
+ /// User definable data pointer.
93
+ /// Generally this points to your the game object class so you can access it
94
+ /// when given a cpShape reference in a callback.
82
95
  cpDataPointer data;
83
96
 
84
- // User defined collision type for the shape.
97
+ /// Collision type of this shape used when picking collision handlers.
85
98
  cpCollisionType collision_type;
86
- // User defined collision group for the shape.
99
+ /// Group of this shape. Shapes in the same group don't collide.
87
100
  cpGroup group;
88
- // User defined layer bitmask for the shape.
101
+ // Layer bitmask for this shape. Shapes only collide if the bitwise and of their layers is non-zero.
89
102
  cpLayers layers;
90
103
 
91
- // *** Internally Used Fields
104
+ CP_PRIVATE(cpSpace *space);
92
105
 
93
- // Shapes form a linked list when added to space on a non-NULL body
94
- CP_PRIVATE(struct cpShape *next);
106
+ CP_PRIVATE(cpShape *next);
107
+ CP_PRIVATE(cpShape *prev);
95
108
 
96
- // Unique id used as the hash value.
97
109
  CP_PRIVATE(cpHashValue hashid);
98
- } cpShape;
99
-
100
- // Low level shape initialization func.
101
- cpShape* cpShapeInit(cpShape *shape, const struct cpShapeClass *klass, cpBody *body);
110
+ };
102
111
 
103
- // Basic destructor functions. (allocation functions are not shared)
112
+ /// Destroy a shape.
104
113
  void cpShapeDestroy(cpShape *shape);
114
+ /// Destroy and Free a shape.
105
115
  void cpShapeFree(cpShape *shape);
106
116
 
107
- // Cache the BBox of the shape.
117
+ /// Update, cache and return the bounding box of a shape based on the body it's attached to.
108
118
  cpBB cpShapeCacheBB(cpShape *shape);
119
+ /// Update, cache and return the bounding box of a shape with an explicit transformation.
120
+ cpBB cpShapeUpdate(cpShape *shape, cpVect pos, cpVect rot);
109
121
 
110
- // Test if a point lies within a shape.
122
+ /// Test if a point lies within a shape.
111
123
  cpBool cpShapePointQuery(cpShape *shape, cpVect p);
112
124
 
113
- #define CP_DeclareShapeGetter(struct, type, name) type struct##Get##name(cpShape *shape)
125
+ /// Perform a nearest point query. It finds the closest point on the surface of shape to a specific point.
126
+ /// The value returned is the distance between the points. A negative distance means the point is inside the shape.
127
+ cpFloat cpShapeNearestPointQuery(cpShape *shape, cpVect p, cpNearestPointQueryInfo *out);
114
128
 
115
- // Circle shape structure.
116
- typedef struct cpCircleShape{
117
- CP_PRIVATE(cpShape shape);
118
-
119
- // Center in body space coordinates
120
- CP_PRIVATE(cpVect c);
121
- // Radius.
122
- CP_PRIVATE(cpFloat r);
129
+ /// Perform a segment query against a shape. @c info must be a pointer to a valid cpSegmentQueryInfo structure.
130
+ cpBool cpShapeSegmentQuery(cpShape *shape, cpVect a, cpVect b, cpSegmentQueryInfo *info);
131
+
132
+ /// Get the hit point for a segment query.
133
+ static inline cpVect cpSegmentQueryHitPoint(const cpVect start, const cpVect end, const cpSegmentQueryInfo info)
134
+ {
135
+ return cpvlerp(start, end, info.t);
136
+ }
137
+
138
+ /// Get the hit distance for a segment query.
139
+ static inline cpFloat cpSegmentQueryHitDist(const cpVect start, const cpVect end, const cpSegmentQueryInfo info)
140
+ {
141
+ return cpvdist(start, end)*info.t;
142
+ }
143
+
144
+ #define CP_DefineShapeStructGetter(type, member, name) \
145
+ static inline type cpShapeGet##name(const cpShape *shape){return shape->member;}
146
+
147
+ #define CP_DefineShapeStructSetter(type, member, name, activates) \
148
+ static inline void cpShapeSet##name(cpShape *shape, type value){ \
149
+ if(activates && shape->body) cpBodyActivate(shape->body); \
150
+ shape->member = value; \
151
+ }
152
+
153
+ #define CP_DefineShapeStructProperty(type, member, name, activates) \
154
+ CP_DefineShapeStructGetter(type, member, name) \
155
+ CP_DefineShapeStructSetter(type, member, name, activates)
156
+
157
+ CP_DefineShapeStructGetter(cpSpace*, CP_PRIVATE(space), Space)
158
+
159
+ CP_DefineShapeStructGetter(cpBody*, body, Body)
160
+ void cpShapeSetBody(cpShape *shape, cpBody *body);
161
+
162
+ CP_DefineShapeStructGetter(cpBB, bb, BB)
163
+ CP_DefineShapeStructProperty(cpBool, sensor, Sensor, cpTrue)
164
+ CP_DefineShapeStructProperty(cpFloat, e, Elasticity, cpFalse)
165
+ CP_DefineShapeStructProperty(cpFloat, u, Friction, cpTrue)
166
+ CP_DefineShapeStructProperty(cpVect, surface_v, SurfaceVelocity, cpTrue)
167
+ CP_DefineShapeStructProperty(cpDataPointer, data, UserData, cpFalse)
168
+ CP_DefineShapeStructProperty(cpCollisionType, collision_type, CollisionType, cpTrue)
169
+ CP_DefineShapeStructProperty(cpGroup, group, Group, cpTrue)
170
+ CP_DefineShapeStructProperty(cpLayers, layers, Layers, cpTrue)
171
+
172
+ /// When initializing a shape, it's hash value comes from a counter.
173
+ /// Because the hash value may affect iteration order, you can reset the shape ID counter
174
+ /// when recreating a space. This will make the simulation be deterministic.
175
+ void cpResetShapeIdCounter(void);
176
+
177
+ #define CP_DeclareShapeGetter(struct, type, name) type struct##Get##name(const cpShape *shape)
178
+
179
+ /// @}
180
+ /// @defgroup cpCircleShape cpCircleShape
181
+
182
+ /// @private
183
+ typedef struct cpCircleShape {
184
+ cpShape shape;
123
185
 
124
- // Transformed center. (world space coordinates)
125
- CP_PRIVATE(cpVect tc);
186
+ cpVect c, tc;
187
+ cpFloat r;
126
188
  } cpCircleShape;
127
189
 
128
- // Basic allocation functions for cpCircleShape.
129
- cpCircleShape *cpCircleShapeAlloc(void);
130
- cpCircleShape *cpCircleShapeInit(cpCircleShape *circle, cpBody *body, cpFloat radius, cpVect offset);
131
- cpShape *cpCircleShapeNew(cpBody *body, cpFloat radius, cpVect offset);
190
+ /// Allocate a circle shape.
191
+ cpCircleShape* cpCircleShapeAlloc(void);
192
+ /// Initialize a circle shape.
193
+ cpCircleShape* cpCircleShapeInit(cpCircleShape *circle, cpBody *body, cpFloat radius, cpVect offset);
194
+ /// Allocate and initialize a circle shape.
195
+ cpShape* cpCircleShapeNew(cpBody *body, cpFloat radius, cpVect offset);
132
196
 
133
197
  CP_DeclareShapeGetter(cpCircleShape, cpVect, Offset);
134
198
  CP_DeclareShapeGetter(cpCircleShape, cpFloat, Radius);
135
199
 
136
- // Segment shape structure.
137
- typedef struct cpSegmentShape{
138
- CP_PRIVATE(cpShape shape);
139
-
140
- // Endpoints and normal of the segment. (body space coordinates)
141
- cpVect CP_PRIVATE(a), CP_PRIVATE(b), CP_PRIVATE(n);
142
- // Radius of the segment. (Thickness)
143
- cpFloat CP_PRIVATE(r);
200
+ /// @}
201
+ /// @defgroup cpSegmentShape cpSegmentShape
144
202
 
145
- // Transformed endpoints and normal. (world space coordinates)
146
- cpVect CP_PRIVATE(ta), CP_PRIVATE(tb), CP_PRIVATE(tn);
203
+ /// @private
204
+ typedef struct cpSegmentShape {
205
+ cpShape shape;
206
+
207
+ cpVect a, b, n;
208
+ cpVect ta, tb, tn;
209
+ cpFloat r;
210
+
211
+ cpVect a_tangent, b_tangent;
147
212
  } cpSegmentShape;
148
213
 
149
- // Basic allocation functions for cpSegmentShape.
214
+ /// Allocate a segment shape.
150
215
  cpSegmentShape* cpSegmentShapeAlloc(void);
216
+ /// Initialize a segment shape.
151
217
  cpSegmentShape* cpSegmentShapeInit(cpSegmentShape *seg, cpBody *body, cpVect a, cpVect b, cpFloat radius);
218
+ /// Allocate and initialize a segment shape.
152
219
  cpShape* cpSegmentShapeNew(cpBody *body, cpVect a, cpVect b, cpFloat radius);
153
220
 
221
+ void cpSegmentShapeSetNeighbors(cpShape *shape, cpVect prev, cpVect next);
222
+
154
223
  CP_DeclareShapeGetter(cpSegmentShape, cpVect, A);
155
224
  CP_DeclareShapeGetter(cpSegmentShape, cpVect, B);
156
225
  CP_DeclareShapeGetter(cpSegmentShape, cpVect, Normal);
157
226
  CP_DeclareShapeGetter(cpSegmentShape, cpFloat, Radius);
158
227
 
159
- // For determinism, you can reset the shape id counter.
160
- void cpResetShapeIdCounter(void);
161
-
162
- // Directed segment queries against individual shapes.
163
- void cpSegmentQueryInfoPrint(cpSegmentQueryInfo *info);
164
-
165
- cpBool cpShapeSegmentQuery(cpShape *shape, cpVect a, cpVect b, cpSegmentQueryInfo *info);
166
-
167
- static inline cpVect
168
- cpSegmentQueryHitPoint(const cpVect start, const cpVect end, const cpSegmentQueryInfo info)
169
- {
170
- return cpvlerp(start, end, info.t);
171
- }
172
-
173
- static inline cpFloat
174
- cpSegmentQueryHitDist(const cpVect start, const cpVect end, const cpSegmentQueryInfo info)
175
- {
176
- return cpvdist(start, end)*info.t;
177
- }
228
+ /// @}
@@ -19,39 +19,45 @@
19
19
  * SOFTWARE.
20
20
  */
21
21
 
22
- #include <stdlib.h>
23
-
24
22
  #include "chipmunk_private.h"
25
23
  #include "constraints/util.h"
26
24
 
27
25
  static void
28
- preStep(cpSimpleMotor *joint, cpFloat dt, cpFloat dt_inv)
26
+ preStep(cpSimpleMotor *joint, cpFloat dt)
29
27
  {
30
- CONSTRAINT_BEGIN(joint, a, b);
28
+ cpBody *a = joint->constraint.a;
29
+ cpBody *b = joint->constraint.b;
31
30
 
32
31
  // calculate moment of inertia coefficient.
33
32
  joint->iSum = 1.0f/(a->i_inv + b->i_inv);
34
-
35
- // compute max impulse
36
- joint->jMax = J_MAX(joint, dt);
33
+ }
37
34
 
38
- // apply joint torque
39
- a->w -= joint->jAcc*a->i_inv;
40
- b->w += joint->jAcc*b->i_inv;
35
+ static void
36
+ applyCachedImpulse(cpSimpleMotor *joint, cpFloat dt_coef)
37
+ {
38
+ cpBody *a = joint->constraint.a;
39
+ cpBody *b = joint->constraint.b;
40
+
41
+ cpFloat j = joint->jAcc*dt_coef;
42
+ a->w -= j*a->i_inv;
43
+ b->w += j*b->i_inv;
41
44
  }
42
45
 
43
46
  static void
44
- applyImpulse(cpSimpleMotor *joint)
47
+ applyImpulse(cpSimpleMotor *joint, cpFloat dt)
45
48
  {
46
- CONSTRAINT_BEGIN(joint, a, b);
49
+ cpBody *a = joint->constraint.a;
50
+ cpBody *b = joint->constraint.b;
47
51
 
48
52
  // compute relative rotational velocity
49
53
  cpFloat wr = b->w - a->w + joint->rate;
50
54
 
55
+ cpFloat jMax = joint->constraint.maxForce*dt;
56
+
51
57
  // compute normal impulse
52
58
  cpFloat j = -wr*joint->iSum;
53
59
  cpFloat jOld = joint->jAcc;
54
- joint->jAcc = cpfclamp(jOld + j, -joint->jMax, joint->jMax);
60
+ joint->jAcc = cpfclamp(jOld + j, -jMax, jMax);
55
61
  j = joint->jAcc - jOld;
56
62
 
57
63
  // apply impulse
@@ -66,16 +72,17 @@ getImpulse(cpSimpleMotor *joint)
66
72
  }
67
73
 
68
74
  static const cpConstraintClass klass = {
69
- (cpConstraintPreStepFunction)preStep,
70
- (cpConstraintApplyImpulseFunction)applyImpulse,
71
- (cpConstraintGetImpulseFunction)getImpulse,
75
+ (cpConstraintPreStepImpl)preStep,
76
+ (cpConstraintApplyCachedImpulseImpl)applyCachedImpulse,
77
+ (cpConstraintApplyImpulseImpl)applyImpulse,
78
+ (cpConstraintGetImpulseImpl)getImpulse,
72
79
  };
73
80
  CP_DefineClassGetter(cpSimpleMotor)
74
81
 
75
82
  cpSimpleMotor *
76
83
  cpSimpleMotorAlloc(void)
77
84
  {
78
- return (cpSimpleMotor *)cpmalloc(sizeof(cpSimpleMotor));
85
+ return (cpSimpleMotor *)cpcalloc(1, sizeof(cpSimpleMotor));
79
86
  }
80
87
 
81
88
  cpSimpleMotor *
@@ -19,15 +19,14 @@
19
19
  * SOFTWARE.
20
20
  */
21
21
 
22
- #include <stdlib.h>
23
-
24
22
  #include "chipmunk_private.h"
25
23
  #include "constraints/util.h"
26
24
 
27
25
  static void
28
- preStep(cpSlideJoint *joint, cpFloat dt, cpFloat dt_inv)
26
+ preStep(cpSlideJoint *joint, cpFloat dt)
29
27
  {
30
- CONSTRAINT_BEGIN(joint, a, b);
28
+ cpBody *a = joint->constraint.a;
29
+ cpBody *b = joint->constraint.b;
31
30
 
32
31
  joint->r1 = cpvrotate(joint->anchr1, a->rot);
33
32
  joint->r2 = cpvrotate(joint->anchr2, b->rot);
@@ -37,38 +36,40 @@ preStep(cpSlideJoint *joint, cpFloat dt, cpFloat dt_inv)
37
36
  cpFloat pdist = 0.0f;
38
37
  if(dist > joint->max) {
39
38
  pdist = dist - joint->max;
39
+ joint->n = cpvnormalize_safe(delta);
40
40
  } else if(dist < joint->min) {
41
41
  pdist = joint->min - dist;
42
- dist = -dist;
42
+ joint->n = cpvneg(cpvnormalize_safe(delta));
43
+ } else {
44
+ joint->n = cpvzero;
45
+ joint->jnAcc = 0.0f;
43
46
  }
44
- joint->n = cpvmult(delta, 1.0f/(dist ? dist : (cpFloat)INFINITY));
45
47
 
46
48
  // calculate mass normal
47
49
  joint->nMass = 1.0f/k_scalar(a, b, joint->r1, joint->r2, joint->n);
48
50
 
49
51
  // calculate bias velocity
50
52
  cpFloat maxBias = joint->constraint.maxBias;
51
- joint->bias = cpfclamp(-joint->constraint.biasCoef*dt_inv*(pdist), -maxBias, maxBias);
52
-
53
- // compute max impulse
54
- joint->jnMax = J_MAX(joint, dt);
53
+ joint->bias = cpfclamp(-bias_coef(joint->constraint.errorBias, dt)*pdist/dt, -maxBias, maxBias);
54
+ }
55
55
 
56
- // apply accumulated impulse
57
- if(!joint->bias) //{
58
- // if bias is 0, then the joint is not at a limit.
59
- joint->jnAcc = 0.0f;
60
- // } else {
61
- cpVect j = cpvmult(joint->n, joint->jnAcc);
62
- apply_impulses(a, b, joint->r1, joint->r2, j);
63
- // }
56
+ static void
57
+ applyCachedImpulse(cpSlideJoint *joint, cpFloat dt_coef)
58
+ {
59
+ cpBody *a = joint->constraint.a;
60
+ cpBody *b = joint->constraint.b;
61
+
62
+ cpVect j = cpvmult(joint->n, joint->jnAcc*dt_coef);
63
+ apply_impulses(a, b, joint->r1, joint->r2, j);
64
64
  }
65
65
 
66
66
  static void
67
- applyImpulse(cpSlideJoint *joint)
67
+ applyImpulse(cpSlideJoint *joint, cpFloat dt)
68
68
  {
69
- if(!joint->bias) return; // early exit
69
+ if(cpveql(joint->n, cpvzero)) return; // early exit
70
70
 
71
- CONSTRAINT_BEGIN(joint, a, b);
71
+ cpBody *a = joint->constraint.a;
72
+ cpBody *b = joint->constraint.b;
72
73
 
73
74
  cpVect n = joint->n;
74
75
  cpVect r1 = joint->r1;
@@ -81,7 +82,7 @@ applyImpulse(cpSlideJoint *joint)
81
82
  // compute normal impulse
82
83
  cpFloat jn = (joint->bias - vrn)*joint->nMass;
83
84
  cpFloat jnOld = joint->jnAcc;
84
- joint->jnAcc = cpfclamp(jnOld + jn, -joint->jnMax, 0.0f);
85
+ joint->jnAcc = cpfclamp(jnOld + jn, -joint->constraint.maxForce*dt, 0.0f);
85
86
  jn = joint->jnAcc - jnOld;
86
87
 
87
88
  // apply impulse
@@ -95,16 +96,17 @@ getImpulse(cpConstraint *joint)
95
96
  }
96
97
 
97
98
  static const cpConstraintClass klass = {
98
- (cpConstraintPreStepFunction)preStep,
99
- (cpConstraintApplyImpulseFunction)applyImpulse,
100
- (cpConstraintGetImpulseFunction)getImpulse,
99
+ (cpConstraintPreStepImpl)preStep,
100
+ (cpConstraintApplyCachedImpulseImpl)applyCachedImpulse,
101
+ (cpConstraintApplyImpulseImpl)applyImpulse,
102
+ (cpConstraintGetImpulseImpl)getImpulse,
101
103
  };
102
104
  CP_DefineClassGetter(cpSlideJoint)
103
105
 
104
106
  cpSlideJoint *
105
107
  cpSlideJointAlloc(void)
106
108
  {
107
- return (cpSlideJoint *)cpmalloc(sizeof(cpSlideJoint));
109
+ return (cpSlideJoint *)cpcalloc(1, sizeof(cpSlideJoint));
108
110
  }
109
111
 
110
112
  cpSlideJoint *