chipmunk 5.3.4.5 → 6.1.3.0.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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,11 +19,10 @@
19
19
  * SOFTWARE.
20
20
  */
21
21
 
22
- #include <stdlib.h>
23
22
  #include <float.h>
24
- #include <stdarg.h>
25
23
 
26
24
  #include "chipmunk_private.h"
25
+ #include "constraints/util.h"
27
26
 
28
27
  // initialized in cpInitChipmunk()
29
28
  cpBody cpStaticBodySingleton;
@@ -31,41 +30,42 @@ cpBody cpStaticBodySingleton;
31
30
  cpBody*
32
31
  cpBodyAlloc(void)
33
32
  {
34
- return (cpBody *)cpmalloc(sizeof(cpBody));
33
+ return (cpBody *)cpcalloc(1, sizeof(cpBody));
35
34
  }
36
35
 
37
- cpBodyVelocityFunc cpBodyUpdateVelocityDefault = cpBodyUpdateVelocity;
38
- cpBodyPositionFunc cpBodyUpdatePositionDefault = cpBodyUpdatePosition;
39
-
40
- cpBody*
36
+ cpBody *
41
37
  cpBodyInit(cpBody *body, cpFloat m, cpFloat i)
42
38
  {
43
- body->velocity_func = cpBodyUpdateVelocityDefault;
44
- body->position_func = cpBodyUpdatePositionDefault;
39
+ body->space = NULL;
40
+ body->shapeList = NULL;
41
+ body->arbiterList = NULL;
42
+ body->constraintList = NULL;
43
+
44
+ body->velocity_func = cpBodyUpdateVelocity;
45
+ body->position_func = cpBodyUpdatePosition;
46
+
47
+ cpComponentNode node = {NULL, NULL, 0.0f};
48
+ body->node = node;
45
49
 
46
- cpBodySetMass(body, m);
47
- cpBodySetMoment(body, i);
48
-
49
50
  body->p = cpvzero;
50
51
  body->v = cpvzero;
51
52
  body->f = cpvzero;
52
53
 
53
- cpBodySetAngle(body, 0.0f);
54
54
  body->w = 0.0f;
55
55
  body->t = 0.0f;
56
56
 
57
57
  body->v_bias = cpvzero;
58
58
  body->w_bias = 0.0f;
59
59
 
60
- body->data = NULL;
61
60
  body->v_limit = (cpFloat)INFINITY;
62
61
  body->w_limit = (cpFloat)INFINITY;
63
62
 
64
- body->space = NULL;
65
- body->shapesList = NULL;
63
+ body->data = NULL;
66
64
 
67
- cpComponentNode node = {NULL, NULL, 0, 0.0f};
68
- body->node = node;
65
+ // Setters must be called after full initialization so the sanity checks don't assert on garbage data.
66
+ cpBodySetMass(body, m);
67
+ cpBodySetMoment(body, i);
68
+ cpBodySetAngle(body, 0.0f);
69
69
 
70
70
  return body;
71
71
  }
@@ -86,7 +86,7 @@ cpBodyInitStatic(cpBody *body)
86
86
  }
87
87
 
88
88
  cpBody *
89
- cpBodyNewStatic()
89
+ cpBodyNewStatic(void)
90
90
  {
91
91
  return cpBodyInitStatic(cpBodyAlloc());
92
92
  }
@@ -102,32 +102,131 @@ cpBodyFree(cpBody *body)
102
102
  }
103
103
  }
104
104
 
