| 38 | } |
| 39 | |
| 40 | static cpBool StickyPreSolve(cpArbiter* arb, cpSpace* space, void* data) |
| 41 | { |
| 42 | // We want to fudge the collisions a bit to allow shapes to overlap more. |
| 43 | // This simulates their squishy sticky surface, and more importantly |
| 44 | // keeps them from separating and destroying the joint. |
| 45 | |
| 46 | // Track the deepest collision point and use that to determine if a rigid collision should occur. |
| 47 | cpFloat deepest = INFINITY; |
| 48 | |
| 49 | // Grab the contact set and iterate over them. |
| 50 | cpContactPointSet contacts = cpArbiterGetContactPointSet(arb); |
| 51 | for (int i = 0; i < contacts.count; i++) |
| 52 | { |
| 53 | // Sink the contact points into the surface of each shape. |
| 54 | contacts.points[i].pointA = cpvsub(contacts.points[i].pointA, cpvmult(contacts.normal, STICK_SENSOR_THICKNESS)); |
| 55 | contacts.points[i].pointB = cpvadd(contacts.points[i].pointB, cpvmult(contacts.normal, STICK_SENSOR_THICKNESS)); |
| 56 | deepest = cpfmin(deepest, contacts.points[i].distance); // + 2.0f*STICK_SENSOR_THICKNESS); |
| 57 | } |
| 58 | |
| 59 | // Set the new contact point data. |
| 60 | cpArbiterSetContactPointSet(arb, &contacts); |
| 61 | |
| 62 | // If the shapes are overlapping enough, then create a |
| 63 | // joint that sticks them together at the first contact point. |
| 64 | if (!cpArbiterGetUserData(arb) && deepest <= 0.0f) |
| 65 | { |
| 66 | CP_ARBITER_GET_BODIES(arb, bodyA, bodyB); |
| 67 | |
| 68 | // Create a joint at the contact point to hold the body in place. |
| 69 | cpVect anchorA = cpBodyWorldToLocal(bodyA, contacts.points[0].pointA); |
| 70 | cpVect anchorB = cpBodyWorldToLocal(bodyB, contacts.points[0].pointB); |
| 71 | cpConstraint* joint = cpPivotJointNew2(bodyA, bodyB, anchorA, anchorB); |
| 72 | |
| 73 | // Give it a finite force for the stickyness. |
| 74 | cpConstraintSetMaxForce(joint, 3e3); |
| 75 | |
| 76 | // Schedule a post-step() callback to add the joint. |
| 77 | cpSpaceAddPostStepCallback(space, PostStepAddJoint, joint, NULL); |
| 78 | |
| 79 | // Store the joint on the arbiter so we can remove it later. |
| 80 | cpArbiterSetUserData(arb, joint); |
| 81 | } |
| 82 | |
| 83 | // Position correction and velocity are handled separately so changing |
| 84 | // the overlap distance alone won't prevent the collision from occuring. |
| 85 | // Explicitly the collision for this frame if the shapes don't overlap using the new distance. |
| 86 | return (deepest <= 0.0f); |
| 87 | |
| 88 | // Lots more that you could improve upon here as well: |
| 89 | // * Modify the joint over time to make it plastic. |
| 90 | // * Modify the joint in the post-step to make it conditionally plastic (like clay). |
| 91 | // * Track a joint for the deepest contact point instead of the first. |
| 92 | // * Track a joint for each contact point. (more complicated since you only get one data pointer). |
| 93 | } |
| 94 | |
| 95 | static void PostStepRemoveJoint(cpSpace* space, void* key, void* data) |
| 96 | { |
nothing calls this directly
no test coverage detected