1 /* Copyright (c) 2007 Scott Lembcke
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
24 #include "chipmunk/chipmunk_private.h"
26 //MARK: Sleeping Functions
29 cpSpaceActivateBody(cpSpace *space, cpBody *body)
31 cpAssertHard(cpBodyGetType(body) == CP_BODY_TYPE_DYNAMIC, "Internal error: Attempting to activate a non-dynamic body.");
34 // cpSpaceActivateBody() is called again once the space is unlocked
35 if(!cpArrayContains(space->rousedBodies, body)) cpArrayPush(space->rousedBodies, body);
37 cpAssertSoft(body->sleeping.root == NULL && body->sleeping.next == NULL, "Internal error: Activating body non-NULL node pointers.");
38 cpArrayPush(space->dynamicBodies, body);
40 CP_BODY_FOREACH_SHAPE(body, shape){
41 cpSpatialIndexRemove(space->staticShapes, shape, shape->hashid);
42 cpSpatialIndexInsert(space->dynamicShapes, shape, shape->hashid);
45 CP_BODY_FOREACH_ARBITER(body, arb){
46 cpBody *bodyA = arb->body_a;
48 // Arbiters are shared between two bodies that are always woken up together.
49 // You only want to restore the arbiter once, so bodyA is arbitrarily chosen to own the arbiter.
50 // The edge case is when static bodies are involved as the static bodies never actually sleep.
51 // If the static body is bodyB then all is good. If the static body is bodyA, that can easily be checked.
52 if(body == bodyA || cpBodyGetType(bodyA) == CP_BODY_TYPE_STATIC){
53 int numContacts = arb->count;
54 struct cpContact *contacts = arb->contacts;
56 // Restore contact values back to the space's contact buffer memory
57 arb->contacts = cpContactBufferGetArray(space);
58 memcpy(arb->contacts, contacts, numContacts*sizeof(struct cpContact));
59 cpSpacePushContacts(space, numContacts);
61 // Reinsert the arbiter into the arbiter cache
62 const cpShape *a = arb->a, *b = arb->b;
63 const cpShape *shape_pair[] = {a, b};
64 cpHashValue arbHashID = CP_HASH_PAIR((cpHashValue)a, (cpHashValue)b);
65 cpHashSetInsert(space->cachedArbiters, arbHashID, shape_pair, NULL, arb);
67 // Update the arbiter's state
68 arb->stamp = space->stamp;
69 cpArrayPush(space->arbiters, arb);
75 CP_BODY_FOREACH_CONSTRAINT(body, constraint){
76 cpBody *bodyA = constraint->a;
77 if(body == bodyA || cpBodyGetType(bodyA) == CP_BODY_TYPE_STATIC) cpArrayPush(space->constraints, constraint);
83 cpSpaceDeactivateBody(cpSpace *space, cpBody *body)
85 cpAssertHard(cpBodyGetType(body) == CP_BODY_TYPE_DYNAMIC, "Internal error: Attempting to deactivate a non-dynamic body.");
87 cpArrayDeleteObj(space->dynamicBodies, body);
89 CP_BODY_FOREACH_SHAPE(body, shape){
90 cpSpatialIndexRemove(space->dynamicShapes, shape, shape->hashid);
91 cpSpatialIndexInsert(space->staticShapes, shape, shape->hashid);
94 CP_BODY_FOREACH_ARBITER(body, arb){
95 cpBody *bodyA = arb->body_a;
96 if(body == bodyA || cpBodyGetType(bodyA) == CP_BODY_TYPE_STATIC){
97 cpSpaceUncacheArbiter(space, arb);
99 // Save contact values to a new block of memory so they won't time out
100 size_t bytes = arb->count*sizeof(struct cpContact);
101 struct cpContact *contacts = (struct cpContact *)cpcalloc(1, bytes);
102 memcpy(contacts, arb->contacts, bytes);
103 arb->contacts = contacts;
107 CP_BODY_FOREACH_CONSTRAINT(body, constraint){
108 cpBody *bodyA = constraint->a;
109 if(body == bodyA || cpBodyGetType(bodyA) == CP_BODY_TYPE_STATIC) cpArrayDeleteObj(space->constraints, constraint);
113 static inline cpBody *
114 ComponentRoot(cpBody *body)
116 return (body ? body->sleeping.root : NULL);
120 cpBodyActivate(cpBody *body)
122 if(body != NULL && cpBodyGetType(body) == CP_BODY_TYPE_DYNAMIC){
123 body->sleeping.idleTime = 0.0f;
125 cpBody *root = ComponentRoot(body);
126 if(root && cpBodyIsSleeping(root)){
127 // TODO should cpBodyIsSleeping(root) be an assertion?
128 cpAssertSoft(cpBodyGetType(root) == CP_BODY_TYPE_DYNAMIC, "Internal Error: Non-dynamic body component root detected.");
130 cpSpace *space = root->space;
133 cpBody *next = body->sleeping.next;
135 body->sleeping.idleTime = 0.0f;
136 body->sleeping.root = NULL;
137 body->sleeping.next = NULL;
138 cpSpaceActivateBody(space, body);
143 cpArrayDeleteObj(space->sleepingComponents, root);
146 CP_BODY_FOREACH_ARBITER(body, arb){
147 // Reset the idle timer of things the body is touching as well.
148 // That way things don't get left hanging in the air.
149 cpBody *other = (arb->body_a == body ? arb->body_b : arb->body_a);
150 if(cpBodyGetType(other) != CP_BODY_TYPE_STATIC) other->sleeping.idleTime = 0.0f;
156 cpBodyActivateStatic(cpBody *body, cpShape *filter)
158 cpAssertHard(cpBodyGetType(body) == CP_BODY_TYPE_STATIC, "cpBodyActivateStatic() called on a non-static body.");
160 CP_BODY_FOREACH_ARBITER(body, arb){
161 if(!filter || filter == arb->a || filter == arb->b){
162 cpBodyActivate(arb->body_a == body ? arb->body_b : arb->body_a);
166 // TODO: should also activate joints?
170 cpBodyPushArbiter(cpBody *body, cpArbiter *arb)
172 cpAssertSoft(cpArbiterThreadForBody(arb, body)->next == NULL, "Internal Error: Dangling contact graph pointers detected. (A)");
173 cpAssertSoft(cpArbiterThreadForBody(arb, body)->prev == NULL, "Internal Error: Dangling contact graph pointers detected. (B)");
175 cpArbiter *next = body->arbiterList;
176 cpAssertSoft(next == NULL || cpArbiterThreadForBody(next, body)->prev == NULL, "Internal Error: Dangling contact graph pointers detected. (C)");
177 cpArbiterThreadForBody(arb, body)->next = next;
179 if(next) cpArbiterThreadForBody(next, body)->prev = arb;
180 body->arbiterList = arb;
184 ComponentAdd(cpBody *root, cpBody *body){
185 body->sleeping.root = root;
188 body->sleeping.next = root->sleeping.next;
189 root->sleeping.next = body;
194 FloodFillComponent(cpBody *root, cpBody *body)
196 // Kinematic bodies cannot be put to sleep and prevent bodies they are touching from sleeping.
197 // Static bodies are effectively sleeping all the time.
198 if(cpBodyGetType(body) == CP_BODY_TYPE_DYNAMIC){
199 cpBody *other_root = ComponentRoot(body);
200 if(other_root == NULL){
201 ComponentAdd(root, body);
202 CP_BODY_FOREACH_ARBITER(body, arb) FloodFillComponent(root, (body == arb->body_a ? arb->body_b : arb->body_a));
203 CP_BODY_FOREACH_CONSTRAINT(body, constraint) FloodFillComponent(root, (body == constraint->a ? constraint->b : constraint->a));
205 cpAssertSoft(other_root == root, "Internal Error: Inconsistency dectected in the contact graph.");
211 ComponentActive(cpBody *root, cpFloat threshold)
213 CP_BODY_FOREACH_COMPONENT(root, body){
214 if(body->sleeping.idleTime < threshold) return cpTrue;
221 cpSpaceProcessComponents(cpSpace *space, cpFloat dt)
223 cpBool sleep = (space->sleepTimeThreshold != INFINITY);
224 cpArray *bodies = space->dynamicBodies;
227 for(int i=0; i<bodies->num; i++){
228 cpBody *body = (cpBody*)bodies->arr[i];
230 cpAssertSoft(body->sleeping.next == NULL, "Internal Error: Dangling next pointer detected in contact graph.");
231 cpAssertSoft(body->sleeping.root == NULL, "Internal Error: Dangling root pointer detected in contact graph.");
235 // Calculate the kinetic energy of all the bodies.
237 cpFloat dv = space->idleSpeedThreshold;
238 cpFloat dvsq = (dv ? dv*dv : cpvlengthsq(space->gravity)*dt*dt);
240 // update idling and reset component nodes
241 for(int i=0; i<bodies->num; i++){
242 cpBody *body = (cpBody*)bodies->arr[i];
244 // TODO should make a separate array for kinematic bodies.
245 if(cpBodyGetType(body) != CP_BODY_TYPE_DYNAMIC) continue;
247 // Need to deal with infinite mass objects
248 cpFloat keThreshold = (dvsq ? body->m*dvsq : 0.0f);
249 body->sleeping.idleTime = (cpBodyKineticEnergy(body) > keThreshold ? 0.0f : body->sleeping.idleTime + dt);
253 // Awaken any sleeping bodies found and then push arbiters to the bodies' lists.
254 cpArray *arbiters = space->arbiters;
255 for(int i=0, count=arbiters->num; i<count; i++){
256 cpArbiter *arb = (cpArbiter*)arbiters->arr[i];
257 cpBody *a = arb->body_a, *b = arb->body_b;
260 // TODO checking cpBodyIsSleepin() redundant?
261 if(cpBodyGetType(b) == CP_BODY_TYPE_KINEMATIC || cpBodyIsSleeping(a)) cpBodyActivate(a);
262 if(cpBodyGetType(a) == CP_BODY_TYPE_KINEMATIC || cpBodyIsSleeping(b)) cpBodyActivate(b);
265 cpBodyPushArbiter(a, arb);
266 cpBodyPushArbiter(b, arb);
270 // Bodies should be held active if connected by a joint to a kinematic.
271 cpArray *constraints = space->constraints;
272 for(int i=0; i<constraints->num; i++){
273 cpConstraint *constraint = (cpConstraint *)constraints->arr[i];
274 cpBody *a = constraint->a, *b = constraint->b;
276 if(cpBodyGetType(b) == CP_BODY_TYPE_KINEMATIC) cpBodyActivate(a);
277 if(cpBodyGetType(a) == CP_BODY_TYPE_KINEMATIC) cpBodyActivate(b);
280 // Generate components and deactivate sleeping ones
281 for(int i=0; i<bodies->num;){
282 cpBody *body = (cpBody*)bodies->arr[i];
284 if(ComponentRoot(body) == NULL){
285 // Body not in a component yet. Perform a DFS to flood fill mark
286 // the component in the contact graph using this body as the root.
287 FloodFillComponent(body, body);
289 // Check if the component should be put to sleep.
290 if(!ComponentActive(body, space->sleepTimeThreshold)){
291 cpArrayPush(space->sleepingComponents, body);
292 CP_BODY_FOREACH_COMPONENT(body, other) cpSpaceDeactivateBody(space, other);
294 // cpSpaceDeactivateBody() removed the current body from the list.
295 // Skip incrementing the index counter.
302 // Only sleeping bodies retain their component node pointers.
303 body->sleeping.root = NULL;
304 body->sleeping.next = NULL;
310 cpBodySleep(cpBody *body)
312 cpBodySleepWithGroup(body, NULL);
316 cpBodySleepWithGroup(cpBody *body, cpBody *group){
317 cpAssertHard(cpBodyGetType(body) == CP_BODY_TYPE_DYNAMIC, "Non-dynamic bodies cannot be put to sleep.");
319 cpSpace *space = body->space;
320 cpAssertHard(!cpSpaceIsLocked(space), "Bodies cannot be put to sleep during a query or a call to cpSpaceStep(). Put these calls into a post-step callback.");
321 cpAssertHard(cpSpaceGetSleepTimeThreshold(space) < INFINITY, "Sleeping is not enabled on the space. You cannot sleep a body without setting a sleep time threshold on the space.");
322 cpAssertHard(group == NULL || cpBodyIsSleeping(group), "Cannot use a non-sleeping body as a group identifier.");
324 if(cpBodyIsSleeping(body)){
325 cpAssertHard(ComponentRoot(body) == ComponentRoot(group), "The body is already sleeping and it's group cannot be reassigned.");
329 CP_BODY_FOREACH_SHAPE(body, shape) cpShapeCacheBB(shape);
330 cpSpaceDeactivateBody(space, body);
333 cpBody *root = ComponentRoot(group);
335 body->sleeping.root = root;
336 body->sleeping.next = root->sleeping.next;
337 body->sleeping.idleTime = 0.0f;
339 root->sleeping.next = body;
341 body->sleeping.root = body;
342 body->sleeping.next = NULL;
343 body->sleeping.idleTime = 0.0f;
345 cpArrayPush(space->sleepingComponents, body);
348 cpArrayDeleteObj(space->dynamicBodies, body);