105
+ static void cpv_assert_nan(cpVect v, const char *message){cpAssertSoft(v.x == v.x && v.y == v.y, message);}
106
+ static void cpv_assert_infinite(cpVect v, const char *message){cpAssertSoft(cpfabs(v.x) != INFINITY && cpfabs(v.y) != INFINITY, message);}
107
+ static void cpv_assert_sane(cpVect v, const char *message){cpv_assert_nan(v, message); cpv_assert_infinite(v, message);}
108
+
109
+ #ifdef __cplusplus
110
+ extern "C" {
111
+ #endif
112
+
113
+ void
114
+ cpBodySanityCheck(cpBody *body)
115
+ {
116
+ cpAssertSoft(body->m == body->m && body->m_inv == body->m_inv, "Body's mass is invalid.");
117
+ cpAssertSoft(body->i == body->i && body->i_inv == body->i_inv, "Body's moment is invalid.");
118
+
119
+ cpv_assert_sane(body->p, "Body's position is invalid.");
120
+ cpv_assert_sane(body->v, "Body's velocity is invalid.");
121
+ cpv_assert_sane(body->f, "Body's force is invalid.");
122
+
123
+ cpAssertSoft(body->a == body->a && cpfabs(body->a) != INFINITY, "Body's angle is invalid.");
124
+ cpAssertSoft(body->w == body->w && cpfabs(body->w) != INFINITY, "Body's angular velocity is invalid.");
125
+ cpAssertSoft(body->t == body->t && cpfabs(body->t) != INFINITY, "Body's torque is invalid.");
126
+
127
+ cpv_assert_sane(body->rot, "Body's rotation vector is invalid.");
128
+
129
+ cpAssertSoft(body->v_limit == body->v_limit, "Body's velocity limit is invalid.");
130
+ cpAssertSoft(body->w_limit == body->w_limit, "Body's angular velocity limit is invalid.");
131
+ }
132
+
133
+ #ifdef __cplusplus
134
+ }
135
+ #endif
136
+
105
137
  void
106
138
  cpBodySetMass(cpBody *body, cpFloat mass)
107
139
  {
140
+ cpAssertHard(mass > 0.0f, "Mass must be positive and non-zero.");
141
+
142
+ cpBodyActivate(body);
108
143
  body->m = mass;
109
144
  body->m_inv = 1.0f/mass;
145
+ cpBodyAssertSane(body);
110
146
  }
111
147
 
112
148
  void
113
149
  cpBodySetMoment(cpBody *body, cpFloat moment)
114
150
  {
151
+ cpAssertHard(moment > 0.0f, "Moment of Inertia must be positive and non-zero.");
152
+
153
+ cpBodyActivate(body);
115
154
  body->i = moment;
116
155
  body->i_inv = 1.0f/moment;
156
+ cpBodyAssertSane(body);
117
157
  }
118
158
 
119
159
  void
120
- cpBodySetAngle(cpBody *body, cpFloat angle)
160
+ cpBodyAddShape(cpBody *body, cpShape *shape)
161
+ {
162
+ cpShape *next = body->shapeList;
163
+ if(next) next->prev = shape;
164
+
165
+ shape->next = next;
166
+ body->shapeList = shape;
167
+ }
168
+
169
+ void
170
+ cpBodyRemoveShape(cpBody *body, cpShape *shape)
171
+ {
172
+ cpShape *prev = shape->prev;
173
+ cpShape *next = shape->next;
174
+
175
+ if(prev){
176
+ prev->next = next;
177
+ } else {
178
+ body->shapeList = next;
179
+ }
180
+
181
+ if(next){
182
+ next->prev = prev;
183
+ }
184
+
185
+ shape->prev = NULL;
186
+ shape->next = NULL;
187
+ }
188
+
189
+ static cpConstraint *
190
+ filterConstraints(cpConstraint *node, cpBody *body, cpConstraint *filter)
191
+ {
192
+ if(node == filter){
193
+ return cpConstraintNext(node, body);
194
+ } else if(node->a == body){
195
+ node->next_a = filterConstraints(node->next_a, body, filter);
196
+ } else {
197
+ node->next_b = filterConstraints(node->next_b, body, filter);
198
+ }
199
+
200
+ return node;
201
+ }
202
+
203
+ void
204
+ cpBodyRemoveConstraint(cpBody *body, cpConstraint *constraint)
205
+ {
206
+ body->constraintList = filterConstraints(body->constraintList, body, constraint);
207
+ }
208
+
209
+ void
210
+ cpBodySetPos(cpBody *body, cpVect pos)
211
+ {
212
+ cpBodyActivate(body);
213
+ body->p = pos;
214
+ cpBodyAssertSane(body);
215
+ }
216
+
217
+ static inline void
218
+ setAngle(cpBody *body, cpFloat angle)
121
219
  {
122
220
  body->a = angle;//fmod(a, (cpFloat)M_PI*2.0f);
123
221
  body->rot = cpvforangle(angle);
222
+ cpBodyAssertSane(body);
124
223
  }
