annotate trunk/chipmunkd/cpArbiter.d @ 4:7ebbd4d05553

initial commit
author Extrawurst
date Thu, 02 Dec 2010 02:11:26 +0100
parents
children c03a41d47b60
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.cpArbiter;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
5
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
6 import chipmunkd.cpSpace;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
7 import chipmunkd.cpBody;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
8 import chipmunkd.cpShape;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
9 import chipmunkd.chipmunk;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
10 import chipmunkd.chipmunk_types_h;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
11 import chipmunkd.cpVect,chipmunkd.cpVect_h;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
12 import chipmunkd.constraints.util;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
13
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
14 // Determines how fast penetrations resolve themselves.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
15 //extern cpFloat cp_bias_coef;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
16 // Amount of allowed penetration. Used to reduce vibrating contacts.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
17 //extern cpFloat cp_collision_slop;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
18
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
19 // Data structure for contact points.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
20 struct cpContact {
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
21 // Contact point and normal.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
22 cpVect p, n;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
23 // Penetration distance.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
24 cpFloat dist;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
25
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
26 // Calculated by cpArbiterPreStep().
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
27 cpVect r1, r2;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
28 cpFloat nMass, tMass, bounce;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
29
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
30 // Persistant contact information.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
31 cpFloat jnAcc, jtAcc, jBias;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
32 cpFloat bias;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
33
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
34 // Hash value used to (mostly) uniquely identify a contact.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
35 cpHashValue hash;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
36 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
37
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
38 //// Contacts are always allocated in groups.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
39 //cpContact* cpContactInit(cpContact *con, cpVect p, cpVect n, cpFloat dist, cpHashValue hash);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
40 //
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
41 //// Sum the contact impulses. (Can be used after cpSpaceStep() returns)
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
42 //cpVect cpContactsSumImpulses(cpContact *contacts, int numContacts);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
43 //cpVect cpContactsSumImpulsesWithFriction(cpContact *contacts, int numContacts);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
44
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
45 enum cpArbiterState {
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
46 cpArbiterStateNormal,
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
47 cpArbiterStateFirstColl,
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
48 cpArbiterStateIgnore,
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
49 cpArbiterStateSleep,
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
50 cpArbiterStateCached,
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
51 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
52
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
53 // Data structure for tracking collisions between shapes.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
54 struct cpArbiter {
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
55 // Information on the contact points between the objects.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
56 int numContacts;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
57 cpContact *contacts;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
58
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
59 // The two shapes and bodies involved in the collision.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
60 // These variables are NOT in the order defined by the collision handler.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
61 // Using CP_ARBITER_GET_SHAPES and CP_ARBITER_GET_BODIES will save you from
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
62 // many headaches
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
63 cpShape* private_a;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
64 cpShape* private_b;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
65
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
66 // Calculated before calling the pre-solve collision handler
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
67 // Override them with custom values if you want specialized behavior
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
68 cpFloat e;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
69 cpFloat u;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
70 // Used for surface_v calculations, implementation may change
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
71 cpVect surface_vr;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
72
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
73 // Time stamp of the arbiter. (from cpSpace)
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
74 cpTimestamp stamp;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
75
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
76 cpCollisionHandler *handler;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
77
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
78 // Are the shapes swapped in relation to the collision handler?
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
79 cpBool swappedColl;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
80 cpArbiterState state;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
81 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
82
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
83 //// Arbiters are allocated in large buffers by the space and don't require a destroy function
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
84 //cpArbiter* cpArbiterInit(cpArbiter *arb, cpShape *a, cpShape *b);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
85 //
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
86 //// These functions are all intended to be used internally.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
87 //// Inject new contact points into the arbiter while preserving contact history.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
88 //void cpArbiterUpdate(cpArbiter *arb, cpContact *contacts, int numContacts, struct cpCollisionHandler *handler, cpShape *a, cpShape *b);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
89 //// Precalculate values used by the solver.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
90 //void cpArbiterPreStep(cpArbiter *arb, cpFloat dt_inv);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
91 //void cpArbiterApplyCachedImpulse(cpArbiter *arb);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
92 //// Run an iteration of the solver on the arbiter.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
93 //void cpArbiterApplyImpulse(cpArbiter *arb, cpFloat eCoef);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
94 //
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
95 //// Arbiter Helper Functions
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
96 //cpVect cpArbiterTotalImpulse(cpArbiter *arb);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
97 //cpVect cpArbiterTotalImpulseWithFriction(cpArbiter *arb);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
98 //void cpArbiterIgnore(cpArbiter *arb);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
99
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
100
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
101 static void
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
102 cpArbiterGetShapes(/+const+/ cpArbiter *arb, cpShape **a, cpShape **b)
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
103 {
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
104 if(arb.swappedColl){
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
105 (*a) = arb.private_b, (*b) = arb.private_a;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
106 } else {
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
107 (*a) = arb.private_a, (*b) = arb.private_b;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
108 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
109 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
110 //#define CP_ARBITER_GET_SHAPES(arb, a, b) cpShape *a, *b; cpArbiterGetShapes(arb, &a, &b);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
111 template CP_ARBITER_GET_SHAPES(string arb,string a,string b)
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
112 {
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
113 enum CP_ARBITER_GET_SHAPES = "cpShape* "~a~", "~b~";"~
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
114 "cpArbiterGetShapes("~arb~", &"~a~", &"~b~");";
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
115 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
116
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
117 static void
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
118 cpArbiterGetBodies(/+const+/ cpArbiter *arb, cpBody **a, cpBody **b)
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
119 {
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
120 //CP_ARBITER_GET_SHAPES(arb, shape_a, shape_b);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
121 cpShape *shape_a, shape_b; cpArbiterGetShapes(arb, &shape_a, &shape_b);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
122 (*a) = shape_a._body;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
123 (*b) = shape_b._body;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
124 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
125 //#define CP_ARBITER_GET_BODIES(arb, a, b) cpBody *a, *b; cpArbiterGetBodies(arb, &a, &b);
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 cpArbiterIsFirstContact(const cpArbiter *arb)
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
129 {
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
130 return arb.state == cpArbiterState.cpArbiterStateFirstColl;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
131 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
132
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
133 static cpVect
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
134 cpArbiterGetNormal(const cpArbiter *arb, int i)
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
135 {
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
136 cpVect n = arb.contacts[i].n;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
137 return arb.swappedColl ? cpvneg(n) : n;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
138 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
139
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
140 static cpVect
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
141 cpArbiterGetPoint(const cpArbiter *arb, int i)
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
142 {
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
143 return arb.contacts[i].p;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
144 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
145
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
146 cpFloat cp_bias_coef = 0.1f;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
147 cpFloat cp_collision_slop = 0.1f;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
148
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
149 cpContact*
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
150 cpContactInit(cpContact *con, cpVect p, cpVect n, cpFloat dist, cpHashValue hash)
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
151 {
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
152 con.p = p;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
153 con.n = n;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
154 con.dist = dist;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
155
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
156 con.jnAcc = 0.0f;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
157 con.jtAcc = 0.0f;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
158 con.jBias = 0.0f;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
159
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
160 con.hash = hash;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
161
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
162 return con;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
163 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
164
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
165 cpVect
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
166 cpArbiterTotalImpulse(cpArbiter *arb)
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
167 {
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
168 cpContact *contacts = arb.contacts;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
169 cpVect sum = cpvzero;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
170
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
171 for(int i=0, count=arb.numContacts; i<count; i++){
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
172 cpContact *con = &contacts[i];
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
173 sum = cpvadd(sum, cpvmult(con.n, con.jnAcc));
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
174 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
175
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
176 return sum;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
177 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
178
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
179 cpVect
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
180 cpArbiterTotalImpulseWithFriction(cpArbiter *arb)
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
181 {
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
182 cpContact *contacts = arb.contacts;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
183 cpVect sum = cpvzero;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
184
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
185 for(int i=0, count=arb.numContacts; i<count; i++){
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
186 cpContact *con = &contacts[i];
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
187 sum = cpvadd(sum, cpvrotate(con.n, cpv(con.jnAcc, con.jtAcc)));
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
188 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
189
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
190 return sum;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
191 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
192
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
193 cpFloat
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
194 cpContactsEstimateCrushingImpulse(cpContact *contacts, int numContacts)
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
195 {
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
196 cpFloat fsum = 0.0f;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
197 cpVect vsum = cpvzero;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
198
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
199 for(int i=0; i<numContacts; i++){
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
200 cpContact *con = &contacts[i];
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
201 cpVect j = cpvrotate(con.n, cpv(con.jnAcc, con.jtAcc));
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
202
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
203 fsum += cpvlength(j);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
204 vsum = cpvadd(vsum, j);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
205 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
206
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
207 cpFloat vmag = cpvlength(vsum);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
208 return (1.0f - vmag/fsum);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
209 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
210
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
211 void
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
212 cpArbiterIgnore(cpArbiter *arb)
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
213 {
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
214 arb.state = cpArbiterState.cpArbiterStateIgnore;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
215 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
216
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
217 cpArbiter*
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
218 cpArbiterAlloc()
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
219 {
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
220 return cast(cpArbiter *)cpcalloc(1, cpArbiter.sizeof);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
221 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
222
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
223 cpArbiter*
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
224 cpArbiterInit(cpArbiter *arb, cpShape *a, cpShape *b)
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
225 {
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
226 arb.numContacts = 0;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
227 arb.contacts = null;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
228
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
229 arb.private_a = a;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
230 arb.private_b = b;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
231
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
232 arb.stamp = 0;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
233 arb.state = cpArbiterState.cpArbiterStateFirstColl;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
234
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
235 return arb;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
236 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
237
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
238 cpArbiter*
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
239 cpArbiterNew(cpShape *a, cpShape *b)
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
240 {
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
241 return cpArbiterInit(cpArbiterAlloc(), a, b);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
242 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
243
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
244 void
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
245 cpArbiterDestroy(cpArbiter *arb)
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
246 {
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
247 // if(arb.contacts) cpfree(arb.contacts);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
248 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
249
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
250 void
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
251 cpArbiterFree(cpArbiter *arb)
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
252 {
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
253 if(arb){
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
254 cpArbiterDestroy(arb);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
255 cpfree(arb);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
256 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
257 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
258
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
259 void
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
260 cpArbiterUpdate(cpArbiter *arb, cpContact *contacts, int numContacts, cpCollisionHandler *handler, cpShape *a, cpShape *b)
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
261 {
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
262 // Arbiters without contact data may exist if a collision function rejected the collision.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
263 if(arb.contacts){
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
264 // Iterate over the possible pairs to look for hash value matches.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
265 for(int i=0; i<arb.numContacts; i++){
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
266 cpContact *old = &arb.contacts[i];
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
267
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
268 for(int j=0; j<numContacts; j++){
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
269 cpContact *new_contact = &contacts[j];
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
270
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
271 // This could trigger false positives, but is fairly unlikely nor serious if it does.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
272 if(new_contact.hash == old.hash){
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
273 // Copy the persistant contact information.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
274 new_contact.jnAcc = old.jnAcc;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
275 new_contact.jtAcc = old.jtAcc;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
276 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
277 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
278 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
279
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
280 // cpfree(arb.contacts);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
281 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
282
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
283 arb.contacts = contacts;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
284 arb.numContacts = numContacts;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
285
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
286 arb.handler = handler;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
287 arb.swappedColl = (a.collision_type != handler.a);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
288
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
289 arb.e = a.e * b.e;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
290 arb.u = a.u * b.u;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
291 arb.surface_vr = cpvsub(a.surface_v, b.surface_v);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
292
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
293 // For collisions between two similar primitive types, the order could have been swapped.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
294 arb.private_a = a;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
295 arb.private_b = b;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
296
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
297 // mark it as new if it's been cached
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
298 if(arb.state == cpArbiterState.cpArbiterStateCached) arb.state = cpArbiterState.cpArbiterStateFirstColl;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
299 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
300
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
301 void
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
302 cpArbiterPreStep(cpArbiter *arb, cpFloat dt_inv)
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
303 {
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
304 cpBody *a = arb.private_a._body;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
305 cpBody *b = arb.private_b._body;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
306
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
307 for(int i=0; i<arb.numContacts; i++){
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
308 cpContact *con = &arb.contacts[i];
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
309
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
310 // Calculate the offsets.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
311 con.r1 = cpvsub(con.p, a.p);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
312 con.r2 = cpvsub(con.p, b.p);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
313
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
314 // Calculate the mass normal and mass tangent.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
315 con.nMass = 1.0f/k_scalar(a, b, con.r1, con.r2, con.n);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
316 con.tMass = 1.0f/k_scalar(a, b, con.r1, con.r2, cpvperp(con.n));
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
317
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
318 // Calculate the target bias velocity.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
319 con.bias = -cp_bias_coef*dt_inv*cpfmin(0.0f, con.dist + cp_collision_slop);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
320 con.jBias = 0.0f;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
321
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
322 // Calculate the target bounce velocity.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
323 con.bounce = normal_relative_velocity(a, b, con.r1, con.r2, con.n)*arb.e;//cpvdot(con.n, cpvsub(v2, v1))*e;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
324 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
325 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
326
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
327 void
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
328 cpArbiterApplyCachedImpulse(cpArbiter *arb)
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
329 {
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
330 cpShape *shapea = arb.private_a;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
331 cpShape *shapeb = arb.private_b;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
332
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
333 arb.u = shapea.u * shapeb.u;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
334 arb.surface_vr = cpvsub(shapeb.surface_v, shapea.surface_v);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
335
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
336 cpBody *a = shapea._body;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
337 cpBody *b = shapeb._body;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
338
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
339 for(int i=0; i<arb.numContacts; i++){
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
340 cpContact *con = &arb.contacts[i];
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
341 apply_impulses(a, b, con.r1, con.r2, cpvrotate(con.n, cpv(con.jnAcc, con.jtAcc)));
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
342 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
343 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
344
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
345 void
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
346 cpArbiterApplyImpulse(cpArbiter *arb, cpFloat eCoef)
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
347 {
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
348 cpBody *a = arb.private_a._body;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
349 cpBody *b = arb.private_b._body;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
350
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
351 for(int i=0; i<arb.numContacts; i++){
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
352 cpContact *con = &arb.contacts[i];
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
353 cpVect n = con.n;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
354 cpVect r1 = con.r1;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
355 cpVect r2 = con.r2;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
356
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
357 // Calculate the relative bias velocities.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
358 cpVect vb1 = cpvadd(a.v_bias, cpvmult(cpvperp(r1), a.w_bias));
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
359 cpVect vb2 = cpvadd(b.v_bias, cpvmult(cpvperp(r2), b.w_bias));
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
360 cpFloat vbn = cpvdot(cpvsub(vb2, vb1), n);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
361
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
362 // Calculate and clamp the bias impulse.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
363 cpFloat jbn = (con.bias - vbn)*con.nMass;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
364 cpFloat jbnOld = con.jBias;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
365 con.jBias = cpfmax(jbnOld + jbn, 0.0f);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
366 jbn = con.jBias - jbnOld;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
367
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
368 // Apply the bias impulse.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
369 apply_bias_impulses(a, b, r1, r2, cpvmult(n, jbn));
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
370
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
371 // Calculate the relative velocity.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
372 cpVect vr = relative_velocity(a, b, r1, r2);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
373 cpFloat vrn = cpvdot(vr, n);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
374
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
375 // Calculate and clamp the normal impulse.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
376 cpFloat jn = -(con.bounce*eCoef + vrn)*con.nMass;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
377 cpFloat jnOld = con.jnAcc;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
378 con.jnAcc = cpfmax(jnOld + jn, 0.0f);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
379 jn = con.jnAcc - jnOld;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
380
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
381 // Calculate the relative tangent velocity.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
382 cpFloat vrt = cpvdot(cpvadd(vr, arb.surface_vr), cpvperp(n));
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
383
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
384 // Calculate and clamp the friction impulse.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
385 cpFloat jtMax = arb.u*con.jnAcc;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
386 cpFloat jt = -vrt*con.tMass;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
387 cpFloat jtOld = con.jtAcc;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
388 con.jtAcc = cpfclamp(jtOld + jt, -jtMax, jtMax);
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
389 jt = con.jtAcc - jtOld;
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
390
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
391 // Apply the final impulse.
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
392 apply_impulses(a, b, r1, r2, cpvrotate(n, cpv(jn, jt)));
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
393 }
7ebbd4d05553 initial commit
Extrawurst
parents:
diff changeset
394 }