2 * Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com
4 * Permission to use, copy, modify, distribute and sell this software
5 * and its documentation for any purpose is hereby granted without fee,
6 * provided that the above copyright notice appear in all copies.
7 * Erin Catto makes no representations about the suitability
8 * of this software for any purpose.
9 * It is provided "as is" without express or implied warranty.
13 import b2dlite
.arbiter
;
14 import b2dlite
.mathutils
;
18 private import b2dlite
.bbody
: Body
;
24 this (Body b1
, Body b2
) { if (b1
< b2
) { body1
= b1
; body2
= b2
; } else { body1
= b2
; body2
= b1
; } }
29 private import b2dlite
.bbody
, b2dlite
.joint
;
33 Arbiter
[ArbiterKey
] arbiters
;
37 static bool accumulateImpulses
= true;
38 static bool warmStarting
= true;
39 static bool positionCorrection
= true;
42 this() (in auto ref Vec2 agravity
, int aiterations
) {
44 iterations
= aiterations
;
47 void Add (Body bbody
) {
48 if (bbody
!is null) bodies
~= bbody
;
51 void Add (Joint joint
) {
52 if (joint
!is null) joints
~= joint
;
61 void Step (float dt) {
62 float inv_dt
= (dt > 0.0f ?
1.0f/dt : 0.0f);
63 // determine overlapping bodies and update contact points
66 for (int i
= 0; i
< bodies
.length
; ++i
) {
68 if (b
.invMass
== 0.0f) continue;
69 b
.velocity
+= dt*(gravity
+b
.invMass
*b
.force
);
70 b
.angularVelocity
+= dt*b
.invI
*b
.torque
;
73 foreach (Arbiter arb
; arbiters
.byValue
) arb
.PreStep(inv_dt
);
74 for (int i
= 0; i
< joints
.length
; ++i
) joints
[i
].PreStep(inv_dt
);
76 for (int i
= 0; i
< iterations
; ++i
) {
77 foreach (Arbiter arb
; arbiters
.byValue
) arb
.ApplyImpulse();
78 for (int j
= 0; j
< joints
.length
; ++j
) joints
[j
].ApplyImpulse();
80 // integrate velocities
81 for (int i
= 0; i
< bodies
.length
; ++i
) {
84 b
.position
+= dt*b
.velocity
;
85 b
.rotation
+= dt*b
.angularVelocity
;
87 b
.force
.Set(0.0f, 0.0f);
94 for (int i
= 0; i
< bodies
.length
; ++i
) {
96 for (int j
= i
+1; j
< bodies
.length
; ++j
) {
98 if (bi
.invMass
== 0.0f && bj
.invMass
== 0.0f) continue;
99 auto newArb
= new Arbiter(bi
, bj
);
100 if (auto arb
= ArbiterKey(bi
, bj
) in arbiters
) {
101 arb
.Update(newArb
.contacts
.ptr
, newArb
.numContacts
);
103 arbiters
[ArbiterKey(bi
, bj
)] = newArb
;
108 foreach (ref kv; arbiters.byKeyValue) {
109 if (kv.key.body1 is bi && kv.key.body2 is bj) {
111 kv.value.Update(newArb.contacts.ptr, newArb.numContacts);
115 if (!found) arbiters[ArbiterKey(bi, bj)] = newArb;
118 auto newArb = new Arbiter(bi, bj);
119 auto key = new ArbiterKey(bi, bj);
120 if (newArb.numContacts > 0) {
121 ArbIter iter = arbiters.find(key);
122 if (iter == arbiters.end()) {
123 arbiters.insert(ArbPair(key, newArb));
125 iter.second.Update(newArb.contacts, newArb.numContacts);