static inline void mergeBodies(cpSpace *space, cpArray *components, cpArray *rogueBodies, cpBody *a, cpBody *b) { // Ignore connections to static bodies if(cpBodyIsStatic(a) || cpBodyIsStatic(b)) return; cpBody *a_root = componentNodeRoot(a); cpBody *b_root = componentNodeRoot(b); cpBool a_sleep = cpBodyIsSleeping(a_root); cpBool b_sleep = cpBodyIsSleeping(b_root); if(a_sleep && b_sleep){ return; } else if(a_sleep || b_sleep){ componentActivate(a_root); componentActivate(b_root); } // Add any rogue bodies found to the list and reset the idle time of anything they touch. if(cpBodyIsRogue(a)){ cpArrayPush(rogueBodies, a); b->node.idleTime = 0.0f; } if(cpBodyIsRogue(b)){ cpArrayPush(rogueBodies, b); a->node.idleTime = 0.0f; } componentNodeMerge(a_root, b_root); }
void cpBodySleepWithGroup(cpBody *body, cpBody *group){ cpAssert(!cpBodyIsStatic(body) && !cpBodyIsRogue(body), "Rogue and static bodies cannot be put to sleep."); cpSpace *space = body->space; cpAssert(space, "Cannot put a body to sleep that has not been added to a space."); cpAssert(!space->locked, "Bodies can not be put to sleep during a query or a call to cpSpaceSte(). Put these calls into a post-step callback."); cpAssert(!group || cpBodyIsSleeping(group), "Cannot use a non-sleeping body as a group identifier."); if(cpBodyIsSleeping(body)) return; for(cpShape *shape = body->shapesList; shape; shape = shape->next){ cpShapeCacheBB(shape); cpSpaceHashRemove(space->activeShapes, shape, shape->hashid); cpSpaceHashInsert(space->staticShapes, shape, shape->hashid, shape->bb); } if(group){ cpBody *root = componentNodeRoot(group); cpComponentNode node = {root, root->node.next, 0, 0.0f}; body->node = node; root->node.next = body; } else { cpComponentNode node = {NULL, body, 0, 0.0f}; body->node = node; cpArrayPush(space->sleepingComponents, body); } cpArrayDeleteObj(space->bodies, body); }
static inline void mergeBodies(cpSpace *space, cpArray *components, cpArray *rogueBodies, cpBody *a, cpBody *b) { // Don't merge with the static body if(cpBodyIsStatic(a) || cpBodyIsStatic(b)) return; cpBody *a_root = componentNodeRoot(a); cpBody *b_root = componentNodeRoot(b); cpBool a_sleep = cpBodyIsSleeping(a_root); cpBool b_sleep = cpBodyIsSleeping(b_root); if(a_sleep && b_sleep){ return; } else if(a_sleep || b_sleep){ componentActivate(a_root); componentActivate(b_root); } // Add any rogue bodies (bodies not added to the space) if(!a->space) cpArrayPush(rogueBodies, a); if(!b->space) cpArrayPush(rogueBodies, b); componentNodeMerge(a_root, b_root); }
// Hashset filter func to throw away old arbiters. static cpBool cpSpaceArbiterSetFilter(cpArbiter *arb, cpSpace *space) { cpTimestamp ticks = space->stamp - arb->stamp; cpBody *a = arb->body_a, *b = arb->body_b; // TODO should make an arbiter state for this so it doesn't require filtering arbiters for dangling body pointers on body removal. // Preserve arbiters on sensors and rejected arbiters for sleeping objects. if( (cpBodyIsStatic(a) || cpBodyIsSleeping(a)) && (cpBodyIsStatic(b) || cpBodyIsSleeping(b)) ){ return cpTrue; } // Arbiter was used last frame, but not this one if(ticks >= 1 && arb->state != cpArbiterStateCached){ cpArbiterCallSeparate(arb, space); arb->state = cpArbiterStateCached; } if(ticks >= space->collisionPersistence){ arb->contacts = NULL; arb->numContacts = 0; cpArrayPush(space->pooledArbiters, arb); return cpFalse; } return cpTrue; }
NS_CC_EXT_BEGIN /* IMPORTANT - READ ME! This file sets pokes around in the private API a lot to provide efficient debug rendering given nothing more than reference to a Chipmunk space. It is not recommended to write rendering code like this in your own games as the private API may change with little or no warning. */ // 此文件采用了很多私有的API,用于调试中渲染物理空间。 不推荐这么做,私有api最不愿改动 static ccColor4F ColorForBody(cpBody *body) { if (cpBodyIsRogue(body) || cpBodyIsSleeping(body)) { return ccc4f(0.5f, 0.5f, 0.5f ,0.5f); } else if (body->CP_PRIVATE(node).idleTime > body->CP_PRIVATE(space)->sleepTimeThreshold) { return ccc4f(0.33f, 0.33f, 0.33f, 0.5f); } else { return ccc4f(1.0f, 0.0f, 0.0f, 0.5f); } }
NS_CC_EXT_BEGIN #if CC_ENABLE_CHIPMUNK_INTEGRATION /* IMPORTANT - READ ME! This file sets pokes around in the private API a lot to provide efficient debug rendering given nothing more than reference to a Chipmunk space. It is not recommended to write rendering code like this in your own games as the private API may change with little or no warning. */ static Color4F ColorForBody(cpBody *body) { if (CP_BODY_TYPE_STATIC == cpBodyGetType(body) || cpBodyIsSleeping(body)) { return Color4F(0.5f, 0.5f, 0.5f ,0.5f); } else if (body->sleeping.idleTime > cpBodyGetSpace(body)->sleepTimeThreshold) { return Color4F(0.33f, 0.33f, 0.33f, 0.5f); } else { return Color4F(1.0f, 0.0f, 0.0f, 0.5f); } }
static int l_physics_isBodySleeping(lua_State* state) { l_tools_checkUserDataPlusErrMsg(state, 1, "You must provide a body"); l_physics_Body* body = (l_physics_Body*)lua_touserdata(state, 1); lua_pushboolean(state, cpBodyIsSleeping(body->body)); return 1; }
// Hashset filter func to throw away old arbiters. static cpBool contactSetFilter(cpArbiter *arb, cpSpace *space) { if(space->sleepTimeThreshold != INFINITY){ cpBody *a = arb->a->body; cpBody *b = arb->b->body; // both bodies are either static or sleeping cpBool sleepingNow = (cpBodyIsStatic(a) || cpBodyIsSleeping(a)) && (cpBodyIsStatic(b) || cpBodyIsSleeping(b)); if(sleepingNow){ arb->state = cpArbiterStateSleep; return cpTrue; } else if(arb->state == cpArbiterStateSleep){ // wake up the arbiter and continue as normal arb->state = cpArbiterStateNormal; // TODO is it possible that cpArbiterStateIgnore should be set here instead? } } cpTimestamp ticks = space->stamp - arb->stamp; // was used last frame, but not this one if(ticks >= 1 && arb->state != cpArbiterStateCached){ // The handler needs to be looked up again as the handler cached on the arbiter may have been deleted since the last step. cpCollisionHandler *handler = lookupCollisionHandler(space, arb->a->collision_type, arb->b->collision_type); handler->separate(arb, space, handler->data); arb->state = cpArbiterStateCached; } if(ticks >= cp_contact_persistence){ arb->contacts = NULL; arb->numContacts = 0; cpArrayPush(space->pooledArbiters, arb); return cpFalse; } return cpTrue; }
static VALUE rb_cpBodySleepWithGroup(VALUE self, VALUE vgroup) { cpBody * group = NIL_P(vgroup) ? NULL : rb_cpBodySleepValidate(vgroup); cpBody * body = rb_cpBodySleepValidate(self); if (!cpBodyIsSleeping(group)) { rb_raise(rb_eArgError, "Cannot use a non-sleeping body as a group identifier."); } cpBodySleepWithGroup(body, group); return self; }
static cpSpaceDebugColor ColorForShape(cpShape *shape, cpDataPointer data) { if(cpShapeGetSensor(shape)){ return LAColor(1.0f, 0.3f); } else { cpBody *body = cpShapeGetBody(shape); if(cpBodyIsSleeping(body)){ return LAColor(0.2f, 0.3f); } else if(body->sleeping.idleTime > shape->space->sleepTimeThreshold) { return LAColor(0.66f, 0.3f); } else { GLfloat intensity = (cpBodyGetType(body) == CP_BODY_TYPE_STATIC ? 0.15f : 0.75f); return RGBAColor(intensity, 0.0f, 0.0f, 0.3f); } } }
static inline void componentActivate(cpBody *root) { if(!cpBodyIsSleeping(root)) return; cpSpace *space = root->space; cpAssert(space, "Trying to activate a body that was never added to a space."); cpBody *body = root, *next; do { next = body->node.next; cpComponentNode node = {NULL, NULL, 0, 0.0f}; body->node = node; cpSpaceActivateBody(space, body); } while((body = next) != root); cpArrayDeleteObj(space->sleepingComponents, root); }
static inline void componentActivate(cpBody *root) { if(!cpBodyIsSleeping(root)) return; cpSpace *space = root->space; cpAssert(space, "Trying to activate a body that was never added to a space."); cpBody *body = root, *next; do { next = body->node.next; body->node.next = NULL; body->node.idleTime = 0.0f; cpArrayPush(space->bodies, body); for(cpShape *shape=body->shapesList; shape; shape=shape->next){ removeShapeRaw(shape, space->staticShapes); addShapeRaw(shape, space->activeShapes); } } while((body = next) != root); cpArrayDeleteObj(space->sleepingComponents, root); }
bool PhysicsBody::isResting() const { return cpBodyIsSleeping(_cpBody) != cpFalse; }
static VALUE rb_cpBodyIsSleeping(VALUE self) { return cpBodyIsSleeping(BODY(self)) ? Qtrue : Qfalse; }
void cpHastySpaceStep(cpSpace *space, cpFloat dt) { // don't step if the timestep is 0! if(dt == 0.0f) return; space->stamp++; cpFloat prev_dt = space->curr_dt; space->curr_dt = dt; cpArray *bodies = space->dynamicBodies; cpArray *constraints = space->constraints; cpArray *arbiters = space->arbiters; // Reset and empty the arbiter list. for(int i=0; i<arbiters->num; i++) { cpArbiter *arb = (cpArbiter *)arbiters->arr[i]; arb->state = CP_ARBITER_STATE_NORMAL; // If both bodies are awake, unthread the arbiter from the contact graph. if(!cpBodyIsSleeping(arb->body_a) && !cpBodyIsSleeping(arb->body_b)) { cpArbiterUnthread(arb); } } arbiters->num = 0; cpSpaceLock(space); { // Integrate positions for(int i=0; i<bodies->num; i++) { cpBody *body = (cpBody *)bodies->arr[i]; body->position_func(body, dt); } // Find colliding pairs. cpSpacePushFreshContactBuffer(space); cpSpatialIndexEach(space->dynamicShapes, (cpSpatialIndexIteratorFunc)cpShapeUpdateFunc, NULL); cpSpatialIndexReindexQuery(space->dynamicShapes, (cpSpatialIndexQueryFunc)cpSpaceCollideShapes, space); } cpSpaceUnlock(space, cpFalse); // Rebuild the contact graph (and detect sleeping components if sleeping is enabled) cpSpaceProcessComponents(space, dt); cpSpaceLock(space); { // Clear out old cached arbiters and call separate callbacks cpHashSetFilter(space->cachedArbiters, (cpHashSetFilterFunc)cpSpaceArbiterSetFilter, space); // Prestep the arbiters and constraints. cpFloat slop = space->collisionSlop; cpFloat biasCoef = 1.0f - cpfpow(space->collisionBias, dt); for(int i=0; i<arbiters->num; i++) { cpArbiterPreStep((cpArbiter *)arbiters->arr[i], dt, slop, biasCoef); } for(int i=0; i<constraints->num; i++) { cpConstraint *constraint = (cpConstraint *)constraints->arr[i]; cpConstraintPreSolveFunc preSolve = constraint->preSolve; if(preSolve) preSolve(constraint, space); constraint->klass->preStep(constraint, dt); } // Integrate velocities. cpFloat damping = cpfpow(space->damping, dt); cpVect gravity = space->gravity; for(int i=0; i<bodies->num; i++) { cpBody *body = (cpBody *)bodies->arr[i]; body->velocity_func(body, gravity, damping, dt); } // Apply cached impulses cpFloat dt_coef = (prev_dt == 0.0f ? 0.0f : dt/prev_dt); for(int i=0; i<arbiters->num; i++) { cpArbiterApplyCachedImpulse((cpArbiter *)arbiters->arr[i], dt_coef); } for(int i=0; i<constraints->num; i++) { cpConstraint *constraint = (cpConstraint *)constraints->arr[i]; constraint->klass->applyCachedImpulse(constraint, dt_coef); } // Run the impulse solver. cpHastySpace *hasty = (cpHastySpace *)space; if((unsigned long)(arbiters->num + constraints->num) > hasty->constraint_count_threshold) { RunWorkers(hasty, Solver); } else { Solver(space, 0, 1); } // Run the constraint post-solve callbacks for(int i=0; i<constraints->num; i++) { cpConstraint *constraint = (cpConstraint *)constraints->arr[i]; cpConstraintPostSolveFunc postSolve = constraint->postSolve; if(postSolve) postSolve(constraint, space); } // run the post-solve callbacks for(int i=0; i<arbiters->num; i++) { cpArbiter *arb = (cpArbiter *) arbiters->arr[i]; cpCollisionHandler *handler = arb->handler; handler->postSolveFunc(arb, space, handler->userData); } } cpSpaceUnlock(space, cpTrue); }
void cpSpaceStep(cpSpace *space, cpFloat dt) { // don't step if the timestep is 0! if(dt == 0.0f) return; space->stamp++; cpFloat prev_dt = space->curr_dt; space->curr_dt = dt; // Reset and empty the arbiter list. cpArray *arbiters = space->arbiters; for(int i=0; i<arbiters->num; i++){ cpArbiter *arb = (cpArbiter *)arbiters->arr[i]; arb->state = cpArbiterStateNormal; // If both bodies are awake, unthread the arbiter from the contact graph. if(!cpBodyIsSleeping(arb->body_a) && !cpBodyIsSleeping(arb->body_b)){ cpArbiterUnthread(arb); } } arbiters->num = 0; // Integrate positions cpArray *bodies = space->bodies; for(int i=0; i<bodies->num; i++){ cpBody *body = (cpBody *)bodies->arr[i]; body->position_func(body, dt); } // Find colliding pairs. cpSpaceLock(space); { cpSpacePushFreshContactBuffer(space); cpSpatialIndexEach(space->activeShapes, (cpSpatialIndexIteratorFunc)cpShapeUpdateFunc, NULL); cpSpatialIndexReindexQuery(space->activeShapes, (cpSpatialIndexQueryFunc)collideShapes, space); } cpSpaceUnlock(space, cpFalse); // If body sleeping is enabled, do that now. if(space->sleepTimeThreshold != INFINITY || space->enableContactGraph){ cpSpaceProcessComponents(space, dt); } // Clear out old cached arbiters and call separate callbacks cpHashSetFilter(space->cachedArbiters, (cpHashSetFilterFunc)cpSpaceArbiterSetFilter, space); // Prestep the arbiters and constraints. cpFloat slop = space->collisionSlop; cpFloat biasCoef = 1.0f - cpfpow(space->collisionBias, dt); for(int i=0; i<arbiters->num; i++){ cpArbiterPreStep((cpArbiter *)arbiters->arr[i], dt, slop, biasCoef); } cpArray *constraints = space->constraints; for(int i=0; i<constraints->num; i++){ cpConstraint *constraint = (cpConstraint *)constraints->arr[i]; cpConstraintPreSolveFunc preSolve = constraint->preSolve; if(preSolve) preSolve(constraint, space); constraint->klass->preStep(constraint, dt); } // Integrate velocities. cpFloat damping = cpfpow(space->damping, dt); cpVect gravity = space->gravity; for(int i=0; i<bodies->num; i++){ cpBody *body = (cpBody *)bodies->arr[i]; body->velocity_func(body, gravity, damping, dt); } // Apply cached impulses cpFloat dt_coef = (prev_dt == 0.0f ? 0.0f : dt/prev_dt); for(int i=0; i<arbiters->num; i++){ cpArbiterApplyCachedImpulse((cpArbiter *)arbiters->arr[i], dt_coef); } for(int i=0; i<constraints->num; i++){ cpConstraint *constraint = (cpConstraint *)constraints->arr[i]; constraint->klass->applyCachedImpulse(constraint, dt_coef); } // Run the impulse solver. for(int i=0; i<space->iterations; i++){ for(int j=0; j<arbiters->num; j++){ cpArbiterApplyImpulse((cpArbiter *)arbiters->arr[j]); } for(int j=0; j<constraints->num; j++){ cpConstraint *constraint = (cpConstraint *)constraints->arr[j]; constraint->klass->applyImpulse(constraint); } } // Run the constraint post-solve callbacks for(int i=0; i<constraints->num; i++){ cpConstraint *constraint = (cpConstraint *)constraints->arr[i]; cpConstraintPostSolveFunc postSolve = constraint->postSolve; if(postSolve) postSolve(constraint, space); } // run the post-solve callbacks cpSpaceLock(space); for(int i=0; i<arbiters->num; i++){ cpArbiter *arb = (cpArbiter *) arbiters->arr[i]; cpCollisionHandler *handler = arb->handler; handler->postSolve(arb, space, handler->data); } cpSpaceUnlock(space, cpTrue); }
bool RigidBody2D::IsSleeping() const { return cpBodyIsSleeping(m_handle) != 0; }
bool cBody::IsSleeping() { return cpFalse != cpBodyIsSleeping( mBody ); }
bool PhysicsBody::isResting() { return cpBodyIsSleeping(_info->body) == cpTrue; }
bool Body::isSleeping(){ return cpBodyIsSleeping(body); }