box2d-rails 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. data/.gitignore +17 -0
  2. data/Gemfile +4 -0
  3. data/LICENSE.txt +22 -0
  4. data/README.md +29 -0
  5. data/Rakefile +1 -0
  6. data/box2d-rails.gemspec +20 -0
  7. data/lib/box2d-rails.rb +8 -0
  8. data/lib/box2d-rails/version.rb +5 -0
  9. data/vendor/assets/javascripts/box2d/collision/ClipVertex.js +35 -0
  10. data/vendor/assets/javascripts/box2d/collision/Features.js +61 -0
  11. data/vendor/assets/javascripts/box2d/collision/b2AABB.js +45 -0
  12. data/vendor/assets/javascripts/box2d/collision/b2Bound.js +43 -0
  13. data/vendor/assets/javascripts/box2d/collision/b2BoundValues.js +31 -0
  14. data/vendor/assets/javascripts/box2d/collision/b2BroadPhase.js +898 -0
  15. data/vendor/assets/javascripts/box2d/collision/b2BufferedPair.js +26 -0
  16. data/vendor/assets/javascripts/box2d/collision/b2Collision.js +738 -0
  17. data/vendor/assets/javascripts/box2d/collision/b2ContactID.js +52 -0
  18. data/vendor/assets/javascripts/box2d/collision/b2ContactPoint.js +35 -0
  19. data/vendor/assets/javascripts/box2d/collision/b2Distance.js +333 -0
  20. data/vendor/assets/javascripts/box2d/collision/b2Manifold.js +34 -0
  21. data/vendor/assets/javascripts/box2d/collision/b2OBB.js +34 -0
  22. data/vendor/assets/javascripts/box2d/collision/b2Pair.js +60 -0
  23. data/vendor/assets/javascripts/box2d/collision/b2PairCallback.js +34 -0
  24. data/vendor/assets/javascripts/box2d/collision/b2PairManager.js +386 -0
  25. data/vendor/assets/javascripts/box2d/collision/b2Proxy.js +40 -0
  26. data/vendor/assets/javascripts/box2d/collision/shapes/b2BoxDef.js +49 -0
  27. data/vendor/assets/javascripts/box2d/collision/shapes/b2CircleDef.js +49 -0
  28. data/vendor/assets/javascripts/box2d/collision/shapes/b2CircleShape.js +198 -0
  29. data/vendor/assets/javascripts/box2d/collision/shapes/b2MassData.js +36 -0
  30. data/vendor/assets/javascripts/box2d/collision/shapes/b2PolyDef.js +58 -0
  31. data/vendor/assets/javascripts/box2d/collision/shapes/b2PolyShape.js +492 -0
  32. data/vendor/assets/javascripts/box2d/collision/shapes/b2Shape.js +339 -0
  33. data/vendor/assets/javascripts/box2d/collision/shapes/b2ShapeDef.js +109 -0
  34. data/vendor/assets/javascripts/box2d/common/b2Settings.js +72 -0
  35. data/vendor/assets/javascripts/box2d/common/math/b2Mat22.js +130 -0
  36. data/vendor/assets/javascripts/box2d/common/math/b2Math.js +218 -0
  37. data/vendor/assets/javascripts/box2d/common/math/b2Vec2.js +131 -0
  38. data/vendor/assets/javascripts/box2d/dynamics/b2Body.js +469 -0
  39. data/vendor/assets/javascripts/box2d/dynamics/b2BodyDef.js +69 -0
  40. data/vendor/assets/javascripts/box2d/dynamics/b2CollisionFilter.js +42 -0
  41. data/vendor/assets/javascripts/box2d/dynamics/b2ContactManager.js +337 -0
  42. data/vendor/assets/javascripts/box2d/dynamics/b2Island.js +331 -0
  43. data/vendor/assets/javascripts/box2d/dynamics/b2TimeStep.js +27 -0
  44. data/vendor/assets/javascripts/box2d/dynamics/b2World.js +522 -0
  45. data/vendor/assets/javascripts/box2d/dynamics/b2WorldListener.js +52 -0
  46. data/vendor/assets/javascripts/box2d/dynamics/contacts/b2CircleContact.js +102 -0
  47. data/vendor/assets/javascripts/box2d/dynamics/contacts/b2Conservative.js +228 -0
  48. data/vendor/assets/javascripts/box2d/dynamics/contacts/b2Contact.js +201 -0
  49. data/vendor/assets/javascripts/box2d/dynamics/contacts/b2ContactConstraint.js +45 -0
  50. data/vendor/assets/javascripts/box2d/dynamics/contacts/b2ContactConstraintPoint.js +40 -0
  51. data/vendor/assets/javascripts/box2d/dynamics/contacts/b2ContactNode.js +33 -0
  52. data/vendor/assets/javascripts/box2d/dynamics/contacts/b2ContactRegister.js +30 -0
  53. data/vendor/assets/javascripts/box2d/dynamics/contacts/b2ContactSolver.js +537 -0
  54. data/vendor/assets/javascripts/box2d/dynamics/contacts/b2NullContact.js +65 -0
  55. data/vendor/assets/javascripts/box2d/dynamics/contacts/b2PolyAndCircleContact.js +103 -0
  56. data/vendor/assets/javascripts/box2d/dynamics/contacts/b2PolyContact.js +163 -0
  57. data/vendor/assets/javascripts/box2d/dynamics/joints/b2DistanceJoint.js +264 -0
  58. data/vendor/assets/javascripts/box2d/dynamics/joints/b2DistanceJointDef.js +49 -0
  59. data/vendor/assets/javascripts/box2d/dynamics/joints/b2GearJoint.js +307 -0
  60. data/vendor/assets/javascripts/box2d/dynamics/joints/b2GearJointDef.js +50 -0
  61. data/vendor/assets/javascripts/box2d/dynamics/joints/b2Jacobian.js +49 -0
  62. data/vendor/assets/javascripts/box2d/dynamics/joints/b2Joint.js +200 -0
  63. data/vendor/assets/javascripts/box2d/dynamics/joints/b2JointDef.js +40 -0
  64. data/vendor/assets/javascripts/box2d/dynamics/joints/b2JointNode.js +33 -0
  65. data/vendor/assets/javascripts/box2d/dynamics/joints/b2MouseJoint.js +234 -0
  66. data/vendor/assets/javascripts/box2d/dynamics/joints/b2MouseJointDef.js +53 -0
  67. data/vendor/assets/javascripts/box2d/dynamics/joints/b2PrismaticJoint.js +676 -0
  68. data/vendor/assets/javascripts/box2d/dynamics/joints/b2PrismaticJointDef.js +56 -0
  69. data/vendor/assets/javascripts/box2d/dynamics/joints/b2PulleyJoint.js +618 -0
  70. data/vendor/assets/javascripts/box2d/dynamics/joints/b2PulleyJointDef.js +70 -0
  71. data/vendor/assets/javascripts/box2d/dynamics/joints/b2RevoluteJoint.js +491 -0
  72. data/vendor/assets/javascripts/box2d/dynamics/joints/b2RevoluteJointDef.js +55 -0
  73. metadata +133 -0