125
224
 
126
225
  void
127
- cpBodySlew(cpBody *body, cpVect pos, cpFloat dt)
226
+ cpBodySetAngle(cpBody *body, cpFloat angle)
128
227
  {
129
- cpVect delta = cpvsub(pos, body->p);
130
- body->v = cpvmult(delta, 1.0f/dt);
228
+ cpBodyActivate(body);
229
+ setAngle(body, angle);
131
230
  }
132
231
 
133
232
  void
@@ -137,21 +236,26 @@ cpBodyUpdateVelocity(cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt)
137
236
 
138
237
  cpFloat w_limit = body->w_limit;
139
238
  body->w = cpfclamp(body->w*damping + body->t*body->i_inv*dt, -w_limit, w_limit);
239
+
240
+ cpBodySanityCheck(body);
140
241
  }
141
242
 
142
243
  void
143
244
  cpBodyUpdatePosition(cpBody *body, cpFloat dt)
144
245
  {
145
246
  body->p = cpvadd(body->p, cpvmult(cpvadd(body->v, body->v_bias), dt));
146
- cpBodySetAngle(body, body->a + (body->w + body->w_bias)*dt);
247
+ setAngle(body, body->a + (body->w + body->w_bias)*dt);
147
248
 
148
249
  body->v_bias = cpvzero;
149
250
  body->w_bias = 0.0f;
251
+
252
+ cpBodySanityCheck(body);
150
253
  }
151
254
 
152
255
  void
153
256
  cpBodyResetForces(cpBody *body)
154
257
  {
258
+ cpBodyActivate(body);
155
259
  body->f = cpvzero;
156
260
  body->t = 0.0f;
157
261
  }
@@ -159,34 +263,68 @@ cpBodyResetForces(cpBody *body)
159
263
  void
160
264
  cpBodyApplyForce(cpBody *body, cpVect force, cpVect r)
161
265
  {
266
+ cpBodyActivate(body);
162
267
  body->f = cpvadd(body->f, force);
163
268
  body->t += cpvcross(r, force);
164
269
  }
165
270
 
166
271
  void
167
- cpApplyDampedSpring(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat rlen, cpFloat k, cpFloat dmp, cpFloat dt)
272
+ cpBodyApplyImpulse(cpBody *body, const cpVect j, const cpVect r)
168
273
  {
169
- // Calculate the world space anchor coordinates.
170
- cpVect r1 = cpvrotate(anchr1, a->rot);
171
- cpVect r2 = cpvrotate(anchr2, b->rot);
172
-
173
- cpVect delta = cpvsub(cpvadd(b->p, r2), cpvadd(a->p, r1));
174
- cpFloat dist = cpvlength(delta);
175
- cpVect n = dist ? cpvmult(delta, 1.0f/dist) : cpvzero;
176
-
177
- cpFloat f_spring = (dist - rlen)*k;
274
+ cpBodyActivate(body);
275
+ apply_impulse(body, j, r);
276
+ }
178
277
 
