MCPcopy Create free account
hub / github.com/axmolengine/axmol / StickyPreSolve

Function StickyPreSolve

tests/cpp-tests/Source/ChipmunkTestBed/demo/Sticky.cpp:40–93  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

38}
39
40static 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
95static void PostStepRemoveJoint(cpSpace* space, void* key, void* data)
96{

Callers

nothing calls this directly

Calls 12

cpvsubFunction · 0.85
cpvmultFunction · 0.85
cpvaddFunction · 0.85
cpfminFunction · 0.85
cpArbiterGetUserDataFunction · 0.85
cpBodyWorldToLocalFunction · 0.85
cpPivotJointNew2Function · 0.85
cpConstraintSetMaxForceFunction · 0.85
cpArbiterSetUserDataFunction · 0.85

Tested by

no test coverage detected