chipmunk 5.3.4.5 → 6.1.3.0.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
|