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.
- data/ext/chipmunk/chipmunk.c +199 -28
- data/ext/chipmunk/chipmunk.h +123 -68
- data/ext/chipmunk/chipmunk_ffi.h +129 -11
- data/ext/chipmunk/chipmunk_private.h +232 -16
- data/ext/chipmunk/chipmunk_types.h +94 -30
- data/ext/chipmunk/chipmunk_unsafe.h +12 -3
- data/ext/chipmunk/constraints/cpConstraint.h +90 -34
- data/ext/chipmunk/{cpDampedRotarySpring.h → constraints/cpDampedRotarySpring.h} +18 -8
- data/ext/chipmunk/{cpDampedSpring.h → constraints/cpDampedSpring.h} +27 -16
- data/ext/chipmunk/constraints/cpGearJoint.h +17 -7
- data/ext/chipmunk/constraints/cpGrooveJoint.h +19 -10
- data/ext/chipmunk/constraints/cpPinJoint.h +17 -8
- data/ext/chipmunk/constraints/cpPivotJoint.h +18 -9
- data/ext/chipmunk/constraints/cpRatchetJoint.h +17 -8
- data/ext/chipmunk/constraints/cpRotaryLimitJoint.h +16 -7
- data/ext/chipmunk/{cpSimpleMotor.h → constraints/cpSimpleMotor.h} +15 -6
- data/ext/chipmunk/constraints/cpSlideJoint.h +18 -9
- data/ext/chipmunk/constraints/util.h +36 -44
- data/ext/chipmunk/cpArbiter.c +159 -94
- data/ext/chipmunk/cpArbiter.h +135 -129
- data/ext/chipmunk/cpArray.c +37 -56
- data/ext/chipmunk/cpBB.c +1 -12
- data/ext/chipmunk/cpBB.h +80 -18
- data/ext/chipmunk/cpBBTree.c +891 -0
- data/ext/chipmunk/cpBody.c +185 -47
- data/ext/chipmunk/cpBody.h +156 -124
- data/ext/chipmunk/cpCollision.c +126 -115
- data/ext/chipmunk/cpConstraint.c +10 -6
- data/ext/chipmunk/cpDampedRotarySpring.c +26 -17
- data/ext/chipmunk/cpDampedSpring.c +25 -18
- data/ext/chipmunk/cpGearJoint.c +23 -17
- data/ext/chipmunk/cpGrooveJoint.c +26 -22
- data/ext/chipmunk/cpHashSet.c +51 -51
- data/ext/chipmunk/cpPinJoint.c +26 -19
- data/ext/chipmunk/cpPivotJoint.c +23 -19
- data/ext/chipmunk/cpPolyShape.c +93 -69
- data/ext/chipmunk/cpPolyShape.h +33 -69
- data/ext/chipmunk/cpRatchetJoint.c +26 -21
- data/ext/chipmunk/cpRotaryLimitJoint.c +28 -22
- data/ext/chipmunk/cpShape.c +122 -133
- data/ext/chipmunk/cpShape.h +146 -95
- data/ext/chipmunk/cpSimpleMotor.c +24 -17
- data/ext/chipmunk/cpSlideJoint.c +28 -26
- data/ext/chipmunk/cpSpace.c +251 -196
- data/ext/chipmunk/cpSpace.h +173 -103
- data/ext/chipmunk/cpSpaceComponent.c +236 -159
- data/ext/chipmunk/cpSpaceHash.c +259 -159
- data/ext/chipmunk/cpSpaceQuery.c +127 -59
- data/ext/chipmunk/cpSpaceStep.c +235 -197
- data/ext/chipmunk/cpSpatialIndex.c +69 -0
- data/ext/chipmunk/cpSpatialIndex.h +227 -0
- data/ext/chipmunk/cpSweep1D.c +254 -0
- data/ext/chipmunk/cpVect.c +11 -26
- data/ext/chipmunk/cpVect.h +76 -71
- data/ext/chipmunk/extconf.rb +4 -31
- data/ext/chipmunk/prime.h +1 -1
- data/ext/chipmunk/rb_chipmunk.c +36 -45
- data/ext/chipmunk/rb_chipmunk.h +6 -3
- data/ext/chipmunk/rb_cpArbiter.c +2 -2
- data/ext/chipmunk/rb_cpBB.c +116 -35
- data/ext/chipmunk/rb_cpBody.c +5 -12
- data/ext/chipmunk/rb_cpConstraint.c +144 -9
- data/ext/chipmunk/rb_cpShape.c +69 -78
- data/ext/chipmunk/rb_cpSpace.c +81 -76
- metadata +61 -61
- data/LICENSE +0 -22
- data/README +0 -110
- data/Rakefile +0 -102
- data/ext/chipmunk/cpArray.h +0 -49
- data/ext/chipmunk/cpCollision.h +0 -28
- data/ext/chipmunk/cpHashSet.h +0 -82
- data/ext/chipmunk/cpSpaceHash.h +0 -110
- data/lib/chipmunk.rb +0 -194
data/ext/chipmunk/cpBody.c
CHANGED
@@ -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 *)
|
33
|
+
return (cpBody *)cpcalloc(1, sizeof(cpBody));
|
35
34
|
}
|
36
35
|
|
37
|
-
|
38
|
-
cpBodyPositionFunc cpBodyUpdatePositionDefault = cpBodyUpdatePosition;
|
39
|
-
|
40
|
-
cpBody*
|
36
|
+
cpBody *
|
41
37
|
cpBodyInit(cpBody *body, cpFloat m, cpFloat i)
|
42
38
|
{
|
43
|
-
body->
|
44
|
-
body->
|
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->
|
65
|
-
body->shapesList = NULL;
|
63
|
+
body->data = NULL;
|
66
64
|
|
67
|
-
|
68
|
-
body
|
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
|
-
|
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
|
-
|
226
|
+
cpBodySetAngle(cpBody *body, cpFloat angle)
|
128
227
|
{
|
129
|
-
|
130
|
-
body
|
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
|
-
|
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
|
-
|
272
|
+
cpBodyApplyImpulse(cpBody *body, const cpVect j, const cpVect r)
|
168
273
|
{
|
169
|
-
|
170
|
-
|
171
|
-
|
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
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
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
|
}
|
data/ext/chipmunk/cpBody.h
CHANGED
@@ -19,194 +19,213 @@
|
|
19
19
|
* SOFTWARE.
|
20
20
|
*/
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
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
|
-
|
37
|
-
|
38
|
-
int rank;
|
36
|
+
cpBody *root;
|
37
|
+
cpBody *next;
|
39
38
|
cpFloat idleTime;
|
40
39
|
} cpComponentNode;
|
41
40
|
|
42
|
-
|
43
|
-
|
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
|
-
|
46
|
+
/// Function that is called to integrate the body's position. (Defaults to cpBodyUpdatePosition)
|
49
47
|
cpBodyPositionFunc position_func;
|
50
48
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
cpFloat
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
cpFloat i
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
cpVect p
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
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
|
-
|
75
|
-
|
76
|
-
|
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
|
-
|
80
|
-
|
81
|
-
|
82
|
-
cpFloat
|
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
|
-
|
91
|
-
CP_PRIVATE(struct cpSpace *space);
|
93
|
+
CP_PRIVATE(cpSpace *space);
|
92
94
|
|
93
|
-
|
94
|
-
|
95
|
-
CP_PRIVATE(
|
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
|
-
}
|
100
|
+
};
|
100
101
|
|
101
|
-
|
102
|
-
cpBody
|
103
|
-
|
104
|
-
cpBody *
|
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
|
-
|
107
|
-
cpBody *
|
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
|
-
|
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
|
-
|
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
|
-
|
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).
|
141
|
+
return (CP_PRIVATE(body->node).root != ((cpBody*)0));
|
124
142
|
}
|
125
143
|
|
126
|
-
|
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
|
-
|
133
|
-
|
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) == ((
|
154
|
+
return (body->CP_PRIVATE(space) == ((cpSpace*)0));
|
136
155
|
}
|
137
156
|
|
138
157
|
|
139
|
-
#define
|
158
|
+
#define CP_DefineBodyStructGetter(type, member, name) \
|
140
159
|
static inline type cpBodyGet##name(const cpBody *body){return body->member;}
|
141
160
|
|
142
|
-
#define
|
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
|
150
|
-
|
151
|
-
|
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
|
-
|
155
|
-
|
175
|
+
CP_DefineBodyStructGetter(cpFloat, m, Mass)
|
176
|
+
/// Set the mass of a body.
|
156
177
|
void cpBodySetMass(cpBody *body, cpFloat m);
|
157
178
|
|
158
|
-
|
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
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
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
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
218
|
-
|
219
|
-
|
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
|
+
///@}
|