1 /* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
3 * Permission is hereby granted, free of charge, to any person obtaining a copy
4 * of this software and associated documentation files (the "Software"), to deal
5 * in the Software without restriction, including without limitation the rights
6 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 * copies of the Software, and to permit persons to whom the Software is
8 * furnished to do so, subject to the following conditions:
10 * The above copyright notice and this permission notice shall be included in
11 * all copies or substantial portions of the Software.
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 #include "chipmunk/chipmunk_private.h"
30 return (cpBody *)cpcalloc(1, sizeof(cpBody));
34 cpBodyInit(cpBody *body, cpFloat mass, cpFloat moment)
37 body->shapeList = NULL;
38 body->arbiterList = NULL;
39 body->constraintList = NULL;
41 body->velocity_func = cpBodyUpdateVelocity;
42 body->position_func = cpBodyUpdatePosition;
44 body->sleeping.root = NULL;
45 body->sleeping.next = NULL;
46 body->sleeping.idleTime = 0.0f;
55 body->v_bias = cpvzero;
58 body->userData = NULL;
59 body->userData2 = NULL;
61 // Setters must be called after full initialization so the sanity checks don't assert on garbage data.
62 cpBodySetMass(body, mass);
63 cpBodySetMoment(body, moment);
64 cpBodySetAngle(body, 0.0f);
70 cpBodyNew(cpFloat mass, cpFloat moment)
72 return cpBodyInit(cpBodyAlloc(), mass, moment);
78 cpBody *body = cpBodyNew(0.0f, 0.0f);
79 cpBodySetType(body, CP_BODY_TYPE_KINEMATIC);
87 cpBody *body = cpBodyNew(0.0f, 0.0f);
88 cpBodySetType(body, CP_BODY_TYPE_STATIC);
93 void cpBodyDestroy(cpBody *body){}
96 cpBodyFree(cpBody *body)
105 #define cpAssertSaneBody(body)
107 static void cpv_assert_nan(cpVect v, char *message){cpAssertHard(v.x == v.x && v.y == v.y, message);}
108 static void cpv_assert_infinite(cpVect v, char *message){cpAssertHard(cpfabs(v.x) != INFINITY && cpfabs(v.y) != INFINITY, message);}
109 static void cpv_assert_sane(cpVect v, char *message){cpv_assert_nan(v, message); cpv_assert_infinite(v, message);}
112 cpBodySanityCheck(const cpBody *body)
114 cpAssertHard(body->m == body->m && body->m_inv == body->m_inv, "Body's mass is NaN.");
115 cpAssertHard(body->i == body->i && body->i_inv == body->i_inv, "Body's moment is NaN.");
116 cpAssertHard(body->m >= 0.0f, "Body's mass is negative.");
117 cpAssertHard(body->i >= 0.0f, "Body's moment is negative.");
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.");
123 cpAssertHard(body->a == body->a && cpfabs(body->a) != INFINITY, "Body's angle is invalid.");
124 cpAssertHard(body->w == body->w && cpfabs(body->w) != INFINITY, "Body's angular velocity is invalid.");
125 cpAssertHard(body->t == body->t && cpfabs(body->t) != INFINITY, "Body's torque is invalid.");
128 #define cpAssertSaneBody(body) cpBodySanityCheck(body)
132 cpBodyIsSleeping(const cpBody *body)
134 return (body->sleeping.root != ((cpBody*)0));
138 cpBodyIsSleepThresholdExceeded(const cpBody *body, const cpShape *shape)
140 return body->sleeping.idleTime > shape->space->sleepTimeThreshold;
144 cpBodyGetType(cpBody *body)
146 if(body->sleeping.idleTime == INFINITY){
147 return CP_BODY_TYPE_STATIC;
148 } else if(body->m == INFINITY){
149 return CP_BODY_TYPE_KINEMATIC;
151 return CP_BODY_TYPE_DYNAMIC;
156 cpBodySetType(cpBody *body, cpBodyType type)
158 cpBodyType oldType = cpBodyGetType(body);
159 if(oldType == type) return;
161 // Static bodies have their idle timers set to infinity.
162 // Non-static bodies should have their idle timer reset.
163 body->sleeping.idleTime = (type == CP_BODY_TYPE_STATIC ? INFINITY : 0.0f);
165 if(type == CP_BODY_TYPE_DYNAMIC){
166 body->m = body->i = 0.0f;
167 body->m_inv = body->i_inv = INFINITY;
169 cpBodyAccumulateMassFromShapes(body);
171 body->m = body->i = INFINITY;
172 body->m_inv = body->i_inv = 0.0f;
178 // If the body is added to a space already, we'll need to update some space data structures.
179 cpSpace *space = cpBodyGetSpace(body);
181 cpAssertSpaceUnlocked(space);
183 if(oldType == CP_BODY_TYPE_STATIC){
184 // TODO This is probably not necessary
185 // cpBodyActivateStatic(body, NULL);
187 cpBodyActivate(body);
190 // Move the bodies to the correct array.
191 cpArray *fromArray = cpSpaceArrayForBodyType(space, oldType);
192 cpArray *toArray = cpSpaceArrayForBodyType(space, type);
193 if(fromArray != toArray){
194 cpArrayDeleteObj(fromArray, body);
195 cpArrayPush(toArray, body);
198 // Move the body's shapes to the correct spatial index.
199 cpSpatialIndex *fromIndex = (oldType == CP_BODY_TYPE_STATIC ? space->staticShapes : space->dynamicShapes);
200 cpSpatialIndex *toIndex = (type == CP_BODY_TYPE_STATIC ? space->staticShapes : space->dynamicShapes);
201 if(fromIndex != toIndex){
202 CP_BODY_FOREACH_SHAPE(body, shape){
203 cpSpatialIndexRemove(fromIndex, shape, shape->hashid);
204 cpSpatialIndexInsert(toIndex, shape, shape->hashid);
212 // Should *only* be called when shapes with mass info are modified, added or removed.
214 cpBodyAccumulateMassFromShapes(cpBody *body)
216 if(body == NULL || cpBodyGetType(body) != CP_BODY_TYPE_DYNAMIC) return;
218 // Reset the body's mass data.
219 body->m = body->i = 0.0f;
222 // Cache the position to realign it at the end.
223 cpVect pos = cpBodyGetPosition(body);
225 // Accumulate mass from shapes.
226 CP_BODY_FOREACH_SHAPE(body, shape){
227 struct cpShapeMassInfo *info = &shape->massInfo;
231 cpFloat msum = body->m + m;
233 body->i += m*info->i + cpvdistsq(body->cog, info->cog)*(m*body->m)/msum;
234 body->cog = cpvlerp(body->cog, info->cog, m/msum);
239 // Recalculate the inverses.
240 body->m_inv = 1.0f/body->m;
241 body->i_inv = 1.0f/body->i;
243 // Realign the body since the CoG has probably moved.
244 cpBodySetPosition(body, pos);
245 cpAssertSaneBody(body);
249 cpBodyGetSpace(const cpBody *body)
255 cpBodyGetMass(const cpBody *body)
261 cpBodySetMass(cpBody *body, cpFloat mass)
263 cpAssertHard(cpBodyGetType(body) == CP_BODY_TYPE_DYNAMIC, "You cannot set the mass of kinematic or static bodies.");
264 cpAssertHard(0.0f <= mass && mass < INFINITY, "Mass must be positive and finite.");
266 cpBodyActivate(body);
268 body->m_inv = mass == 0.0f ? INFINITY : 1.0f/mass;
269 cpAssertSaneBody(body);
273 cpBodyGetMoment(const cpBody *body)
279 cpBodySetMoment(cpBody *body, cpFloat moment)
281 cpAssertHard(moment >= 0.0f, "Moment of Inertia must be positive.");
283 cpBodyActivate(body);
285 body->i_inv = moment == 0.0f ? INFINITY : 1.0f/moment;
286 cpAssertSaneBody(body);
290 cpBodyGetRotation(const cpBody *body)
292 return cpv(body->transform.a, body->transform.b);
296 cpBodyAddShape(cpBody *body, cpShape *shape)
298 cpShape *next = body->shapeList;
299 if(next) next->prev = shape;
302 body->shapeList = shape;
304 if(shape->massInfo.m > 0.0f){
305 cpBodyAccumulateMassFromShapes(body);
310 cpBodyRemoveShape(cpBody *body, cpShape *shape)
312 cpShape *prev = shape->prev;
313 cpShape *next = shape->next;
318 body->shapeList = next;
328 if(cpBodyGetType(body) == CP_BODY_TYPE_DYNAMIC && shape->massInfo.m > 0.0f){
329 cpBodyAccumulateMassFromShapes(body);
333 static cpConstraint *
334 filterConstraints(cpConstraint *node, cpBody *body, cpConstraint *filter)
337 return cpConstraintNext(node, body);
338 } else if(node->a == body){
339 node->next_a = filterConstraints(node->next_a, body, filter);
341 node->next_b = filterConstraints(node->next_b, body, filter);
348 cpBodyRemoveConstraint(cpBody *body, cpConstraint *constraint)
350 body->constraintList = filterConstraints(body->constraintList, body, constraint);
353 // 'p' is the position of the CoG
355 SetTransform(cpBody *body, cpVect p, cpFloat a)
357 cpVect rot = cpvforangle(a);
358 cpVect c = body->cog;
360 body->transform = cpTransformNewTranspose(
361 rot.x, -rot.y, p.x - (c.x*rot.x - c.y*rot.y),
362 rot.y, rot.x, p.y - (c.x*rot.y + c.y*rot.x)
366 static inline cpFloat
367 SetAngle(cpBody *body, cpFloat a)
370 cpAssertSaneBody(body);
376 cpBodyGetPosition(const cpBody *body)
378 return cpTransformPoint(body->transform, cpvzero);
382 cpBodySetPosition(cpBody *body, cpVect position)
384 cpBodyActivate(body);
385 cpVect p = body->p = cpvadd(cpTransformVect(body->transform, body->cog), position);
386 cpAssertSaneBody(body);
388 SetTransform(body, p, body->a);
392 cpBodyGetCenterOfGravity(const cpBody *body)
398 cpBodySetCenterOfGravity(cpBody *body, cpVect cog)
400 cpBodyActivate(body);
402 cpAssertSaneBody(body);
406 cpBodyGetVelocity(const cpBody *body)
412 cpBodySetVelocity(cpBody *body, cpVect velocity)
414 cpBodyActivate(body);
416 cpAssertSaneBody(body);
420 cpBodyGetForce(const cpBody *body)
426 cpBodySetForce(cpBody *body, cpVect force)
428 cpBodyActivate(body);
430 cpAssertSaneBody(body);
434 cpBodyGetAngle(const cpBody *body)
440 cpBodySetAngle(cpBody *body, cpFloat angle)
442 cpBodyActivate(body);
443 SetAngle(body, angle);
445 SetTransform(body, body->p, angle);
449 cpBodyGetAngularVelocity(const cpBody *body)
455 cpBodySetAngularVelocity(cpBody *body, cpFloat angularVelocity)
457 cpBodyActivate(body);
458 body->w = angularVelocity;
459 cpAssertSaneBody(body);
463 cpBodyGetTorque(const cpBody *body)
469 cpBodySetTorque(cpBody *body, cpFloat torque)
471 cpBodyActivate(body);
473 cpAssertSaneBody(body);
477 cpBodyGetUserData(const cpBody *body)
479 return body->userData;
483 cpBodySetUserData(cpBody *body, cpDataPointer userData)
485 body->userData = userData;
488 cpBodyGetUserData2(const cpBody *body)
490 return body->userData2;
494 cpBodySetUserData2(cpBody *body, cpDataPointer userData)
496 body->userData2 = userData;
500 cpBodySetVelocityUpdateFunc(cpBody *body, cpBodyVelocityFunc velocityFunc)
502 body->velocity_func = velocityFunc;
506 cpBodySetPositionUpdateFunc(cpBody *body, cpBodyPositionFunc positionFunc)
508 body->position_func = positionFunc;
512 cpBodyUpdateVelocity(cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt)
514 // Skip kinematic bodies.
515 if(cpBodyGetType(body) == CP_BODY_TYPE_KINEMATIC) return;
517 cpAssertSoft(body->m > 0.0f && body->i > 0.0f, "Body's mass and moment must be positive to simulate. (Mass: %f Moment: %f)", body->m, body->i);
519 body->v = cpvadd(cpvmult(body->v, damping), cpvmult(cpvadd(gravity, cpvmult(body->f, body->m_inv)), dt));
520 body->w = body->w*damping + body->t*body->i_inv*dt;
526 cpAssertSaneBody(body);
530 cpBodyUpdatePosition(cpBody *body, cpFloat dt)
532 cpVect p = body->p = cpvadd(body->p, cpvmult(cpvadd(body->v, body->v_bias), dt));
533 cpFloat a = SetAngle(body, body->a + (body->w + body->w_bias)*dt);
534 SetTransform(body, p, a);
536 body->v_bias = cpvzero;
539 cpAssertSaneBody(body);
543 cpBodyLocalToWorld(const cpBody *body, const cpVect point)
545 return cpTransformPoint(body->transform, point);
549 cpBodyWorldToLocal(const cpBody *body, const cpVect point)
551 return cpTransformPoint(cpTransformRigidInverse(body->transform), point);
555 cpBodyApplyForceAtWorldPoint(cpBody *body, cpVect force, cpVect point)
557 cpBodyActivate(body);
558 body->f = cpvadd(body->f, force);
560 cpVect r = cpvsub(point, cpTransformPoint(body->transform, body->cog));
561 body->t += cpvcross(r, force);
565 cpBodyApplyForceAtLocalPoint(cpBody *body, cpVect force, cpVect point)
567 cpBodyApplyForceAtWorldPoint(body, cpTransformVect(body->transform, force), cpTransformPoint(body->transform, point));
571 cpBodyApplyImpulseAtWorldPoint(cpBody *body, cpVect impulse, cpVect point)
573 cpBodyActivate(body);
575 cpVect r = cpvsub(point, cpTransformPoint(body->transform, body->cog));
576 apply_impulse(body, impulse, r);
580 cpBodyApplyImpulseAtLocalPoint(cpBody *body, cpVect impulse, cpVect point)
582 cpBodyApplyImpulseAtWorldPoint(body, cpTransformVect(body->transform, impulse), cpTransformPoint(body->transform, point));
586 cpBodyGetVelocityAtLocalPoint(const cpBody *body, cpVect point)
588 cpVect r = cpTransformVect(body->transform, cpvsub(point, body->cog));
589 return cpvadd(body->v, cpvmult(cpvperp(r), body->w));
593 cpBodyGetVelocityAtWorldPoint(const cpBody *body, cpVect point)
595 cpVect r = cpvsub(point, cpTransformPoint(body->transform, body->cog));
596 return cpvadd(body->v, cpvmult(cpvperp(r), body->w));
600 cpBodyKineticEnergy(const cpBody *body)
602 // Need to do some fudging to avoid NaNs
603 cpFloat vsq = cpvdot(body->v, body->v);
604 cpFloat wsq = body->w*body->w;
605 return (vsq ? vsq*body->m : 0.0f) + (wsq ? wsq*body->i : 0.0f);
609 cpBodyEachShape(cpBody *body, cpBodyShapeIteratorFunc func, void *data)
611 cpShape *shape = body->shapeList;
613 cpShape *next = shape->next;
614 func(body, shape, data);
620 cpBodyEachConstraint(cpBody *body, cpBodyConstraintIteratorFunc func, void *data)
622 cpConstraint *constraint = body->constraintList;
624 cpConstraint *next = cpConstraintNext(constraint, body);
625 func(body, constraint, data);
631 cpBodyEachArbiter(cpBody *body, cpBodyArbiterIteratorFunc func, void *data)
633 cpArbiter *arb = body->arbiterList;
635 cpArbiter *next = cpArbiterNext(arb, body);
637 cpBool swapped = arb->swapped; {
638 arb->swapped = (body == arb->body_b);
639 func(body, arb, data);
640 } arb->swapped = swapped;