public void ShatterShape(cpPolyShape shape, float cellSize, cpVect focus) { space.RemoveShape(shape); space.RemoveBody(shape.GetBody()); cpBB bb = shape.bb; int width = (int)((bb.r - bb.l) / cellSize) + 1; int height = (int)((bb.t - bb.b) / cellSize) + 1; // printf("Splitting as %dx%d\n", width, height); WorleyContex context = new WorleyContex((int)RandomHelper.frand(), cellSize, width, height, bb, focus); for (int i = 0; i < context.width; i++) { for (int j = 0; j < context.height; j++) { cpVect cell = WorleyPoint(i, j, ref context); cpPointQueryInfo cp = null; if (shape.PointQuery(cell, ref cp) < 0.0f) { ShatterCell(shape, cell, i, j, ref context); } } } //cpBodyFree(cpShapeGetBody(shape)); //cpShapeFree(shape); }
int ClipCell(cpShape shape, cpVect center, int i, int j, WorleyContex context, cpVect[] verts, cpVect[] clipped, int count) { cpVect other = WorleyPoint(i, j, ref context); // printf(" other %dx%d: (% 5.2f, % 5.2f) ", i, j, other.x, other.y); cpPointQueryInfo queryInfo = null; if (shape.PointQuery(other, ref queryInfo) > 0.0f) { for (int x = 0; x < count; x++) { clipped[x] = new cpVect(verts[x]); } return(count); } else { // printf("clipped\n"); } cpVect n = cpVect.cpvsub(other, center); float dist = cpVect.cpvdot(n, cpVect.cpvlerp(center, other, 0.5f)); int clipped_count = 0; for (j = 0, i = count - 1; j < count; i = j, j++) { cpVect a = verts[i]; float a_dist = cpVect.cpvdot(a, n) - dist; if (a_dist <= 0.0f) { clipped[clipped_count] = a; clipped_count++; } cpVect b = verts[j]; float b_dist = cpVect.cpvdot(b, n) - dist; if (a_dist * b_dist < 0.0f) { float t = cp.cpfabs(a_dist) / (cp.cpfabs(a_dist) + cp.cpfabs(b_dist)); clipped[clipped_count] = cpVect.cpvlerp(a, b, t); clipped_count++; } } return(clipped_count); }
cpVect WorleyPoint(int i, int j, ref WorleyContex context) { float size = context.cellSize; int width = context.width; int height = context.height; cpBB bb = context.bb; // cpVect fv = cpv(0.5, 0.5); cpVect fv = HashVect(i, j, context.seed); return(new cpVect( cp.cpflerp(bb.l, bb.r, 0.5f) + size * (i + fv.x - width * 0.5f), cp.cpflerp(bb.b, bb.t, 0.5f) + size * (j + fv.y - height * 0.5f) )); }
public void ShatterCell(cpPolyShape shape, cpVect cell, int cell_i, int cell_j, ref WorleyContex context) { // printf("cell %dx%d: (% 5.2f, % 5.2f)\n", cell_i, cell_j, cell.x, cell.y); cpBody body = shape.body; // cpShapeGetBody(shape); cpVect[] ping = new cpVect[MAX_VERTEXES_PER_VORONOI]; // cpVect[ (cpVect*)alloca( * sizeof(cpVect)); cpVect[] pong = new cpVect[MAX_VERTEXES_PER_VORONOI]; //(cpVect*)alloca(MAX_VERTEXES_PER_VORONOI * sizeof(cpVect)); int count = shape.Count; // cpPolyShapeGetCount(); count = (count > MAX_VERTEXES_PER_VORONOI ? MAX_VERTEXES_PER_VORONOI : count); for (int i = 0; i < count; i++) { ping[i] = body.LocalToWorld(shape.GetVert(i)); } cpPointQueryInfo info = null; for (int i = 0; i < context.width; i++) { for (int j = 0; j < context.height; j++) { if ( !(i == cell_i && j == cell_j) && shape.PointQuery(cell, ref info) < 0 ) { count = ClipCell(shape, cell, i, j, context, ping, pong, count); for (int u = 0; u < pong.Length; u++) { if (pong[u] != null) { ping[u] = new cpVect(pong[u]); } } } } } cpVect centroid = cp.CentroidForPoly(count, ping); float mass = cp.AreaForPoly(count, ping, 0) * DENSITY; float moment = cp.MomentForPoly(mass, count, ping, cpVect.cpvneg(centroid), 0); cpBody new_body = space.AddBody(new cpBody(mass, moment)); new_body.SetPosition(centroid); new_body.SetPosition(centroid); new_body.SetVelocity(body.GetVelocityAtLocalPoint(centroid)); new_body.SetAngularVelocity(body.GetAngularVelocity()); cpTransform transform = cpTransform.Translate(cpVect.cpvneg(centroid)); cpShape new_shape = space.AddShape(new cpPolyShape(new_body, count, ping, transform, 0)); // Copy whatever properties you have set on the original shape that are important new_shape.SetFriction(shape.GetFriction()); }