179
- // Calculate the world relative velocities of the anchor points.
180
- cpVect v1 = cpvadd(a->v, cpvmult(cpvperp(r1), a->w));
181
- cpVect v2 = cpvadd(b->v, cpvmult(cpvperp(r2), b->w));
182
-
183
- // Calculate the damping force.
184
- // This really should be in the impulse solver and can produce problems when using large damping values.
185
- cpFloat vrn = cpvdot(cpvsub(v2, v1), n);
186
- cpFloat f_damp = vrn*cpfmin(dmp, 1.0f/(dt*(a->m_inv + b->m_inv)));
187
-
188
- // Apply!
189
- cpVect f = cpvmult(n, f_spring + f_damp);
190
- cpBodyApplyForce(a, f, r1);
191
- cpBodyApplyForce(b, cpvneg(f), r2);
278
+ static inline cpVect
279
+ cpBodyGetVelAtPoint(cpBody *body, cpVect r)
280
+ {
281
+ return cpvadd(body->v, cpvmult(cpvperp(r), body->w));
282
+ }
283
+
284
+ cpVect
285
+ cpBodyGetVelAtWorldPoint(cpBody *body, cpVect point)
286
+ {
287
+ return cpBodyGetVelAtPoint(body, cpvsub(point, body->p));
288
+ }
289
+
290
+ cpVect
291
+ cpBodyGetVelAtLocalPoint(cpBody *body, cpVect point)
292
+ {
293
+ return cpBodyGetVelAtPoint(body, cpvrotate(point, body->rot));
294
+ }
295
+
296
+ void
297
+ cpBodyEachShape(cpBody *body, cpBodyShapeIteratorFunc func, void *data)
298
+ {
299
+ cpShape *shape = body->shapeList;
300
+ while(shape){
301
+ cpShape *next = shape->next;
302
+ func(body, shape, data);
303
+ shape = next;
304
+ }
305
+ }
306
+
307
+ void
308
+ cpBodyEachConstraint(cpBody *body, cpBodyConstraintIteratorFunc func, void *data)
309
+ {
310
+ cpConstraint *constraint = body->constraintList;
311
+ while(constraint){
312
+ cpConstraint *next = cpConstraintNext(constraint, body);
313
+ func(body, constraint, data);
314
+ constraint = next;
315
+ }
316
+ }
317
+
318
+ void
319
+ cpBodyEachArbiter(cpBody *body, cpBodyArbiterIteratorFunc func, void *data)
320
+ {
321
+ cpArbiter *arb = body->arbiterList;
322
+ while(arb){
323
+ cpArbiter *next = cpArbiterNext(arb, body);
324
+
325
+ arb->swappedColl = (body == arb->body_b);
326
+ func(body, arb, data);
327
+
328
+ arb = next;
329
+ }
192
330
  }
@@ -19,194 +19,213 @@
19
19
  * SOFTWARE.
20
20
  */
21
21
 
22
- struct cpBody;
23
- struct cpShape;
24
- struct cpSpace;
25
-
26
- typedef void (*cpBodyVelocityFunc)(struct cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt);
27
- typedef void (*cpBodyPositionFunc)(struct cpBody *body, cpFloat dt);
28
-
29
- extern cpBodyVelocityFunc cpBodyUpdateVelocityDefault;
30
- extern cpBodyPositionFunc cpBodyUpdatePositionDefault;
31
-
32
- // Structure to hold information about the contact graph components
33
- // when putting groups of objects to sleep.
34
- // No interesting user accessible fields.
22
+ /// @defgroup cpBody cpBody
23
+ /// Chipmunk's rigid body type. Rigid bodies hold the physical properties of an object like
24
+ /// it's mass, and position and velocity of it's center of gravity. They don't have an shape on their own.
25
+ /// They are given a shape by creating collision shapes (cpShape) that point to the body.
26
+ /// @{
27
+
28
+ /// Rigid body velocity update function type.
29
+ typedef void (*cpBodyVelocityFunc)(cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt);
30
+ /// Rigid body position update function type.
31
+ typedef void (*cpBodyPositionFunc)(cpBody *body, cpFloat dt);
32
+
33
+ /// Used internally to track information on the collision graph.
34
+ /// @private
35
35
  typedef struct cpComponentNode {
36
- struct cpBody *parent;
37
- struct cpBody *next;
38
- int rank;
36
+ cpBody *root;
37
+ cpBody *next;
39
38
  cpFloat idleTime;
40
39
  } cpComponentNode;
41
40
 
