public bool StickyPreSolve(cpArbiter arb, object data) { // We want to fudge the collisions a bit to allow shapes to overlap more. // This simulates their squishy sticky surface, and more importantly // keeps them from separating and destroying the joint. // Track the deepest collision point and use that to determine if a rigid collision should occur. float deepest = cp.Infinity; // Grab the contact set and iterate over them. cpContactPointSet contacts = arb.GetContactPointSet(); for (int i = 0; i < contacts.count; i++) { // Sink the contact points into the surface of each shape. contacts.points[i].pointA = cpVect.cpvsub(contacts.points[i].pointA, cpVect.cpvmult(contacts.normal, STICK_SENSOR_THICKNESS)); contacts.points[i].pointB = cpVect.cpvadd(contacts.points[i].pointB, cpVect.cpvmult(contacts.normal, STICK_SENSOR_THICKNESS)); deepest = cp.cpfmin(deepest, contacts.points[i].distance); // + 2.0f*STICK_SENSOR_THICKNESS); } // Set the new contact point data. arb.SetContactPointSet(ref contacts); // If the shapes are overlapping enough, then create a // joint that sticks them together at the first contact point. if (arb.GetUserData() == null && deepest <= 0.0f) { cpBody bodyA, bodyB; arb.GetBodies(out bodyA, out bodyB); // Create a joint at the contact point to hold the body in place. cpVect anchorA = bodyA.WorldToLocal(contacts.points[0].pointA); cpVect anchorB = bodyB.WorldToLocal(contacts.points[0].pointB); cpConstraint joint = new cpPivotJoint(bodyA, bodyB, anchorA, anchorB); // Give it a finite force for the stickyness. joint.SetMaxForce(3e3f); // Schedule a post-step() callback to add the joint. space.AddPostStepCallback( (s, o1, o2) => PostStepAddJoint(joint, null), joint, null); // Store the joint on the arbiter so we can remove it later. arb.SetUserData(joint); } // Position correction and velocity are handled separately so changing // the overlap distance alone won't prevent the collision from occuring. // Explicitly the collision for this frame if the shapes don't overlap using the new distance. return(deepest <= 0.0f); // Lots more that you could improve upon here as well: // * Modify the joint over time to make it plastic. // * Modify the joint in the post-step to make it conditionally plastic (like clay). // * Track a joint for the deepest contact point instead of the first. // * Track a joint for each contact point. (more complicated since you only get one data pointer). }
private void Draw(cpPivotJoint constraint) { cpVect a = cpTransform.Point(constraint.a.transform, constraint.GetAnchorA()); cpVect b = cpTransform.Point(constraint.b.transform, constraint.GetAnchorB()); //DrawSegment(a, b, 1, cpColor.Grey); DrawDot(a, 3, CONSTRAINT_COLOR); DrawDot(b, 3, CONSTRAINT_COLOR); }
//static PhysicsJointPin* ruct(PhysicsBody* a, PhysicsBody* b, cpVect anchr); #region PROTECTED FUNC protected bool Init(CCPhysicsBody a, CCPhysicsBody b, CCPoint anchr) { if (!base.Init(a, b)) { return(false); } cpConstraint joint = new cpPivotJoint(GetBodyInfo(a).Body, GetBodyInfo(b).Body, PhysicsHelper.CCPointToCpVect(anchr)); if (joint == null) { return(false); } _info.Add(joint); return(true); }
protected bool Init(CCPhysicsBody a, CCPhysicsBody b, CCPoint anchr) { if (!base.Init(a, b)) { return(false); } GetBodyNode(a).Position = anchr; GetBodyNode(b).Position = anchr; // add a pivot joint to fixed two body together //cpConstraint joint = cpPivotJoint.cpPivotJointNew(getBodyInfo(a).getBody(), // getBodyInfo(b).getBody(), // anchr); cpConstraint joint = new cpPivotJoint(GetBodyInfo(a).Body, GetBodyInfo(b).Body, PhysicsHelper.CCPointToCpVect(anchr)); if (joint == null) { return(false); } _info.Add(joint); // add a gear joint to make two body have the same rotation. joint = new cpGearJoint(GetBodyInfo(a).Body, GetBodyInfo(b).Body, 0, 1); if (joint == null) { return(false); } _info.Add(joint); SetCollisionEnable(false); return(true); }