chipmunk 5.3.4.5 → 6.1.3.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- data/ext/chipmunk/chipmunk.c +199 -28
- data/ext/chipmunk/chipmunk.h +123 -68
- data/ext/chipmunk/chipmunk_ffi.h +129 -11
- data/ext/chipmunk/chipmunk_private.h +232 -16
- data/ext/chipmunk/chipmunk_types.h +94 -30
- data/ext/chipmunk/chipmunk_unsafe.h +12 -3
- data/ext/chipmunk/constraints/cpConstraint.h +90 -34
- data/ext/chipmunk/{cpDampedRotarySpring.h → constraints/cpDampedRotarySpring.h} +18 -8
- data/ext/chipmunk/{cpDampedSpring.h → constraints/cpDampedSpring.h} +27 -16
- data/ext/chipmunk/constraints/cpGearJoint.h +17 -7
- data/ext/chipmunk/constraints/cpGrooveJoint.h +19 -10
- data/ext/chipmunk/constraints/cpPinJoint.h +17 -8
- data/ext/chipmunk/constraints/cpPivotJoint.h +18 -9
- data/ext/chipmunk/constraints/cpRatchetJoint.h +17 -8
- data/ext/chipmunk/constraints/cpRotaryLimitJoint.h +16 -7
- data/ext/chipmunk/{cpSimpleMotor.h → constraints/cpSimpleMotor.h} +15 -6
- data/ext/chipmunk/constraints/cpSlideJoint.h +18 -9
- data/ext/chipmunk/constraints/util.h +36 -44
- data/ext/chipmunk/cpArbiter.c +159 -94
- data/ext/chipmunk/cpArbiter.h +135 -129
- data/ext/chipmunk/cpArray.c +37 -56
- data/ext/chipmunk/cpBB.c +1 -12
- data/ext/chipmunk/cpBB.h +80 -18
- data/ext/chipmunk/cpBBTree.c +891 -0
- data/ext/chipmunk/cpBody.c +185 -47
- data/ext/chipmunk/cpBody.h +156 -124
- data/ext/chipmunk/cpCollision.c +126 -115
- data/ext/chipmunk/cpConstraint.c +10 -6
- data/ext/chipmunk/cpDampedRotarySpring.c +26 -17
- data/ext/chipmunk/cpDampedSpring.c +25 -18
- data/ext/chipmunk/cpGearJoint.c +23 -17
- data/ext/chipmunk/cpGrooveJoint.c +26 -22
- data/ext/chipmunk/cpHashSet.c +51 -51
- data/ext/chipmunk/cpPinJoint.c +26 -19
- data/ext/chipmunk/cpPivotJoint.c +23 -19
- data/ext/chipmunk/cpPolyShape.c +93 -69
- data/ext/chipmunk/cpPolyShape.h +33 -69
- data/ext/chipmunk/cpRatchetJoint.c +26 -21
- data/ext/chipmunk/cpRotaryLimitJoint.c +28 -22
- data/ext/chipmunk/cpShape.c +122 -133
- data/ext/chipmunk/cpShape.h +146 -95
- data/ext/chipmunk/cpSimpleMotor.c +24 -17
- data/ext/chipmunk/cpSlideJoint.c +28 -26
- data/ext/chipmunk/cpSpace.c +251 -196
- data/ext/chipmunk/cpSpace.h +173 -103
- data/ext/chipmunk/cpSpaceComponent.c +236 -159
- data/ext/chipmunk/cpSpaceHash.c +259 -159
- data/ext/chipmunk/cpSpaceQuery.c +127 -59
- data/ext/chipmunk/cpSpaceStep.c +235 -197
- data/ext/chipmunk/cpSpatialIndex.c +69 -0
- data/ext/chipmunk/cpSpatialIndex.h +227 -0
- data/ext/chipmunk/cpSweep1D.c +254 -0
- data/ext/chipmunk/cpVect.c +11 -26
- data/ext/chipmunk/cpVect.h +76 -71
- data/ext/chipmunk/extconf.rb +4 -31
- data/ext/chipmunk/prime.h +1 -1
- data/ext/chipmunk/rb_chipmunk.c +36 -45
- data/ext/chipmunk/rb_chipmunk.h +6 -3
- data/ext/chipmunk/rb_cpArbiter.c +2 -2
- data/ext/chipmunk/rb_cpBB.c +116 -35
- data/ext/chipmunk/rb_cpBody.c +5 -12
- data/ext/chipmunk/rb_cpConstraint.c +144 -9
- data/ext/chipmunk/rb_cpShape.c +69 -78
- data/ext/chipmunk/rb_cpSpace.c +81 -76
- metadata +61 -61
- data/LICENSE +0 -22
- data/README +0 -110
- data/Rakefile +0 -102
- data/ext/chipmunk/cpArray.h +0 -49
- data/ext/chipmunk/cpCollision.h +0 -28
- data/ext/chipmunk/cpHashSet.h +0 -82
- data/ext/chipmunk/cpSpaceHash.h +0 -110
- data/lib/chipmunk.rb +0 -194
@@ -0,0 +1,69 @@
|
|
1
|
+
/* Copyright (c) 2010 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 "chipmunk_private.h"
|
23
|
+
|
24
|
+
void
|
25
|
+
cpSpatialIndexFree(cpSpatialIndex *index)
|
26
|
+
{
|
27
|
+
if(index){
|
28
|
+
cpSpatialIndexDestroy(index);
|
29
|
+
cpfree(index);
|
30
|
+
}
|
31
|
+
}
|
32
|
+
|
33
|
+
cpSpatialIndex *
|
34
|
+
cpSpatialIndexInit(cpSpatialIndex *index, cpSpatialIndexClass *klass, cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex)
|
35
|
+
{
|
36
|
+
index->klass = klass;
|
37
|
+
index->bbfunc = bbfunc;
|
38
|
+
index->staticIndex = staticIndex;
|
39
|
+
|
40
|
+
if(staticIndex){
|
41
|
+
cpAssertHard(!staticIndex->dynamicIndex, "This static index is already associated with a dynamic index.");
|
42
|
+
staticIndex->dynamicIndex = index;
|
43
|
+
}
|
44
|
+
|
45
|
+
return index;
|
46
|
+
}
|
47
|
+
|
48
|
+
typedef struct dynamicToStaticContext {
|
49
|
+
cpSpatialIndexBBFunc bbfunc;
|
50
|
+
cpSpatialIndex *staticIndex;
|
51
|
+
cpSpatialIndexQueryFunc queryFunc;
|
52
|
+
void *data;
|
53
|
+
} dynamicToStaticContext;
|
54
|
+
|
55
|
+
static void
|
56
|
+
dynamicToStaticIter(void *obj, dynamicToStaticContext *context)
|
57
|
+
{
|
58
|
+
cpSpatialIndexQuery(context->staticIndex, obj, context->bbfunc(obj), context->queryFunc, context->data);
|
59
|
+
}
|
60
|
+
|
61
|
+
void
|
62
|
+
cpSpatialIndexCollideStatic(cpSpatialIndex *dynamicIndex, cpSpatialIndex *staticIndex, cpSpatialIndexQueryFunc func, void *data)
|
63
|
+
{
|
64
|
+
if(staticIndex && cpSpatialIndexCount(staticIndex) > 0){
|
65
|
+
dynamicToStaticContext context = {dynamicIndex->bbfunc, staticIndex, func, data};
|
66
|
+
cpSpatialIndexEach(dynamicIndex, (cpSpatialIndexIteratorFunc)dynamicToStaticIter, &context);
|
67
|
+
}
|
68
|
+
}
|
69
|
+
|
@@ -0,0 +1,227 @@
|
|
1
|
+
/* Copyright (c) 2010 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
|
+
/**
|
23
|
+
@defgroup cpSpatialIndex cpSpatialIndex
|
24
|
+
|
25
|
+
Spatial indexes are data structures that are used to accelerate collision detection
|
26
|
+
and spatial queries. Chipmunk provides a number of spatial index algorithms to pick from
|
27
|
+
and they are programmed in a generic way so that you can use them for holding more than
|
28
|
+
just cpShape structs.
|
29
|
+
|
30
|
+
It works by using @c void pointers to the objects you add and using a callback to ask your code
|
31
|
+
for bounding boxes when it needs them. Several types of queries can be performed an index as well
|
32
|
+
as reindexing and full collision information. All communication to the spatial indexes is performed
|
33
|
+
through callback functions.
|
34
|
+
|
35
|
+
Spatial indexes should be treated as opaque structs.
|
36
|
+
This meanns you shouldn't be reading any of the struct fields.
|
37
|
+
@{
|
38
|
+
*/
|
39
|
+
|
40
|
+
//MARK: Spatial Index
|
41
|
+
|
42
|
+
/// Spatial index bounding box callback function type.
|
43
|
+
/// The spatial index calls this function and passes you a pointer to an object you added
|
44
|
+
/// when it needs to get the bounding box associated with that object.
|
45
|
+
typedef cpBB (*cpSpatialIndexBBFunc)(void *obj);
|
46
|
+
/// Spatial index/object iterator callback function type.
|
47
|
+
typedef void (*cpSpatialIndexIteratorFunc)(void *obj, void *data);
|
48
|
+
/// Spatial query callback function type.
|
49
|
+
typedef void (*cpSpatialIndexQueryFunc)(void *obj1, void *obj2, void *data);
|
50
|
+
/// Spatial segment query callback function type.
|
51
|
+
typedef cpFloat (*cpSpatialIndexSegmentQueryFunc)(void *obj1, void *obj2, void *data);
|
52
|
+
|
53
|
+
|
54
|
+
typedef struct cpSpatialIndexClass cpSpatialIndexClass;
|
55
|
+
typedef struct cpSpatialIndex cpSpatialIndex;
|
56
|
+
|
57
|
+
/// @private
|
58
|
+
struct cpSpatialIndex {
|
59
|
+
cpSpatialIndexClass *klass;
|
60
|
+
|
61
|
+
cpSpatialIndexBBFunc bbfunc;
|
62
|
+
|
63
|
+
cpSpatialIndex *staticIndex, *dynamicIndex;
|
64
|
+
};
|
65
|
+
|
66
|
+
|
67
|
+
//MARK: Spatial Hash
|
68
|
+
|
69
|
+
typedef struct cpSpaceHash cpSpaceHash;
|
70
|
+
|
71
|
+
/// Allocate a spatial hash.
|
72
|
+
cpSpaceHash* cpSpaceHashAlloc(void);
|
73
|
+
/// Initialize a spatial hash.
|
74
|
+
cpSpatialIndex* cpSpaceHashInit(cpSpaceHash *hash, cpFloat celldim, int numcells, cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex);
|
75
|
+
/// Allocate and initialize a spatial hash.
|
76
|
+
cpSpatialIndex* cpSpaceHashNew(cpFloat celldim, int cells, cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex);
|
77
|
+
|
78
|
+
/// Change the cell dimensions and table size of the spatial hash to tune it.
|
79
|
+
/// The cell dimensions should roughly match the average size of your objects
|
80
|
+
/// and the table size should be ~10 larger than the number of objects inserted.
|
81
|
+
/// Some trial and error is required to find the optimum numbers for efficiency.
|
82
|
+
void cpSpaceHashResize(cpSpaceHash *hash, cpFloat celldim, int numcells);
|
83
|
+
|
84
|
+
//MARK: AABB Tree
|
85
|
+
|
86
|
+
typedef struct cpBBTree cpBBTree;
|
87
|
+
|
88
|
+
/// Allocate a bounding box tree.
|
89
|
+
cpBBTree* cpBBTreeAlloc(void);
|
90
|
+
/// Initialize a bounding box tree.
|
91
|
+
cpSpatialIndex* cpBBTreeInit(cpBBTree *tree, cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex);
|
92
|
+
/// Allocate and initialize a bounding box tree.
|
93
|
+
cpSpatialIndex* cpBBTreeNew(cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex);
|
94
|
+
|
95
|
+
/// Perform a static top down optimization of the tree.
|
96
|
+
void cpBBTreeOptimize(cpSpatialIndex *index);
|
97
|
+
|
98
|
+
/// Bounding box tree velocity callback function.
|
99
|
+
/// This function should return an estimate for the object's velocity.
|
100
|
+
typedef cpVect (*cpBBTreeVelocityFunc)(void *obj);
|
101
|
+
/// Set the velocity function for the bounding box tree to enable temporal coherence.
|
102
|
+
void cpBBTreeSetVelocityFunc(cpSpatialIndex *index, cpBBTreeVelocityFunc func);
|
103
|
+
|
104
|
+
//MARK: Single Axis Sweep
|
105
|
+
|
106
|
+
typedef struct cpSweep1D cpSweep1D;
|
107
|
+
|
108
|
+
/// Allocate a 1D sort and sweep broadphase.
|
109
|
+
cpSweep1D* cpSweep1DAlloc(void);
|
110
|
+
/// Initialize a 1D sort and sweep broadphase.
|
111
|
+
cpSpatialIndex* cpSweep1DInit(cpSweep1D *sweep, cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex);
|
112
|
+
/// Allocate and initialize a 1D sort and sweep broadphase.
|
113
|
+
cpSpatialIndex* cpSweep1DNew(cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex);
|
114
|
+
|
115
|
+
//MARK: Spatial Index Implementation
|
116
|
+
|
117
|
+
typedef void (*cpSpatialIndexDestroyImpl)(cpSpatialIndex *index);
|
118
|
+
|
119
|
+
typedef int (*cpSpatialIndexCountImpl)(cpSpatialIndex *index);
|
120
|
+
typedef void (*cpSpatialIndexEachImpl)(cpSpatialIndex *index, cpSpatialIndexIteratorFunc func, void *data);
|
121
|
+
|
122
|
+
typedef cpBool (*cpSpatialIndexContainsImpl)(cpSpatialIndex *index, void *obj, cpHashValue hashid);
|
123
|
+
typedef void (*cpSpatialIndexInsertImpl)(cpSpatialIndex *index, void *obj, cpHashValue hashid);
|
124
|
+
typedef void (*cpSpatialIndexRemoveImpl)(cpSpatialIndex *index, void *obj, cpHashValue hashid);
|
125
|
+
|
126
|
+
typedef void (*cpSpatialIndexReindexImpl)(cpSpatialIndex *index);
|
127
|
+
typedef void (*cpSpatialIndexReindexObjectImpl)(cpSpatialIndex *index, void *obj, cpHashValue hashid);
|
128
|
+
typedef void (*cpSpatialIndexReindexQueryImpl)(cpSpatialIndex *index, cpSpatialIndexQueryFunc func, void *data);
|
129
|
+
|
130
|
+
typedef void (*cpSpatialIndexQueryImpl)(cpSpatialIndex *index, void *obj, cpBB bb, cpSpatialIndexQueryFunc func, void *data);
|
131
|
+
typedef void (*cpSpatialIndexSegmentQueryImpl)(cpSpatialIndex *index, void *obj, cpVect a, cpVect b, cpFloat t_exit, cpSpatialIndexSegmentQueryFunc func, void *data);
|
132
|
+
|
133
|
+
struct cpSpatialIndexClass {
|
134
|
+
cpSpatialIndexDestroyImpl destroy;
|
135
|
+
|
136
|
+
cpSpatialIndexCountImpl count;
|
137
|
+
cpSpatialIndexEachImpl each;
|
138
|
+
|
139
|
+
cpSpatialIndexContainsImpl contains;
|
140
|
+
cpSpatialIndexInsertImpl insert;
|
141
|
+
cpSpatialIndexRemoveImpl remove;
|
142
|
+
|
143
|
+
cpSpatialIndexReindexImpl reindex;
|
144
|
+
cpSpatialIndexReindexObjectImpl reindexObject;
|
145
|
+
cpSpatialIndexReindexQueryImpl reindexQuery;
|
146
|
+
|
147
|
+
cpSpatialIndexQueryImpl query;
|
148
|
+
cpSpatialIndexSegmentQueryImpl segmentQuery;
|
149
|
+
};
|
150
|
+
|
151
|
+
/// Destroy and free a spatial index.
|
152
|
+
void cpSpatialIndexFree(cpSpatialIndex *index);
|
153
|
+
/// Collide the objects in @c dynamicIndex against the objects in @c staticIndex using the query callback function.
|
154
|
+
void cpSpatialIndexCollideStatic(cpSpatialIndex *dynamicIndex, cpSpatialIndex *staticIndex, cpSpatialIndexQueryFunc func, void *data);
|
155
|
+
|
156
|
+
/// Destroy a spatial index.
|
157
|
+
static inline void cpSpatialIndexDestroy(cpSpatialIndex *index)
|
158
|
+
{
|
159
|
+
if(index->klass) index->klass->destroy(index);
|
160
|
+
}
|
161
|
+
|
162
|
+
/// Get the number of objects in the spatial index.
|
163
|
+
static inline int cpSpatialIndexCount(cpSpatialIndex *index)
|
164
|
+
{
|
165
|
+
return index->klass->count(index);
|
166
|
+
}
|
167
|
+
|
168
|
+
/// Iterate the objects in the spatial index. @c func will be called once for each object.
|
169
|
+
static inline void cpSpatialIndexEach(cpSpatialIndex *index, cpSpatialIndexIteratorFunc func, void *data)
|
170
|
+
{
|
171
|
+
index->klass->each(index, func, data);
|
172
|
+
}
|
173
|
+
|
174
|
+
/// Returns true if the spatial index contains the given object.
|
175
|
+
/// Most spatial indexes use hashed storage, so you must provide a hash value too.
|
176
|
+
static inline cpBool cpSpatialIndexContains(cpSpatialIndex *index, void *obj, cpHashValue hashid)
|
177
|
+
{
|
178
|
+
return index->klass->contains(index, obj, hashid);
|
179
|
+
}
|
180
|
+
|
181
|
+
/// Add an object to a spatial index.
|
182
|
+
/// Most spatial indexes use hashed storage, so you must provide a hash value too.
|
183
|
+
static inline void cpSpatialIndexInsert(cpSpatialIndex *index, void *obj, cpHashValue hashid)
|
184
|
+
{
|
185
|
+
index->klass->insert(index, obj, hashid);
|
186
|
+
}
|
187
|
+
|
188
|
+
/// Remove an object from a spatial index.
|
189
|
+
/// Most spatial indexes use hashed storage, so you must provide a hash value too.
|
190
|
+
static inline void cpSpatialIndexRemove(cpSpatialIndex *index, void *obj, cpHashValue hashid)
|
191
|
+
{
|
192
|
+
index->klass->remove(index, obj, hashid);
|
193
|
+
}
|
194
|
+
|
195
|
+
/// Perform a full reindex of a spatial index.
|
196
|
+
static inline void cpSpatialIndexReindex(cpSpatialIndex *index)
|
197
|
+
{
|
198
|
+
index->klass->reindex(index);
|
199
|
+
}
|
200
|
+
|
201
|
+
/// Reindex a single object in the spatial index.
|
202
|
+
static inline void cpSpatialIndexReindexObject(cpSpatialIndex *index, void *obj, cpHashValue hashid)
|
203
|
+
{
|
204
|
+
index->klass->reindexObject(index, obj, hashid);
|
205
|
+
}
|
206
|
+
|
207
|
+
/// Perform a rectangle query against the spatial index, calling @c func for each potential match.
|
208
|
+
static inline void cpSpatialIndexQuery(cpSpatialIndex *index, void *obj, cpBB bb, cpSpatialIndexQueryFunc func, void *data)
|
209
|
+
{
|
210
|
+
index->klass->query(index, obj, bb, func, data);
|
211
|
+
}
|
212
|
+
|
213
|
+
/// Perform a segment query against the spatial index, calling @c func for each potential match.
|
214
|
+
static inline void cpSpatialIndexSegmentQuery(cpSpatialIndex *index, void *obj, cpVect a, cpVect b, cpFloat t_exit, cpSpatialIndexSegmentQueryFunc func, void *data)
|
215
|
+
{
|
216
|
+
index->klass->segmentQuery(index, obj, a, b, t_exit, func, data);
|
217
|
+
}
|
218
|
+
|
219
|
+
/// Simultaneously reindex and find all colliding objects.
|
220
|
+
/// @c func will be called once for each potentially overlapping pair of objects found.
|
221
|
+
/// If the spatial index was initialized with a static index, it will collide it's objects against that as well.
|
222
|
+
static inline void cpSpatialIndexReindexQuery(cpSpatialIndex *index, cpSpatialIndexQueryFunc func, void *data)
|
223
|
+
{
|
224
|
+
index->klass->reindexQuery(index, func, data);
|
225
|
+
}
|
226
|
+
|
227
|
+
///@}
|
@@ -0,0 +1,254 @@
|
|
1
|
+
/* Copyright (c) 2010 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 "chipmunk_private.h"
|
23
|
+
|
24
|
+
static inline cpSpatialIndexClass *Klass();
|
25
|
+
|
26
|
+
//MARK: Basic Structures
|
27
|
+
|
28
|
+
typedef struct Bounds {
|
29
|
+
cpFloat min, max;
|
30
|
+
} Bounds;
|
31
|
+
|
32
|
+
typedef struct TableCell {
|
33
|
+
void *obj;
|
34
|
+
Bounds bounds;
|
35
|
+
} TableCell;
|
36
|
+
|
37
|
+
struct cpSweep1D
|
38
|
+
{
|
39
|
+
cpSpatialIndex spatialIndex;
|
40
|
+
|
41
|
+
int num;
|
42
|
+
int max;
|
43
|
+
TableCell *table;
|
44
|
+
};
|
45
|
+
|
46
|
+
static inline cpBool
|
47
|
+
BoundsOverlap(Bounds a, Bounds b)
|
48
|
+
{
|
49
|
+
return (a.min <= b.max && b.min <= a.max);
|
50
|
+
}
|
51
|
+
|
52
|
+
static inline Bounds
|
53
|
+
BBToBounds(cpSweep1D *sweep, cpBB bb)
|
54
|
+
{
|
55
|
+
Bounds bounds = {bb.l, bb.r};
|
56
|
+
return bounds;
|
57
|
+
}
|
58
|
+
|
59
|
+
static inline TableCell
|
60
|
+
MakeTableCell(cpSweep1D *sweep, void *obj)
|
61
|
+
{
|
62
|
+
TableCell cell = {obj, BBToBounds(sweep, sweep->spatialIndex.bbfunc(obj))};
|
63
|
+
return cell;
|
64
|
+
}
|
65
|
+
|
66
|
+
//MARK: Memory Management Functions
|
67
|
+
|
68
|
+
cpSweep1D *
|
69
|
+
cpSweep1DAlloc(void)
|
70
|
+
{
|
71
|
+
return (cpSweep1D *)cpcalloc(1, sizeof(cpSweep1D));
|
72
|
+
}
|
73
|
+
|
74
|
+
static void
|
75
|
+
ResizeTable(cpSweep1D *sweep, int size)
|
76
|
+
{
|
77
|
+
sweep->max = size;
|
78
|
+
sweep->table = (TableCell *)cprealloc(sweep->table, size*sizeof(TableCell));
|
79
|
+
}
|
80
|
+
|
81
|
+
cpSpatialIndex *
|
82
|
+
cpSweep1DInit(cpSweep1D *sweep, cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex)
|
83
|
+
{
|
84
|
+
cpSpatialIndexInit((cpSpatialIndex *)sweep, Klass(), bbfunc, staticIndex);
|
85
|
+
|
86
|
+
sweep->num = 0;
|
87
|
+
ResizeTable(sweep, 32);
|
88
|
+
|
89
|
+
return (cpSpatialIndex *)sweep;
|
90
|
+
}
|
91
|
+
|
92
|
+
cpSpatialIndex *
|
93
|
+
cpSweep1DNew(cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex)
|
94
|
+
{
|
95
|
+
return cpSweep1DInit(cpSweep1DAlloc(), bbfunc, staticIndex);
|
96
|
+
}
|
97
|
+
|
98
|
+
static void
|
99
|
+
cpSweep1DDestroy(cpSweep1D *sweep)
|
100
|
+
{
|
101
|
+
cpfree(sweep->table);
|
102
|
+
sweep->table = NULL;
|
103
|
+
}
|
104
|
+
|
105
|
+
//MARK: Misc
|
106
|
+
|
107
|
+
static int
|
108
|
+
cpSweep1DCount(cpSweep1D *sweep)
|
109
|
+
{
|
110
|
+
return sweep->num;
|
111
|
+
}
|
112
|
+
|
113
|
+
static void
|
114
|
+
cpSweep1DEach(cpSweep1D *sweep, cpSpatialIndexIteratorFunc func, void *data)
|
115
|
+
{
|
116
|
+
TableCell *table = sweep->table;
|
117
|
+
for(int i=0, count=sweep->num; i<count; i++) func(table[i].obj, data);
|
118
|
+
}
|
119
|
+
|
120
|
+
static int
|
121
|
+
cpSweep1DContains(cpSweep1D *sweep, void *obj, cpHashValue hashid)
|
122
|
+
{
|
123
|
+
TableCell *table = sweep->table;
|
124
|
+
for(int i=0, count=sweep->num; i<count; i++){
|
125
|
+
if(table[i].obj == obj) return cpTrue;
|
126
|
+
}
|
127
|
+
|
128
|
+
return cpFalse;
|
129
|
+
}
|
130
|
+
|
131
|
+
//MARK: Basic Operations
|
132
|
+
|
133
|
+
static void
|
134
|
+
cpSweep1DInsert(cpSweep1D *sweep, void *obj, cpHashValue hashid)
|
135
|
+
{
|
136
|
+
if(sweep->num == sweep->max) ResizeTable(sweep, sweep->max*2);
|
137
|
+
|
138
|
+
sweep->table[sweep->num] = MakeTableCell(sweep, obj);
|
139
|
+
sweep->num++;
|
140
|
+
}
|
141
|
+
|
142
|
+
static void
|
143
|
+
cpSweep1DRemove(cpSweep1D *sweep, void *obj, cpHashValue hashid)
|
144
|
+
{
|
145
|
+
TableCell *table = sweep->table;
|
146
|
+
for(int i=0, count=sweep->num; i<count; i++){
|
147
|
+
if(table[i].obj == obj){
|
148
|
+
int num = --sweep->num;
|
149
|
+
|
150
|
+
table[i] = table[num];
|
151
|
+
table[num].obj = NULL;
|
152
|
+
|
153
|
+
return;
|
154
|
+
}
|
155
|
+
}
|
156
|
+
}
|
157
|
+
|
158
|
+
//MARK: Reindexing Functions
|
159
|
+
|
160
|
+
static void
|
161
|
+
cpSweep1DReindexObject(cpSweep1D *sweep, void *obj, cpHashValue hashid)
|
162
|
+
{
|
163
|
+
// Nothing to do here
|
164
|
+
}
|
165
|
+
|
166
|
+
static void
|
167
|
+
cpSweep1DReindex(cpSweep1D *sweep)
|
168
|
+
{
|
169
|
+
// Nothing to do here
|
170
|
+
// Could perform a sort, but queries are not accelerated anyway.
|
171
|
+
}
|
172
|
+
|
173
|
+
//MARK: Query Functions
|
174
|
+
|
175
|
+
static void
|
176
|
+
cpSweep1DQuery(cpSweep1D *sweep, void *obj, cpBB bb, cpSpatialIndexQueryFunc func, void *data)
|
177
|
+
{
|
178
|
+
// Implementing binary search here would allow you to find an upper limit
|
179
|
+
// but not a lower limit. Probably not worth the hassle.
|
180
|
+
|
181
|
+
Bounds bounds = BBToBounds(sweep, bb);
|
182
|
+
|
183
|
+
TableCell *table = sweep->table;
|
184
|
+
for(int i=0, count=sweep->num; i<count; i++){
|
185
|
+
TableCell cell = table[i];
|
186
|
+
if(BoundsOverlap(bounds, cell.bounds) && obj != cell.obj) func(obj, cell.obj, data);
|
187
|
+
}
|
188
|
+
}
|
189
|
+
|
190
|
+
static void
|
191
|
+
cpSweep1DSegmentQuery(cpSweep1D *sweep, void *obj, cpVect a, cpVect b, cpFloat t_exit, cpSpatialIndexSegmentQueryFunc func, void *data)
|
192
|
+
{
|
193
|
+
cpBB bb = cpBBExpand(cpBBNew(a.x, a.y, a.x, a.y), b);
|
194
|
+
Bounds bounds = BBToBounds(sweep, bb);
|
195
|
+
|
196
|
+
TableCell *table = sweep->table;
|
197
|
+
for(int i=0, count=sweep->num; i<count; i++){
|
198
|
+
TableCell cell = table[i];
|
199
|
+
if(BoundsOverlap(bounds, cell.bounds)) func(obj, cell.obj, data);
|
200
|
+
}
|
201
|
+
}
|
202
|
+
|
203
|
+
//MARK: Reindex/Query
|
204
|
+
|
205
|
+
static int
|
206
|
+
TableSort(TableCell *a, TableCell *b)
|
207
|
+
{
|
208
|
+
return (a->bounds.min < b->bounds.min ? -1 : (a->bounds.min > b->bounds.min ? 1 : 0));
|
209
|
+
}
|
210
|
+
|
211
|
+
static void
|
212
|
+
cpSweep1DReindexQuery(cpSweep1D *sweep, cpSpatialIndexQueryFunc func, void *data)
|
213
|
+
{
|
214
|
+
TableCell *table = sweep->table;
|
215
|
+
int count = sweep->num;
|
216
|
+
|
217
|
+
// Update bounds and sort
|
218
|
+
for(int i=0; i<count; i++) table[i] = MakeTableCell(sweep, table[i].obj);
|
219
|
+
qsort(table, count, sizeof(TableCell), (int (*)(const void *, const void *))TableSort); // TODO use insertion sort instead
|
220
|
+
|
221
|
+
for(int i=0; i<count; i++){
|
222
|
+
TableCell cell = table[i];
|
223
|
+
cpFloat max = cell.bounds.max;
|
224
|
+
|
225
|
+
for(int j=i+1; table[j].bounds.min < max && j<count; j++){
|
226
|
+
func(cell.obj, table[j].obj, data);
|
227
|
+
}
|
228
|
+
}
|
229
|
+
|
230
|
+
// Reindex query is also responsible for colliding against the static index.
|
231
|
+
// Fortunately there is a helper function for that.
|
232
|
+
cpSpatialIndexCollideStatic((cpSpatialIndex *)sweep, sweep->spatialIndex.staticIndex, func, data);
|
233
|
+
}
|
234
|
+
|
235
|
+
static cpSpatialIndexClass klass = {
|
236
|
+
(cpSpatialIndexDestroyImpl)cpSweep1DDestroy,
|
237
|
+
|
238
|
+
(cpSpatialIndexCountImpl)cpSweep1DCount,
|
239
|
+
(cpSpatialIndexEachImpl)cpSweep1DEach,
|
240
|
+
(cpSpatialIndexContainsImpl)cpSweep1DContains,
|
241
|
+
|
242
|
+
(cpSpatialIndexInsertImpl)cpSweep1DInsert,
|
243
|
+
(cpSpatialIndexRemoveImpl)cpSweep1DRemove,
|
244
|
+
|
245
|
+
(cpSpatialIndexReindexImpl)cpSweep1DReindex,
|
246
|
+
(cpSpatialIndexReindexObjectImpl)cpSweep1DReindexObject,
|
247
|
+
(cpSpatialIndexReindexQueryImpl)cpSweep1DReindexQuery,
|
248
|
+
|
249
|
+
(cpSpatialIndexQueryImpl)cpSweep1DQuery,
|
250
|
+
(cpSpatialIndexSegmentQueryImpl)cpSweep1DSegmentQuery,
|
251
|
+
};
|
252
|
+
|
253
|
+
static inline cpSpatialIndexClass *Klass(){return &klass;}
|
254
|
+
|