42
- typedef struct cpBody{
43
- // *** Integration Functions.
44
-
45
- // Function that is called to integrate the body's velocity. (Defaults to cpBodyUpdateVelocity)
41
+ /// Chipmunk's rigid body struct.
42
+ struct cpBody {
43
+ /// Function that is called to integrate the body's velocity. (Defaults to cpBodyUpdateVelocity)
46
44
  cpBodyVelocityFunc velocity_func;
47
45
 
48
- // Function that is called to integrate the body's position. (Defaults to cpBodyUpdatePosition)
46
+ /// Function that is called to integrate the body's position. (Defaults to cpBodyUpdatePosition)
49
47
  cpBodyPositionFunc position_func;
50
48
 
51
- // *** Mass Properties
52
-
53
- // Mass and it's inverse.
54
- // Always use cpBodySetMass() whenever changing the mass as these values must agree.
55
- cpFloat m, m_inv;
56
-
57
- // Moment of inertia and it's inverse.
58
- // Always use cpBodySetMoment() whenever changing the moment as these values must agree.
59
- cpFloat i, i_inv;
60
-
61
- // *** Positional Properties
62
-
63
- // Linear components of motion (position, velocity, and force)
64
- cpVect p, v, f;
65
-
66
- // Angular components of motion (angle, angular velocity, and torque)
67
- // Always use cpBodySetAngle() to set the angle of the body as a and rot must agree.
68
- cpFloat a, w, t;
69
-
70
- // Cached unit length vector representing the angle of the body.
71
- // Used for fast vector rotation using cpvrotate().
49
+ /// Mass of the body.
50
+ /// Must agree with cpBody.m_inv! Use cpBodySetMass() when changing the mass for this reason.
51
+ cpFloat m;
52
+ /// Mass inverse.
53
+ cpFloat m_inv;
54
+
55
+ /// Moment of inertia of the body.
56
+ /// Must agree with cpBody.i_inv! Use cpBodySetMoment() when changing the moment for this reason.
57
+ cpFloat i;
58
+ /// Moment of inertia inverse.
59
+ cpFloat i_inv;
60
+
61
+ /// Position of the rigid body's center of gravity.
62
+ cpVect p;
63
+ /// Velocity of the rigid body's center of gravity.
64
+ cpVect v;
65
+ /// Force acting on the rigid body's center of gravity.
66
+ cpVect f;
67
+
68
+ /// Rotation of the body around it's center of gravity in radians.
69
+ /// Must agree with cpBody.rot! Use cpBodySetAngle() when changing the angle for this reason.
70
+ cpFloat a;
71
+ /// Angular velocity of the body around it's center of gravity in radians/second.
72
+ cpFloat w;
73
+ /// Torque applied to the body around it's center of gravity.
74
+ cpFloat t;
75
+
76
+ /// Cached unit length vector representing the angle of the body.
77
+ /// Used for fast rotations using cpvrotate().
72
78
  cpVect rot;
73
79
 
74
- // *** User Definable Fields
75
-
76
- // User defined data pointer.
80
+ /// User definable data pointer.
81
+ /// Generally this points to your the game object class so you can access it
82
+ /// when given a cpBody reference in a callback.
77
83
  cpDataPointer data;
78
84
 
79
- // *** Other Fields
80
-
81
- // Maximum velocities this body can move at after integrating velocity
82
- cpFloat v_limit, w_limit;
83
-
84
- // *** Internally Used Fields
85
+ /// Maximum velocity allowed when updating the velocity.
86
+ cpFloat v_limit;
87
+ /// Maximum rotational rate (in radians/second) allowed when updating the angular velocity.
88
+ cpFloat w_limit;
85
89
 
86
- // Velocity bias values used when solving penetrations and correcting constraints.
87
90
  CP_PRIVATE(cpVect v_bias);
88
91
  CP_PRIVATE(cpFloat w_bias);
89
92
 
90
- // Space this body has been added to
91
- CP_PRIVATE(struct cpSpace *space);
93
+ CP_PRIVATE(cpSpace *space);
92
94
 
93
- // Pointer to the shape list.
94
- // Shapes form a linked list using cpShape.next when added to a space.
95
- CP_PRIVATE(struct cpShape *shapesList);
95
+ CP_PRIVATE(cpShape *shapeList);
96
+ CP_PRIVATE(cpArbiter *arbiterList);
97
+ CP_PRIVATE(cpConstraint *constraintList);
96
98
 
97
- // Used by cpSpaceStep() to store contact graph information.
98
99
  CP_PRIVATE(cpComponentNode node);
99
- } cpBody;
100
+ };
100
101
 