@@ -0,0 +1,331 @@
1
+ /*
2
+ * Copyright (c) 2006-2007 Erin Catto http:
3
+ *
4
+ * This software is provided 'as-is', without any express or implied
5
+ * warranty. In no event will the authors be held liable for any damages
6
+ * arising from the use of this software.
7
+ * Permission is granted to anyone to use this software for any purpose,
8
+ * including commercial applications, and to alter it and redistribute it
9
+ * freely, subject to the following restrictions:
10
+ * 1. The origin of this software must not be misrepresented; you must not
11
+ * claim that you wrote the original software. If you use this software
12
+ * in a product, an acknowledgment in the product documentation would be
13
+ * appreciated but is not required.
14
+ * 2. Altered source versions must be plainly marked, and must not be
15
+ * misrepresented the original software.
16
+ * 3. This notice may not be removed or altered from any source distribution.
17
+ */
18
+
19
+
20
+
21
+
22
+
23
+ /*
24
+ Position Correction Notes
25
+ =========================
26
+ I tried the several algorithms for position correction of the 2D revolute joint.
27
+ I looked at these systems:
28
+ - simple pendulum (1m diameter sphere on massless 5m stick) with initial angular velocity of 100 rad/s.
29
+ - suspension bridge with 30 1m long planks of length 1m.
30
+ - multi-link chain with 30 1m long links.
31
+
32
+ Here are the algorithms:
33
+
34
+ Baumgarte - A fraction of the position error is added to the velocity error. There is no
35
+ separate position solver.
36
+
37
+ Pseudo Velocities - After the velocity solver and position integration,
38
+ the position error, Jacobian, and effective mass are recomputed. Then
39
+ the velocity constraints are solved with pseudo velocities and a fraction
40
+ of the position error is added to the pseudo velocity error. The pseudo
41
+ velocities are initialized to zero and there is no warm-starting. After
42
+ the position solver, the pseudo velocities are added to the positions.
43
+ This is also called the First Order World method or the Position LCP method.
44
+
45
+ Modified Nonlinear Gauss-Seidel (NGS) - Like Pseudo Velocities except the
46
+ position error is re-computed for each constraint and the positions are updated
47
+ after the constraint is solved. The radius vectors (aka Jacobians) are
48
+ re-computed too (otherwise the algorithm has horrible instability). The pseudo
49
+ velocity states are not needed because they are effectively zero at the beginning
50
+ of each iteration. Since we have the current position error, we allow the
51
+ iterations to terminate early if the error becomes smaller than b2_linearSlop.
52
+
53
+ Full NGS or just NGS - Like Modified NGS except the effective mass are re-computed
54
+ each time a constraint is solved.
55
+
56
+ Here are the results:
57
+ Baumgarte - this is the cheapest algorithm but it has some stability problems,
58
+ especially with the bridge. The chain links separate easily close to the root
59
+ and they jitter struggle to pull together. This is one of the most common
60
+ methods in the field. The big drawback is that the position correction artificially
61
+ affects the momentum, thus leading to instabilities and false bounce. I used a
62
+ bias factor of 0.2. A larger bias factor makes the bridge less stable, a smaller
63
+ factor makes joints and contacts more spongy.
64
+
65
+ Pseudo Velocities - the is more stable than the Baumgarte method. The bridge is
66
+ stable. However, joints still separate with large angular velocities. Drag the
67
+ simple pendulum in a circle quickly and the joint will separate. The chain separates
68
+ easily and does not recover. I used a bias factor of 0.2. A larger value lead to
69
+ the bridge collapsing when a heavy cube drops on it.
70
+
71
+ Modified NGS - this algorithm is better in some ways than Baumgarte and Pseudo
72
+ Velocities, but in other ways it is worse. The bridge and chain are much more
73
+ stable, but the simple pendulum goes unstable at high angular velocities.
74
+
75
+ Full NGS - stable in all tests. The joints display good stiffness. The bridge
76
+ still sags, but this is better than infinite forces.
77
+
78
+ Recommendations
79
+ Pseudo Velocities are not really worthwhile because the bridge and chain cannot
80
+ recover from joint separation. In other cases the benefit over Baumgarte is small.
81
+
82
+ Modified NGS is not a robust method for the revolute joint due to the violent
83
+ instability seen in the simple pendulum. Perhaps it is viable with other constraint
84
+ types, especially scalar constraints where the effective mass is a scalar.
85
+
86
+ This leaves Baumgarte and Full NGS. Baumgarte has small, but manageable instabilities
87
+ and is very fast. I don't think we can escape Baumgarte, especially in highly
88
+ demanding cases where high constraint fidelity is not needed.
89
+
90
+ Full NGS is robust and easy on the eyes. I recommend this option for
91
+ higher fidelity simulation and certainly for suspension bridges and long chains.
92
+ Full NGS might be a good choice for ragdolls, especially motorized ragdolls where
93
+ joint separation can be problematic. The number of NGS iterations can be reduced
94
+ for better performance without harming robustness much.
95
+
96
+ Each joint in a can be handled differently in the position solver. So I recommend
97
+ a system where the user can select the algorithm on a per joint basis. I would
98
+ probably default to the slower Full NGS and let the user select the faster
99
+ Baumgarte method in performance critical scenarios.
100
+ */
101
+
102
+
103
+ var b2Island = Class.create();
104
+ b2Island.prototype =
105
+ {
106
+ initialize: function(bodyCapacity, contactCapacity, jointCapacity, allocator)
107
+ {
108
+ var i = 0;
109
+
110
+ this.m_bodyCapacity = bodyCapacity;
111
+ this.m_contactCapacity = contactCapacity;
112
+ this.m_jointCapacity = jointCapacity;
113
+ this.m_bodyCount = 0;
114
+ this.m_contactCount = 0;
115
+ this.m_jointCount = 0;
116
+
117
+
118
+ //this.m_bodies = (b2Body**)allocator->Allocate(bodyCapacity * sizeof(b2Body*));
119
+ this.m_bodies = new Array(bodyCapacity);
120
+ for (i = 0; i < bodyCapacity; i++)
121
+ this.m_bodies[i] = null;
122
+
123
+ //this.m_contacts = (b2Contact**)allocator->Allocate(contactCapacity * sizeof(b2Contact*));
124
+ this.m_contacts = new Array(contactCapacity);
125
+ for (i = 0; i < contactCapacity; i++)
126
+ this.m_contacts[i] = null;
127
+
128
+ //this.m_joints = (b2Joint**)allocator->Allocate(jointCapacity * sizeof(b2Joint*));
129
+ this.m_joints = new Array(jointCapacity);
130
+ for (i = 0; i < jointCapacity; i++)
131
+ this.m_joints[i] = null;
132
+
133
+ this.m_allocator = allocator;
134
+ },
135
+ //~b2Island();
136
+
137
+ Clear: function()
138
+ {
139
+ this.m_bodyCount = 0;
140
+ this.m_contactCount = 0;
141
+ this.m_jointCount = 0;
142
+ },
143
+
144
+ Solve: function(step, gravity)
145
+ {
146
+ var i = 0;
147
+ var b;
148
+
149
+ for (i = 0; i < this.m_bodyCount; ++i)
150
+ {
151
+ b = this.m_bodies[i];
152
+
153
+ if (b.m_invMass == 0.0)
154
+ continue;
155
+
156
+ b.m_linearVelocity.Add( b2Math.MulFV (step.dt, b2Math.AddVV(gravity, b2Math.MulFV( b.m_invMass, b.m_force ) ) ) );
157
+ b.m_angularVelocity += step.dt * b.m_invI * b.m_torque;
158
+
159
+ //b.m_linearVelocity *= b.m_linearDamping;
160
+ b.m_linearVelocity.Multiply(b.m_linearDamping);
161
+ b.m_angularVelocity *= b.m_angularDamping;
162
+
163
+ // Store positions for conservative advancement.
164
+ b.m_position0.SetV(b.m_position);
165
+ b.m_rotation0 = b.m_rotation;
166
+ }
167
+
168
+ var contactSolver = new b2ContactSolver(this.m_contacts, this.m_contactCount, this.m_allocator);
169
+
170
+ // Pre-solve
171
+ contactSolver.PreSolve();
172
+
173
+ for (i = 0; i < this.m_jointCount; ++i)
174
+ {
175
+ this.m_joints[i].PrepareVelocitySolver();
176
+ }
177
+
178
+ // this.Solve velocity constraints.
179
+ for (i = 0; i < step.iterations; ++i)
180
+ {
181
+ contactSolver.SolveVelocityConstraints();
182
+
183
+ for (var j = 0; j < this.m_jointCount; ++j)
184
+ {
185
+ this.m_joints[j].SolveVelocityConstraints(step);
186
+ }
187
+ }
188
+
189
+ // Integrate positions.
190
+ for (i = 0; i < this.m_bodyCount; ++i)
191
+ {
192
+ b = this.m_bodies[i];
193
+
194
+ if (b.m_invMass == 0.0)
195
+ continue;
196
+
197
+ //b.m_position.Add( b2Math.MulFV (step.dt, b.m_linearVelocity) );
198
+ b.m_position.x += step.dt * b.m_linearVelocity.x;
199
+ b.m_position.y += step.dt * b.m_linearVelocity.y;
200
+ b.m_rotation += step.dt * b.m_angularVelocity;
201
+
202
+ b.m_R.Set(b.m_rotation);
203
+ }
204
+
205
+ for (i = 0; i < this.m_jointCount; ++i)
206
+ {
207
+ this.m_joints[i].PreparePositionSolver();
208
+ }
209
+
210
+ // this.Solve position constraints.
211
+ if (b2World.s_enablePositionCorrection)
212
+ {
213
+ for (b2Island.m_positionIterationCount = 0; b2Island.m_positionIterationCount < step.iterations; ++b2Island.m_positionIterationCount)
214
+ {
215
+ var contactsOkay = contactSolver.SolvePositionConstraints(b2Settings.b2_contactBaumgarte);
216
+
217
+ var jointsOkay = true;
218
+ for (i = 0; i < this.m_jointCount; ++i)
219
+ {
220
+ var jointOkay = this.m_joints[i].SolvePositionConstraints();
221
+ jointsOkay = jointsOkay && jointOkay;
222
+ }
223
+
224
+ if (contactsOkay && jointsOkay)
225
+ {
226
+ break;
227
+ }
228
+ }
229
+ }
230
+
231
+ // Post-solve.
232
+ contactSolver.PostSolve();
233
+
234
+ // Synchronize shapes and reset forces.
235
+ for (i = 0; i < this.m_bodyCount; ++i)
236
+ {
237
+ b = this.m_bodies[i];
238
+
239
+ if (b.m_invMass == 0.0)
240
+ continue;
241
+
242
+ b.m_R.Set(b.m_rotation);
243
+
244
+ b.SynchronizeShapes();
245
+ b.m_force.Set(0.0, 0.0);
246
+ b.m_torque = 0.0;
247
+ }
248
+ },
249
+
250
+ UpdateSleep: function(dt)
251
+ {
252
+ var i = 0;
253
+ var b;
254
+
255
+ var minSleepTime = Number.MAX_VALUE;
256
+
257
+ var linTolSqr = b2Settings.b2_linearSleepTolerance * b2Settings.b2_linearSleepTolerance;
258
+ var angTolSqr = b2Settings.b2_angularSleepTolerance * b2Settings.b2_angularSleepTolerance;
259
+
260
+ for (i = 0; i < this.m_bodyCount; ++i)
261
+ {
262
+ b = this.m_bodies[i];
263
+ if (b.m_invMass == 0.0)
264
+ {
265
+ continue;
266
+ }
267
+
268
+ if ((b.m_flags & b2Body.e_allowSleepFlag) == 0)
269
+ {
270
+ b.m_sleepTime = 0.0;
271
+ minSleepTime = 0.0;
272
+ }
273
+
274
+ if ((b.m_flags & b2Body.e_allowSleepFlag) == 0 ||
275
+ b.m_angularVelocity * b.m_angularVelocity > angTolSqr ||
276
+ b2Math.b2Dot(b.m_linearVelocity, b.m_linearVelocity) > linTolSqr)
277
+ {
278
+ b.m_sleepTime = 0.0;
279
+ minSleepTime = 0.0;
280
+ }
281
+ else
282
+ {
283
+ b.m_sleepTime += dt;
284
+ minSleepTime = b2Math.b2Min(minSleepTime, b.m_sleepTime);
285
+ }
286
+ }
287
+
288
+ if (minSleepTime >= b2Settings.b2_timeToSleep)
289
+ {
290
+ for (i = 0; i < this.m_bodyCount; ++i)
291
+ {
292
+ b = this.m_bodies[i];
293
+ b.m_flags |= b2Body.e_sleepFlag;
294
+ }
295
+ }
296
+ },
297
+
298
+ AddBody: function(body)
299
+ {
300
+ //b2Settings.b2Assert(this.m_bodyCount < this.m_bodyCapacity);
301
+ this.m_bodies[this.m_bodyCount++] = body;
302
+ },
303
+
304
+ AddContact: function(contact)
305
+ {
306
+ //b2Settings.b2Assert(this.m_contactCount < this.m_contactCapacity);
307
+ this.m_contacts[this.m_contactCount++] = contact;
308
+ },
309
+
310
+ AddJoint: function(joint)
311
+ {
312
+ //b2Settings.b2Assert(this.m_jointCount < this.m_jointCapacity);
313
+ this.m_joints[this.m_jointCount++] = joint;
314
+ },
315
+
316
+ m_allocator: null,
317
+
318
+ m_bodies: null,
319
+ m_contacts: null,
320
+ m_joints: null,
321
+
322
+ m_bodyCount: 0,
323
+ m_jointCount: 0,
324
+ m_contactCount: 0,
325
+
326
+ m_bodyCapacity: 0,
327
+ m_contactCapacity: 0,
328
+ m_jointCapacity: 0,
329
+
330
+ m_positionError: null};
331
+ b2Island.m_positionIterationCount = 0;
@@ -0,0 +1,27 @@
1
+ /*
2
+ * Copyright (c) 2006-2007 Erin Catto http:
3
+ *
4
+ * This software is provided 'as-is', without any express or implied
5
+ * warranty. In no event will the authors be held liable for any damages
6
+ * arising from the use of this software.
7
+ * Permission is granted to anyone to use this software for any purpose,
8
+ * including commercial applications, and to alter it and redistribute it
9
+ * freely, subject to the following restrictions:
10
+ * 1. The origin of this software must not be misrepresented; you must not
11
+ * claim that you wrote the original software. If you use this software
12
+ * in a product, an acknowledgment in the product documentation would be
13
+ * appreciated but is not required.
14
+ * 2. Altered source versions must be plainly marked, and must not be
15
+ * misrepresented the original software.
16
+ * 3. This notice may not be removed or altered from any source distribution.
17
+ */
18
+
19
+
20
+
21
+ var b2TimeStep = Class.create();
22
+ b2TimeStep.prototype =
23
+ {
24
+ dt: null,
25
+ inv_dt: null,
26
+ iterations: 0,
27
+ initialize: function() {}};
@@ -0,0 +1,522 @@
1
+ /*
2
+ * Copyright (c) 2006-2007 Erin Catto http:
3
+ *
4
+ * This software is provided 'as-is', without any express or implied
5
+ * warranty. In no event will the authors be held liable for any damages
6
+ * arising from the use of this software.
7
+ * Permission is granted to anyone to use this software for any purpose,
8
+ * including commercial applications, and to alter it and redistribute it
9
+ * freely, subject to the following restrictions:
10
+ * 1. The origin of this software must not be misrepresented; you must not
11
+ * claim that you wrote the original software. If you use this software
12
+ * in a product, an acknowledgment in the product documentation would be
13
+ * appreciated but is not required.
14
+ * 2. Altered source versions must be plainly marked, and must not be
15
+ * misrepresented the original software.
16
+ * 3. This notice may not be removed or altered from any source distribution.
17
+ */
18
+
19
+
20
+
21
+
22
+ var b2World = Class.create();
23
+ b2World.prototype =
24
+ {
25
+ initialize: function(worldAABB, gravity, doSleep){
26
+ // initialize instance variables for references
27
+ this.step = new b2TimeStep();
28
+ this.m_contactManager = new b2ContactManager();
29
+ //
30
+
31
+
32
+ this.m_listener = null;
33
+ this.m_filter = b2CollisionFilter.b2_defaultFilter;
34
+
35
+ this.m_bodyList = null;
36
+ this.m_contactList = null;
37
+ this.m_jointList = null;
38
+
39
+ this.m_bodyCount = 0;
40
+ this.m_contactCount = 0;
41
+ this.m_jointCount = 0;
42
+
43
+ this.m_bodyDestroyList = null;
44
+
45
+ this.m_allowSleep = doSleep;
46
+
47
+ this.m_gravity = gravity;
48
+
49
+ this.m_contactManager.m_world = this;
50
+ this.m_broadPhase = new b2BroadPhase(worldAABB, this.m_contactManager);
51
+
52
+ var bd = new b2BodyDef();
53
+ this.m_groundBody = this.CreateBody(bd);
54
+ },
55
+ //~b2World(){
56
+ // this.DestroyBody(this.m_groundBody);
57
+ // delete this.m_broadPhase;
58
+ //}
59
+
60
+ // Set a callback to notify you when a joint is implicitly destroyed
61
+ // when an attached body is destroyed.
62
+ SetListener: function(listener){
63
+ this.m_listener = listener;
64
+ },
65
+
66
+ // Register a collision filter to provide specific control over collision.
67
+ // Otherwise the default filter is used (b2CollisionFilter).
68
+ SetFilter: function(filter){
69
+ this.m_filter = filter;
70
+ },
71
+
72
+ // Create and destroy rigid bodies. Destruction is deferred until the
73
+ // the next call to this.Step. This is done so that bodies may be destroyed
74
+ // while you iterate through the contact list.
75
+ CreateBody: function(def){
76
+ //void* mem = this.m_blockAllocator.Allocate(sizeof(b2Body));
77
+ var b = new b2Body(def, this);
78
+ b.m_prev = null;
79
+
80
+ b.m_next = this.m_bodyList;
81
+ if (this.m_bodyList)
82
+ {
83
+ this.m_bodyList.m_prev = b;
84
+ }
85
+ this.m_bodyList = b;
86
+ ++this.m_bodyCount;
87
+
88
+ return b;
89
+ },
90
+ // Body destruction is deferred to make contact processing more robust.
91
+ DestroyBody: function(b)
92
+ {
93
+
94
+ if (b.m_flags & b2Body.e_destroyFlag)
95
+ {
96
+ return;
97
+ }
98
+
99
+ // Remove from normal body list.
100
+ if (b.m_prev)
101
+ {
102
+ b.m_prev.m_next = b.m_next;
103
+ }
104
+
105
+ if (b.m_next)
106
+ {
107
+ b.m_next.m_prev = b.m_prev;
108
+ }
109
+
110
+ if (b == this.m_bodyList)
111
+ {
112
+ this.m_bodyList = b.m_next;
113
+ }
114
+
115
+ b.m_flags |= b2Body.e_destroyFlag;
116
+ //b2Settings.b2Assert(this.m_bodyCount > 0);
117
+ --this.m_bodyCount;
118
+
119
+ //b->~b2Body();
120
+ //b.Destroy();
121
+ // Add to the deferred destruction list.
122
+ b.m_prev = null;
123
+ b.m_next = this.m_bodyDestroyList;
124
+ this.m_bodyDestroyList = b;
125
+ },
126
+
127
+ CleanBodyList: function()
128
+ {
129
+ this.m_contactManager.m_destroyImmediate = true;
130
+
131
+ var b = this.m_bodyDestroyList;
132
+ while (b)
133
+ {
134
+ //b2Settings.b2Assert((b.m_flags & b2Body.e_destroyFlag) != 0);
135
+
136
+ // Preserve the next pointer.
137
+ var b0 = b;
138
+ b = b.m_next;
139
+
140
+ // Delete the attached joints
141
+ var jn = b0.m_jointList;
142
+ while (jn)
143
+ {
144
+ var jn0 = jn;
145
+ jn = jn.next;
146
+
147
+ if (this.m_listener)
148
+ {
149
+ this.m_listener.NotifyJointDestroyed(jn0.joint);
150
+ }
151
+
152
+ this.DestroyJoint(jn0.joint);
153
+ }
154
+
155
+ b0.Destroy();
156
+ //this.m_blockAllocator.Free(b0, sizeof(b2Body));
157
+ }
158
+
159
+ // Reset the list.
160
+ this.m_bodyDestroyList = null;
161
+
162
+ this.m_contactManager.m_destroyImmediate = false;
163
+ },
164
+
165
+ CreateJoint: function(def){
166
+ var j = b2Joint.Create(def, this.m_blockAllocator);
167
+
168
+ // Connect to the world list.
169
+ j.m_prev = null;
170
+ j.m_next = this.m_jointList;
171
+ if (this.m_jointList)
172
+ {
173
+ this.m_jointList.m_prev = j;
174
+ }
175
+ this.m_jointList = j;
176
+ ++this.m_jointCount;
177
+
178
+ // Connect to the bodies
179
+ j.m_node1.joint = j;
180
+ j.m_node1.other = j.m_body2;
181
+ j.m_node1.prev = null;
182
+ j.m_node1.next = j.m_body1.m_jointList;
183
+ if (j.m_body1.m_jointList) j.m_body1.m_jointList.prev = j.m_node1;
184
+ j.m_body1.m_jointList = j.m_node1;
185
+
186
+ j.m_node2.joint = j;
187
+ j.m_node2.other = j.m_body1;
188
+ j.m_node2.prev = null;
189
+ j.m_node2.next = j.m_body2.m_jointList;
190
+ if (j.m_body2.m_jointList) j.m_body2.m_jointList.prev = j.m_node2;
191
+ j.m_body2.m_jointList = j.m_node2;
192
+
193
+ // If the joint prevents collisions, then reset collision filtering.
194
+ if (def.collideConnected == false)
195
+ {
196
+ // Reset the proxies on the body with the minimum number of shapes.
197
+ var b = def.body1.m_shapeCount < def.body2.m_shapeCount ? def.body1 : def.body2;
198
+ for (var s = b.m_shapeList; s; s = s.m_next)
199
+ {
200
+ s.ResetProxy(this.m_broadPhase);
201
+ }
202
+ }
203
+
204
+ return j;
205
+ },
206
+ DestroyJoint: function(j)
207
+ {
208
+
209
+ var collideConnected = j.m_collideConnected;
210
+
211
+ // Remove from the world.
212
+ if (j.m_prev)
213
+ {
214
+ j.m_prev.m_next = j.m_next;
215
+ }
216
+
217
+ if (j.m_next)
218
+ {
219
+ j.m_next.m_prev = j.m_prev;
220
+ }
221
+
222
+ if (j == this.m_jointList)
223
+ {
224
+ this.m_jointList = j.m_next;
225
+ }
226
+
227
+ // Disconnect from island graph.
228
+ var body1 = j.m_body1;
229
+ var body2 = j.m_body2;
230
+
231
+ // Wake up touching bodies.
232
+ body1.WakeUp();
233
+ body2.WakeUp();
234
+
235
+ // Remove from body 1
236
+ if (j.m_node1.prev)
237
+ {
238
+ j.m_node1.prev.next = j.m_node1.next;
239
+ }
240
+
241
+ if (j.m_node1.next)
242
+ {
243
+ j.m_node1.next.prev = j.m_node1.prev;
244
+ }
245
+
246
+ if (j.m_node1 == body1.m_jointList)
247
+ {
248
+ body1.m_jointList = j.m_node1.next;
249
+ }
250
+
251
+ j.m_node1.prev = null;
252
+ j.m_node1.next = null;
253
+
254
+ // Remove from body 2
255
+ if (j.m_node2.prev)
256
+ {
257
+ j.m_node2.prev.next = j.m_node2.next;
258
+ }
259
+
260
+ if (j.m_node2.next)
261
+ {
262
+ j.m_node2.next.prev = j.m_node2.prev;
263
+ }
264
+
265
+ if (j.m_node2 == body2.m_jointList)
266
+ {
267
+ body2.m_jointList = j.m_node2.next;
268
+ }
269
+
270
+ j.m_node2.prev = null;
271
+ j.m_node2.next = null;
272
+
273
+ b2Joint.Destroy(j, this.m_blockAllocator);
274
+
275
+ //b2Settings.b2Assert(this.m_jointCount > 0);
276
+ --this.m_jointCount;
277
+
278
+ // If the joint prevents collisions, then reset collision filtering.
279
+ if (collideConnected == false)
280
+ {
281
+ // Reset the proxies on the body with the minimum number of shapes.
282
+ var b = body1.m_shapeCount < body2.m_shapeCount ? body1 : body2;
283
+ for (var s = b.m_shapeList; s; s = s.m_next)
284
+ {
285
+ s.ResetProxy(this.m_broadPhase);
286
+ }
287
+ }
288
+ },
289
+
290
+ // The world provides a single ground body with no collision shapes. You
291
+ // can use this to simplify the creation of joints.
292
+ GetGroundBody: function(){
293
+ return this.m_groundBody;
294
+ },
295
+
296
+
297
+ step: new b2TimeStep(),
298
+ // this.Step
299
+ Step: function(dt, iterations){
300
+
301
+ var b;
302
+ var other;
303
+
304
+
305
+ this.step.dt = dt;
306
+ this.step.iterations = iterations;
307
+ if (dt > 0.0)
308
+ {
309
+ this.step.inv_dt = 1.0 / dt;
310
+ }
311
+ else
312
+ {
313
+ this.step.inv_dt = 0.0;
314
+ }
315
+
316
+ this.m_positionIterationCount = 0;
317
+
318
+ // Handle deferred contact destruction.
319
+ this.m_contactManager.CleanContactList();
320
+
321
+ // Handle deferred body destruction.
322
+ this.CleanBodyList();
323
+
324
+ // Update contacts.
325
+ this.m_contactManager.Collide();
326
+
327
+ // Size the island for the worst case.
328
+ var island = new b2Island(this.m_bodyCount, this.m_contactCount, this.m_jointCount, this.m_stackAllocator);
329
+
330
+ // Clear all the island flags.
331
+ for (b = this.m_bodyList; b != null; b = b.m_next)
332
+ {
333
+ b.m_flags &= ~b2Body.e_islandFlag;
334
+ }
335
+ for (var c = this.m_contactList; c != null; c = c.m_next)
336
+ {
337
+ c.m_flags &= ~b2Contact.e_islandFlag;
338
+ }
339
+ for (var j = this.m_jointList; j != null; j = j.m_next)
340
+ {
341
+ j.m_islandFlag = false;
342
+ }
343
+
344
+ // Build and simulate all awake islands.
345
+ var stackSize = this.m_bodyCount;
346
+ //var stack = (b2Body**)this.m_stackAllocator.Allocate(stackSize * sizeof(b2Body*));
347
+ var stack = new Array(this.m_bodyCount);
348
+ for (var k = 0; k < this.m_bodyCount; k++)
349
+ stack[k] = null;
350
+
351
+ for (var seed = this.m_bodyList; seed != null; seed = seed.m_next)
352
+ {
353
+ if (seed.m_flags & (b2Body.e_staticFlag | b2Body.e_islandFlag | b2Body.e_sleepFlag | b2Body.e_frozenFlag))
354
+ {
355
+ continue;
356
+ }
357
+
358
+ // Reset island and stack.
359
+ island.Clear();
360
+ var stackCount = 0;
361
+ stack[stackCount++] = seed;
362
+ seed.m_flags |= b2Body.e_islandFlag;;
363
+
364
+ // Perform a depth first search (DFS) on the constraint graph.
365
+ while (stackCount > 0)
366
+ {
367
+ // Grab the next body off the stack and add it to the island.
368
+ b = stack[--stackCount];
369
+ island.AddBody(b);
370
+
371
+ // Make sure the body is awake.
372
+ b.m_flags &= ~b2Body.e_sleepFlag;
373
+
374
+ // To keep islands, we don't
375
+ // propagate islands across static bodies.
376
+ if (b.m_flags & b2Body.e_staticFlag)
377
+ {
378
+ continue;
379
+ }
380
+
381
+ // Search all contacts connected to this body.
382
+ for (var cn = b.m_contactList; cn != null; cn = cn.next)
383
+ {
384
+ if (cn.contact.m_flags & b2Contact.e_islandFlag)
385
+ {
386
+ continue;
387
+ }
388
+
389
+ island.AddContact(cn.contact);
390
+ cn.contact.m_flags |= b2Contact.e_islandFlag;
391
+
392
+ other = cn.other;
393
+ if (other.m_flags & b2Body.e_islandFlag)
394
+ {
395
+ continue;
396
+ }
397
+
398
+ //b2Settings.b2Assert(stackCount < stackSize);
399
+ stack[stackCount++] = other;
400
+ other.m_flags |= b2Body.e_islandFlag;
401
+ }
402
+
403
+ // Search all joints connect to this body.
404
+ for (var jn = b.m_jointList; jn != null; jn = jn.next)
405
+ {
406
+ if (jn.joint.m_islandFlag == true)
407
+ {
408
+ continue;
409
+ }
410
+
411
+ island.AddJoint(jn.joint);
412
+ jn.joint.m_islandFlag = true;
413
+
414
+ other = jn.other;
415
+ if (other.m_flags & b2Body.e_islandFlag)
416
+ {
417
+ continue;
418
+ }
419
+
420
+ //b2Settings.b2Assert(stackCount < stackSize);
421
+ stack[stackCount++] = other;
422
+ other.m_flags |= b2Body.e_islandFlag;
423
+ }
424
+ }
425
+
426
+ island.Solve(this.step, this.m_gravity);
427
+
428
+ this.m_positionIterationCount = b2Math.b2Max(this.m_positionIterationCount, b2Island.m_positionIterationCount);
429
+
430
+ if (this.m_allowSleep)
431
+ {
432
+ island.UpdateSleep(dt);
433
+ }
434
+
435
+ // Post solve cleanup.
436
+ for (var i = 0; i < island.m_bodyCount; ++i)
437
+ {
438
+ // Allow static bodies to participate in other islands.
439
+ b = island.m_bodies[i];
440
+ if (b.m_flags & b2Body.e_staticFlag)
441
+ {
442
+ b.m_flags &= ~b2Body.e_islandFlag;
443
+ }
444
+
445
+ // Handle newly frozen bodies.
446
+ if (b.IsFrozen() && this.m_listener)
447
+ {
448
+ var response = this.m_listener.NotifyBoundaryViolated(b);
449
+ if (response == b2WorldListener.b2_destroyBody)
450
+ {
451
+ this.DestroyBody(b);
452
+ b = null;
453
+ island.m_bodies[i] = null;
454
+ }
455
+ }
456
+ }
457
+ }
458
+
459
+ this.m_broadPhase.Commit();
460
+
461
+ //this.m_stackAllocator.Free(stack);
462
+ },
463
+
464
+ // this.Query the world for all shapes that potentially overlap the
465
+ // provided AABB. You provide a shape pointer buffer of specified
466
+ // size. The number of shapes found is returned.
467
+ Query: function(aabb, shapes, maxCount){
468
+
469
+ //void** results = (void**)this.m_stackAllocator.Allocate(maxCount * sizeof(void*));
470
+ var results = new Array();
471
+ var count = this.m_broadPhase.QueryAABB(aabb, results, maxCount);
472
+
473
+ for (var i = 0; i < count; ++i)
474
+ {
475
+ shapes[i] = results[i];
476
+ }
477
+
478
+ //this.m_stackAllocator.Free(results);
479
+ return count;
480
+ },
481
+
482
+ // You can use these to iterate over all the bodies, joints, and contacts.
483
+ GetBodyList: function(){
484
+ return this.m_bodyList;
485
+ },
486
+ GetJointList: function(){
487
+ return this.m_jointList;
488
+ },
489
+ GetContactList: function(){
490
+ return this.m_contactList;
491
+ },
492
+
493
+ //--------------- Internals Below -------------------
494
+
495
+ m_blockAllocator: null,
496
+ m_stackAllocator: null,
497
+
498
+ m_broadPhase: null,
499
+ m_contactManager: new b2ContactManager(),
500
+
501
+ m_bodyList: null,
502
+ m_contactList: null,
503
+ m_jointList: null,
504
+
505
+ m_bodyCount: 0,
506
+ m_contactCount: 0,
507
+ m_jointCount: 0,
508
+
509
+ // These bodies will be destroyed at the next time this.step.
510
+ m_bodyDestroyList: null,
511
+
512
+ m_gravity: null,
513
+ m_allowSleep: null,
514
+
515
+ m_groundBody: null,
516
+
517
+ m_listener: null,
518
+ m_filter: null,
519
+
520
+ m_positionIterationCount: 0};
521
+ b2World.s_enablePositionCorrection = 1;
522
+ b2World.s_enableWarmStarting = 1;