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 }