101
- // Basic allocation/destruction functions
102
- cpBody *cpBodyAlloc(void);
103
- cpBody *cpBodyInit(cpBody *body, cpFloat m, cpFloat i);
104
- cpBody *cpBodyNew(cpFloat m, cpFloat i);
102
+ /// Allocate a cpBody.
103
+ cpBody* cpBodyAlloc(void);
104
+ /// Initialize a cpBody.
105
+ cpBody* cpBodyInit(cpBody *body, cpFloat m, cpFloat i);
106
+ /// Allocate and initialize a cpBody.
107
+ cpBody* cpBodyNew(cpFloat m, cpFloat i);
105
108
 
106
- cpBody *cpBodyInitStatic(cpBody *body);
107
- cpBody *cpBodyNewStatic();
109
+ /// Initialize a static cpBody.
110
+ cpBody* cpBodyInitStatic(cpBody *body);
111
+ /// Allocate and initialize a static cpBody.
112
+ cpBody* cpBodyNewStatic(void);
108
113
 
114
+ /// Destroy a cpBody.
109
115
  void cpBodyDestroy(cpBody *body);
116
+ /// Destroy and free a cpBody.
110
117
  void cpBodyFree(cpBody *body);
111
118
 
112
- // Wake up a sleeping or idle body. (defined in cpSpace.c)
119
+ /// Check that the properties of a body is sane. (Only in debug mode)
120
+ #ifdef NDEBUG
121
+ #define cpBodyAssertSane(body)
122
+ #else
123
+ void cpBodySanityCheck(cpBody *body);
124
+ #define cpBodyAssertSane(body) cpBodySanityCheck(body)
125
+ #endif
126
+
127
+ // Defined in cpSpace.c
128
+ /// Wake up a sleeping or idle body.
113
129
  void cpBodyActivate(cpBody *body);
130
+ /// Wake up any sleeping or idle bodies touching a static body.
131
+ void cpBodyActivateStatic(cpBody *body, cpShape *filter);
114
132
 
115
- // Force a body to sleep;
116
- // defined in cpSpaceComponent.c
133
+ /// Force a body to fall asleep immediately.
117
134
  void cpBodySleep(cpBody *body);
135
+ /// Force a body to fall asleep immediately along with other bodies in a group.
118
136
  void cpBodySleepWithGroup(cpBody *body, cpBody *group);
119
137
 
120
- static inline cpBool
121
- cpBodyIsSleeping(const cpBody *body)
138
+ /// Returns true if the body is sleeping.
139
+ static inline cpBool cpBodyIsSleeping(const cpBody *body)
122
140
  {
123
- return (CP_PRIVATE(body->node).next != ((cpBody*)0));
141
+ return (CP_PRIVATE(body->node).root != ((cpBody*)0));
124
142
  }
125
143
 
126
- static inline cpBool
127
- cpBodyIsStatic(const cpBody *body)
144
+ /// Returns true if the body is static.
145
+ static inline cpBool cpBodyIsStatic(const cpBody *body)
128
146
  {
129
147
  return CP_PRIVATE(body->node).idleTime == INFINITY;
130
148
  }
131
149
 
132
- static inline cpBool
133
- cpBodyIsRogue(const cpBody *body)
150
+ /// Returns true if the body has not been added to a space.
151
+ /// Note: Static bodies are a subtype of rogue bodies.
152
+ static inline cpBool cpBodyIsRogue(const cpBody *body)
134
153
  {
135
- return (body->CP_PRIVATE(space) == ((struct cpSpace*)0));
154
+ return (body->CP_PRIVATE(space) == ((cpSpace*)0));
136
155
  }
137
156
 
138
157
 
139
- #define CP_DefineBodyGetter(type, member, name) \
158
+ #define CP_DefineBodyStructGetter(type, member, name) \
140
159
  static inline type cpBodyGet##name(const cpBody *body){return body->member;}
141
160
 
