space.go 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789
  1. package tamias
  2. // Number of frames that contact information should persist.
  3. var CONTACT_PERSISTENCE = 1
  4. // User collision handler function types.
  5. type CollisionFunc func(arb * Arbiter, space * Space, data interface{}) (int)
  6. // Structure for holding collision pair function information.
  7. // Used internally.
  8. type CollisionHandler struct {
  9. a, b CollisionType
  10. begin, preSolve, postSolve, separate CollisionFunc
  11. data interface {}
  12. }
  13. const CP_MAX_CONTACTS_PER_ARBITER = 6
  14. type ContactBufferHeader struct {
  15. stamp int
  16. next * ContactBufferHeader
  17. numContacts uint
  18. }
  19. type CollisionFuncMap map[HashValue] CollisionFunc
  20. type ContactMap map[HashValue] Contact
  21. type Space struct {
  22. // *** User definable fields
  23. // Number of iterations to use in the impulse solver to solve contacts.
  24. Iterations int
  25. // Number of iterations to use in the impulse solver to solve elastic collisions.
  26. ElasticIterations int
  27. // Default gravity to supply when integrating rigid body motions.
  28. Gravity Vect
  29. // Default damping to supply when integrating rigid body motions.
  30. Damping Float
  31. // *** Internally Used Fields
  32. // When the space is locked, you should not add or remove objects;
  33. locked int
  34. // Time stamp. Is incremented on every call to cpSpaceStep().
  35. stamp int
  36. // The static and active shape spatial hashes.
  37. staticShapes SpaceHash
  38. activeShapes SpaceHash
  39. // List of bodies in the system.
  40. bodies *Array
  41. // List of active arbiters for the impulse solver.
  42. arbiters, pooledArbiters *Array;
  43. // Linked list ring of contact buffers.
  44. // Head is the current buffer. Tail is the oldest buffer.
  45. // The list points in the direction of tail.head.
  46. contactBuffersHead, contactBuffersTail *ContactBufferHeader;
  47. // List of buffers to be free()ed when destroying the space.
  48. // Not needed in Go
  49. // cpArray *allocatedBuffers;
  50. // Persistant contact set.
  51. contactSet ContactMap;
  52. // List of constraints in the system.
  53. constraints *Array;
  54. // Set of collisionpair functions.
  55. collFuncSet CollisionFuncMap;
  56. // Default collision handler.
  57. defaultHandler CollisionHandler;
  58. postStepCallbacks *HashSet;
  59. }
  60. /*
  61. type contactSet [2]*Shape;
  62. // Equal function for contactSet.
  63. func (set * contactSet) Equals(arbi interface {}) bool {
  64. arb, ok := arbi.(*Arbiter)
  65. if !ok { return false; }
  66. a := set[0]
  67. b := set[1]
  68. if a == arb.private_a && b == arb.private_b { return true }
  69. if b == arb.private_a && a == arb.private_b { return true }
  70. return false
  71. }
  72. // Transformation function for contactSet.
  73. // Not needed, I think.
  74. // contactSetTrans(cpShape **shapes, cpSpace *space)
  75. func (check * CollisionHandler) Equals(pairi interface {}) bool {
  76. pair, ok := pairi.(*CollisionHandler)
  77. if !ok { return false; }
  78. if pair.a == check.a && pair.b == check.b { return true }
  79. if pair.b == check.a && pair.a == check.b { return true }
  80. return false
  81. }
  82. type PostStepFunc func(obj, data interface{})
  83. type postStepCallback struct {
  84. fun PostStepFunc
  85. obj, data interface{}
  86. }
  87. func (a * postStepCallback) Equals(bi interface{}) bool {
  88. b, ok := arbi.(*CollisionHandler)
  89. if !ok { return false; }
  90. return a.obj == b.obj
  91. }
  92. // Default collision functions.
  93. func alwaysCollide(arb * Arbiter, space * Space, data interface{}) (int) {
  94. return 1;
  95. }
  96. func nothing(arb * Arbiter, space * Space, data interface{}) (int) {
  97. return 0;
  98. }
  99. func (shape * Shape) GetBB() (BB) {
  100. return shape.BB
  101. }
  102. const CONTACTS_BUFFER_SIZE = 100
  103. type ContactBuffer struct {
  104. header ContactBufferHeader;
  105. contacts [CONTACTS_BUFFER_SIZE]Contact;
  106. }
  107. func AllocContactBufferHeader() (*ContactBufferHeader) {
  108. return &ContactBufferHeader{}
  109. }
  110. func (header *ContactBufferHeader) Init(space * Space) (*ContactBufferHeader) {
  111. header.stamp = space.stamp
  112. header.next = space.contactBuffersTail
  113. header.numContacts = 0
  114. return header
  115. }
  116. func (header *ContactBufferHeader) ContactBufferHeaderNew(space * Space) (
  117. *ContactBufferHeader) {
  118. return AllocContactBufferHeader().Init(space)
  119. }
  120. func SpaceAlloc() (*Space) {
  121. return &Space{}
  122. }
  123. var DEFAULT_DIM_SIZE = Float(100.0)
  124. var DEFAULT_COUNT = 1000
  125. var DEFAULT_ITERATIONS = 10
  126. var DEFAULT_ELASTIC_ITERATIONS = 0
  127. var defaultHandler = CollisionHandler{ 0, 0, alwaysCollide, alwaysCollide, nothing, nothing, nil};
  128. func (space *Space) Init() (*Space) {
  129. space.iterations = DEFAULT_ITERATIONS
  130. space.elasticIterations = DEFAULT_ELASTIC_ITERATIONS
  131. space.Gravity = VZERO
  132. space.Damping = Float(1.0)
  133. space.locked = 0
  134. space.stamp = 0
  135. space.staticShapes = SpaceHashNew(DEFAULT_DIM_SIZE, DEFAULT_COUNT)
  136. space.activeShapes = SpaceHashNew(DEFAULT_DIM_SIZE, DEFAULT_COUNT)
  137. space.bodies = ArrayNew(0)
  138. space.arbiters = ArrayNew(0)
  139. space.pooledArbiters = ArrayNew(0)
  140. header := ContactBufferHeaderNew(space)
  141. space.contactBuffersTail= header
  142. space.contactBuffersHead= header
  143. header.next = header
  144. // set up ring buffer in cyclical way
  145. space.contactSet = make(ContactSet)
  146. space.constraints = ArrayNew(0)
  147. space.defaultHandler = defaultHandler
  148. space.collFuncSet = make(CollisionFuncMap)
  149. space.postStepCallbacks = HashSetNew(0)
  150. return space
  151. }
  152. func (space *Space) New() (*Space) {
  153. return SpaceAlloc().Init()
  154. }
  155. func (space * Space) AddCollisionHandler(a, b CollisionType,
  156. begin, preSolve, postSolve, separate CollisionFunc, data interface{}) {
  157. // Remove any old function so the new one will get added.
  158. space.RemoveCollisionHandler(space, a, b)
  159. handler = CollisionHandler { a , b, begin,
  160. presolve, postSolve, separate , data }
  161. space.collFuncSet[HASH_PAIR(a, b)] = &handler
  162. }
  163. func (space * Space)RemoveCollisionHandler(a, b CollisionType) {
  164. space.collFuncSet[HASH_PAIR(a, b)] = nil, false
  165. }
  166. func (space * Space) SetDefaultHandler( a, b CollisionType,
  167. begin, preSolve, postSolve, separate CollisionFunc, data interface{}) {
  168. // Remove any old function so the new one will get added.
  169. space.RemoveCollisionHandler(space, a, b)
  170. handler = CollisionHandler { a , b, begin,
  171. presolve, postSolve, separate , data }
  172. space.defaultHandler = &handler
  173. }
  174. func (space * Space) AssertUnlocked() {
  175. Assert(!space.locked, "This addition/removal cannot be done safely during a call to cpSpaceStep(). Put these calls into a Post Step Callback.")
  176. }
  177. func (space * Space) AddShape(shape * Shape) (* Shape) {
  178. Assert(shape.body != nil, "Cannot add a shape with a nil body.")
  179. old := space.activeShapes.Find(shape, shape.hashid)
  180. Assert(old == nil, "Cannot add the same shape more than once")
  181. space.AssertUnlocked()
  182. shape.CacheBB()
  183. space.activeShapes.Insert(shape, shape.hashid, shape.bb)
  184. return shape
  185. }
  186. func (space * Space) AddStaticShape(shape * Shape) (* Shape) {
  187. Assert(shape.body != nil, "Cannot add a static shape with a nil body.")
  188. old := space.staticShapes.Find(shape, shape.hashid)
  189. Assert(old == nil, "Cannot add the same static shape more than once")
  190. space.AssertUnlocked()
  191. shape.CacheBB()
  192. space.staticShapes.Insert(shape, shape.hashid, shape.bb)
  193. return shape
  194. }
  195. func (space * Space) AddBody(body * Body) (* Body) {
  196. Assert(!space.bodies.Contains(body),
  197. "Cannot add the same body more than once.")
  198. space.Bodies.Push(body)
  199. return body
  200. }
  201. func (space * Space) AddConstraint(constraint * Constraint) {
  202. Assert(!space.constraints.Contains(constraint), "Cannot add the same constraint more than once.")
  203. space.constraints.Push(constraint);
  204. return constraint;
  205. }
  206. typedef struct removalContext {
  207. cpSpace *space;
  208. cpShape *shape;
  209. } removalContext;
  210. // Hashset filter func to throw away old arbiters.
  211. static int
  212. contactSetFilterRemovedShape(cpArbiter *arb, removalContext *context)
  213. {
  214. if(context.shape == arb.private_a || context.shape == arb.private_b){
  215. arb.handler.separate(arb, context.space, arb.handler.data);
  216. cpArrayPush(context.space.pooledArbiters, arb);
  217. return 0;
  218. }
  219. return 1;
  220. }
  221. func (space * Space) RemoveShape(shape * Shape) {
  222. space.AssertUnlocked()
  223. for k, v := range space.contactSet {
  224. if shape == v.private_a || shape == v.private_b {
  225. v.handler.separate(v, space, v.handler.data)
  226. space.contactSet[k] = nil, false
  227. // remove all contacts of this shape
  228. }
  229. }
  230. space.activeShapes.Remove(shape, shape.hashid)
  231. }
  232. func (space * Space) RemoveStaticShape(shape * Shape) {
  233. space.AssertUnlocked()
  234. for k, v := range space.contactSet {
  235. if shape == v.private_a || shape == v.private_b {
  236. v.handler.separate(v, space, v.handler.data)
  237. space.contactSet[k] = nil, false
  238. // remove all contacts of this shape
  239. }
  240. }
  241. space.staticShapes.Remove(shape, shape.hashid)
  242. }
  243. func (space * Space) RemoveBody(body * Body) {
  244. space.AssertUnlocked()
  245. space.bodies.DeleteObj(body)
  246. }
  247. func (space * Space) RemoveConstraint(constraint * Constraint) {
  248. space.AssertUnlocked()
  249. space.constraints.DeleteObj(constraint)
  250. }
  251. func (space * Space) AddPostStepCallback(fun * PostStepFunc,
  252. obj, data interface{}) {
  253. callback := &postStepCallback{fun, obj, data};
  254. space.postStepCallbacks.Insert(callback, HashValue(obj))
  255. // BDM: This also sucks
  256. }
  257. func removeShape(shape * Shape, space * space) {
  258. space.RemoveShape(shape)
  259. }
  260. func (space * Space) PostStepRemoveShape(shape * shape) {
  261. shape.AddPostStepCallback(removeShape, shape, space)
  262. }
  263. type pointQueryContext struct {
  264. layers Layers;
  265. group Group;
  266. fun SpacePointQueryFunc;
  267. data interface{};
  268. }
  269. func pointQueryHelper(point * Vect, shape * Shape,
  270. context * pointQueryContext) (bool) {
  271. if shape.group > 0 && context.group == shape.group { return false }
  272. // no collision is in the same nonzero group
  273. if (context.layers & shape.layers) == 0 { return false }
  274. // no collision if in different, non-overlapping layers
  275. // call the callback if the shape responds true to the point query
  276. if shape.PointQuery(*point) {
  277. return context.fun(shape, context.data)
  278. }
  279. }
  280. func (space * Space) SpacePointQuery(point Vect, layers Layers,
  281. group Group, fun SpacePointQueryFunc, data interface{}) {
  282. context := pointQueryContext{layers, group, fun, data};
  283. space.activeShapes.PointQuery(point, pointQueryHelper, &context);
  284. space.staticShapes.PointQuery(point, pointQueryHelper, &context);
  285. }
  286. /*
  287. Allthis sucks a bit. Better recode it to be more Go-like
  288. static void
  289. rememberLastPointQuery(cpShape *shape, cpShape **outShape)
  290. {
  291. (*outShape) = shape;
  292. }
  293. cpShape *
  294. cpSpacePointQueryFirst(cpSpace *space, cpVect point, cpLayers layers, cpGroup group)
  295. {
  296. cpShape *shape = NULL;
  297. cpSpacePointQuery(space, point, layers, group, (cpSpacePointQueryFunc)rememberLastPointQuery, &shape);
  298. return shape;
  299. }
  300. */
  301. func (space * Space) EachBody() (chan *Body) {
  302. out := make(chan * Body)
  303. go func() {
  304. for i:=0; i < space.bodies.Size(); i++ {
  305. out <- space.bodies.Index(i).(*Body)
  306. }
  307. }()
  308. return out
  309. }
  310. /*
  311. typedef struct segQueryContext {
  312. cpVect start, end;
  313. cpLayers layers;
  314. cpGroup group;
  315. cpSpaceSegmentQueryFunc func;
  316. int anyCollision;
  317. } segQueryContext;
  318. static cpFloat
  319. segQueryFunc(segQueryContext *context, cpShape *shape, void *data)
  320. {
  321. cpSegmentQueryInfo info;
  322. if(
  323. !(shape.group && context.group == shape.group) && (context.layers&shape.layers) &&
  324. cpShapeSegmentQuery(shape, context.start, context.end, &info)
  325. ){
  326. if(context.func){
  327. context.func(shape, info.t, info.n, data);
  328. }
  329. context.anyCollision = 1;
  330. }
  331. return 1.0f;
  332. }
  333. int
  334. cpSpaceSegmentQuery(cpSpace *space, cpVect start, cpVect end, cpLayers layers, cpGroup group, cpSpaceSegmentQueryFunc func, void *data)
  335. {
  336. segQueryContext context = {
  337. start, end,
  338. layers, group,
  339. func,
  340. 0,
  341. };
  342. cpSpaceHashSegmentQuery(space.staticShapes, &context, start, end, 1.0f, (cpSpaceHashSegmentQueryFunc)segQueryFunc, data);
  343. cpSpaceHashSegmentQuery(space.activeShapes, &context, start, end, 1.0f, (cpSpaceHashSegmentQueryFunc)segQueryFunc, data);
  344. return context.anyCollision;
  345. }
  346. typedef struct segQueryFirstContext {
  347. cpVect start, end;
  348. cpLayers layers;
  349. cpGroup group;
  350. } segQueryFirstContext;
  351. static cpFloat
  352. segQueryFirst(segQueryFirstContext *context, cpShape *shape, cpSegmentQueryInfo *out)
  353. {
  354. cpSegmentQueryInfo info;// = {NULL, 1.0f, cpvzero};
  355. if(
  356. !(shape.group && context.group == shape.group) && (context.layers&shape.layers) &&
  357. cpShapeSegmentQuery(shape, context.start, context.end, &info)
  358. ){
  359. if(info.t < out.t){
  360. out.shape = info.shape;
  361. out.t = info.t;
  362. out.n = info.n;
  363. }
  364. return info.t;
  365. }
  366. return 1.0f;
  367. }
  368. cpShape *
  369. cpSpaceSegmentQueryFirst(cpSpace *space, cpVect start, cpVect end, cpLayers layers, cpGroup group, cpSegmentQueryInfo *out)
  370. {
  371. cpSegmentQueryInfo info = {NULL, 1.0f, cpvzero};
  372. if(out){
  373. (*out) = info;
  374. } else {
  375. out = &info;
  376. }
  377. out.t = 1.0f;
  378. segQueryFirstContext context = {
  379. start, end,
  380. layers, group
  381. };
  382. cpSpaceHashSegmentQuery(space.staticShapes, &context, start, end, 1.0f, (cpSpaceHashSegmentQueryFunc)segQueryFirst, out);
  383. cpSpaceHashSegmentQuery(space.activeShapes, &context, start, end, out.t, (cpSpaceHashSegmentQueryFunc)segQueryFirst, out);
  384. return out.shape;
  385. }
  386. #pragma mark BB Query functions
  387. typedef struct bbQueryContext {
  388. cpLayers layers;
  389. cpGroup group;
  390. cpSpaceBBQueryFunc func;
  391. void *data;
  392. } bbQueryContext;
  393. static void
  394. bbQueryHelper(cpBB *bb, cpShape *shape, bbQueryContext *context)
  395. {
  396. if(
  397. !(shape.group && context.group == shape.group) && (context.layers&shape.layers) &&
  398. cpBBintersects(*bb, shape.bb)
  399. ){
  400. context.func(shape, context.data);
  401. }
  402. }
  403. void
  404. cpSpaceBBQuery(cpSpace *space, cpBB bb, cpLayers layers, cpGroup group, cpSpaceBBQueryFunc func, void *data)
  405. {
  406. bbQueryContext context = {layers, group, func, data};
  407. cpSpaceHashQuery(space.activeShapes, &bb, bb, (cpSpaceHashQueryFunc)bbQueryHelper, &context);
  408. cpSpaceHashQuery(space.staticShapes, &bb, bb, (cpSpaceHashQueryFunc)bbQueryHelper, &context);
  409. }
  410. #pragma mark Spatial Hash Management
  411. // Iterator function used for updating shape BBoxes.
  412. static void
  413. updateBBCache(cpShape *shape, void *unused)
  414. {
  415. cpShapeCacheBB(shape);
  416. }
  417. void
  418. cpSpaceResizeStaticHash(cpSpace *space, cpFloat dim, int count)
  419. {
  420. cpSpaceHashResize(space.staticShapes, dim, count);
  421. cpSpaceHashRehash(space.staticShapes);
  422. }
  423. void
  424. cpSpaceResizeActiveHash(cpSpace *space, cpFloat dim, int count)
  425. {
  426. cpSpaceHashResize(space.activeShapes, dim, count);
  427. }
  428. void
  429. cpSpaceRehashStatic(cpSpace *space)
  430. {
  431. cpSpaceHashEach(space.staticShapes, (cpSpaceHashIterator)&updateBBCache, NULL);
  432. cpSpaceHashRehash(space.staticShapes);
  433. }
  434. #pragma mark Collision Detection Functions
  435. static cpContactBufferHeader *
  436. cpSpaceGetFreeContactBuffer(cpSpace *space)
  437. {
  438. if(space.stamp - space.contactBuffersTail.stamp > cp_contact_persistence){
  439. cpContactBufferHeader *header = space.contactBuffersTail;
  440. space.contactBuffersTail = header.next;
  441. return cpContactBufferHeaderInit(header, space);
  442. } else {
  443. cpContactBufferHeader *header = cpSpaceAllocContactBuffer(space);
  444. return cpContactBufferHeaderInit(header, space);
  445. }
  446. }
  447. static void
  448. cpSpacePushNewContactBuffer(cpSpace *space)
  449. {
  450. // for(cpContactBuffer *buffer = space.contactBuffersTail; buffer != space.contactBuffersHead; buffer = buffer.next){
  451. // printf("%p . ", buffer);
  452. // }
  453. // printf("%p (head)\n", space.contactBuffersHead);
  454. cpContactBufferHeader *buffer = cpSpaceGetFreeContactBuffer(space);
  455. space.contactBuffersHead.next = buffer;
  456. space.contactBuffersHead = buffer;
  457. }
  458. static inline int
  459. queryReject(cpShape *a, cpShape *b)
  460. {
  461. return
  462. // BBoxes must overlap
  463. !cpBBintersects(a.bb, b.bb)
  464. // Don't collide shapes attached to the same body.
  465. || a.body == b.body
  466. // Don't collide objects in the same non-zero group
  467. || (a.group && b.group && a.group == b.group)
  468. // Don't collide objects that don't share at least on layer.
  469. || !(a.layers & b.layers);
  470. }
  471. // Callback from the spatial hash.
  472. static void
  473. queryFunc(cpShape *a, cpShape *b, cpSpace *space)
  474. {
  475. // Reject any of the simple cases
  476. if(queryReject(a,b)) return;
  477. // Find the collision pair function for the shapes.
  478. struct{cpCollisionType a, b;} ids = {a.collision_type, b.collision_type};
  479. cpHashValue collHashID = CP_HASH_PAIR(a.collision_type, b.collision_type);
  480. cpCollisionHandler *handler = (cpCollisionHandler *)cpHashSetFind(space.collFuncSet, collHashID, &ids);
  481. int sensor = a.sensor || b.sensor;
  482. if(sensor && handler == &space.defaultHandler) return;
  483. // Shape 'a' should have the lower shape type. (required by cpCollideShapes() )
  484. if(a.klass.type > b.klass.type){
  485. cpShape *temp = a;
  486. a = b;
  487. b = temp;
  488. }
  489. if(space.contactBuffersHead.numContacts + CP_MAX_CONTACTS_PER_ARBITER > CP_CONTACTS_BUFFER_SIZE){
  490. // contact buffer could overflow on the next collision, push a fresh one.
  491. cpSpacePushNewContactBuffer(space);
  492. }
  493. // Narrow-phase collision detection.
  494. cpContact *contacts = ((cpContactBuffer *)(space.contactBuffersHead)).contacts + space.contactBuffersHead.numContacts;
  495. int numContacts = cpCollideShapes(a, b, contacts);
  496. if(!numContacts) return; // Shapes are not colliding.
  497. space.contactBuffersHead.numContacts += numContacts;
  498. // Get an arbiter from space.contactSet for the two shapes.
  499. // This is where the persistant contact magic comes from.
  500. cpShape *shape_pair[] = {a, b};
  501. cpHashValue arbHashID = CP_HASH_PAIR((size_t)a, (size_t)b);
  502. cpArbiter *arb = (cpArbiter *)cpHashSetInsert(space.contactSet, arbHashID, shape_pair, space);
  503. cpArbiterUpdate(arb, contacts, numContacts, handler, a, b); // retains the contacts array
  504. // Call the begin function first if it's the first step
  505. if(arb.stamp == -1 && !handler.begin(arb, space, handler.data)){
  506. cpArbiterIgnore(arb); // permanently ignore the collision until separation
  507. }
  508. if(
  509. // Ignore the arbiter if it has been flagged
  510. (arb.state != cpArbiterStateIgnore) &&
  511. // Call preSolve
  512. handler.preSolve(arb, space, handler.data) &&
  513. // Process, but don't add collisions for sensors.
  514. !sensor
  515. ){
  516. cpArrayPush(space.arbiters, arb);
  517. } else {
  518. // cpfree(arb.contacts);
  519. space.contactBuffersHead.numContacts -= numContacts;
  520. arb.contacts = NULL;
  521. arb.numContacts = 0;
  522. }
  523. // Time stamp the arbiter so we know it was used recently.
  524. arb.stamp = space.stamp;
  525. }
  526. // Iterator for active/static hash collisions.
  527. static void
  528. active2staticIter(cpShape *shape, cpSpace *space)
  529. {
  530. cpSpaceHashQuery(space.staticShapes, shape, shape.bb, (cpSpaceHashQueryFunc)queryFunc, space);
  531. }
  532. // Hashset filter func to throw away old arbiters.
  533. static int
  534. contactSetFilter(cpArbiter *arb, cpSpace *space)
  535. {
  536. int ticks = space.stamp - arb.stamp;
  537. // was used last frame, but not this one
  538. if(ticks == 1){
  539. arb.handler.separate(arb, space, arb.handler.data);
  540. arb.stamp = -1; // mark it as a new pair again.
  541. }
  542. if(ticks >= cp_contact_persistence){
  543. cpArrayPush(space.pooledArbiters, arb);
  544. return 0;
  545. }
  546. return 1;
  547. }
  548. // Hashset filter func to call and throw away post step callbacks.
  549. static int
  550. postStepCallbackSetFilter(postStepCallback *callback, cpSpace *space)
  551. {
  552. callback.func(space, callback.obj, callback.data);
  553. cpfree(callback);
  554. return 0;
  555. }
  556. #pragma mark All Important cpSpaceStep() Function
  557. void
  558. cpSpaceStep(cpSpace *space, cpFloat dt)
  559. {
  560. if(!dt) return; // don't step if the timestep is 0!
  561. cpFloat dt_inv = 1.0f/dt;
  562. cpArray *bodies = space.bodies;
  563. cpArray *constraints = space.constraints;
  564. space.locked = 1;
  565. // Empty the arbiter list.
  566. space.arbiters.num = 0;
  567. // Integrate positions.
  568. for(int i=0; i<bodies.num; i++){
  569. cpBody *body = (cpBody *)bodies.arr[i];
  570. body.position_func(body, dt);
  571. }
  572. // Pre-cache BBoxes and shape data.
  573. cpSpaceHashEach(space.activeShapes, (cpSpaceHashIterator)updateBBCache, NULL);
  574. // Collide!
  575. cpSpacePushNewContactBuffer(space);
  576. cpSpaceHashEach(space.activeShapes, (cpSpaceHashIterator)active2staticIter, space);
  577. cpSpaceHashQueryRehash(space.activeShapes, (cpSpaceHashQueryFunc)queryFunc, space);
  578. // Clear out old cached arbiters and dispatch untouch functions
  579. cpHashSetFilter(space.contactSet, (cpHashSetFilterFunc)contactSetFilter, space);
  580. // Prestep the arbiters.
  581. cpArray *arbiters = space.arbiters;
  582. for(int i=0; i<arbiters.num; i++)
  583. cpArbiterPreStep((cpArbiter *)arbiters.arr[i], dt_inv);
  584. // Prestep the constraints.
  585. for(int i=0; i<constraints.num; i++){
  586. cpConstraint *constraint = (cpConstraint *)constraints.arr[i];
  587. constraint.klass.preStep(constraint, dt, dt_inv);
  588. }
  589. for(int i=0; i<space.elasticIterations; i++){
  590. for(int j=0; j<arbiters.num; j++)
  591. cpArbiterApplyImpulse((cpArbiter *)arbiters.arr[j], 1.0f);
  592. for(int j=0; j<constraints.num; j++){
  593. cpConstraint *constraint = (cpConstraint *)constraints.arr[j];
  594. constraint.klass.applyImpulse(constraint);
  595. }
  596. }
  597. // Integrate velocities.
  598. cpFloat damping = cpfpow(1.0f/space.damping, -dt);
  599. for(int i=0; i<bodies.num; i++){
  600. cpBody *body = (cpBody *)bodies.arr[i];
  601. body.velocity_func(body, space.gravity, damping, dt);
  602. }
  603. for(int i=0; i<arbiters.num; i++)
  604. cpArbiterApplyCachedImpulse((cpArbiter *)arbiters.arr[i]);
  605. // run the old-style elastic solver if elastic iterations are disabled
  606. cpFloat elasticCoef = (space.elasticIterations ? 0.0f : 1.0f);
  607. // Run the impulse solver.
  608. for(int i=0; i<space.iterations; i++){
  609. for(int j=0; j<arbiters.num; j++)
  610. cpArbiterApplyImpulse((cpArbiter *)arbiters.arr[j], elasticCoef);
  611. for(int j=0; j<constraints.num; j++){
  612. cpConstraint *constraint = (cpConstraint *)constraints.arr[j];
  613. constraint.klass.applyImpulse(constraint);
  614. }
  615. }
  616. space.locked = 0;
  617. // run the post solve callbacks
  618. for(int i=0; i<arbiters.num; i++){
  619. cpArbiter *arb = arbiters.arr[i];
  620. cpCollisionHandler *handler = arb.handler;
  621. handler.postSolve(arb, space, handler.data);
  622. arb.state = cpArbiterStateNormal;
  623. }
  624. // Run the post step callbacks
  625. // Use filter as an easy way to clear out the queue as it runs
  626. cpHashSetFilter(space.postStepCallbacks, (cpHashSetFilterFunc)postStepCallbackSetFilter, space);
  627. // cpFloat dvsq = cpvdot(space.gravity, space.gravity);
  628. // dvsq *= dt*dt * space.damping*space.damping;
  629. // for(int i=0; i<bodies.num; i++)
  630. // cpBodyMarkLowEnergy(bodies.arr[i], dvsq, space.sleepTicks);
  631. // Increment the stamp.
  632. space.stamp++;
  633. }
  634. */