Index: Demo/drawSpace.c =================================================================== --- Demo/drawSpace.c (revision 330) +++ Demo/drawSpace.c (working copy) @@ -132,10 +132,10 @@ glRotatef(body->a*180.0f/M_PI, 0.0f, 0.0f, 1.0f); glScalef(circle->r, circle->r, 1.0f); - if(!circle->shape.sensor){ - glColor_from_pointer(circle); - glDrawArrays(GL_TRIANGLE_FAN, 0, circleVAR_count - 1); - } +// if(!circle->shape.sensor){ +// glColor_from_pointer(circle); +// glDrawArrays(GL_TRIANGLE_FAN, 0, circleVAR_count - 1); +// } glColor3f(LINE_COLOR); glDrawArrays(GL_LINE_STRIP, 0, circleVAR_count); @@ -253,6 +253,7 @@ switch(shape->klass->type){ case CP_CIRCLE_SHAPE: + case CP_RING_SHAPE: drawCircleShape(body, (cpCircleShape *)shape); break; case CP_SEGMENT_SHAPE: Index: Demo/ChipmunkDemo.c =================================================================== --- Demo/ChipmunkDemo.c (revision 330) +++ Demo/ChipmunkDemo.c (working copy) @@ -80,24 +80,24 @@ //extern chipmunkDemo Test; static chipmunkDemo *demos[] = { - &LogoSmash, +// &LogoSmash, &Simple, - &PyramidStack, - &Plink, - &Tumble, - &PyramidTopple, - &Bounce, - &Planet, - &Springies, - &Pump, - &TheoJansen, - &MagnetsElectric, - &UnsafeOps, - &Query, - &OneWay, - &Player, - &Sensors, - &Joints, +// &PyramidStack, +// &Plink, +// &Tumble, +// &PyramidTopple, +// &Bounce, +// &Planet, +// &Springies, +// &Pump, +// &TheoJansen, +// &MagnetsElectric, +// &UnsafeOps, +// &Query, +// &OneWay, +// &Player, +// &Sensors, +// &Joints, }; static const int demoCount = sizeof(demos)/sizeof(chipmunkDemo *); static chipmunkDemo *currDemo = NULL; Index: Demo/Simple.c =================================================================== --- Demo/Simple.c (revision 330) +++ Demo/Simple.c (working copy) @@ -30,61 +30,60 @@ cpSpace *space; cpBody *staticBody; +extern cpShapeClass cpRingShapeClass; + // Init is called by the demo code to set up the demo. static cpSpace * init(void) { - // Create an infinite mass body to attach ground segments and other static geometry to. - // We won't be adding this body to the space, because we don't want it to be simulated at all. - // Adding bodies to the space simulates them. (fall under the influence of gravity, etc) - // We want the static body to stay right where it is at all times. staticBody = cpBodyNew(INFINITY, INFINITY); - - // Create a space, a space is a simulation world. It simulates the motions of rigid bodies, - // handles collisions between them, and simulates the joints between them. space = cpSpaceNew(); - - // Lets set some parameters of the space: - // More iterations make the simulation more accurate but slower space->iterations = 10; - // These parameters tune the efficiency of the collision detection. - // For more info: http://code.google.com/p/chipmunk-physics/wiki/cpSpace cpSpaceResizeStaticHash(space, 30.0f, 1000); cpSpaceResizeActiveHash(space, 30.0f, 1000); - // Give it some gravity space->gravity = cpv(0, -100); - // Create A ground segment along the bottom of the screen cpShape *ground = cpSegmentShapeNew(staticBody, cpv(-320,-240), cpv(320,-240), 0.0f); - // Set some parameters of the shape. - // For more info: http://code.google.com/p/chipmunk-physics/wiki/cpShape ground->e = 1.0f; ground->u = 1.0f; ground->layers = NOT_GRABABLE_MASK; // Used by the Demo mouse grabbing code - // Add the shape to the space as a static shape - // If a shape never changes position, add it as static so Chipmunk knows it only needs to - // calculate collision information for it once when it is added. - // Do not change the postion of a static shape after adding it. cpSpaceAddStaticShape(space, ground); - // Add a moving circle object. - cpFloat radius = 15.0f; - cpFloat mass = 10.0f; - // This time we need to give a mass and moment of inertia when creating the circle. - cpBody *ballBody = cpBodyNew(mass, cpMomentForCircle(mass, 0.0f, radius, cpvzero)); - // Set some parameters of the body: - // For more info: http://code.google.com/p/chipmunk-physics/wiki/cpBody - ballBody->p = cpv(0, -240 + radius+5); - // Add the body to the space so it will be simulated and move around. - cpSpaceAddBody(space, ballBody); + cpFloat radius, mass; + cpBody *body; + cpShape *shape; + // inner ball + radius = 15.0f; + mass = 1.0f; + body = cpBodyNew(mass, cpMomentForCircle(mass, 0.0f, radius, cpvzero)); + cpSpaceAddBody(space, body); - // Add a circle shape for the ball. - // Shapes are always defined relative to the center of gravity of the body they are attached to. - // When the body moves or rotates, the shape will move with it. - // Additionally, all of the cpSpaceAdd*() functions return the thing they added so you can create and add in one go. - cpShape *ballShape = cpSpaceAddShape(space, cpCircleShapeNew(ballBody, radius, cpvzero)); - ballShape->e = 0.0f; ballShape->u = 0.9f; + shape = cpSpaceAddShape(space, cpCircleShapeNew(body, radius, cpvzero)); + shape->e = 0.0f; shape->u = 0.9f; + shape->group = 1; // don't collide with the outer ring + + // hamster ball + radius = 60.0f; + mass = 1.0f; + body = cpBodyNew(mass, cpMomentForCircle(mass, radius, radius, cpvzero)); + body->p = cpv(0.0f, 30.0f); + cpSpaceAddBody(space, body); + + // center circle shape + shape = cpSpaceAddShape(space, cpCircleShapeNew(body, 15.0f, cpvzero)); + shape->e = 0.0f; shape->u = 0.9f; + + // outer ring shape + shape = cpSpaceAddShape(space, cpCircleShapeNew(body, radius, cpvzero)); + shape->e = 0.0f; shape->u = 0.9f; + shape->group = 1; + + // inner ring shape + shape = cpSpaceAddShape(space, cpCircleShapeNew(body, radius, cpvzero)); + shape->e = 0.0f; shape->u = 0.9f; + shape->klass = &cpRingShapeClass; + return space; } Index: src/cpCollision.c =================================================================== --- src/cpCollision.c (revision 330) +++ src/cpCollision.c (working copy) @@ -65,6 +65,40 @@ return circle2circleQuery(circ1->tc, circ2->tc, circ1->r, circ2->r, arr); } +// Collide circle shapes. +static int +circle2ring(cpShape *shape1, cpShape *shape2, cpContact **con) +{ + cpCircleShape *circ = (cpCircleShape *)shape1; + cpCircleShape *ring = (cpCircleShape *)shape2; + + cpVect p1 = circ->tc; + cpVect p2 = ring->tc; + cpFloat r1 = circ->r; + cpFloat r2 = ring->r; + + cpFloat maxdist = r2 - r1; + cpVect delta = cpvsub(p2, p1); + cpFloat distsq = cpvlengthsq(delta); + if(distsq <= maxdist*maxdist) return 0; + + cpFloat dist = cpfsqrt(distsq); + // To avoid singularities, do nothing in the case of dist = 0. + cpFloat non_zero_dist = (dist ? dist : INFINITY); + + // Allocate and initialize the contact. + (*con) = (cpContact *)cpmalloc(sizeof(cpContact)); + cpContactInit( + (*con), + cpvadd(p1, cpvmult(delta, (-r1)/non_zero_dist)), + cpvmult(delta, -1.0f/non_zero_dist), + maxdist - dist, + 0 + ); + + return 1; +} + // Collide circles to segment shapes. static int circle2segment(cpShape *circleShape, cpShape *segmentShape, cpContact **con) @@ -385,6 +419,7 @@ colfuncs = (collisionFunc *)cpcalloc(CP_NUM_SHAPES*CP_NUM_SHAPES, sizeof(collisionFunc)); addColFunc(CP_CIRCLE_SHAPE, CP_CIRCLE_SHAPE, circle2circle); + addColFunc(CP_CIRCLE_SHAPE, CP_RING_SHAPE, circle2ring); addColFunc(CP_CIRCLE_SHAPE, CP_SEGMENT_SHAPE, circle2segment); addColFunc(CP_SEGMENT_SHAPE, CP_POLY_SHAPE, seg2poly); addColFunc(CP_CIRCLE_SHAPE, CP_POLY_SHAPE, circle2poly); Index: src/cpShape.c =================================================================== --- src/cpShape.c (revision 330) +++ src/cpShape.c (working copy) @@ -183,6 +183,14 @@ cpCircleShapeSegmentQuery, }; +const cpShapeClass cpRingShapeClass = { + CP_RING_SHAPE, + cpCircleShapeCacheData, + NULL, + cpCircleShapePointQuery, + cpCircleShapeSegmentQuery, +}; + cpCircleShape * cpCircleShapeInit(cpCircleShape *circle, cpBody *body, cpFloat radius, cpVect offset) { Index: src/cpShape.h =================================================================== --- src/cpShape.h (revision 330) +++ src/cpShape.h (working copy) @@ -32,6 +32,7 @@ // Enumeration of shape types. typedef enum cpShapeType{ CP_CIRCLE_SHAPE, + CP_RING_SHAPE, CP_SEGMENT_SHAPE, CP_POLY_SHAPE, CP_NUM_SHAPES