142
- #define CP_DefineBodySetter(type, member, name) \
143
- static inline void \
144
- cpBodySet##name(cpBody *body, const type value){ \
161
+ #define CP_DefineBodyStructSetter(type, member, name) \
162
+ static inline void cpBodySet##name(cpBody *body, const type value){ \
145
163
  cpBodyActivate(body); \
146
164
  body->member = value; \
147
- } \
165
+ cpBodyAssertSane(body); \
166
+ }
148
167
 
149
- #define CP_DefineBodyProperty(type, member, name) \
150
- CP_DefineBodyGetter(type, member, name) \
151
- CP_DefineBodySetter(type, member, name)
168
+ #define CP_DefineBodyStructProperty(type, member, name) \
169
+ CP_DefineBodyStructGetter(type, member, name) \
170
+ CP_DefineBodyStructSetter(type, member, name)
152
171
 
172
+ // TODO add to docs
173
+ CP_DefineBodyStructGetter(cpSpace*, CP_PRIVATE(space), Space)
153
174
 
154
- // Accessors for cpBody struct members
155
- CP_DefineBodyGetter(cpFloat, m, Mass);
175
+ CP_DefineBodyStructGetter(cpFloat, m, Mass)
176
+ /// Set the mass of a body.
156
177
  void cpBodySetMass(cpBody *body, cpFloat m);
157
178
 
158
- CP_DefineBodyGetter(cpFloat, i, Moment);
179
+ CP_DefineBodyStructGetter(cpFloat, i, Moment)
180
+ /// Set the moment of a body.
159
181
  void cpBodySetMoment(cpBody *body, cpFloat i);
160
182
 
161
-
162
- CP_DefineBodyProperty(cpVect, p, Pos);
163
- CP_DefineBodyProperty(cpVect, v, Vel);
164
- CP_DefineBodyProperty(cpVect, f, Force);
165
- CP_DefineBodyGetter(cpFloat, a, Angle);
183
+ CP_DefineBodyStructGetter(cpVect, p, Pos)
184
+ /// Set the position of a body.
185
+ void cpBodySetPos(cpBody *body, cpVect pos);
186
+ CP_DefineBodyStructProperty(cpVect, v, Vel)
187
+ CP_DefineBodyStructProperty(cpVect, f, Force)
188
+ CP_DefineBodyStructGetter(cpFloat, a, Angle)
189
+ /// Set the angle of a body.
166
190
  void cpBodySetAngle(cpBody *body, cpFloat a);
167
- CP_DefineBodyProperty(cpFloat, w, AngVel);
168
- CP_DefineBodyProperty(cpFloat, t, Torque);
169
- CP_DefineBodyGetter(cpVect, rot, Rot);
170
- CP_DefineBodyProperty(cpFloat, v_limit, VelLimit);
171
- CP_DefineBodyProperty(cpFloat, w_limit, AngVelLimit);
172
-
173
- // Modify the velocity of the body so that it will move to the specified absolute coordinates in the next timestep.
174
- // Intended for objects that are moved manually with a custom velocity integration function.
175
- void cpBodySlew(cpBody *body, cpVect pos, cpFloat dt);
176
-
177
- // Default Integration functions.
191
+ CP_DefineBodyStructProperty(cpFloat, w, AngVel)
192
+ CP_DefineBodyStructProperty(cpFloat, t, Torque)
193
+ CP_DefineBodyStructGetter(cpVect, rot, Rot)
194
+ CP_DefineBodyStructProperty(cpFloat, v_limit, VelLimit)
195
+ CP_DefineBodyStructProperty(cpFloat, w_limit, AngVelLimit)
196
+ CP_DefineBodyStructProperty(cpDataPointer, data, UserData)
197
+
198
+ /// Default Integration functions.
178
199
  void cpBodyUpdateVelocity(cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt);
179
200
  void cpBodyUpdatePosition(cpBody *body, cpFloat dt);
180
201
 
181
- // Convert body local to world coordinates
182
- static inline cpVect
183
- cpBodyLocal2World(const cpBody *body, const cpVect v)
202
+ /// Convert body relative/local coordinates to absolute/world coordinates.
203
+ static inline cpVect cpBodyLocal2World(const cpBody *body, const cpVect v)
184
204
  {
185
205
  return cpvadd(body->p, cpvrotate(v, body->rot));
186
206
  }
