static void update(cpSpace *space) { cpFloat tolerance = 2.0; if(ChipmunkDemoRightClick && cpShapeNearestPointQuery(shape, ChipmunkDemoMouse, NULL) > tolerance){ cpBody *body = cpShapeGetBody(shape); int count = cpPolyShapeGetNumVerts(shape); // Allocate the space for the new vertexes on the stack. cpVect *verts = (cpVect *)alloca((count + 1)*sizeof(cpVect)); for(int i=0; i<count; i++){ verts[i] = cpPolyShapeGetVert(shape, i); } verts[count] = cpBodyWorld2Local(body, ChipmunkDemoMouse); // This function builds a convex hull for the vertexes. // Because the result array is NULL, it will reduce the input array instead. int hullCount = cpConvexHull(count + 1, verts, NULL, NULL, tolerance); // Figure out how much to shift the body by. cpVect centroid = cpCentroidForPoly(hullCount, verts); // Recalculate the body properties to match the updated shape. cpFloat mass = cpAreaForPoly(hullCount, verts)*DENSITY; cpBodySetMass(body, mass); cpBodySetMoment(body, cpMomentForPoly(mass, hullCount, verts, cpvneg(centroid))); cpBodySetPos(body, cpBodyLocal2World(body, centroid)); // Use the setter function from chipmunk_unsafe.h. // You could also remove and recreate the shape if you wanted. cpPolyShapeSetVerts(shape, hullCount, verts, cpvneg(centroid)); } int steps = 1; cpFloat dt = 1.0f/60.0f/(cpFloat)steps; for(int i=0; i<steps; i++){ cpSpaceStep(space, dt); } }
void wrPolyShapeSetVerts(cpShape *shape, int numVerts, cpVect *verts, cpVect *offset) { cpPolyShapeSetVerts(shape, numVerts, verts, *offset); }
static void pullControlPoint(cpShape *shape) { int i; float origArea, newArea, newMass; control_point_t *cp; cpPolyShape *ps; cpCircleShape *circle; cpVect lp; cpVect verts[4]; cpConstraint *mouseJoint; mouseJoint = atlMouseJoint(); if (!mouseJoint) { lp = cpBodyWorld2Local(shape->body, atlMouseClickPos()); } else { /* update joint position */ lp = cpBodyWorld2Local(shape->body, atlMousePos()); atlRemoveMouseJoint(g_Space); } atlCreateMouseJoint(g_Space, shape->body, lp); cp = (control_point_t *)shape->data; ps = (cpPolyShape *)cp->dom->shape; control_point_t *circlePoint; for (i = 0; i < 4; ++i) { verts[i] = cpPolyShapeGetVert((cpShape *)ps, i); if (lp.x > 0) { if (verts[i].x > 0) verts[i].x = lp.x; else verts[i].x = -lp.x; } else if (lp.x < 0) { if (verts[i].x < 0) verts[i].x = lp.x; else verts[i].x = -lp.x; } if (lp.y > 0) { if (verts[i].y > 0) verts[i].y = lp.y; else verts[i].y = -lp.y; } else if (lp.y < 0) { if (verts[i].y < 0) verts[i].y = lp.y; else verts[i].y = -lp.y; } circlePoint = (control_point_t *)cp->dom->pControlPoints[i]; circle = (cpCircleShape *)circlePoint->shape; cpCircleShapeSetOffset((cpShape *)circle, verts[i]); } origArea = (fabs(dominoVerts[0].x)+dominoVerts[3].x) * (fabs(dominoVerts[0].y)+dominoVerts[1].y); newArea = (fabs(verts[0].x)+verts[3].x) * (fabs(verts[0].y)+verts[1].y); if (newArea > origArea) newMass = newArea/origArea * 0.05f; else newMass = 1.0f; cpBodySetMass(cp->dom->body, newMass); cpPolyShapeSetVerts((cpShape *)ps, ps->numVerts, verts, cpvzero); }