annotate trunk/chipmunkd/cpSpaceStep.d @ 13:c03a41d47b60

- finished all constraints properties - implemented cpAssertWarn the mixin way
author Extrawurst
date Fri, 03 Dec 2010 21:38:01 +0100
parents 7ebbd4d05553
children 4ceef5833c8c
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
4
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
1
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
2 // written in the D programming language
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
3
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
4 module chipmunkd.cpSpaceStep;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
5
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
6 import chipmunkd.chipmunk;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
7 //import chipmunkd.chipmunk_types_h;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
8 //import chipmunkd.cpVect,chipmunkd.cpVect_h;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
9 //import chipmunkd.cpHashSet;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
10 //import chipmunkd.cpCollision;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
11 //import chipmunkd.cpBody;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
12 //import chipmunkd.cpArray;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
13 //import chipmunkd.cpShape;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
14 //import chipmunkd.cpBB;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
15 //import chipmunkd.cpArbiter;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
16 //import chipmunkd.cpSpaceHash;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
17 //import chipmunkd.constraints.cpConstraint;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
18 //import chipmunkd.cpSpaceQuery;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
19 //
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
20 //#pragma mark Post Step Callback Functions
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
21
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
22 struct postStepCallback {
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
23 cpPostStepFunc func;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
24 void *obj;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
25 void *data;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
26 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
27
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
28 static cpBool
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
29 postStepFuncSetEql(postStepCallback *a, postStepCallback *b){
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
30 return a.obj == b.obj;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
31 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
32
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
33 static void *
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
34 postStepFuncSetTrans(postStepCallback *callback, void *ignored)
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
35 {
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
36 postStepCallback *value = cast(postStepCallback *)cpmalloc(postStepCallback.sizeof);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
37 (*value) = (*callback);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
38
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
39 return value;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
40 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
41
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
42 void
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
43 cpSpaceAddPostStepCallback(cpSpace *space, cpPostStepFunc func, void *obj, void *data)
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
44 {
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
45 if(!space.postStepCallbacks){
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
46 space.postStepCallbacks = cpHashSetNew(0, cast(cpHashSetEqlFunc)&postStepFuncSetEql, cast(cpHashSetTransFunc)&postStepFuncSetTrans);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
47 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
48
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
49 postStepCallback callback = {func, obj, data};
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
50 cpHashSetInsert(space.postStepCallbacks, cast(cpHashValue)cast(size_t)obj, &callback, null);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
51 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
52
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
53 //#pragma mark Contact Buffer Functions
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
54
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
55 enum CP_CONTACTS_BUFFER_SIZE = ((CP_BUFFER_BYTES - cpContactBufferHeader.sizeof)/cpContact.sizeof);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
56
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
57 struct cpContactBuffer {
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
58 cpContactBufferHeader header;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
59 cpContact[CP_CONTACTS_BUFFER_SIZE] contacts;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
60 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
61
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
62 static cpContactBufferHeader *
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
63 cpSpaceAllocContactBuffer(cpSpace *space)
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
64 {
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
65 cpContactBuffer *buffer = cast(cpContactBuffer *)cpmalloc(cpContactBuffer.sizeof);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
66 cpArrayPush(space.allocatedBuffers, buffer);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
67 return cast(cpContactBufferHeader *)buffer;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
68 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
69
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
70 static cpContactBufferHeader *
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
71 cpContactBufferHeaderInit(cpContactBufferHeader *header, cpTimestamp stamp, cpContactBufferHeader *splice)
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
72 {
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
73 header.stamp = stamp;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
74 header.next = (splice ? splice.next : header);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
75 header.numContacts = 0;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
76
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
77 return header;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
78 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
79
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
80 static void
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
81 cpSpacePushFreshContactBuffer(cpSpace *space)
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
82 {
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
83 cpTimestamp stamp = space.stamp;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
84
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
85 cpContactBufferHeader *head = space.contactBuffersHead;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
86
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
87 if(!head){
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
88 // No buffers have been allocated, make one
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
89 space.contactBuffersHead = cpContactBufferHeaderInit(cpSpaceAllocContactBuffer(space), stamp, null);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
90 } else if(stamp - head.next.stamp > cp_contact_persistence){
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
91 // The tail buffer is available, rotate the ring
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
92 cpContactBufferHeader *tail = head.next;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
93 space.contactBuffersHead = cpContactBufferHeaderInit(tail, stamp, tail);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
94 } else {
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
95 // Allocate a new buffer and push it into the ring
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
96 cpContactBufferHeader *buffer = cpContactBufferHeaderInit(cpSpaceAllocContactBuffer(space), stamp, head);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
97 space.contactBuffersHead = head.next = buffer;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
98 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
99 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
100
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
101
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
102 static cpContact *
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
103 cpContactBufferGetArray(cpSpace *space)
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
104 {
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
105 if(space.contactBuffersHead.numContacts + CP_MAX_CONTACTS_PER_ARBITER > CP_CONTACTS_BUFFER_SIZE){
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
106 // contact buffer could overflow on the next collision, push a fresh one.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
107 cpSpacePushFreshContactBuffer(space);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
108 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
109
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
110 cpContactBufferHeader *head = space.contactBuffersHead;
13
c03a41d47b60 - finished all constraints properties
Extrawurst
parents: 4
diff changeset
111 return &(cast(cpContactBuffer *)head).contacts[head.numContacts];
4
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
112 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
113
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
114 static void
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
115 cpSpacePushContacts(cpSpace *space, int count){
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
116 assert(count <= CP_MAX_CONTACTS_PER_ARBITER, "Internal error, too many contact point overflow!");
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
117 space.contactBuffersHead.numContacts += count;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
118 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
119
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
120 static void
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
121 cpSpacePopContacts(cpSpace *space, int count){
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
122 space.contactBuffersHead.numContacts -= count;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
123 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
124
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
125 //#pragma mark Collision Detection Functions
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
126
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
127 static cpBool
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
128 queryReject(cpShape *a, cpShape *b)
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
129 {
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
130 return
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
131 // BBoxes must overlap
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
132 !cpBBintersects(a.bb, b.bb)
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
133 // Don't collide shapes attached to the same body.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
134 || a._body == b._body
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
135 // Don't collide objects in the same non-zero group
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
136 || (a.group && a.group == b.group)
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
137 // Don't collide objects that don't share at least on layer.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
138 || !(a.layers & b.layers);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
139 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
140
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
141 // Callback from the spatial hash.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
142 static void
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
143 queryFunc(cpShape *a, cpShape *b, cpSpace *space)
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
144 {
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
145 // Reject any of the simple cases
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
146 if(queryReject(a,b)) return;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
147
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
148 // Find the collision pair function for the shapes.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
149 struct tmp{cpCollisionType a, b;} tmp ids = {a.collision_type, b.collision_type};
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
150 cpHashValue collHashID = CP_HASH_PAIR(a.collision_type, b.collision_type);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
151 cpCollisionHandler *handler = cast(cpCollisionHandler *)cpHashSetFind(space.collFuncSet, collHashID, &ids);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
152
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
153 cpBool sensor = a.sensor || b.sensor;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
154 if(sensor && handler == &space.defaultHandler) return;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
155
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
156 // Shape 'a' should have the lower shape type. (required by cpCollideShapes() )
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
157 if(a.klass.type > b.klass.type){
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
158 cpShape *temp = a;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
159 a = b;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
160 b = temp;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
161 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
162
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
163 // Narrow-phase collision detection.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
164 cpContact *contacts = cpContactBufferGetArray(space);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
165 int numContacts = cpCollideShapes(a, b, contacts);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
166 if(!numContacts) return; // Shapes are not colliding.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
167 cpSpacePushContacts(space, numContacts);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
168
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
169 // Get an arbiter from space.contactSet for the two shapes.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
170 // This is where the persistant contact magic comes from.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
171 cpShape *shape_pair[] = [a, b];
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
172 cpHashValue arbHashID = CP_HASH_PAIR(cast(size_t)a, cast(size_t)b);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
173 cpArbiter *arb = cast(cpArbiter *)cpHashSetInsert(space.contactSet, arbHashID, shape_pair.ptr, space);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
174 cpArbiterUpdate(arb, contacts, numContacts, handler, a, b); // retains the contacts array
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
175
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
176 // Call the begin function first if it's the first step
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
177 if(arb.state == cpArbiterState.cpArbiterStateFirstColl && !handler.begin(arb, space, handler.data)){
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
178 cpArbiterIgnore(arb); // permanently ignore the collision until separation
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
179 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
180
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
181 if(
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
182 // Ignore the arbiter if it has been flagged
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
183 (arb.state != cpArbiterState.cpArbiterStateIgnore) &&
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
184 // Call preSolve
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
185 handler.preSolve(arb, space, handler.data) &&
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
186 // Process, but don't add collisions for sensors.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
187 !sensor
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
188 ){
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
189 cpArrayPush(space.arbiters, arb);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
190 } else {
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
191 cpSpacePopContacts(space, numContacts);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
192
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
193 arb.contacts = null;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
194 arb.numContacts = 0;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
195
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
196 // Normally arbiters are set as used after calling the post-step callback.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
197 // However, post-step callbacks are not called for sensors or arbiters rejected from pre-solve.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
198 if(arb.state != cpArbiterState.cpArbiterStateIgnore) arb.state = cpArbiterState.cpArbiterStateNormal;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
199 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
200
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
201 // Time stamp the arbiter so we know it was used recently.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
202 arb.stamp = space.stamp;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
203 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
204
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
205 // Iterator for active/static hash collisions.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
206 static void
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
207 active2staticIter(cpShape *shape, cpSpace *space)
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
208 {
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
209 cpSpaceHashQuery(space.staticShapes, shape, shape.bb, cast(cpSpaceHashQueryFunc)&queryFunc, space);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
210 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
211
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
212 // Hashset filter func to throw away old arbiters.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
213 static cpBool
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
214 contactSetFilter(cpArbiter *arb, cpSpace *space)
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
215 {
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
216 if(space.sleepTimeThreshold != INFINITY){
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
217 cpBody *a = arb.private_a._body;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
218 cpBody *b = arb.private_b._body;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
219
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
220 // both bodies are either static or sleeping
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
221 cpBool sleepingNow =
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
222 (cpBodyIsStatic(a) || cpBodyIsSleeping(a)) &&
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
223 (cpBodyIsStatic(b) || cpBodyIsSleeping(b));
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
224
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
225 if(sleepingNow){
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
226 arb.state = cpArbiterState.cpArbiterStateSleep;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
227 return cpTrue;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
228 } else if(arb.state == cpArbiterState.cpArbiterStateSleep){
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
229 // wake up the arbiter and continue as normal
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
230 arb.state = cpArbiterState.cpArbiterStateNormal;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
231 // TODO is it possible that cpArbiterStateIgnore should be set here instead?
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
232 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
233 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
234
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
235 cpTimestamp ticks = space.stamp - arb.stamp;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
236
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
237 // was used last frame, but not this one
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
238 if(ticks >= 1 && arb.state != cpArbiterState.cpArbiterStateCached){
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
239 arb.handler.separate(arb, space, arb.handler.data);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
240 arb.state = cpArbiterState.cpArbiterStateCached;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
241 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
242
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
243 if(ticks >= cp_contact_persistence){
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
244 arb.contacts = null;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
245 arb.numContacts = 0;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
246
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
247 cpArrayPush(space.pooledArbiters, arb);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
248 return cpFalse;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
249 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
250
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
251 return cpTrue;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
252 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
253
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
254 // Hashset filter func to call and throw away post step callbacks.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
255 static void
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
256 postStepCallbackSetIter(postStepCallback *callback, cpSpace *space)
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
257 {
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
258 callback.func(space, callback.obj, callback.data);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
259 cpfree(callback);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
260 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
261
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
262 //#pragma mark All Important cpSpaceStep() Function
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
263
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
264 //void cpSpaceProcessComponents(cpSpace *space, cpFloat dt);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
265
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
266 static void updateBBCache(cpShape *shape, void *unused){cpShapeCacheBB(shape);}
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
267
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
268 void
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
269 cpSpaceStep(cpSpace *space, cpFloat dt)
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
270 {
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
271 if(!dt) return; // don't step if the timestep is 0!
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
272
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
273 cpFloat dt_inv = 1.0f/dt;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
274
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
275 cpArray *bodies = space.bodies;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
276 cpArray *constraints = space.constraints;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
277
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
278 space.locked = cpTrue;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
279
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
280 // Empty the arbiter list.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
281 space.arbiters.num = 0;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
282
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
283 // Integrate positions.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
284 for(int i=0; i<bodies.num; i++){
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
285 cpBody *_body = cast(cpBody *)bodies.arr[i];
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
286 _body.position_func(_body, dt);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
287 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
288
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
289 // Pre-cache BBoxes and shape data.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
290 cpSpaceHashEach(space.activeShapes, cast(cpSpaceHashIterator)&updateBBCache, null);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
291
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
292 // Collide!
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
293 cpSpacePushFreshContactBuffer(space);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
294 if(space.staticShapes.handleSet.entries)
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
295 cpSpaceHashEach(space.activeShapes, cast(cpSpaceHashIterator)&active2staticIter, space);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
296 cpSpaceHashQueryRehash(space.activeShapes, cast(cpSpaceHashQueryFunc)&queryFunc, space);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
297
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
298 // If body sleeping is enabled, do that now.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
299 if(space.sleepTimeThreshold != INFINITY){
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
300 cpSpaceProcessComponents(space, dt);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
301 bodies = space.bodies; // rebuilt by processContactComponents()
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
302 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
303
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
304 // Clear out old cached arbiters and dispatch untouch functions
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
305 cpHashSetFilter(space.contactSet, cast(cpHashSetFilterFunc)&contactSetFilter, space);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
306
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
307 // Prestep the arbiters.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
308 cpArray *arbiters = space.arbiters;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
309 for(int i=0; i<arbiters.num; i++)
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
310 cpArbiterPreStep(cast(cpArbiter *)arbiters.arr[i], dt_inv);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
311
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
312 // Prestep the constraints.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
313 for(int i=0; i<constraints.num; i++){
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
314 cpConstraint *constraint = cast(cpConstraint *)constraints.arr[i];
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
315 constraint.klass.preStep(constraint, dt, dt_inv);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
316 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
317
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
318 for(int i=0; i<space.elasticIterations; i++){
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
319 for(int j=0; j<arbiters.num; j++)
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
320 cpArbiterApplyImpulse(cast(cpArbiter *)arbiters.arr[j], 1.0f);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
321
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
322 for(int j=0; j<constraints.num; j++){
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
323 cpConstraint *constraint = cast(cpConstraint *)constraints.arr[j];
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
324 constraint.klass.applyImpulse(constraint);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
325 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
326 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
327
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
328 // Integrate velocities.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
329 cpFloat damping = cpfpow(1.0f/space.damping, -dt);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
330 for(int i=0; i<bodies.num; i++){
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
331 cpBody *_body = cast(cpBody *)bodies.arr[i];
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
332 _body.velocity_func(_body, space.gravity, damping, dt);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
333 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
334
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
335 for(int i=0; i<arbiters.num; i++)
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
336 cpArbiterApplyCachedImpulse(cast(cpArbiter *)arbiters.arr[i]);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
337
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
338 // run the old-style elastic solver if elastic iterations are disabled
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
339 cpFloat elasticCoef = (space.elasticIterations ? 0.0f : 1.0f);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
340
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
341 // Run the impulse solver.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
342 for(int i=0; i<space.iterations; i++){
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
343 for(int j=0; j<arbiters.num; j++)
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
344 cpArbiterApplyImpulse(cast(cpArbiter *)arbiters.arr[j], elasticCoef);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
345
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
346 for(int j=0; j<constraints.num; j++){
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
347 cpConstraint *constraint = cast(cpConstraint *)constraints.arr[j];
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
348 constraint.klass.applyImpulse(constraint);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
349 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
350 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
351
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
352 space.locked = cpFalse;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
353
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
354 // run the post solve callbacks
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
355 for(int i=0; i<arbiters.num; i++){
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
356 cpArbiter *arb = cast(cpArbiter *) arbiters.arr[i];
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
357
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
358 cpCollisionHandler *handler = arb.handler;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
359 handler.postSolve(arb, space, handler.data);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
360
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
361 arb.state = cpArbiterState.cpArbiterStateNormal;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
362 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
363
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
364 // Run the post step callbacks
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
365 // Loop because post step callbacks may create more post step callbacks
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
366 while(space.postStepCallbacks){
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
367 cpHashSet *callbacks = space.postStepCallbacks;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
368 space.postStepCallbacks = null;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
369
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
370 cpHashSetEach(callbacks, cast(cpHashSetIterFunc)&postStepCallbackSetIter, space);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
371 cpHashSetFree(callbacks);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
372 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
373
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
374 // Increment the stamp.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
375 space.stamp++;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
376 }