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,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
+ ///@}