chipmunk 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+ }
@@ -0,0 +1,100 @@
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
+ // The spatial hash is Chipmunk's default (and currently only) spatial index type.
23
+ // Based on a chained hash table.
24
+
25
+ // Used internally to track objects added to the hash
26
+ typedef struct cpHandle{
27
+ // Pointer to the object
28
+ void *obj;
29
+ // Retain count
30
+ int retain;
31
+ // Query stamp. Used to make sure two objects
32
+ // aren't identified twice in the same query.
33
+ int stamp;
34
+ } cpHandle;
35
+
36
+ // Linked list element for in the chains.
37
+ typedef struct cpSpaceHashBin{
38
+ cpHandle *handle;
39
+ struct cpSpaceHashBin *next;
40
+ } cpSpaceHashBin;
41
+
42
+ // BBox callback. Called whenever the hash needs a bounding box from an object.
43
+ typedef cpBB (*cpSpaceHashBBFunc)(void *obj);
44
+
45
+ typedef struct cpSpaceHash{
46
+ // Number of cells in the table.
47
+ int numcells;
48
+ // Dimentions of the cells.
49
+ cpFloat celldim;
50
+
51
+ // BBox callback.
52
+ cpSpaceHashBBFunc bbfunc;
53
+
54
+ // Hashset of all the handles.
55
+ cpHashSet *handleSet;
56
+
57
+ cpSpaceHashBin **table;
58
+ // List of recycled bins.
59
+ cpSpaceHashBin *bins;
60
+
61
+ // Incremented on each query. See cpHandle.stamp.
62
+ int stamp;
63
+ } cpSpaceHash;
64
+
65
+ //Basic allocation/destruction functions.
66
+ cpSpaceHash *cpSpaceHashAlloc(void);
67
+ cpSpaceHash *cpSpaceHashInit(cpSpaceHash *hash, cpFloat celldim, int cells, cpSpaceHashBBFunc bbfunc);
68
+ cpSpaceHash *cpSpaceHashNew(cpFloat celldim, int cells, cpSpaceHashBBFunc bbfunc);
69
+
70
+ void cpSpaceHashDestroy(cpSpaceHash *hash);
71
+ void cpSpaceHashFree(cpSpaceHash *hash);
72
+
73
+ // Resize the hashtable. (Does not rehash! You must call cpSpaceHashRehash() if needed.)
74
+ void cpSpaceHashResize(cpSpaceHash *hash, cpFloat celldim, int numcells);
75
+
76
+ // Add an object to the hash.
77
+ void cpSpaceHashInsert(cpSpaceHash *hash, void *obj, unsigned int id, cpBB bb);
78
+ // Remove an object from the hash.
79
+ void cpSpaceHashRemove(cpSpaceHash *hash, void *obj, unsigned int id);
80
+
81
+ // Iterator function
82
+ typedef void (*cpSpaceHashIterator)(void *obj, void *data);
83
+ // Iterate over the objects in the hash.
84
+ void cpSpaceHashEach(cpSpaceHash *hash, cpSpaceHashIterator func, void *data);
85
+
86
+ // Rehash the contents of the hash.
87
+ void cpSpaceHashRehash(cpSpaceHash *hash);
88
+ // Rehash only a specific object.
89
+ void cpSpaceHashRehashObject(cpSpaceHash *hash, void *obj, unsigned int id);
90
+
91
+ // Query callback.
92
+ typedef int (*cpSpaceHashQueryFunc)(void *obj1, void *obj2, void *data);
93
+ // Point query the hash. A reference to the query point is passed as obj1 to the query callback.
94
+ void cpSpaceHashPointQuery(cpSpaceHash *hash, cpVect point, cpSpaceHashQueryFunc func, void *data);
95
+ // Query the hash for a given BBox.
96
+ void cpSpaceHashQuery(cpSpaceHash *hash, void *obj, cpBB bb, cpSpaceHashQueryFunc func, void *data);
97
+ // Run a query for the object, then insert it. (Optimized case)
98
+ void cpSpaceHashQueryInsert(cpSpaceHash *hash, void *obj, cpBB bb, cpSpaceHashQueryFunc func, void *data);
99
+ // Rehashes while querying for each object. (Optimized case)
100
+ void cpSpaceHashQueryRehash(cpSpaceHash *hash, cpSpaceHashQueryFunc func, void *data);
@@ -0,0 +1,63 @@
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 "stdio.h"
23
+ #include "math.h"
24
+
25
+ #include "chipmunk.h"
26
+
27
+ cpFloat
28
+ cpvlength(const cpVect v)
29
+ {
30
+ return sqrtf( cpvdot(v, v) );
31
+ }
32
+
33
+ cpFloat
34
+ cpvlengthsq(const cpVect v)
35
+ {
36
+ return cpvdot(v, v);
37
+ }
38
+
39
+ cpVect
40
+ cpvnormalize(const cpVect v)
41
+ {
42
+ return cpvmult( v, 1.0f/cpvlength(v) );
43
+ }
44
+
45
+ cpVect
46
+ cpvforangle(const cpFloat a)
47
+ {
48
+ return cpv(cos(a), sin(a));
49
+ }
50
+
51
+ cpFloat
52
+ cpvtoangle(const cpVect v)
53
+ {
54
+ return atan2(v.y, v.x);
55
+ }
56
+
57
+ char*
58
+ cpvstr(const cpVect v)
59
+ {
60
+ static char str[256];
61
+ sprintf(str, "(% .3f, % .3f)", v.x, v.y);
62
+ return str;
63
+ }
@@ -0,0 +1,106 @@
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
+ typedef struct cpVect{
23
+ cpFloat x,y;
24
+ } cpVect;
25
+
26
+ static const cpVect cpvzero={0.0f,0.0f};
27
+
28
+ static inline cpVect
29
+ cpv(const cpFloat x, const cpFloat y)
30
+ {
31
+ cpVect v = {x, y};
32
+ return v;
33
+ }
34
+
35
+ static inline cpVect
36
+ cpvadd(const cpVect v1, const cpVect v2)
37
+ {
38
+ return cpv(v1.x + v2.x, v1.y + v2.y);
39
+ }
40
+
41
+ static inline cpVect
42
+ cpvneg(const cpVect v)
43
+ {
44
+ return cpv(-v.x, -v.y);
45
+ }
46
+
47
+ static inline cpVect
48
+ cpvsub(const cpVect v1, const cpVect v2)
49
+ {
50
+ return cpv(v1.x - v2.x, v1.y - v2.y);
51
+ }
52
+
53
+ static inline cpVect
54
+ cpvmult(const cpVect v, const cpFloat s)
55
+ {
56
+ return cpv(v.x*s, v.y*s);
57
+ }
58
+
59
+ static inline cpFloat
60
+ cpvdot(const cpVect v1, const cpVect v2)
61
+ {
62
+ return v1.x*v2.x + v1.y*v2.y;
63
+ }
64
+
65
+ static inline cpFloat
66
+ cpvcross(const cpVect v1, const cpVect v2)
67
+ {
68
+ return v1.x*v2.y - v1.y*v2.x;
69
+ }
70
+
71
+ static inline cpVect
72
+ cpvperp(const cpVect v)
73
+ {
74
+ return cpv(-v.y, v.x);
75
+ }
76
+
77
+ static inline cpVect
78
+ cpvrperp(const cpVect v)
79
+ {
80
+ return cpv(v.y, -v.x);
81
+ }
82
+
83
+ static inline cpVect
84
+ cpvproject(const cpVect v1, const cpVect v2)
85
+ {
86
+ return cpvmult(v2, cpvdot(v1, v2)/cpvdot(v2, v2));
87
+ }
88
+
89
+ static inline cpVect
90
+ cpvrotate(const cpVect v1, const cpVect v2)
91
+ {
92
+ return cpv(v1.x*v2.x - v1.y*v2.y, v1.x*v2.y + v1.y*v2.x);
93
+ }
94
+
95
+ static inline cpVect
96
+ cpvunrotate(const cpVect v1, const cpVect v2)
97
+ {
98
+ return cpv(v1.x*v2.x + v1.y*v2.y, v1.y*v2.x - v1.x*v2.y);
99
+ }
100
+
101
+ cpFloat cpvlength(const cpVect v);
102
+ cpFloat cpvlengthsq(const cpVect v); // no sqrt() call
103
+ cpVect cpvnormalize(const cpVect v);
104
+ cpVect cpvforangle(const cpFloat a); // convert radians to a normalized vector
105
+ cpFloat cpvtoangle(const cpVect v); // convert a vector to radians
106
+ char *cpvstr(const cpVect v); // get a string representation of a vector