187
207
 
188
- // Convert world to body local coordinates
189
- static inline cpVect
190
- cpBodyWorld2Local(const cpBody *body, const cpVect v)
208
+ /// Convert body absolute/world coordinates to relative/local coordinates.
209
+ static inline cpVect cpBodyWorld2Local(const cpBody *body, const cpVect v)
191
210
  {
192
211
  return cpvunrotate(cpvsub(v, body->p), body->rot);
193
212
  }
194
213
 
195
- // Apply an impulse (in world coordinates) to the body at a point relative to the center of gravity (also in world coordinates).
196
- static inline void
197
- cpBodyApplyImpulse(cpBody *body, const cpVect j, const cpVect r)
198
- {
199
- body->v = cpvadd(body->v, cpvmult(j, body->m_inv));
200
- body->w += body->i_inv*cpvcross(r, j);
201
- }
202
-
203
- // Zero the forces on a body.
214
+ /// Set the forces and torque or a body to zero.
204
215
  void cpBodyResetForces(cpBody *body);
205
- // Apply a force (in world coordinates) to a body at a point relative to the center of gravity (also in world coordinates).
216
+ /// Apply an force (in world coordinates) to the body at a point relative to the center of gravity (also in world coordinates).
206
217
  void cpBodyApplyForce(cpBody *body, const cpVect f, const cpVect r);
218
+ /// Apply an impulse (in world coordinates) to the body at a point relative to the center of gravity (also in world coordinates).
219
+ void cpBodyApplyImpulse(cpBody *body, const cpVect j, const cpVect r);
220
+
221
+ /// Get the velocity on a body (in world units) at a point on the body in world coordinates.
222
+ cpVect cpBodyGetVelAtWorldPoint(cpBody *body, cpVect point);
223
+ /// Get the velocity on a body (in world units) at a point on the body in local coordinates.
224
+ cpVect cpBodyGetVelAtLocalPoint(cpBody *body, cpVect point);
225
+
207
226
 
208
- static inline cpFloat
209
- cpBodyKineticEnergy(const cpBody *body)
227
+ /// Get the kinetic energy of a body.
228
+ static inline cpFloat cpBodyKineticEnergy(const cpBody *body)
210
229
  {
211
230
  // Need to do some fudging to avoid NaNs
212
231
  cpFloat vsq = cpvdot(body->v, body->v);
@@ -214,6 +233,19 @@ cpBodyKineticEnergy(const cpBody *body)
214
233
  return (vsq ? vsq*body->m : 0.0f) + (wsq ? wsq*body->i : 0.0f);
215
234
  }
216
235
 
217
- // Apply a damped spring force between two bodies.
218
- // Warning: Large damping values can be unstable. Use a cpDampedSpring constraint for this instead.
219
- void cpApplyDampedSpring(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat rlen, cpFloat k, cpFloat dmp, cpFloat dt);
236
+ /// Body/shape iterator callback function type.
237
+ typedef void (*cpBodyShapeIteratorFunc)(cpBody *body, cpShape *shape, void *data);
238
+ /// Call @c func once for each shape attached to @c body and added to the space.
239
+ void cpBodyEachShape(cpBody *body, cpBodyShapeIteratorFunc func, void *data);
240
+
241
+ /// Body/constraint iterator callback function type.
242
+ typedef void (*cpBodyConstraintIteratorFunc)(cpBody *body, cpConstraint *constraint, void *data);
243
+ /// Call @c func once for each constraint attached to @c body and added to the space.
244
+ void cpBodyEachConstraint(cpBody *body, cpBodyConstraintIteratorFunc func, void *data);
245
+
246
+ /// Body/arbiter iterator callback function type.
247
+ typedef void (*cpBodyArbiterIteratorFunc)(cpBody *body, cpArbiter *arbiter, void *data);
248
+ /// Call @c func once for each arbiter that is currently active on the body.
249
+ void cpBodyEachArbiter(cpBody *body, cpBodyArbiterIteratorFunc func, void *data);
250
+
251
+ ///@}