1 /*
2  * Copyright (c) 2007-2013 Scott Lembcke and Howling Moon Software
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to deal
6  * in the Software without restriction, including without limitation the rights
7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20  * SOFTWARE.
21  */
22 module dchip.cpArbiter;
23 
24 import std..string;
25 
26 import dchip.cpBody;
27 import dchip.chipmunk;
28 import dchip.chipmunk_private;
29 import dchip.chipmunk_types;
30 import dchip.constraints_util;
31 import dchip.cpSpace;
32 import dchip.cpSpatialIndex;
33 import dchip.cpShape;
34 import dchip.cpVect;
35 import dchip.util;
36 
37 /// The cpArbiter struct controls pairs of colliding shapes.
38 /// They are also used in conjuction with collision handler callbacks
39 /// allowing you to retrieve information on the collision and control it.
40 
41 /// Collision begin event function callback type.
42 /// Returning false from a begin callback causes the collision to be ignored until
43 /// the the separate callback is called when the objects stop colliding.
44 alias cpCollisionBeginFunc = cpBool function(cpArbiter* arb, cpSpace* space, void* data);
45 
46 /// Collision pre-solve event function callback type.
47 /// Returning false from a pre-step callback causes the collision to be ignored until the next step.
48 alias cpCollisionPreSolveFunc = cpBool function(cpArbiter* arb, cpSpace* space, void* data);
49 
50 /// Collision post-solve event function callback type.
51 alias cpCollisionPostSolveFunc = void function(cpArbiter* arb, cpSpace* space, void* data);
52 
53 /// Collision separate event function callback type.
54 alias cpCollisionSeparateFunc = void function(cpArbiter* arb, cpSpace* space, void* data);
55 
56 /// @private
57 struct cpCollisionHandler
58 {
59     cpCollisionType a;
60     cpCollisionType b;
61     cpCollisionBeginFunc begin;
62     cpCollisionPreSolveFunc preSolve;
63     cpCollisionPostSolveFunc postSolve;
64     cpCollisionSeparateFunc separate;
65     void* data;
66 }
67 
68 enum CP_MAX_CONTACTS_PER_ARBITER = 2;
69 
70 /// @private
71 enum cpArbiterState
72 {
73     // Arbiter is active and its the first collision.
74     cpArbiterStateFirstColl,
75 
76     // Arbiter is active and its not the first collision.
77     cpArbiterStateNormal,
78 
79     // Collision has been explicitly ignored.
80     // Either by returning false from a begin collision handler or calling cpArbiterIgnore().
81     cpArbiterStateIgnore,
82 
83     // Collison is no longer active. A space will cache an arbiter for up to cpSpace.collisionPersistence more steps.
84     cpArbiterStateCached,
85 }
86 
87 ///
88 mixin _ExportEnumMembers!cpArbiterState;
89 
90 /// @private
91 struct cpArbiterThread
92 {
93     // Links to next and previous arbiters in the contact graph.
94     cpArbiter* next;
95     cpArbiter* prev;
96 }
97 
98 /// A colliding pair of shapes.
99 struct cpArbiter
100 {
101     /// Calculated value to use for the elasticity coefficient.
102     /// Override in a pre-solve collision handler for custom behavior.
103     cpFloat e = 0;
104 
105     /// Calculated value to use for the friction coefficient.
106     /// Override in a pre-solve collision handler for custom behavior.
107     cpFloat u = 0;
108 
109     /// Calculated value to use for applying surface velocities.
110     /// Override in a pre-solve collision handler for custom behavior.
111     cpVect surface_vr;
112 
113     /// User definable data pointer.
114     /// The value will persist for the pair of shapes until the separate() callback is called.
115     /// NOTE: If you need to clean up this pointer, you should implement the separate() callback to do it.
116     cpDataPointer data;
117 
118     version (CHIP_ALLOW_PRIVATE_ACCESS)
119         cpShape * a;
120     else
121         package cpShape * a;
122 
123     version (CHIP_ALLOW_PRIVATE_ACCESS)
124         cpShape * b;
125     else
126         package cpShape * b;
127 
128     version (CHIP_ALLOW_PRIVATE_ACCESS)
129         cpBody * body_a;
130     else
131         package cpBody * body_a;
132 
133     version (CHIP_ALLOW_PRIVATE_ACCESS)
134         cpBody * body_b;
135     else
136         package cpBody * body_b;
137 
138     version (CHIP_ALLOW_PRIVATE_ACCESS)
139         cpArbiterThread thread_a;
140     else
141         package cpArbiterThread thread_a;
142 
143     version (CHIP_ALLOW_PRIVATE_ACCESS)
144         cpArbiterThread thread_b;
145     else
146         package cpArbiterThread thread_b;
147 
148     version (CHIP_ALLOW_PRIVATE_ACCESS)
149         int numContacts;
150     else
151         package int numContacts;
152 
153     version (CHIP_ALLOW_PRIVATE_ACCESS)
154         cpContact * contacts;
155     else
156         package cpContact * contacts;
157 
158     version (CHIP_ALLOW_PRIVATE_ACCESS)
159         cpTimestamp stamp;
160     else
161         package cpTimestamp stamp;
162 
163     version (CHIP_ALLOW_PRIVATE_ACCESS)
164         cpCollisionHandler * handler;
165     else
166         package cpCollisionHandler * handler;
167 
168     version (CHIP_ALLOW_PRIVATE_ACCESS)
169         cpBool swappedColl;
170     else
171         package cpBool swappedColl;
172 
173     version (CHIP_ALLOW_PRIVATE_ACCESS)
174         cpArbiterState state;
175     else
176         package cpArbiterState state;
177 }
178 
179 mixin template CP_DefineArbiterStructGetter(type, string member, string name)
180 {
181     mixin(q{
182         type cpArbiterGet%s(const cpArbiter * arb) { return cast(typeof(return))arb.%s; }
183     }.format(name, member));
184 }
185 
186 mixin template CP_DefineArbiterStructSetter(type, string member, string name)
187 {
188     mixin(q{
189         void cpArbiterSet%s(cpArbiter * arb, type value) { arb.%s = value; }
190     }.format(name, member));
191 }
192 
193 mixin template CP_DefineArbiterStructProperty(type, string member, string name)
194 {
195     mixin CP_DefineArbiterStructGetter!(type, member, name);
196     mixin CP_DefineArbiterStructSetter!(type, member, name);
197 }
198 
199 mixin CP_DefineArbiterStructProperty!(cpFloat, "e", "Elasticity");
200 mixin CP_DefineArbiterStructProperty!(cpFloat, "u", "Friction");
201 
202 mixin CP_DefineArbiterStructProperty!(cpDataPointer, "data", "UserData");
203 
204 /// Return the colliding shapes involved for this arbiter.
205 /// The order of their cpSpace.collision_type values will match
206 /// the order set when the collision handler was registered.
207 void cpArbiterGetShapes(const cpArbiter* arb, cpShape** a, cpShape** b)
208 {
209     if (arb.swappedColl)
210     {
211         (*a) = cast(typeof(*a))arb.b;
212         (*b) = cast(typeof(*a))arb.a;
213     }
214     else
215     {
216         (*a) = cast(typeof(*a))arb.a;
217         (*b) = cast(typeof(*b))arb.b;
218     }
219 }
220 
221 /// A macro shortcut for defining and retrieving the shapes from an arbiter.
222 string CP_ARBITER_GET_SHAPES(string arb, string a, string b)()
223 {
224     return q{
225         cpShape * %2$s;
226         cpShape * %3$s;
227         cpArbiterGetShapes(%1$s, &%2$s, &%3$s);
228     }.format(arb, a, b);
229 }
230 
231 /// Return the colliding bodies involved for this arbiter.
232 /// The order of the cpSpace.collision_type the bodies are associated with values will match
233 /// the order set when the collision handler was registered.
234 void cpArbiterGetBodies(const cpArbiter* arb, cpBody** a, cpBody** b)
235 {
236     mixin(CP_ARBITER_GET_SHAPES!("arb", "shape_a", "shape_b"));
237     (*a) = shape_a.body_;
238     (*b) = shape_b.body_;
239 }
240 
241 /// A macro shortcut for defining and retrieving the bodies from an arbiter.
242 template CP_ARBITER_GET_BODIES(string arb, string a, string b)
243 {
244     enum CP_ARBITER_GET_BODIES = q{
245         cpBody * %2$s;
246         cpBody * %3$s;
247         cpArbiterGetBodies(%1$s, &%2$s, &%3$s);
248     }.format(arb, a, b);
249 }
250 
251 /// A struct that wraps up the important collision data for an arbiter.
252 struct cpContactPointSet
253 {
254     /// The number of contact points in the set.
255     int count;
256 
257     /// The array of contact points.
258     struct Point
259     {
260         /// The position of the contact point.
261         cpVect point;
262 
263         /// The normal of the contact point.
264         cpVect normal;
265 
266         /// The depth of the contact point.
267         cpFloat dist = 0;
268     }
269 
270     Point[CP_MAX_CONTACTS_PER_ARBITER] points;
271 }
272 
273 cpContact* cpContactInit(cpContact* con, cpVect p, cpVect n, cpFloat dist, cpHashValue hash)
274 {
275     con.p    = p;
276     con.n    = n;
277     con.dist = dist;
278 
279     con.jnAcc = 0.0f;
280     con.jtAcc = 0.0f;
281     con.jBias = 0.0f;
282 
283     con.hash = hash;
284 
285     return con;
286 }
287 
288 // TODO make this generic so I can reuse it for constraints also.
289 void unthreadHelper(cpArbiter* arb, cpBody* body_)
290 {
291     cpArbiterThread* thread = cpArbiterThreadForBody(arb, body_);
292     cpArbiter* prev = thread.prev;
293     cpArbiter* next = thread.next;
294 
295     if (prev)
296     {
297         cpArbiterThreadForBody(prev, body_).next = next;
298     }
299     else if (body_.arbiterList == arb)
300     {
301         // IFF prev is null and body_.arbiterList == arb, is arb at the head of the list.
302         // This function may be called for an arbiter that was never in a list.
303         // In that case, we need to protect it from wiping out the body_.arbiterList pointer.
304         body_.arbiterList = next;
305     }
306 
307     if (next)
308         cpArbiterThreadForBody(next, body_).prev = prev;
309 
310     thread.prev = null;
311     thread.next = null;
312 }
313 
314 void cpArbiterUnthread(cpArbiter* arb)
315 {
316     unthreadHelper(arb, arb.body_a);
317     unthreadHelper(arb, arb.body_b);
318 }
319 
320 cpBool cpArbiterIsFirstContact(const cpArbiter* arb)
321 {
322     return arb.state == cpArbiterStateFirstColl;
323 }
324 
325 int cpArbiterGetCount(const cpArbiter* arb)
326 {
327     // Return 0 contacts if we are in a separate callback.
328     return (arb.state != cpArbiterStateCached ? arb.numContacts : 0);
329 }
330 
331 cpVect cpArbiterGetNormal(const cpArbiter* arb, int i)
332 {
333     cpAssertHard(0 <= i && i < cpArbiterGetCount(arb), "Index error: The specified contact index is invalid for this arbiter");
334 
335     cpVect n = arb.contacts[i].n;
336     return arb.swappedColl ? cpvneg(n) : n;
337 }
338 
339 cpVect cpArbiterGetPoint(const cpArbiter* arb, int i)
340 {
341     cpAssertHard(0 <= i && i < cpArbiterGetCount(arb), "Index error: The specified contact index is invalid for this arbiter");
342 
343     return arb.contacts[i].p;
344 }
345 
346 cpFloat cpArbiterGetDepth(const cpArbiter* arb, int i)
347 {
348     cpAssertHard(0 <= i && i < cpArbiterGetCount(arb), "Index error: The specified contact index is invalid for this arbiter");
349 
350     return arb.contacts[i].dist;
351 }
352 
353 cpContactPointSet cpArbiterGetContactPointSet(const cpArbiter* arb)
354 {
355     cpContactPointSet set;
356     set.count = cpArbiterGetCount(arb);
357 
358     for (int i = 0; i < set.count; i++)
359     {
360         set.points[i].point  = arb.contacts[i].p;
361         set.points[i].normal = arb.contacts[i].n;
362         set.points[i].dist   = arb.contacts[i].dist;
363     }
364 
365     return set;
366 }
367 
368 void cpArbiterSetContactPointSet(cpArbiter* arb, cpContactPointSet* set)
369 {
370     int count = set.count;
371     cpAssertHard(count == arb.numContacts, "The number of contact points cannot be changed.");
372 
373     for (int i = 0; i < count; i++)
374     {
375         arb.contacts[i].p    = set.points[i].point;
376         arb.contacts[i].n    = set.points[i].normal;
377         arb.contacts[i].dist = set.points[i].dist;
378     }
379 }
380 
381 cpVect cpArbiterTotalImpulse(const cpArbiter* arb)
382 {
383     cpContact* contacts = cast(cpContact*)arb.contacts;
384     cpVect sum = cpvzero;
385 
386     for (int i = 0, count = cpArbiterGetCount(arb); i < count; i++)
387     {
388         cpContact* con = &contacts[i];
389         sum = cpvadd(sum, cpvmult(con.n, con.jnAcc));
390     }
391 
392     return (arb.swappedColl ? sum : cpvneg(sum));
393 }
394 
395 cpVect cpArbiterTotalImpulseWithFriction(const cpArbiter* arb)
396 {
397     cpContact* contacts = cast(cpContact*)arb.contacts;
398     cpVect sum = cpvzero;
399 
400     for (int i = 0, count = cpArbiterGetCount(arb); i < count; i++)
401     {
402         cpContact* con = &contacts[i];
403         sum = cpvadd(sum, cpvrotate(con.n, cpv(con.jnAcc, con.jtAcc)));
404     }
405 
406     return (arb.swappedColl ? sum : cpvneg(sum));
407 }
408 
409 cpFloat cpArbiterTotalKE(const cpArbiter* arb)
410 {
411     cpFloat eCoef = (1 - arb.e) / (1 + arb.e);
412     cpFloat sum   = 0.0;
413 
414     cpContact* contacts = cast(cpContact*)arb.contacts;
415 
416     for (int i = 0, count = cpArbiterGetCount(arb); i < count; i++)
417     {
418         cpContact* con = &contacts[i];
419         cpFloat jnAcc  = con.jnAcc;
420         cpFloat jtAcc  = con.jtAcc;
421 
422         sum += eCoef * jnAcc * jnAcc / con.nMass + jtAcc * jtAcc / con.tMass;
423     }
424 
425     return sum;
426 }
427 
428 void cpArbiterIgnore(cpArbiter* arb)
429 {
430     arb.state = cpArbiterStateIgnore;
431 }
432 
433 cpVect cpArbiterGetSurfaceVelocity(cpArbiter* arb)
434 {
435     return cpvmult(arb.surface_vr, arb.swappedColl ? -1.0f : 1.0);
436 }
437 
438 void cpArbiterSetSurfaceVelocity(cpArbiter* arb, cpVect vr)
439 {
440     arb.surface_vr = cpvmult(vr, arb.swappedColl ? -1.0f : 1.0);
441 }
442 
443 cpArbiter* cpArbiterInit(cpArbiter* arb, cpShape* a, cpShape* b)
444 {
445     arb.handler     = null;
446     arb.swappedColl = cpFalse;
447 
448     arb.e = 0.0f;
449     arb.u = 0.0f;
450     arb.surface_vr = cpvzero;
451 
452     arb.numContacts = 0;
453     arb.contacts    = null;
454 
455     arb.a      = a;
456     arb.body_a = a.body_;
457     arb.b      = b;
458     arb.body_b = b.body_;
459 
460     arb.thread_a.next = null;
461     arb.thread_b.next = null;
462     arb.thread_a.prev = null;
463     arb.thread_b.prev = null;
464 
465     arb.stamp = 0;
466     arb.state = cpArbiterStateFirstColl;
467 
468     arb.data = null;
469 
470     return arb;
471 }
472 
473 void cpArbiterUpdate(cpArbiter* arb, cpContact* contacts, int numContacts, cpCollisionHandler* handler, cpShape* a, cpShape* b)
474 {
475     // Iterate over the possible pairs to look for hash value matches.
476     for (int i = 0; i < numContacts; i++)
477     {
478         cpContact* con = &contacts[i];
479 
480         for (int j = 0; j < arb.numContacts; j++)
481         {
482             cpContact* old = &arb.contacts[j];
483 
484             // This could trigger false positives, but is fairly unlikely nor serious if it does.
485             if (con.hash == old.hash)
486             {
487                 // Copy the persistant contact information.
488                 con.jnAcc = old.jnAcc;
489                 con.jtAcc = old.jtAcc;
490             }
491         }
492     }
493 
494     arb.contacts    = contacts;
495     arb.numContacts = numContacts;
496 
497     arb.handler     = handler;
498     arb.swappedColl = (a.collision_type != handler.a);
499 
500     arb.e = a.e * b.e;
501     arb.u = a.u * b.u;
502 
503     // Currently all contacts will have the same normal.
504     // This may change in the future.
505     cpVect n = (numContacts ? contacts[0].n : cpvzero);
506     cpVect surface_vr = cpvsub(a.surface_v, b.surface_v);
507     arb.surface_vr = cpvsub(surface_vr, cpvmult(n, cpvdot(surface_vr, n)));
508 
509     // For collisions between two similar primitive types, the order could have been swapped.
510     arb.a      = a;
511     arb.body_a = a.body_;
512     arb.b      = b;
513     arb.body_b = b.body_;
514 
515     // mark it as new if it's been cached
516     if (arb.state == cpArbiterStateCached)
517         arb.state = cpArbiterStateFirstColl;
518 }
519 
520 void cpArbiterPreStep(cpArbiter* arb, cpFloat dt, cpFloat slop, cpFloat bias)
521 {
522     cpBody* a = arb.body_a;
523     cpBody* b = arb.body_b;
524 
525     for (int i = 0; i < arb.numContacts; i++)
526     {
527         cpContact* con = &arb.contacts[i];
528 
529         // Calculate the offsets.
530         con.r1 = cpvsub(con.p, a.p);
531         con.r2 = cpvsub(con.p, b.p);
532 
533         // Calculate the mass normal and mass tangent.
534         con.nMass = 1.0f / k_scalar(a, b, con.r1, con.r2, con.n);
535         con.tMass = 1.0f / k_scalar(a, b, con.r1, con.r2, cpvperp(con.n));
536 
537         // Calculate the target bias velocity.
538         con.bias  = -bias* cpfmin(0.0f, con.dist + slop) / dt;
539         con.jBias = 0.0f;
540 
541         // Calculate the target bounce velocity.
542         con.bounce = normal_relative_velocity(a, b, con.r1, con.r2, con.n) * arb.e;
543     }
544 }
545 
546 void cpArbiterApplyCachedImpulse(cpArbiter* arb, cpFloat dt_coef)
547 {
548     if (cpArbiterIsFirstContact(arb))
549         return;
550 
551     cpBody* a = arb.body_a;
552     cpBody* b = arb.body_b;
553 
554     for (int i = 0; i < arb.numContacts; i++)
555     {
556         cpContact* con = &arb.contacts[i];
557         cpVect j       = cpvrotate(con.n, cpv(con.jnAcc, con.jtAcc));
558         apply_impulses(a, b, con.r1, con.r2, cpvmult(j, dt_coef));
559     }
560 }
561 
562 // TODO is it worth splitting velocity/position correction?
563 
564 void cpArbiterApplyImpulse(cpArbiter* arb)
565 {
566     cpBody* a = arb.body_a;
567     cpBody* b = arb.body_b;
568     cpVect  surface_vr = arb.surface_vr;
569     cpFloat friction   = arb.u;
570 
571     for (int i = 0; i < arb.numContacts; i++)
572     {
573         cpContact* con = &arb.contacts[i];
574         cpFloat nMass  = con.nMass;
575         cpVect  n      = con.n;
576         cpVect  r1     = con.r1;
577         cpVect  r2     = con.r2;
578 
579         cpVect vb1 = cpvadd(a.v_bias, cpvmult(cpvperp(r1), a.w_bias));
580         cpVect vb2 = cpvadd(b.v_bias, cpvmult(cpvperp(r2), b.w_bias));
581         cpVect vr  = cpvadd(relative_velocity(a, b, r1, r2), surface_vr);
582 
583         cpFloat vbn = cpvdot(cpvsub(vb2, vb1), n);
584         cpFloat vrn = cpvdot(vr, n);
585         cpFloat vrt = cpvdot(vr, cpvperp(n));
586 
587         cpFloat jbn    = (con.bias - vbn) * nMass;
588         cpFloat jbnOld = con.jBias;
589         con.jBias = cpfmax(jbnOld + jbn, 0.0f);
590 
591         cpFloat jn    = -(con.bounce + vrn) * nMass;
592         cpFloat jnOld = con.jnAcc;
593         con.jnAcc = cpfmax(jnOld + jn, 0.0f);
594 
595         cpFloat jtMax = friction * con.jnAcc;
596         cpFloat jt    = -vrt * con.tMass;
597         cpFloat jtOld = con.jtAcc;
598         con.jtAcc = cpfclamp(jtOld + jt, -jtMax, jtMax);
599 
600         apply_bias_impulses(a, b, r1, r2, cpvmult(n, con.jBias - jbnOld));
601         apply_impulses(a, b, r1, r2, cpvrotate(n, cpv(con.jnAcc - jnOld, con.jtAcc - jtOld)));
602     }
603 }