예제 #1
0
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);
}
예제 #2
0
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);
}
예제 #4
0
// 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;
}
예제 #5
0
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);
	}
}
예제 #6
0
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);
    }
}
예제 #7
0
파일: physics.c 프로젝트: dns/CLove
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;
}
예제 #8
0
// 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;
}
예제 #9
0
파일: rb_cpBody.c 프로젝트: Anaxim/chipmunk
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;
}
예제 #10
0
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);
        }
    }
}
예제 #11
0
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);
}
예제 #13
0
bool PhysicsBody::isResting() const
{
    return cpBodyIsSleeping(_cpBody) != cpFalse;
}
예제 #14
0
파일: rb_cpBody.c 프로젝트: Anaxim/chipmunk
static VALUE
rb_cpBodyIsSleeping(VALUE self) {
  return cpBodyIsSleeping(BODY(self)) ? Qtrue : Qfalse;
}
예제 #15
0
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);
}
예제 #16
0
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);
}
예제 #17
0
	bool RigidBody2D::IsSleeping() const
	{
		return cpBodyIsSleeping(m_handle) != 0;
	}
예제 #18
0
파일: cbody.cpp 프로젝트: dogtwelve/eepp
bool cBody::IsSleeping() {
	return cpFalse != cpBodyIsSleeping( mBody );
}
예제 #19
0
bool PhysicsBody::isResting()
{
    return cpBodyIsSleeping(_info->body) == cpTrue;
}
예제 #20
0
bool Body::isSleeping(){
	return cpBodyIsSleeping(body);
}