chipmunk 4.1.0-x86-mswin32

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,120 @@
1
+ /* Copyright (c) 2007 Scott Lembcke
2
+ *
3
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ * of this software and associated documentation files (the "Software"), to deal
5
+ * in the Software without restriction, including without limitation the rights
6
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ * copies of the Software, and to permit persons to whom the Software is
8
+ * furnished to do so, subject to the following conditions:
9
+ *
10
+ * The above copyright notice and this permission notice shall be included in
11
+ * all copies or substantial portions of the Software.
12
+ *
13
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ * SOFTWARE.
20
+ */
21
+
22
+ // Number of frames that contact information should persist.
23
+ extern int cp_contact_persistence;
24
+
25
+ // User collision pair function.
26
+ typedef int (*cpCollFunc)(cpShape *a, cpShape *b, cpContact *contacts, int numContacts, cpFloat normal_coef, void *data);
27
+
28
+ // Structure for holding collision pair function information.
29
+ // Used internally.
30
+ typedef struct cpCollPairFunc {
31
+ unsigned int a;
32
+ unsigned int b;
33
+ cpCollFunc func;
34
+ void *data;
35
+ } cpCollPairFunc;
36
+
37
+ typedef struct cpSpace{
38
+ // *** User definable fields
39
+
40
+ // Number of iterations to use in the impulse solver to solve contacts.
41
+ int iterations;
42
+
43
+ // Number of iterations to use in the impulse solver to solve elastic collisions.
44
+ int elasticIterations;
45
+
46
+ // Default gravity to supply when integrating rigid body motions.
47
+ cpVect gravity;
48
+
49
+ // Default damping to supply when integrating rigid body motions.
50
+ cpFloat damping;
51
+
52
+ // *** Internally Used Fields
53
+
54
+ // Time stamp. Is incremented on every call to cpSpaceStep().
55
+ int stamp;
56
+
57
+ // The static and active shape spatial hashes.
58
+ cpSpaceHash *staticShapes;
59
+ cpSpaceHash *activeShapes;
60
+
61
+ // List of bodies in the system.
62
+ cpArray *bodies;
63
+ // List of active arbiters for the impulse solver.
64
+ cpArray *arbiters;
65
+ // Persistant contact set.
66
+ cpHashSet *contactSet;
67
+
68
+ // List of joints in the system.
69
+ cpArray *joints;
70
+
71
+ // Set of collisionpair functions.
72
+ cpHashSet *collFuncSet;
73
+ // Default collision pair function.
74
+ cpCollPairFunc defaultPairFunc;
75
+ } cpSpace;
76
+
77
+ // Basic allocation/destruction functions.
78
+ cpSpace* cpSpaceAlloc(void);
79
+ cpSpace* cpSpaceInit(cpSpace *space);
80
+ cpSpace* cpSpaceNew(void);
81
+
82
+ void cpSpaceDestroy(cpSpace *space);
83
+ void cpSpaceFree(cpSpace *space);
84
+
85
+ // Convenience function. Frees all referenced entities. (bodies, shapes and joints)
86
+ void cpSpaceFreeChildren(cpSpace *space);
87
+
88
+ // Collision pair function management functions.
89
+ void cpSpaceAddCollisionPairFunc(cpSpace *space, unsigned int a, unsigned int b,
90
+ cpCollFunc func, void *data);
91
+ void cpSpaceRemoveCollisionPairFunc(cpSpace *space, unsigned int a, unsigned int b);
92
+ void cpSpaceSetDefaultCollisionPairFunc(cpSpace *space, cpCollFunc func, void *data);
93
+
94
+ // Add and remove entities from the system.
95
+ void cpSpaceAddShape(cpSpace *space, cpShape *shape);
96
+ void cpSpaceAddStaticShape(cpSpace *space, cpShape *shape);
97
+ void cpSpaceAddBody(cpSpace *space, cpBody *body);
98
+ void cpSpaceAddJoint(cpSpace *space, cpJoint *joint);
99
+
100
+ void cpSpaceRemoveShape(cpSpace *space, cpShape *shape);
101
+ void cpSpaceRemoveStaticShape(cpSpace *space, cpShape *shape);
102
+ void cpSpaceRemoveBody(cpSpace *space, cpBody *body);
103
+ void cpSpaceRemoveJoint(cpSpace *space, cpJoint *joint);
104
+
105
+ // Point query callback function
106
+ typedef void (*cpSpacePointQueryFunc)(cpShape *shape, void *data);
107
+ void cpSpaceShapePointQuery(cpSpace *space, cpVect point, cpSpacePointQueryFunc func, void *data);
108
+ void cpSpaceStaticShapePointQuery(cpSpace *space, cpVect point, cpSpacePointQueryFunc func, void *data);
109
+
110
+ // Iterator function for iterating the bodies in a space.
111
+ typedef void (*cpSpaceBodyIterator)(cpBody *body, void *data);
112
+ void cpSpaceEachBody(cpSpace *space, cpSpaceBodyIterator func, void *data);
113
+
114
+ // Spatial hash management functions.
115
+ void cpSpaceResizeStaticHash(cpSpace *space, cpFloat dim, int count);
116
+ void cpSpaceResizeActiveHash(cpSpace *space, cpFloat dim, int count);
117
+ void cpSpaceRehashStatic(cpSpace *space);
118
+
119
+ // Update the space.
120
+ void cpSpaceStep(cpSpace *space, cpFloat dt);
@@ -0,0 +1,455 @@
1
+ /* Copyright (c) 2007 Scott Lembcke
2
+ *
3
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ * of this software and associated documentation files (the "Software"), to deal
5
+ * in the Software without restriction, including without limitation the rights
6
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ * copies of the Software, and to permit persons to whom the Software is
8
+ * furnished to do so, subject to the following conditions:
9
+ *
10
+ * The above copyright notice and this permission notice shall be included in
11
+ * all copies or substantial portions of the Software.
12
+ *
13
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ * SOFTWARE.
20
+ */
21
+
22
+ #include <stdlib.h>
23
+ #include <stdio.h>
24
+ #include <math.h>
25
+ #include <assert.h>
26
+
27
+ #include "chipmunk.h"
28
+ #include "prime.h"
29
+
30
+ static cpHandle*
31
+ cpHandleAlloc(void)
32
+ {
33
+ return (cpHandle *)malloc(sizeof(cpHandle));
34
+ }
35
+
36
+ static cpHandle*
37
+ cpHandleInit(cpHandle *hand, void *obj)
38
+ {
39
+ hand->obj = obj;
40
+ hand->retain = 0;
41
+ hand->stamp = 0;
42
+
43
+ return hand;
44
+ }
45
+
46
+ static cpHandle*
47
+ cpHandleNew(void *obj)
48
+ {
49
+ return cpHandleInit(cpHandleAlloc(), obj);
50
+ }
51
+
52
+ static inline void
53
+ cpHandleRetain(cpHandle *hand)
54
+ {
55
+ hand->retain++;
56
+ }
57
+
58
+ static inline void
59
+ cpHandleFree(cpHandle *hand)
60
+ {
61
+ free(hand);
62
+ }
63
+
64
+ static inline void
65
+ cpHandleRelease(cpHandle *hand)
66
+ {
67
+ hand->retain--;
68
+ if(hand->retain == 0)
69
+ cpHandleFree(hand);
70
+ }
71
+
72
+
73
+ cpSpaceHash*
74
+ cpSpaceHashAlloc(void)
75
+ {
76
+ return (cpSpaceHash *)calloc(1, sizeof(cpSpaceHash));
77
+ }
78
+
79
+ // Frees the old table, and allocates a new one.
80
+ static void
81
+ cpSpaceHashAllocTable(cpSpaceHash *hash, int numcells)
82
+ {
83
+ free(hash->table);
84
+
85
+ hash->numcells = numcells;
86
+ hash->table = (cpSpaceHashBin **)calloc(numcells, sizeof(cpSpaceHashBin *));
87
+ }
88
+
89
+ // Equality function for the handleset.
90
+ static int
91
+ handleSetEql(void *obj, void *elt)
92
+ {
93
+ cpHandle *hand = (cpHandle *)elt;
94
+ return (obj == hand->obj);
95
+ }
96
+
97
+ // Transformation function for the handleset.
98
+ static void *
99
+ handleSetTrans(void *obj, void *unused)
100
+ {
101
+ cpHandle *hand = cpHandleNew(obj);
102
+ cpHandleRetain(hand);
103
+
104
+ return hand;
105
+ }
106
+
107
+ cpSpaceHash*
108
+ cpSpaceHashInit(cpSpaceHash *hash, cpFloat celldim, int numcells, cpSpaceHashBBFunc bbfunc)
109
+ {
110
+ cpSpaceHashAllocTable(hash, next_prime(numcells));
111
+ hash->celldim = celldim;
112
+ hash->bbfunc = bbfunc;
113
+
114
+ hash->bins = NULL;
115
+ hash->handleSet = cpHashSetNew(0, &handleSetEql, &handleSetTrans);
116
+
117
+ hash->stamp = 1;
118
+
119
+ return hash;
120
+ }
121
+
122
+ cpSpaceHash*
123
+ cpSpaceHashNew(cpFloat celldim, int cells, cpSpaceHashBBFunc bbfunc)
124
+ {
125
+ return cpSpaceHashInit(cpSpaceHashAlloc(), celldim, cells, bbfunc);
126
+ }
127
+
128
+ static inline void
129
+ clearHashCell(cpSpaceHash *hash, int index)
130
+ {
131
+ cpSpaceHashBin *bin = hash->table[index];
132
+ while(bin){
133
+ cpSpaceHashBin *next = bin->next;
134
+
135
+ // Release the lock on the handle.
136
+ cpHandleRelease(bin->handle);
137
+ // Recycle the bin.
138
+ bin->next = hash->bins;
139
+ hash->bins = bin;
140
+
141
+ bin = next;
142
+ }
143
+
144
+ hash->table[index] = NULL;
145
+ }
146
+
147
+ // Clear all cells in the hashtable.
148
+ static void
149
+ clearHash(cpSpaceHash *hash)
150
+ {
151
+ for(int i=0; i<hash->numcells; i++)
152
+ clearHashCell(hash, i);
153
+ }
154
+
155
+ // Free the recycled hash bins.
156
+ static void
157
+ freeBins(cpSpaceHash *hash)
158
+ {
159
+ cpSpaceHashBin *bin = hash->bins;
160
+ while(bin){
161
+ cpSpaceHashBin *next = bin->next;
162
+ free(bin);
163
+ bin = next;
164
+ }
165
+ }
166
+
167
+ // Hashset iterator function to free the handles.
168
+ static void
169
+ handleFreeWrap(void *elt, void *unused)
170
+ {
171
+ cpHandle *hand = (cpHandle *)elt;
172
+ cpHandleFree(hand);
173
+ }
174
+
175
+ void
176
+ cpSpaceHashDestroy(cpSpaceHash *hash)
177
+ {
178
+ clearHash(hash);
179
+ freeBins(hash);
180
+
181
+ // Free the handles.
182
+ cpHashSetEach(hash->handleSet, &handleFreeWrap, NULL);
183
+ cpHashSetFree(hash->handleSet);
184
+
185
+ free(hash->table);
186
+ }
187
+
188
+ void
189
+ cpSpaceHashFree(cpSpaceHash *hash)
190
+ {
191
+ if(!hash) return;
192
+ cpSpaceHashDestroy(hash);
193
+ free(hash);
194
+ }
195
+
196
+ void
197
+ cpSpaceHashResize(cpSpaceHash *hash, cpFloat celldim, int numcells)
198
+ {
199
+ // Clear the hash to release the old handle locks.
200
+ clearHash(hash);
201
+
202
+ hash->celldim = celldim;
203
+ cpSpaceHashAllocTable(hash, next_prime(numcells));
204
+ }
205
+
206
+ // Return true if the chain contains the handle.
207
+ static inline int
208
+ containsHandle(cpSpaceHashBin *bin, cpHandle *hand)
209
+ {
210
+ while(bin){
211
+ if(bin->handle == hand) return 1;
212
+ bin = bin->next;
213
+ }
214
+
215
+ return 0;
216
+ }
217
+
218
+ // Get a recycled or new bin.
219
+ static inline cpSpaceHashBin *
220
+ getEmptyBin(cpSpaceHash *hash)
221
+ {
222
+ cpSpaceHashBin *bin = hash->bins;
223
+
224
+ // Make a new one if necessary.
225
+ if(bin == NULL) return (cpSpaceHashBin *)malloc(sizeof(cpSpaceHashBin));
226
+
227
+ hash->bins = bin->next;
228
+ return bin;
229
+ }
230
+
231
+ // The hash function itself.
232
+ static inline unsigned int
233
+ hash_func(unsigned int x, unsigned int y, unsigned int n)
234
+ {
235
+ return (x*2185031351ul ^ y*4232417593ul) % n;
236
+ }
237
+
238
+ static inline void
239
+ hashHandle(cpSpaceHash *hash, cpHandle *hand, cpBB bb)
240
+ {
241
+ // Find the dimensions in cell coordinates.
242
+ cpFloat dim = hash->celldim;
243
+ int l = bb.l/dim;
244
+ int r = bb.r/dim;
245
+ int b = bb.b/dim;
246
+ int t = bb.t/dim;
247
+
248
+ int n = hash->numcells;
249
+ for(int i=l; i<=r; i++){
250
+ for(int j=b; j<=t; j++){
251
+ int index = hash_func(i,j,n);
252
+ cpSpaceHashBin *bin = hash->table[index];
253
+
254
+ // Don't add an object twice to the same cell.
255
+ if(containsHandle(bin, hand)) continue;
256
+
257
+ cpHandleRetain(hand);
258
+ // Insert a new bin for the handle in this cell.
259
+ cpSpaceHashBin *newBin = getEmptyBin(hash);
260
+ newBin->handle = hand;
261
+ newBin->next = bin;
262
+ hash->table[index] = newBin;
263
+ }
264
+ }
265
+ }
266
+
267
+ void
268
+ cpSpaceHashInsert(cpSpaceHash *hash, void *obj, unsigned int id, cpBB bb)
269
+ {
270
+ cpHandle *hand = (cpHandle *)cpHashSetInsert(hash->handleSet, id, obj, NULL);
271
+ hashHandle(hash, hand, bb);
272
+ }
273
+
274
+ void
275
+ cpSpaceHashRehashObject(cpSpaceHash *hash, void *obj, unsigned int id)
276
+ {
277
+ cpHandle *hand = (cpHandle *)cpHashSetFind(hash->handleSet, id, obj);
278
+ hashHandle(hash, hand, hash->bbfunc(obj));
279
+ }
280
+
281
+ // Hashset iterator function for rehashing the spatial hash. (hash hash hash hash?)
282
+ static void
283
+ handleRehashHelper(void *elt, void *data)
284
+ {
285
+ cpHandle *hand = (cpHandle *)elt;
286
+ cpSpaceHash *hash = (cpSpaceHash *)data;
287
+
288
+ hashHandle(hash, hand, hash->bbfunc(hand->obj));
289
+ }
290
+
291
+ void
292
+ cpSpaceHashRehash(cpSpaceHash *hash)
293
+ {
294
+ clearHash(hash);
295
+
296
+ // Rehash all of the handles.
297
+ cpHashSetEach(hash->handleSet, &handleRehashHelper, hash);
298
+ }
299
+
300
+ void
301
+ cpSpaceHashRemove(cpSpaceHash *hash, void *obj, unsigned int id)
302
+ {
303
+ cpHandle *hand = (cpHandle *)cpHashSetRemove(hash->handleSet, id, obj);
304
+
305
+ if(hand){
306
+ hand->obj = NULL;
307
+ cpHandleRelease(hand);
308
+ }
309
+ }
310
+
311
+ // Used by the cpSpaceHashEach() iterator.
312
+ typedef struct eachPair {
313
+ cpSpaceHashIterator func;
314
+ void *data;
315
+ } eachPair;
316
+
317
+ // Calls the user iterator function. (Gross I know.)
318
+ static void
319
+ eachHelper(void *elt, void *data)
320
+ {
321
+ cpHandle *hand = (cpHandle *)elt;
322
+ eachPair *pair = (eachPair *)data;
323
+
324
+ pair->func(hand->obj, pair->data);
325
+ }
326
+
327
+ // Iterate over the objects in the spatial hash.
328
+ void
329
+ cpSpaceHashEach(cpSpaceHash *hash, cpSpaceHashIterator func, void *data)
330
+ {
331
+ // Bundle the callback up to send to the hashset iterator.
332
+ eachPair pair = {func, data};
333
+
334
+ cpHashSetEach(hash->handleSet, &eachHelper, &pair);
335
+ }
336
+
337
+ // Calls the callback function for the objects in a given chain.
338
+ static inline void
339
+ query(cpSpaceHash *hash, cpSpaceHashBin *bin, void *obj, cpSpaceHashQueryFunc func, void *data)
340
+ {
341
+ for(; bin; bin = bin->next){
342
+ cpHandle *hand = bin->handle;
343
+ void *other = hand->obj;
344
+
345
+ // Skip over certain conditions
346
+ if(
347
+ // Have we already tried this pair in this query?
348
+ hand->stamp == hash->stamp
349
+ // Is obj the same as other?
350
+ || obj == other
351
+ // Has other been removed since the last rehash?
352
+ || !other
353
+ ) continue;
354
+
355
+ func(obj, other, data);
356
+
357
+ // Stamp that the handle was checked already against this object.
358
+ hand->stamp = hash->stamp;
359
+ }
360
+ }
361
+
362
+ void
363
+ cpSpaceHashPointQuery(cpSpaceHash *hash, cpVect point, cpSpaceHashQueryFunc func, void *data)
364
+ {
365
+ cpFloat dim = hash->celldim;
366
+ int index = hash_func((int)(point.x/dim), (int)(point.y/dim), hash->numcells);
367
+
368
+ query(hash, hash->table[index], &point, func, data);
369
+
370
+ // Increment the stamp.
371
+ // Only one cell is checked, but query() requires it anyway.
372
+ hash->stamp++;
373
+ }
374
+
375
+ void
376
+ cpSpaceHashQuery(cpSpaceHash *hash, void *obj, cpBB bb, cpSpaceHashQueryFunc func, void *data)
377
+ {
378
+ // Get the dimensions in cell coordinates.
379
+ cpFloat dim = hash->celldim;
380
+ int l = bb.l/dim;
381
+ int r = bb.r/dim;
382
+ int b = bb.b/dim;
383
+ int t = bb.t/dim;
384
+
385
+ int n = hash->numcells;
386
+
387
+ // Iterate over the cells and query them.
388
+ for(int i=l; i<=r; i++){
389
+ for(int j=b; j<=t; j++){
390
+ int index = hash_func(i,j,n);
391
+ query(hash, hash->table[index], obj, func, data);
392
+ }
393
+ }
394
+
395
+ // Increment the stamp.
396
+ hash->stamp++;
397
+ }
398
+
399
+ // Similar to struct eachPair above.
400
+ typedef struct queryRehashPair {
401
+ cpSpaceHash *hash;
402
+ cpSpaceHashQueryFunc func;
403
+ void *data;
404
+ } queryRehashPair;
405
+
406
+ // Hashset iterator func used with cpSpaceHashQueryRehash().
407
+ static void
408
+ handleQueryRehashHelper(void *elt, void *data)
409
+ {
410
+ cpHandle *hand = (cpHandle *)elt;
411
+
412
+ // Unpack the user callback data.
413
+ queryRehashPair *pair = (queryRehashPair *)data;
414
+ cpSpaceHash *hash = pair->hash;
415
+ cpSpaceHashQueryFunc func = pair->func;
416
+
417
+ cpFloat dim = hash->celldim;
418
+ int n = hash->numcells;
419
+
420
+ void *obj = hand->obj;
421
+ cpBB bb = hash->bbfunc(obj);
422
+
423
+ int l = bb.l/dim;
424
+ int r = bb.r/dim;
425
+ int b = bb.b/dim;
426
+ int t = bb.t/dim;
427
+
428
+ for(int i=l; i<=r; i++){
429
+ for(int j=b; j<=t; j++){
430
+ int index = hash_func(i,j,n);
431
+ cpSpaceHashBin *bin = hash->table[index];
432
+
433
+ if(containsHandle(bin, hand)) continue;
434
+ query(hash, bin, obj, func, pair->data);
435
+
436
+ cpHandleRetain(hand);
437
+ cpSpaceHashBin *newBin = getEmptyBin(hash);
438
+ newBin->handle = hand;
439
+ newBin->next = bin;
440
+ hash->table[index] = newBin;
441
+ }
442
+ }
443
+
444
+ // Increment the stamp for each object we hash.
445
+ hash->stamp++;
446
+ }
447
+
448
+ void
449
+ cpSpaceHashQueryRehash(cpSpaceHash *hash, cpSpaceHashQueryFunc func, void *data)
450
+ {
451
+ clearHash(hash);
452
+
453
+ queryRehashPair pair = {hash, func, data};
454
+ cpHashSetEach(hash->handleSet, &handleQueryRehashHelper, &pair);
455
+ }