/// A colliding pair of shapes. public cpArbiter(cpShape a, cpShape b) { this.handler = null; this.swapped = false; this.handlerA = null; this.handlerB = null; /// Calculated value to use for the elasticity coefficient. /// Override in a pre-solve collision handler for custom behavior. this.e = 0; /// Calculated value to use for the friction coefficient. /// Override in a pre-solve collision handler for custom behavior. this.u = 0; /// Calculated value to use for applying surface velocities. /// Override in a pre-solve collision handler for custom behavior. this.surface_vr = cpVect.Zero; this.a = a; this.body_a = a.body; this.b = b; this.body_b = b.body; this.thread_a = new cpArbiterThread(null, null); this.thread_b = new cpArbiterThread(null, null); this.contacts = new List <cpContact>(); this.stamp = 0; this.state = cpArbiterState.FirstCollision; }
// Equal function for arbiterSet. public static bool SetEql(cpShape[] shapes, cpArbiter arb) { cpShape a = shapes[0]; cpShape b = shapes[1]; return((a == arb.a && b == arb.b) || (b == arb.a && a == arb.b)); }
public SupportContext(cpShape shape1, cpShape shape2, Func <cpShape, cpVect, SupportPoint> func1, Func <cpShape, cpVect, SupportPoint> func2) { this.shape1 = shape1; this.shape2 = shape2; this.func1 = func1; this.func2 = func2; }
/// Remove a collision shape from the simulation. public void RemoveShape(cpShape shape) { var body = shape.body; cp.AssertHard(ContainsShape(shape), "Cannot remove a shape that was not added to the space. (Removed twice maybe?)"); cp.AssertSpaceUnlocked(this); bool isStatic = body.bodyType == cpBodyType.STATIC; if (isStatic) { body.ActivateStatic(shape); } else { body.Activate(); } body.RemoveShape(shape); this.FilterArbiters(body, shape); (isStatic ? this.staticShapes : this.dynamicShapes).Remove(shape.hashid); shape.space = null; shape.hashid = 0; }
public static void CircleSegmentQuery(cpShape shape, cpVect center, float r1, cpVect a, cpVect b, float r2, ref cpSegmentQueryInfo info) { // offset the line to be relative to the circle cpVect da = cpVect.cpvsub(a, center); cpVect db = cpVect.cpvsub(b, center); float rsum = r1 + r2; float qa = cpVect.cpvdot(da, da) - 2 * cpVect.cpvdot(da, db) + cpVect.cpvdot(db, db); float qb = cpVect.cpvdot(da, db) - cpVect.cpvdot(da, da); float det = qb * qb - qa * (cpVect.cpvdot(da, da) - rsum * rsum); if (det >= 0.0f) { float t = (-qb - cp.cpfsqrt(det)) / (qa); if (0.0f <= t && t <= 1.0f) { { cpVect n = cpVect.cpvnormalize(cpVect.cpvlerp(da, db, t)); info.shape = shape; info.point = cpVect.cpvsub(cpVect.cpvlerp(da, db, t), cpVect.cpvmult(n, r2)); info.normal = n; info.alpha = t; } } } }
/// Add a collision shape to the simulation. /// If the shape is attached to a static body, it will be added as a static shape. public cpShape AddShape(cpShape shape) { var body = shape.body; cp.AssertHard(shape.space != this, "You have already added this shape to this space. You must not add it a second time."); cp.AssertHard(shape.space == null, "You have already added this shape to another space. You cannot add it to a second."); cp.AssertSpaceUnlocked(this); bool isStatic = body.bodyType == cpBodyType.STATIC; if (!isStatic) { body.Activate(); } body.AddShape(shape); shape.hashid = cp.shapeIDCounter++; shape.Update(body.transform); (isStatic ? this.staticShapes : this.dynamicShapes).Insert(shape.hashid, shape); shape.space = this; return(shape); }
public void FilterArbiters(cpBody body, cpShape filter) { List <ulong> safeDelete = new List <ulong>(); foreach (var hash in this.cachedArbiters) { cpArbiter arb = hash.Value; // Match on the filter shape, or if it's null the filter body if ( (body == arb.body_a && (filter == arb.a || filter == null)) || (body == arb.body_b && (filter == arb.b || filter == null)) ) { // Call separate when removing shapes. if (filter != null && arb.state != cpArbiterState.Cached) { arb.state = cpArbiterState.Invalidated; cpCollisionHandler handler = arb.handler; handler.separateFunc(arb, this, handler.userData); } arb.Unthread(); this.arbiters.Remove(arb); safeDelete.Add(hash.Key); } } foreach (var item in safeDelete) { cachedArbiters.Remove(item); } }
/// Test if a point lies within a shape. public static cpContactPointSet Collide(cpShape a, cpShape b, ref List <cpContact> contacts) { //cpContact[] contacts = new cpContact[cpArbiter.CP_MAX_CONTACTS_PER_ARBITER]; cpCollisionInfo info = cpCollision.cpCollide(a, b, 0, ref contacts); cpContactPointSet set = new cpContactPointSet(); set.count = info.count; set.points = new PointsDistance[set.count]; // cpCollideShapes() may have swapped the contact order. Flip the normal. bool swapped = (a != info.a); set.normal = (swapped ? cpVect.cpvneg(info.n) : info.n); for (int i = 0; i < info.count; i++) { cpVect p1 = contacts[i].r1; cpVect p2 = contacts[i].r2; set.points[i] = new PointsDistance(); set.points[i].pointA = (swapped ? p2 : p1); set.points[i].pointB = (swapped ? p1 : p2); set.points[i].distance = cpVect.cpvdot(cpVect.cpvsub(p2, p1), set.normal); } return(set); }
public void RemoveShape(cpShape shape) { cpShape prev = shape.prev; cpShape next = shape.next; if (prev != null) { prev.next = next; } else { this.shapeList = next; } if (next != null) { next.prev = prev; } shape.prev = null; shape.next = null; if (bodyType == cpBodyType.DYNAMIC && shape.massInfo.m > 0.0f) { AccumulateMassFromShapes(); } }
public void eachShape(Action <cpShape, object> func, object data) { for (cpShape var = this.shapeList; var != null; var = var.next) { func(var, data); } }
public static cpColor GetShapeColor(cpShape shape) { if (shape.sensor) { return(new cpColor(128, 128, 128)); } else { if (shape.body.IsSleeping()) { return(new cpColor(125, 125, 125)); } else if (shape.body.nodeIdleTime > shape.space.sleepTimeThreshold) { return(new cpColor(170, 170, 170)); } else if (shape.body.bodyType == cpBodyType.STATIC) { return(new cpColor(75, 75, 75)); } else { return(styles[(int)shape.hashid % styles.Count]); } } }
public void GetBodies(out cpBody a, out cpBody b) { cpShape shape_a, shape_b; GetShapes(out shape_a, out shape_b); a = shape_a.body; b = shape_b.body; }
public void DrawShape(cpShape shape) { cpBody body = shape.body; cpColor color = cp.GetShapeColor(shape);; // ColorForBody(body); switch (shape.shapeType) { case cpShapeType.Circle: { cpCircleShape circle = (cpCircleShape)shape; if (Flags.HasFlag(PhysicsDrawFlags.BB) || Flags.HasFlag(PhysicsDrawFlags.All)) { Draw(circle.bb); } if (Flags.HasFlag(PhysicsDrawFlags.Shapes) || Flags.HasFlag(PhysicsDrawFlags.All)) { Draw(circle, color); } } break; case cpShapeType.Segment: { cpSegmentShape seg = (cpSegmentShape)shape; if (Flags.HasFlag(PhysicsDrawFlags.BB) || Flags.HasFlag(PhysicsDrawFlags.All)) { Draw(seg.bb); } if (Flags.HasFlag(PhysicsDrawFlags.Shapes) || Flags.HasFlag(PhysicsDrawFlags.All)) { Draw(seg, color); } } break; case cpShapeType.Polygon: { cpPolyShape poly = (cpPolyShape)shape; if (Flags.HasFlag(PhysicsDrawFlags.BB) || Flags.HasFlag(PhysicsDrawFlags.All)) { Draw(poly.bb); } if (Flags.HasFlag(PhysicsDrawFlags.Shapes) || Flags.HasFlag(PhysicsDrawFlags.All)) { Draw(poly, color); } } break; default: cp.AssertHard(false, "Bad assertion in DrawShape()"); break; } }
public cpPointQueryExtendedInfo(cpShape tShape) { /// The nearest shape, NULL if no shape was within range. this.shape = tShape; /// The closest point on the shape's surface. (in world space coordinates) this.d = cp.Infinity; /// The distance to the point. The distance is negative if the point is inside the shape. this.n = cpVect.Zero; }
public PhysicSprite(cpBody body, cpShape shape) { _body = body; _shape = shape; Active = true; _body.SetUserData(this); }
public void ActivateBody(cpBody body) { cp.AssertHard(body.bodyType == cpBodyType.DYNAMIC, "Internal error: Attempting to deactivate a non-dynamic body."); if (this.IsLocked) { // cpSpaceActivateBody() is called again once the space is unlocked if (!this.rousedBodies.Contains(body)) { this.rousedBodies.Add(body); } } else { cp.AssertSoft(body.nodeRoot == null && body.nodeNext == null, "Internal error: Activating body non-NULL node pointers."); this.dynamicBodies.Add(body); body.eachShape((s, o) => { this.staticShapes.Remove(s.hashid); this.dynamicShapes.Insert(s.hashid, s); }, null); body.eachArbiter((arb, o) => { cpBody bodyA = arb.body_a; // Arbiters are shared between two bodies that are always woken up together. // You only want to restore the arbiter once, so bodyA is arbitrarily chosen to own the arbiter. // The edge case is when static bodies are involved as the static bodies never actually sleep. // If the static body is bodyB then all is good. If the static body is bodyA, that can easily be checked. if (body == bodyA || bodyA.bodyType == cpBodyType.STATIC) { cpShape a = arb.a, b = arb.b; this.cachedArbiters.Add(cp.CP_HASH_PAIR(a.hashid, b.hashid), arb); // Update the arbiter's state arb.stamp = this.stamp; arb.handler = this.LookupHandler(a.type, b.type, defaultHandler); this.arbiters.Add(arb); } }, null); body.eachConstraint((constraint, o) => { var bodyA = constraint.a; if (body == bodyA || bodyA.bodyType == cpBodyType.STATIC) { this.constraints.Add(constraint); } }, null); } }
public void Set(cpPointQueryInfo newPointInfo) { /// The nearest shape, NULL if no shape was within range. shape = newPointInfo.shape; point = newPointInfo.point; distance = newPointInfo.distance; gradient = newPointInfo.gradient; // g = newPointInfo.g; }
public cpCollisionInfo(cpShape a, cpShape b, ulong id, cpVect n, List <cpContact> contacts) { // TODO: Complete member initialization this.a = a; this.b = b; this.id = id; this.n = n; this.arr = contacts; }
public cpSegmentQueryInfo(cpShape shape, cpVect point, cpVect normal, float alpha) { /// The shape that was hit, NULL if no collision occured. this.shape = shape; /// The normalized distance along the query segment in the range [0, 1]. this.alpha = alpha; /// The normal of the surface hit. this.normal = normal; this.point = point; }
public cpPointQueryInfo(cpShape shape, cpVect point, float distance, cpVect gradient) { /// The nearest shape, NULL if no shape was within range. this.shape = shape; /// The closest point on the shape's surface. (in world space coordinates) this.point = point; /// The distance to the point. The distance is negative if the point is inside the shape. this.distance = distance; this.gradient = gradient; }
public void Set(cpSegmentQueryInfo info1) { /// The shape that was hit, NULL if no collision occured. this.shape = info1.shape; /// The normalized distance along the query segment in the range [0, 1]. this.alpha = info1.alpha; /// The normal of the surface hit. this.normal = info1.normal; this.point = info1.point; }
/// Return the colliding shapes involved for this arbiter. /// The order of their cpSpace.collision_type values will match /// the order set when the collision handler was registered. public void GetShapes(out cpShape a, out cpShape b) { if (swapped) { a = this.b; b = this.a; } else { a = this.a; } b = this.b; }
/// Update the collision detection data for a specific shape in the space. public void ReindexShape(cpShape shape) { cp.AssertHard(!IsLocked, "You cannot manually reindex objects while the space is locked. Wait until the current query or step is complete."); //var body = shape.body; shape.CacheBB(); //shape.Update(body.GetPosition(), body.GetRotation()); // attempt to rehash the shape in both hashes this.dynamicShapes.ReindexObject(shape, shape.hashid); this.staticShapes.ReindexObject(shape, shape.hashid); }
//MARK: BB Query Functions public ulong BBQueryFunc(BBQueryContext context, cpShape shape, ulong id, object data) { if ( !cpShapeFilter.Reject(shape.filter, context.filter) && context.bb.Intersects(shape.bb) ) { context.func(shape, data); } return(id); }
public static bool QueryReject(cpShape a, cpShape b) { return( // BBoxes must overlap !a.bb.Intersects(b.bb) // Don't collide shapes attached to the same body. || a.body == b.body // Don't collide shapes that are filtered. || a.filter.Reject(b.filter) // Don't collide bodies if they have a constraint with collideBodies == cpFalse. || QueryRejectConstraint(a.body, b.body) ); }
// Wake up any sleeping or idle bodies touching a static body. public void ActivateStatic(cpShape filter) { cp.AssertHard(bodyType == cpBodyType.STATIC, "Body.activateStatic() called on a non-static body."); eachArbiter((arb, o) => { if (filter == null || filter == arb.a || filter == arb.b) { (arb.body_a == this ? arb.body_b : arb.body_a).Activate(); } }, null); // TODO should also activate joints! }
//MARK: Segment Query Functions public float SegmentQueryFunc(SegmentQueryContext context, cpShape shape, object data) { cpSegmentQueryInfo info = null; if ( !cpShapeFilter.Reject(shape.filter, context.filter) && shape.SegmentQuery(context.start, context.end, context.radius, ref info) ) { context.func(shape, info.point, info.normal, info.alpha, data); } return(1.0f); }
public float SegmentQueryFirstFunc(SegmentQueryContext context, cpShape shape, cpSegmentQueryInfo output) { cpSegmentQueryInfo info = null; if ( !cpShapeFilter.Reject(shape.filter, context.filter) && !shape.sensor && shape.SegmentQuery(context.start, context.end, context.radius, ref info) && info.alpha < output.alpha ) { output = info; } return(output.alpha); }
public ulong NearestPointQuery(PointQueryContext context, cpShape shape, ulong id, object data) { if ( !cpShapeFilter.Reject(shape.filter, context.filter) ) { cpPointQueryInfo info = null; shape.PointQuery(context.point, ref info); if (info.shape != null && info.distance < context.maxDistance) { context.func(shape, info.point, info.distance, info.gradient, data); } } return(id); }
//MARK: Collision Functions // Collide circle shapes. public static void CircleToCircle(cpShape cir1, cpShape cir2, ref cpCollisionInfo info) { cpCircleShape c1 = (cpCircleShape)cir1; cpCircleShape c2 = (cpCircleShape)cir2; float mindist = c1.r + c2.r; cpVect delta = cpVect.cpvsub(c2.tc, c1.tc); float distsq = cpVect.cpvlengthsq(delta); if (distsq < mindist * mindist) { float dist = cp.cpfsqrt(distsq); cpVect n = info.n = (dist > 0.0f ? cpVect.cpvmult(delta, 1.0f / dist) : cpVect.cpv(1.0f, 0.0f)); InfoPushContact(ref info, cpVect.cpvadd(c1.tc, cpVect.cpvmult(n, c1.r)), cpVect.cpvadd(c2.tc, cpVect.cpvmult(n, -c2.r)), 0); } }
public void AddShape(cpShape shape) { //this.shapeList.Add(shape); cpShape next = this.shapeList; if (next != null) { next.prev = shape; } shape.next = next; this.shapeList = shape; if (shape.massInfo.m > 0.0f) { AccumulateMassFromShapes(); } }
/// <summary> /// CREATES A BODY WITH MASS AND INERTIA /// </summary> /// <param name="mass"></param> /// <param name="moment"></param> public cpBody(float mass, float moment) { transform = new cpTransform(); this.cog = cpVect.Zero; this.space = null; this.shapeList = null; this.arbiterList = null; // These are both wacky linked lists. this.constraintList = null; velocity_func = UpdateVelocity; position_func = UpdatePosition; // This stuff is used to track information on the collision graph. this.nodeRoot = null; this.nodeNext = null; this.nodeIdleTime = 0; /// Position of the rigid body's center of gravity. this.p = cpVect.Zero; /// Velocity of the rigid body's center of gravity. this.v = cpVect.Zero; /// Force acting on the rigid body's center of gravity. this.f = cpVect.Zero; /// Angular velocity of the body around it's center of gravity in radians/second. this.w = 0; /// Torque applied to the body around it's center of gravity. this.t = 0; // This stuff is all private. this.v_bias = cpVect.Zero; //x = this.v_biasy = 0; this.w_bias = 0; this.userData = null; this.SetMass(mass); this.SetMoment(moment); this.SetAngle(0.0f); }
public ulong NearestPointQueryNearest(object ctx, cpShape shape, ulong id, ref object outp) { PointQueryContext context = (PointQueryContext)ctx; cpPointQueryInfo output = (cpPointQueryInfo)outp; if ( !cpShapeFilter.Reject(shape.filter, context.filter) && !shape.sensor ) { cpPointQueryInfo info = null; shape.PointQuery(context.point, ref info); if (info.distance < output.distance) { outp = (object)info; } } return(id); }
public static void GetShapesAtPointFunc(cpShape shape, float distance, CCPoint point, ref List<CCPhysicsShape> arr) { CCPhysicsShapeInfo it; cp.AssertWarn(!CCPhysicsShapeInfo.Map.TryGetValue(shape, out it)); arr.Add(it.getShape()); // (it.second.getShape()); }
public static void QueryRectCallbackFunc(cpShape shape, CCRectQueryCallbackInfo info) { CCPhysicsShapeInfo it; cp.AssertWarn(!CCPhysicsShapeInfo.Map.TryGetValue(shape, out it)); if (!continues) { return; } continues = info.func(info.world, it.getShape(), info.data); }
public static void QueryPointFunc(cpShape shape, float distance, CCPoint point, ref CCPointQueryCallbackInfo info) { CCPhysicsShapeInfo it; cp.AssertWarn(!CCPhysicsShapeInfo.Map.TryGetValue(shape, out it)); continues = info.func(info.world, it.getShape(), info.data); }
public static void QueryPointFunc(cpShape shape, float distance, CCPoint point, ref CCPointQueryCallbackInfo info) { CCPhysicsShapeInfo it; cp.AssertWarn(!CCPhysicsShapeInfo.Map.TryGetValue(shape, out it)); Continues = info.Function(info.World, it.Shape, info.Data); }
public static void RayCastCallbackFunc(cpShape shape, float t, CCPoint n, ref CCRayCastCallbackInfo info) { if (!continues) { return; } CCPhysicsShapeInfo it; cp.AssertWarn(!CCPhysicsShapeInfo.Map.TryGetValue(shape, out it)); CCPhysicsRayCastInfo callbackInfo = new CCPhysicsRayCastInfo( it.getShape(), info.p1, info.p2, new CCPoint(info.p1.X + (info.p2.X - info.p1.X) * t, info.p1.Y + (info.p2.Y - info.p1.Y) * t), new CCPoint(n.Y, n.Y), t, null ); continues = info.func(info.world, callbackInfo, info.data); }
/// Return the colliding shapes involved for this arbiter. /// The order of their cpSpace.collision_type values will match /// the order set when the collision handler was registered. public void GetShapes(out cpShape a, out cpShape b) { if (swapped) { a = this.b; b = this.a; } else a = this.a; b = this.b; }
public static void QueryRectCallbackFunc(cpShape shape, CCRectQueryCallbackInfo info) { CCPhysicsShapeInfo it; cp.AssertWarn(!CCPhysicsShapeInfo.Map.TryGetValue(shape, out it)); if (!Continues) { return; } Continues = info.Function(info.World, it.Shape, info.Data); }
public ulong NearestPointQuery(PointQueryContext context, cpShape shape, ulong id, object data) { if ( !cpShapeFilter.Reject(shape.filter, context.filter) ) { cpPointQueryInfo info = null; shape.PointQuery(context.point, ref info); if (info.shape != null && info.distance < context.maxDistance) context.func(shape, info.point, info.distance, info.gradient, data); } return id; }
//MARK: BB Query Functions public ulong BBQueryFunc(BBQueryContext context, cpShape shape, ulong id, object data) { if ( !cpShapeFilter.Reject(shape.filter, context.filter) && context.bb.Intersects(shape.bb) ) { context.func(shape, data); } return id; }
public float SegmentQueryFirstFunc(SegmentQueryContext context, cpShape shape, cpSegmentQueryInfo output) { cpSegmentQueryInfo info = null; if ( !cpShapeFilter.Reject(shape.filter, context.filter) && !shape.sensor && shape.SegmentQuery(context.start, context.end, context.radius, ref info) && info.alpha < output.alpha ) { output = info; } return output.alpha; }
public ulong NearestPointQueryNearest(object ctx, cpShape shape, ulong id, ref object outp) { PointQueryContext context = (PointQueryContext)ctx; cpPointQueryInfo output = (cpPointQueryInfo)outp; if ( !cpShapeFilter.Reject(shape.filter, context.filter) && !shape.sensor ) { cpPointQueryInfo info = null; shape.PointQuery(context.point, ref info); if (info.distance < output.distance) outp = (object)info; } return id; }
public ulong ShapeQueryFunc(cpShape a, cpShape b, ulong id, ShapeQueryContext context) { if (cpShapeFilter.Reject(a.filter, b.filter) || a == b) return id; List<cpContact> contacts = new List<cpContact>(); cpContactPointSet set = cpShape.Collide(a, b, ref contacts); if (set.count > 0) { if (context.func != null) context.func(b, set, context.data); context.anyCollision = !(a.sensor || b.sensor); } return id; }
public static void UpdateFunc(cpShape shape, object unused) { shape.CacheBB(); }
public cpCollisionInfo(cpShape a, cpShape b, ulong id, cpVect n, List<cpContact> contacts) { // TODO: Complete member initialization this.a = a; this.b = b; this.id = id; this.n = n; this.arr = contacts; }
public static void RayCastCallbackFunc(cpShape shape, float t, CCPoint n, ref CCRayCastCallbackInfo info) { if (!Continues) { return; } CCPhysicsShapeInfo it; cp.AssertWarn(!CCPhysicsShapeInfo.Map.TryGetValue(shape, out it)); CCPhysicsRayCastInfo callbackInfo = new CCPhysicsRayCastInfo( it.Shape, info.Pont1, info.Point2, new CCPoint(info.Pont1.X + (info.Point2.X - info.Pont1.X) * t, info.Pont1.Y + (info.Point2.Y - info.Pont1.Y) * t), new CCPoint(n.Y, n.Y), t, null ); Continues = info.Function(info.World, callbackInfo, info.Data); }
/// Test if a point lies within a shape. public static cpContactPointSet Collide(cpShape a, cpShape b, ref List<cpContact> contacts) { //cpContact[] contacts = new cpContact[cpArbiter.CP_MAX_CONTACTS_PER_ARBITER]; cpCollisionInfo info = cpCollision.cpCollide(a, b, 0, ref contacts); cpContactPointSet set = new cpContactPointSet(); set.count = info.count; set.points = new PointsDistance[set.count]; // cpCollideShapes() may have swapped the contact order. Flip the normal. bool swapped = (a != info.a); set.normal = (swapped ? cpVect.cpvneg(info.n) : info.n); for (int i = 0; i < info.count; i++) { cpVect p1 = contacts[i].r1; cpVect p2 = contacts[i].r2; set.points[i] = new PointsDistance(); set.points[i].pointA = (swapped ? p2 : p1); set.points[i].pointB = (swapped ? p1 : p2); set.points[i].distance = cpVect.cpvdot(cpVect.cpvsub(p2, p1), set.normal); } return set; }
public void Update(cpCollisionInfo info, cpSpace space) { cpShape a = info.a, b = info.b; // For collisions between two similar primitive types, the order could have been swapped since the last frame. this.a = a; this.body_a = a.body; this.b = b; this.body_b = b.body; // Iterate over the possible pairs to look for hash value matches. for (int i = 0; i < info.count; i++) { cpContact con = info.arr[i]; // r1 and r2 store absolute offsets at init time. // Need to convert them to relative offsets. con.r1 = cpVect.cpvsub(con.r1, a.body.p); con.r2 = cpVect.cpvsub(con.r2, b.body.p); // Cached impulses are not zeroed at init time. con.jnAcc = con.jtAcc = 0.0f; for (int j = 0; j < this.Count; j++) { cpContact old = this.contacts[j]; // This could trigger false positives, but is fairly unlikely nor serious if it does. if (con.hash == old.hash) { // Copy the persistant contact information. con.jnAcc = old.jnAcc; con.jtAcc = old.jtAcc; } } } //TODO: revise this.contacts = info.arr.ToList(); //this.count = info.count; this.n = info.n; this.e = a.e * b.e; this.u = a.u * b.u; cpVect surface_vr = cpVect.cpvsub(b.surfaceV, a.surfaceV); this.surface_vr = cpVect.cpvsub(surface_vr, cpVect.cpvmult(info.n, cpVect.cpvdot(surface_vr, info.n))); ulong typeA = info.a.type, typeB = info.b.type; cpCollisionHandler defaultHandler = space.defaultHandler; cpCollisionHandler handler = this.handler = space.LookupHandler(typeA, typeB, defaultHandler); // Check if the types match, but don't swap for a default handler which use the wildcard for type A. bool swapped = this.swapped = (typeA != handler.typeA && handler.typeA != cp.WILDCARD_COLLISION_TYPE); if (handler != defaultHandler || space.usesWildcards) { // The order of the main handler swaps the wildcard handlers too. Uffda. this.handlerA = space.LookupHandler(swapped ? typeB : typeA, cp.WILDCARD_COLLISION_TYPE, cpCollisionHandler.cpCollisionHandlerDoNothing); this.handlerB = space.LookupHandler(swapped ? typeA : typeB, cp.WILDCARD_COLLISION_TYPE, cpCollisionHandler.cpCollisionHandlerDoNothing); } // mark it as new if it's been cached if (this.state == cpArbiterState.Cached) this.state = cpArbiterState.FirstCollision; }
public cpContactPointSet Collide(cpShape b, ref List<cpContact> contacts) { return Collide(this, b, ref contacts); }
//MARK: Segment Query Functions public float SegmentQueryFunc(SegmentQueryContext context, cpShape shape, object data) { cpSegmentQueryInfo info = null; if ( !cpShapeFilter.Reject(shape.filter, context.filter) && shape.SegmentQuery(context.start, context.end, context.radius, ref info) ) { context.func(shape, info.point, info.normal, info.alpha, data); } return 1.0f; }
// Equal function for arbiterSet. public static bool SetEql(cpShape[] shapes, cpArbiter arb) { cpShape a = shapes[0]; cpShape b = shapes[1]; return ((a == arb.a && b == arb.b) || (b == arb.a && a == arb.b)); }
public void DrawShape(cpShape shape) { cpBody body = shape.body; cpColor color = cp.GetShapeColor(shape); ;// ColorForBody(body); switch (shape.shapeType) { case cpShapeType.Circle: { cpCircleShape circle = (cpCircleShape)shape; if (Flags.HasFlag(PhysicsDrawFlags.BB) || Flags.HasFlag(PhysicsDrawFlags.All)) Draw(circle.bb); if (Flags.HasFlag(PhysicsDrawFlags.Shapes) || Flags.HasFlag(PhysicsDrawFlags.All)) Draw(circle, color); } break; case cpShapeType.Segment: { cpSegmentShape seg = (cpSegmentShape)shape; if (Flags.HasFlag(PhysicsDrawFlags.BB) || Flags.HasFlag(PhysicsDrawFlags.All)) Draw(seg.bb); if (Flags.HasFlag(PhysicsDrawFlags.Shapes) || Flags.HasFlag(PhysicsDrawFlags.All)) { Draw(seg, color); } } break; case cpShapeType.Polygon: { cpPolyShape poly = (cpPolyShape)shape; if (Flags.HasFlag(PhysicsDrawFlags.BB) || Flags.HasFlag(PhysicsDrawFlags.All)) Draw(poly.bb); if (Flags.HasFlag(PhysicsDrawFlags.Shapes) || Flags.HasFlag(PhysicsDrawFlags.All)) { Draw(poly, color); } } break; default: cp.AssertHard(false, "Bad assertion in DrawShape()"); break; } }
public bool ShapeQuery(cpShape shape, Action<cpShape, cpContactPointSet, object> func, object data) { cpBody body = shape.body; cpBB bb = (body != null ? shape.Update(body.transform) : shape.bb); ShapeQueryContext context = new ShapeQueryContext(func, data, false); object ctx = (object)context; Lock(); { this.staticShapes.Query(shape, bb, (o1, o2, s, o3) => ShapeQueryFunc(o1 as cpShape, o2 as cpShape, s, (ShapeQueryContext)o3) , ctx); this.dynamicShapes.Query(shape, bb, (o1, o2, s, o3) => ShapeQueryFunc(o1 as cpShape, o2 as cpShape, s, (ShapeQueryContext)o3) , ctx); } Unlock(true); return ((ShapeQueryContext)ctx).anyCollision; }