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.cpSpaceStep; 23 24 import dchip.cpBB; 25 import dchip.cpBody; 26 import dchip.cpCollision; 27 import dchip.chipmunk; 28 import dchip.chipmunk_private; 29 import dchip.chipmunk_types; 30 import dchip.cpArbiter; 31 import dchip.cpArray; 32 import dchip.cpConstraint; 33 import dchip.cpHashSet; 34 import dchip.cpShape; 35 import dchip.cpSpace; 36 import dchip.cpSpaceComponent; 37 import dchip.cpSpatialIndex; 38 import dchip.util; 39 40 cpPostStepCallback* cpSpaceGetPostStepCallback(cpSpace* space, void* key) 41 { 42 cpArray* arr = space.postStepCallbacks; 43 44 for (int i = 0; i < arr.num; i++) 45 { 46 cpPostStepCallback* callback = cast(cpPostStepCallback*)arr.arr[i]; 47 48 if (callback && callback.key == key) 49 return callback; 50 } 51 52 return null; 53 } 54 55 void PostStepDoNothing(cpSpace* space, void* obj, void* data) 56 { 57 } 58 59 cpBool cpSpaceAddPostStepCallback(cpSpace* space, cpPostStepFunc func, void* key, void* data) 60 { 61 cpAssertWarn(space.locked, 62 "Adding a post-step callback when the space is not locked is unnecessary. " 63 "Post-step callbacks will not called until the end of the next call to cpSpaceStep() or the next query."); 64 65 if (!cpSpaceGetPostStepCallback(space, key)) 66 { 67 cpPostStepCallback* callback = cast(cpPostStepCallback*)cpcalloc(1, cpPostStepCallback.sizeof); 68 callback.func = (func ? func : &PostStepDoNothing); 69 callback.key = key; 70 callback.data = data; 71 72 cpArrayPush(space.postStepCallbacks, callback); 73 return cpTrue; 74 } 75 else 76 { 77 return cpFalse; 78 } 79 } 80 81 //MARK: Locking Functions 82 83 void cpSpaceLock(cpSpace* space) 84 { 85 space.locked++; 86 } 87 88 void cpSpaceUnlock(cpSpace* space, cpBool runPostStep) 89 { 90 space.locked--; 91 cpAssertHard(space.locked >= 0, "Internal Error: Space lock underflow."); 92 93 if (space.locked == 0) 94 { 95 cpArray* waking = space.rousedBodies; 96 97 for (int i = 0, count = waking.num; i < count; i++) 98 { 99 cpSpaceActivateBody(space, cast(cpBody*)waking.arr[i]); 100 waking.arr[i] = null; 101 } 102 103 waking.num = 0; 104 105 if (space.locked == 0 && runPostStep && !space.skipPostStep) 106 { 107 space.skipPostStep = cpTrue; 108 109 cpArray* arr = space.postStepCallbacks; 110 111 for (int i = 0; i < arr.num; i++) 112 { 113 cpPostStepCallback* callback = cast(cpPostStepCallback*)arr.arr[i]; 114 cpPostStepFunc func = callback.func; 115 116 // Mark the func as null in case calling it calls cpSpaceRunPostStepCallbacks() again. 117 // TODO need more tests around this case I think. 118 callback.func = null; 119 120 if (func) 121 func(space, callback.key, callback.data); 122 123 arr.arr[i] = null; 124 cpfree(callback); 125 } 126 127 arr.num = 0; 128 space.skipPostStep = cpFalse; 129 } 130 } 131 } 132 133 //MARK: Contact Buffer Functions 134 135 struct cpContactBufferHeader 136 { 137 cpTimestamp stamp; 138 cpContactBufferHeader* next; 139 uint numContacts; 140 } 141 142 enum CP_CONTACTS_BUFFER_SIZE = (CP_BUFFER_BYTES - cpContactBufferHeader.sizeof) / cpContact.sizeof; 143 144 struct cpContactBuffer 145 { 146 cpContactBufferHeader header; 147 cpContact[CP_CONTACTS_BUFFER_SIZE] contacts; 148 } 149 150 cpContactBufferHeader* cpSpaceAllocContactBuffer(cpSpace* space) 151 { 152 cpContactBuffer* buffer = cast(cpContactBuffer*)cpcalloc(1, cpContactBuffer.sizeof); 153 cpArrayPush(space.allocatedBuffers, buffer); 154 return cast(cpContactBufferHeader*)buffer; 155 } 156 157 cpContactBufferHeader* cpContactBufferHeaderInit(cpContactBufferHeader* header, cpTimestamp stamp, cpContactBufferHeader* splice) 158 { 159 header.stamp = stamp; 160 header.next = (splice ? splice.next : header); 161 header.numContacts = 0; 162 163 return header; 164 } 165 166 void cpSpacePushFreshContactBuffer(cpSpace* space) 167 { 168 cpTimestamp stamp = space.stamp; 169 170 cpContactBufferHeader* head = space.contactBuffersHead; 171 172 if (!head) 173 { 174 // No buffers have been allocated, make one 175 space.contactBuffersHead = cpContactBufferHeaderInit(cpSpaceAllocContactBuffer(space), stamp, null); 176 } 177 else if (stamp - head.next.stamp > space.collisionPersistence) 178 { 179 // The tail buffer is available, rotate the ring 180 cpContactBufferHeader* tail = head.next; 181 space.contactBuffersHead = cpContactBufferHeaderInit(tail, stamp, tail); 182 } 183 else 184 { 185 // Allocate a new buffer and push it into the ring 186 cpContactBufferHeader* buffer = cpContactBufferHeaderInit(cpSpaceAllocContactBuffer(space), stamp, head); 187 space.contactBuffersHead = head.next = buffer; 188 } 189 } 190 191 cpContact* cpContactBufferGetArray(cpSpace* space) 192 { 193 if (space.contactBuffersHead.numContacts + CP_MAX_CONTACTS_PER_ARBITER > CP_CONTACTS_BUFFER_SIZE) 194 { 195 // contact buffer could overflow on the next collision, push a fresh one. 196 cpSpacePushFreshContactBuffer(space); 197 } 198 199 cpContactBufferHeader* head = space.contactBuffersHead; 200 return &(cast(cpContactBuffer*)head).contacts[head.numContacts]; 201 } 202 203 void cpSpacePushContacts(cpSpace* space, int count) 204 { 205 cpAssertHard(count <= CP_MAX_CONTACTS_PER_ARBITER, "Internal Error: Contact buffer overflow!"); 206 space.contactBuffersHead.numContacts += count; 207 } 208 209 void cpSpacePopContacts(cpSpace* space, int count) 210 { 211 space.contactBuffersHead.numContacts -= count; 212 } 213 214 //MARK: Collision Detection Functions 215 216 void* cpSpaceArbiterSetTrans(cpShape** shapes, cpSpace* space) 217 { 218 if (space.pooledArbiters.num == 0) 219 { 220 // arbiter pool is exhausted, make more 221 int count = CP_BUFFER_BYTES / cpArbiter.sizeof; 222 cpAssertHard(count, "Internal Error: Buffer size too small."); 223 224 cpArbiter* buffer = cast(cpArbiter*)cpcalloc(1, CP_BUFFER_BYTES); 225 cpArrayPush(space.allocatedBuffers, buffer); 226 227 for (int i = 0; i < count; i++) 228 cpArrayPush(space.pooledArbiters, buffer + i); 229 } 230 231 return cpArbiterInit(cast(cpArbiter*)cpArrayPop(space.pooledArbiters), shapes[0], shapes[1]); 232 } 233 234 cpBool queryReject(cpShape* a, cpShape* b) 235 { 236 return ( 237 238 // BBoxes must overlap 239 !cpBBIntersects(a.bb, b.bb) 240 241 // Don't collide shapes attached to the same body. 242 || a.body_ == b.body_ 243 244 // Don't collide objects in the same non-zero group 245 || (a.group && a.group == b.group) 246 247 // Don't collide objects that don't share at least on layer. 248 || !(a.layers & b.layers) 249 250 // Don't collide infinite mass objects 251 || (a.body_.m == INFINITY && b.body_.m == INFINITY) 252 ); 253 } 254 255 // Callback from the spatial hash. 256 cpCollisionID cpSpaceCollideShapes(cpShape* a, cpShape* b, cpCollisionID id, cpSpace* space) 257 { 258 // Reject any of the simple cases 259 if (queryReject(a, b)) 260 return id; 261 262 cpCollisionHandler* handler = cpSpaceLookupHandler(space, a.collision_type, b.collision_type); 263 264 cpBool sensor = a.sensor || b.sensor; 265 266 if (sensor && handler == &cpDefaultCollisionHandler) 267 return id; 268 269 // Shape 'a' should have the lower shape type. (required by cpCollideShapes() ) 270 // TODO remove me: a < b comparison is for debugging collisions 271 if (a.klass.type > b.klass.type || (a.klass.type == b.klass.type && a < b)) 272 { 273 cpShape* temp = a; 274 a = b; 275 b = temp; 276 } 277 278 // Narrow-phase collision detection. 279 cpContact* contacts = cpContactBufferGetArray(space); 280 int numContacts = cpCollideShapes(a, b, &id, contacts); 281 282 if (!numContacts) 283 return id; // Shapes are not colliding. 284 cpSpacePushContacts(space, numContacts); 285 286 // Get an arbiter from space.arbiterSet for the two shapes. 287 // This is where the persistant contact magic comes from. 288 cpShape*[2] shape_pair; 289 shape_pair[0] = a; 290 shape_pair[1] = b; 291 cpHashValue arbHashID = CP_HASH_PAIR(cast(cpHashValue)a, cast(cpHashValue)b); 292 cpArbiter * arb = cast(cpArbiter*)cpHashSetInsert(space.cachedArbiters, arbHashID, shape_pair.ptr, space, cast(cpHashSetTransFunc)&cpSpaceArbiterSetTrans); 293 cpArbiterUpdate(arb, contacts, numContacts, handler, a, b); 294 295 // Call the begin function first if it's the first step 296 if (arb.state == cpArbiterStateFirstColl && !handler.begin(arb, space, handler.data)) 297 { 298 cpArbiterIgnore(arb); // permanently ignore the collision until separation 299 } 300 301 if ( 302 303 // Ignore the arbiter if it has been flagged 304 (arb.state != cpArbiterStateIgnore) && 305 306 // Call preSolve 307 handler.preSolve(arb, space, handler.data) && 308 309 // Process, but don't add collisions for sensors. 310 !sensor 311 ) 312 { 313 cpArrayPush(space.arbiters, arb); 314 } 315 else 316 { 317 cpSpacePopContacts(space, numContacts); 318 319 arb.contacts = null; 320 arb.numContacts = 0; 321 322 // Normally arbiters are set as used after calling the post-solve callback. 323 // However, post-solve callbacks are not called for sensors or arbiters rejected from pre-solve. 324 if (arb.state != cpArbiterStateIgnore) 325 arb.state = cpArbiterStateNormal; 326 } 327 328 // Time stamp the arbiter so we know it was used recently. 329 arb.stamp = space.stamp; 330 return id; 331 } 332 333 // Hashset filter func to throw away old arbiters. 334 cpBool cpSpaceArbiterSetFilter(cpArbiter* arb, cpSpace* space) 335 { 336 cpTimestamp ticks = space.stamp - arb.stamp; 337 338 cpBody* a = arb.body_a; 339 cpBody* b = arb.body_b; 340 341 // TODO should make an arbiter state for this so it doesn't require filtering arbiters for dangling body pointers on body removal. 342 // Preserve arbiters on sensors and rejected arbiters for sleeping objects. 343 // This prevents errant separate callbacks from happenening. 344 if ( 345 (cpBodyIsStatic(a) || cpBodyIsSleeping(a)) && 346 (cpBodyIsStatic(b) || cpBodyIsSleeping(b)) 347 ) 348 { 349 return cpTrue; 350 } 351 352 // Arbiter was used last frame, but not this one 353 if (ticks >= 1 && arb.state != cpArbiterStateCached) 354 { 355 arb.state = cpArbiterStateCached; 356 cpArbiterCallSeparate(arb, space); 357 } 358 359 if (ticks >= space.collisionPersistence) 360 { 361 arb.contacts = null; 362 arb.numContacts = 0; 363 364 cpArrayPush(space.pooledArbiters, arb); 365 return cpFalse; 366 } 367 368 return cpTrue; 369 } 370 371 //MARK: All Important cpSpaceStep() Function 372 373 void cpShapeUpdateFunc(cpShape* shape, void* unused) 374 { 375 cpBody* body_ = shape.body_; 376 cpShapeUpdate(shape, body_.p, body_.rot); 377 } 378 379 void cpSpaceStep(cpSpace* space, cpFloat dt) 380 { 381 // don't step if the timestep is 0! 382 if (dt == 0.0f) 383 return; 384 385 space.stamp++; 386 387 cpFloat prev_dt = space.curr_dt; 388 space.curr_dt = dt; 389 390 cpArray* bodies = space.bodies; 391 cpArray* constraints = space.constraints; 392 cpArray* arbiters = space.arbiters; 393 394 // Reset and empty the arbiter lists. 395 for (int i = 0; i < arbiters.num; i++) 396 { 397 cpArbiter* arb = cast(cpArbiter*)arbiters.arr[i]; 398 arb.state = cpArbiterStateNormal; 399 400 // If both bodies are awake, unthread the arbiter from the contact graph. 401 if (!cpBodyIsSleeping(arb.body_a) && !cpBodyIsSleeping(arb.body_b)) 402 { 403 cpArbiterUnthread(arb); 404 } 405 } 406 407 arbiters.num = 0; 408 409 cpSpaceLock(space); 410 { 411 // Integrate positions 412 for (int i = 0; i < bodies.num; i++) 413 { 414 cpBody* body_ = cast(cpBody*)bodies.arr[i]; 415 body_.position_func(body_, dt); 416 } 417 418 // Find colliding pairs. 419 cpSpacePushFreshContactBuffer(space); 420 cpSpatialIndexEach(space.activeShapes, safeCast!cpSpatialIndexIteratorFunc(&cpShapeUpdateFunc), null); 421 cpSpatialIndexReindexQuery(space.activeShapes, safeCast!cpSpatialIndexQueryFunc(&cpSpaceCollideShapes), space); 422 } 423 cpSpaceUnlock(space, cpFalse); 424 425 // Rebuild the contact graph (and detect sleeping components if sleeping is enabled) 426 cpSpaceProcessComponents(space, dt); 427 428 cpSpaceLock(space); 429 { 430 // Clear out old cached arbiters and call separate callbacks 431 cpHashSetFilter(space.cachedArbiters, cast(cpHashSetFilterFunc)&cpSpaceArbiterSetFilter, space); 432 433 // Prestep the arbiters and constraints. 434 cpFloat slop = space.collisionSlop; 435 cpFloat biasCoef = 1.0f - cpfpow(space.collisionBias, dt); 436 437 for (int i = 0; i < arbiters.num; i++) 438 { 439 cpArbiterPreStep(cast(cpArbiter*)arbiters.arr[i], dt, slop, biasCoef); 440 } 441 442 for (int i = 0; i < constraints.num; i++) 443 { 444 cpConstraint* constraint = cast(cpConstraint*)constraints.arr[i]; 445 446 cpConstraintPreSolveFunc preSolve = constraint.preSolve; 447 448 if (preSolve) 449 preSolve(constraint, space); 450 451 constraint.klass.preStep(constraint, dt); 452 } 453 454 // Integrate velocities. 455 cpFloat damping = cpfpow(space.damping, dt); 456 cpVect gravity = space.gravity; 457 458 for (int i = 0; i < bodies.num; i++) 459 { 460 cpBody* body_ = cast(cpBody*)bodies.arr[i]; 461 body_.velocity_func(body_, gravity, damping, dt); 462 } 463 464 // Apply cached impulses 465 cpFloat dt_coef = (prev_dt == 0.0f ? 0.0f : dt / prev_dt); 466 467 for (int i = 0; i < arbiters.num; i++) 468 { 469 cpArbiterApplyCachedImpulse(cast(cpArbiter*)arbiters.arr[i], dt_coef); 470 } 471 472 for (int i = 0; i < constraints.num; i++) 473 { 474 cpConstraint* constraint = cast(cpConstraint*)constraints.arr[i]; 475 constraint.klass.applyCachedImpulse(constraint, dt_coef); 476 } 477 478 // Run the impulse solver. 479 for (int i = 0; i < space.iterations; i++) 480 { 481 for (int j = 0; j < arbiters.num; j++) 482 { 483 cpArbiterApplyImpulse(cast(cpArbiter*)arbiters.arr[j]); 484 } 485 486 for (int j = 0; j < constraints.num; j++) 487 { 488 cpConstraint* constraint = cast(cpConstraint*)constraints.arr[j]; 489 constraint.klass.applyImpulse(constraint, dt); 490 } 491 } 492 493 // Run the constraint post-solve callbacks 494 for (int i = 0; i < constraints.num; i++) 495 { 496 cpConstraint* constraint = cast(cpConstraint*)constraints.arr[i]; 497 498 cpConstraintPostSolveFunc postSolve = constraint.postSolve; 499 500 if (postSolve) 501 postSolve(constraint, space); 502 } 503 504 // run the post-solve callbacks 505 for (int i = 0; i < arbiters.num; i++) 506 { 507 cpArbiter* arb = cast(cpArbiter*)arbiters.arr[i]; 508 509 cpCollisionHandler* handler = arb.handler; 510 handler.postSolve(arb, space, handler.data); 511 } 512 } 513 cpSpaceUnlock(space, cpTrue); 514 }