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()); }
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); }
public override void Update(float dt) { base.Update(dt); if (CCMouse.Instance.rightclick) { cpPointQueryInfo info = null; cpShape nearest = space.PointQueryNearest(CCMouse.Instance.Position, 0.0f, GRAB_FILTER, ref info); if (nearest != null) { cpBody body = nearest.GetBody(); // cpShapeGetBody(); if (body.bodyType == cpBodyType.STATIC) { body.SetBodyType(cpBodyType.DYNAMIC); body.SetMass(pentagon_mass); body.SetMoment(pentagon_moment); } else if (body.bodyType == cpBodyType.DYNAMIC) { body.SetBodyType(cpBodyType.STATIC); } } } space.EachBody(eachBody, null); space.Step(dt); }
public override void Update(float dt) { base.Update(dt); var tolerance = 2; //var mouse = new cpVect(mouseState.X, mouseState.Y); if (!CCMouse.Instance.HasPosition) { return; } cpPointQueryInfo info = null; //CCMouse.Instance.UpdatePosition() var d = this.shape.PointQuery(CCMouse.Instance.Position, ref info); var actualShape = (shape as cpPolyShape); if ((CCMouse.Instance.rightclick || CCMouse.Instance.dblclick) && d > tolerance) { var body = actualShape.body; var count = actualShape.Count; // Allocate the space for the new vertexes on the stack. cpVect[] verts = new cpVect[count + 1]; // * sizeof(cpVect)); for (int i = 0; i < count; i++) { verts[i] = actualShape.GetVert(i); } verts[count] = body.WorldToLocal(CCMouse.Instance.Position); // This function builds a convex hull for the vertexes. // Because the result array is NULL, it will reduce the input array instead. int hullCount = cp.ConvexHull(count + 1, verts, ref verts, null, tolerance); // Figure out how much to shift the body by. var centroid = cp.CentroidForPoly(hullCount, verts); // Recalculate the body properties to match the updated shape. var mass = cp.AreaForPoly(hullCount, verts, 0.0f) * DENSITY; body.SetMass(mass); body.SetMoment(cp.MomentForPoly(mass, hullCount, verts, cpVect.cpvneg(centroid), 0.0f)); body.SetPosition(body.LocalToWorld(centroid)); // Use the setter function from chipmunk_unsafe.h. // You could also remove and recreate the shape if you wanted. actualShape.SetVerts(hullCount, verts, cpTransform.Translate(cpVect.cpvneg(centroid))); } var steps = 1; dt = dt / steps; for (var i = 0; i < steps; i++) { this.space.Step(dt); } }
/** Test point is in shape or not */ public bool ContainsPoint(CCPoint point) { foreach (var shape in _info.GetShapes()) { cpPointQueryInfo info = null; shape.PointQuery(PhysicsHelper.CCPointToCpVect(point), ref info); if (info != null) { return(true); } } return(false); }
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); }
public override void Update(float dt) { base.Update(dt); if (CCMouse.Instance.rightclick) { QUERY_START = CCMouse.Instance.Position; } start = QUERY_START; end = CCMouse.Instance.Position; float radius = 10; segInfo = null; m_debugDraw.DrawSegment(start, end, 1, cpColor.Green); shapeInfo = this.space.SegmentQueryFirst(start, end, radius, cpShape.FILTER_ALL, ref segInfo); if (shapeInfo != null) { font.Text = string.Format("Segment Query: Dist({0}) Normal({1},{2})", segInfo.alpha * cpVect.cpvdist(start, end), segInfo.normal.x, segInfo.normal.y); } else { font.Text = string.Format("Segment Query (None)"); } nearestInfo = null; space.PointQueryNearest(CCMouse.Instance.Position, 100, cpShape.FILTER_ALL, ref nearestInfo); if (nearestInfo != null) { // Draw a grey line to the closest shape. m_debugDraw.Draw(CCMouse.Instance.Position, new cpColor(127, 127, 127, 255)); m_debugDraw.DrawSegment(CCMouse.Instance.Position, nearestInfo.point, 1, new cpColor(127, 127, 127, 255)); // Draw a red bounding box around the shape under the mouse. if (nearestInfo.distance < 0) { m_debugDraw.Draw(nearestInfo.shape.bb, cpColor.Red); } } space.Step(dt); }
public void SliceQuery(cpShape shape, float t, cpVect n, SliceContext context) { cpVect a = context.a; cpVect b = context.b; // Check that the slice was complete by checking that the endpoints aren't in the sliced shape. cpPointQueryInfo inf1 = null; cpPointQueryInfo inf2 = null; if (shape.PointQuery(a, ref inf1) > 0 && shape.PointQuery(b, ref inf2) > 0) { // Can't modify the space during a query. // Must make a post-step callback to do the actual slicing. context.space.AddPostStepCallback( (s, o1, o2) => SliceShapePostStep(s, (cpShape)o1, (SliceContext)o2), shape, context); } }
public virtual void OnTouchesBegan(List <CCTouch> touches, CCEvent e) { var touch = touches.FirstOrDefault(); CCMouse.Instance.UpdatePositionLocation(touch.LocationOnScreen, this); //Update mouse mouse position CCMouse.Instance.UpdateBodyPosition(); CCMouse.Instance.OnTouchBegan(touch, this); if (!CCMouse.Instance.HasBodyJoined) { float radius = 5.0f; cpPointQueryInfo info = null; var shape = space.PointQueryNearest( CCMouse.Instance.Position, radius, GRAB_FILTER, ref info); if (shape != null) { cpVect nearest = (info.distance > 0.0d ? info.point : CCMouse.Instance.Position); CCMouse.Instance.mouseJoint = new cpPivotJoint(CCMouse.Instance.mouseBody, shape.body, cpVect.Zero, shape.body.WorldToLocal(nearest)); CCMouse.Instance.mouseJoint.SetMaxForce(50000); CCMouse.Instance.mouseJoint.SetErrorBias(cp.cpfpow(1f - 0.15f, 60f)); space.AddConstraint(CCMouse.Instance.mouseJoint); return; } } //Arrastramos el logo if (logo.BoundingBox.ContainsPoint(CCMouse.Instance.PositionParentSpace)) { logo.MoveOffset = touch.LocationOnScreen - logo.Position; CCMouse.Instance.IsDragBlocked = logo.IsMoving = true; return; } }
public override void Update(float dt) { base.Update(dt); space.Step(dt); if (CCMouse.Instance.rightclick || CCMouse.Instance.dblclick) { cpPointQueryInfo info = null; if (space.PointQueryNearest(CCMouse.Instance.Position, 0, GRAB_FILTER, ref info) != null) { cpBB bb = info.shape.GetBB(); // cpShapeGetBB(); float cell_size = cp.cpfmax(bb.r - bb.l, bb.t - bb.b) / 5.0f; if (cell_size > 5) { ShatterShape(info.shape as cpPolyShape, cell_size, CCMouse.Instance.Position); } else { //printf("Too small to splinter %f\n", cell_size); } } } }