Permalink
Browse files

Adding functions to conver bodies between static/dynamic.

  • Loading branch information...
1 parent b78d345 commit 2de4a8b7f76c7ee2491825bb7ba3bafd7e045173 @slembcke committed Mar 19, 2013
Showing with 79 additions and 9 deletions.
  1. +30 −8 Demo/Plink.c
  2. +9 −0 include/chipmunk/cpSpace.h
  3. +40 −1 src/cpSpace.c
View
@@ -22,6 +22,9 @@
#include "chipmunk.h"
#include "ChipmunkDemo.h"
+static cpFloat pentagon_mass = 0.0f;
+static cpFloat pentagon_moment = 0.0f;
+
// Iterate over all of the bodies and reset the ones that have fallen offscreen.
static void
eachBody(cpBody *body, void *unused)
@@ -36,6 +39,20 @@ eachBody(cpBody *body, void *unused)
static void
update(cpSpace *space)
{
+ if(ChipmunkDemoRightDown){
+ cpShape *nearest = cpSpaceNearestPointQueryNearest(space, ChipmunkDemoMouse, 0.0, GRABABLE_MASK_BIT, CP_NO_GROUP, NULL);
+ if(nearest){
+ cpBody *body = cpShapeGetBody(nearest);
+ if(cpBodyIsStatic(body)){
+ cpSpaceConvertBodyToDynamic(space, body, 1.0f, cpMomentForBox(1.0f, 30.0f, 30.0f));
+ cpSpaceAddBody(space, body);
+ } else {
+ cpSpaceRemoveBody(space, body);
+ cpSpaceConvertBodyToStatic(space, body);
+ }
+ }
+ }
+
int steps = 1;
cpFloat dt = 1.0f/60.0f/(cpFloat)steps;
@@ -50,20 +67,15 @@ update(cpSpace *space)
static cpSpace *
init(void)
{
+ ChipmunkDemoMessageString = "Right click to make pentagons static/dynamic.";
+
cpSpace *space = cpSpaceNew();
cpSpaceSetIterations(space, 5);
cpSpaceSetGravity(space, cpv(0, -100));
cpBody *body, *staticBody = cpSpaceGetStaticBody(space);
cpShape *shape;
- // Create vertexes for a pentagon shape.
- cpVect verts[NUM_VERTS];
- for(int i=0; i<NUM_VERTS; i++){
- cpFloat angle = -2*M_PI*i/((cpFloat) NUM_VERTS);
- verts[i] = cpv(10*cos(angle), 10*sin(angle));
- }
-
// Vertexes for a triangle shape.
cpVect tris[] = {
cpv(-15,-15),
@@ -83,9 +95,19 @@ init(void)
}
}
+ // Create vertexes for a pentagon shape.
+ cpVect verts[NUM_VERTS];
+ for(int i=0; i<NUM_VERTS; i++){
+ cpFloat angle = -2*M_PI*i/((cpFloat) NUM_VERTS);
+ verts[i] = cpv(10*cos(angle), 10*sin(angle));
+ }
+
+ pentagon_mass = 1.0;
+ pentagon_moment = cpMomentForPoly(1.0f, NUM_VERTS, verts, cpvzero);
+
// Add lots of pentagons.
for(int i=0; i<300; i++){
- body = cpSpaceAddBody(space, cpBodyNew(1.0f, cpMomentForPoly(1.0f, NUM_VERTS, verts, cpvzero)));
+ body = cpSpaceAddBody(space, cpBodyNew(pentagon_mass, pentagon_moment));
cpFloat x = rand()/(cpFloat)RAND_MAX*640 - 320;
cpBodySetPos(body, cpv(x, 350));
@@ -201,6 +201,15 @@ cpBool cpSpaceContainsBody(cpSpace *space, cpBody *body);
/// Test if a constraint has been added to the space.
cpBool cpSpaceContainsConstraint(cpSpace *space, cpConstraint *constraint);
+/// Convert a dynamic rogue body to a static one.
+/// This will convert any shapes attached to the body into static shapes, but does not handle constraints.
+/// If the body is active, you must remove it from the space first.
+void cpSpaceConvertBodyToStatic(cpSpace *space, cpBody *body);
+/// Convert a body to a dynamic rogue body.
+/// This will convert any static shapes attached to the body into regular ones.
+/// If you want the body to be active after the transition, you must add it to the space also.
+void cpSpaceConvertBodyToDynamic(cpSpace *space, cpBody *body, cpFloat mass, cpFloat moment);
+
/// Post Step callback function type.
typedef void (*cpPostStepFunc)(cpSpace *space, void *key, void *data);
/// Schedule a post-step callback to be called when cpSpaceStep() finishes.
View
@@ -185,7 +185,7 @@ cpSpaceFree(cpSpace *space)
#define cpAssertSpaceUnlocked(space) \
cpAssertHard(!space->locked, \
- "This addition/removal cannot be done safely during a call to cpSpaceStep() or during a query. " \
+ "This operation cannot be done safely during a call to cpSpaceStep() or during a query. " \
"Put these calls into a post-step callback." \
);
@@ -434,6 +434,45 @@ cpBool cpSpaceContainsConstraint(cpSpace *space, cpConstraint *constraint)
return (constraint->space == space);
}
+//MARK: Static/rogue body conversion.
+
+void
+cpSpaceConvertBodyToStatic(cpSpace *space, cpBody *body)
+{
+ cpAssertHard(!cpBodyIsStatic(body), "Body is already static.");
+ cpAssertHard(cpBodyIsRogue(body), "Remove the body from the space before calling this function.");
+ cpAssertSpaceUnlocked(space);
+
+ cpBodySetMass(body, INFINITY);
+ cpBodySetMoment(body, INFINITY);
+
+ cpBodySetVel(body, cpvzero);
+ cpBodySetAngVel(body, 0.0f);
+
+ body->node.idleTime = INFINITY;
+ CP_BODY_FOREACH_SHAPE(body, shape){
+ cpSpatialIndexRemove(space->activeShapes, shape, shape->hashid);
+ cpSpatialIndexInsert(space->staticShapes, shape, shape->hashid);
+ }
+}
+
+void
+cpSpaceConvertBodyToDynamic(cpSpace *space, cpBody *body, cpFloat m, cpFloat i)
+{
+ cpAssertHard(cpBodyIsStatic(body), "Body is already dynamic.");
+ cpAssertSpaceUnlocked(space);
+
+ cpBodyActivateStatic(body, NULL);
+
+ cpBodySetMass(body, m);
+ cpBodySetMoment(body, i);
+
+ body->node.idleTime = 0.0f;
+ CP_BODY_FOREACH_SHAPE(body, shape){
+ cpSpatialIndexRemove(space->staticShapes, shape, shape->hashid);
+ cpSpatialIndexInsert(space->activeShapes, shape, shape->hashid);
+ }
+}
//MARK: Iteration

0 comments on commit 2de4a8b

Please sign in to comment.