void RigidBody2D::SetMass(float mass, bool recomputeMoment) { if (m_mass > 0.f) { if (mass > 0.f) { m_world->RegisterPostStep(this, [mass, recomputeMoment](Nz::RigidBody2D* body) { cpBodySetMass(body->GetHandle(), mass); if (recomputeMoment) cpBodySetMoment(body->GetHandle(), body->GetGeom()->ComputeMomentOfInertia(mass)); }); } else m_world->RegisterPostStep(this, [](Nz::RigidBody2D* body) { cpBodySetType(body->GetHandle(), (body->IsStatic()) ? CP_BODY_TYPE_STATIC : CP_BODY_TYPE_KINEMATIC); } ); } else if (mass > 0.f) { m_world->RegisterPostStep(this, [mass, recomputeMoment](Nz::RigidBody2D* body) { if (cpBodyGetType(body->GetHandle()) != CP_BODY_TYPE_DYNAMIC) { cpBodySetType(body->GetHandle(), CP_BODY_TYPE_DYNAMIC); cpBodySetMass(body->GetHandle(), mass); if (recomputeMoment) cpBodySetMoment(body->GetHandle(), body->GetGeom()->ComputeMomentOfInertia(mass)); } }); } m_mass = mass; }
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); } }
void cpSpaceActivateBody(cpSpace *space, cpBody *body) { cpAssertHard(cpBodyGetType(body) == CP_BODY_TYPE_DYNAMIC, "Internal error: Attempting to activate a non-dynamic body."); if(space->locked){ // cpSpaceActivateBody() is called again once the space is unlocked if(!cpArrayContains(space->rousedBodies, body)) cpArrayPush(space->rousedBodies, body); } else { cpAssertSoft(body->sleeping.root == NULL && body->sleeping.next == NULL, "Internal error: Activating body non-NULL node pointers."); cpArrayPush(space->dynamicBodies, body); CP_BODY_FOREACH_SHAPE(body, shape){ cpSpatialIndexRemove(space->staticShapes, shape, shape->hashid); cpSpatialIndexInsert(space->dynamicShapes, shape, shape->hashid); } CP_BODY_FOREACH_ARBITER(body, arb){ cpBody *bodyA = arb->body_a; // Arbiters are shared between two bodies that are always woken up together. // You only want to restore the arbiter once, so bodyA is arbitrarily chosen to own the arbiter. // The edge case is when static bodies are involved as the static bodies never actually sleep. // If the static body is bodyB then all is good. If the static body is bodyA, that can easily be checked. if(body == bodyA || cpBodyGetType(bodyA) == CP_BODY_TYPE_STATIC){ int numContacts = arb->count; struct cpContact *contacts = arb->contacts; // Restore contact values back to the space's contact buffer memory arb->contacts = cpContactBufferGetArray(space); memcpy(arb->contacts, contacts, numContacts*sizeof(struct cpContact)); cpSpacePushContacts(space, numContacts); // Reinsert the arbiter into the arbiter cache const cpShape *a = arb->a, *b = arb->b; const cpShape *shape_pair[] = {a, b}; cpHashValue arbHashID = CP_HASH_PAIR((cpHashValue)a, (cpHashValue)b); cpHashSetInsert(space->cachedArbiters, arbHashID, shape_pair, NULL, arb); // Update the arbiter's state arb->stamp = space->stamp; cpArrayPush(space->arbiters, arb); cpfree(contacts); } }
cpBody * cpSpaceAddBody(cpSpace *space, cpBody *body) { cpAssertHard(body->space != space, "You have already added this body to this space. You must not add it a second time."); cpAssertHard(!body->space, "You have already added this body to another space. You cannot add it to a second."); cpAssertSpaceUnlocked(space); cpArrayPush(cpSpaceArrayForBodyType(space, cpBodyGetType(body)), body); body->space = space; return body; }
void cpSpaceRemoveBody(cpSpace *space, cpBody *body) { cpAssertHard(body != cpSpaceGetStaticBody(space), "Cannot remove the designated static body for the space."); cpAssertHard(cpSpaceContainsBody(space, body), "Cannot remove a body that was not added to the space. (Removed twice maybe?)"); // cpAssertHard(body->shapeList == NULL, "Cannot remove a body from the space before removing the bodies attached to it."); // cpAssertHard(body->constraintList == NULL, "Cannot remove a body from the space before removing the constraints attached to it."); cpAssertSpaceUnlocked(space); cpBodyActivate(body); // cpSpaceFilterArbiters(space, body, NULL); cpArrayDeleteObj(cpSpaceArrayForBodyType(space, cpBodyGetType(body)), body); body->space = NULL; }
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); } } }
void cpSpaceRemoveShape(cpSpace *space, cpShape *shape) { cpBody *body = shape->body; cpAssertHard(cpSpaceContainsShape(space, shape), "Cannot remove a shape that was not added to the space. (Removed twice maybe?)"); cpAssertSpaceUnlocked(space); cpBool isStatic = (cpBodyGetType(body) == CP_BODY_TYPE_STATIC); if(isStatic){ cpBodyActivateStatic(body, shape); } else { cpBodyActivate(body); } cpBodyRemoveShape(body, shape); cpSpaceFilterArbiters(space, body, shape); cpSpatialIndexRemove(isStatic ? space->staticShapes : space->dynamicShapes, shape, shape->hashid); shape->space = NULL; shape->hashid = 0; }
//MARK: Body, Shape, and Joint Management cpShape * cpSpaceAddShape(cpSpace *space, cpShape *shape) { cpBody *body = shape->body; cpAssertHard(shape->space != space, "You have already added this shape to this space. You must not add it a second time."); cpAssertHard(!shape->space, "You have already added this shape to another space. You cannot add it to a second."); // cpAssertHard(body->space == space, "The shape's body must be added to the space before the shape."); cpAssertSpaceUnlocked(space); cpBool isStatic = (cpBodyGetType(body) == CP_BODY_TYPE_STATIC); if(!isStatic) cpBodyActivate(body); cpBodyAddShape(body, shape); shape->hashid = space->shapeIDCounter++; cpShapeUpdate(shape, body->transform); cpSpatialIndexInsert(isStatic ? space->staticShapes : space->dynamicShapes, shape, shape->hashid); shape->space = space; return shape; }
static void internalBodyUpdateVelocity(cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt) { cpBodyUpdateVelocity(body, cpvzero, damping, dt); // Skip kinematic bodies. if(cpBodyGetType(body) == CP_BODY_TYPE_KINEMATIC) return; 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); cocos2d::PhysicsBody *physicsBody = static_cast<cocos2d::PhysicsBody*>(body->userData); if(physicsBody->isGravityEnabled()) body->v = cpvclamp(cpvadd(cpvmult(body->v, damping), cpvmult(cpvadd(gravity, cpvmult(body->f, body->m_inv)), dt)), physicsBody->getVelocityLimit()); else body->v = cpvclamp(cpvadd(cpvmult(body->v, damping), cpvmult(cpvmult(body->f, body->m_inv), dt)), physicsBody->getVelocityLimit()); cpFloat w_limit = physicsBody->getAngularVelocityLimit(); body->w = cpfclamp(body->w*damping + body->t*body->i_inv*dt, -w_limit, w_limit); // Reset forces. body->f = cpvzero; //to check body sanity cpBodySetTorque(body, 0.0f); }
static int l_physics_getBodyType(lua_State* state) { l_tools_checkUserDataPlusErrMsg(state, 1, "You must provide a body"); l_physics_Body* body = (l_physics_Body*)lua_touserdata(state, 1); cpBodyType type = cpBodyGetType(body->body); const char* s_type; if (type == CP_BODY_TYPE_STATIC) s_type = "static"; else if (type == CP_BODY_TYPE_DYNAMIC) s_type = "dynamic"; else if (type == CP_BODY_TYPE_KINEMATIC) s_type = "kinematic"; else s_type = "unknown"; lua_pushstring(state, s_type); return 1; }
CP_BODY_FOREACH_CONSTRAINT(body, constraint){ cpBody *bodyA = constraint->a; if(body == bodyA || cpBodyGetType(bodyA) == CP_BODY_TYPE_STATIC) cpArrayPush(space->constraints, constraint); }