pbox2d 0.6.0-java → 0.8.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (154) hide show
  1. checksums.yaml +4 -4
  2. data/.mvn/extensions.xml +8 -0
  3. data/.mvn/wrapper/maven-wrapper.properties +1 -0
  4. data/.travis.yml +23 -0
  5. data/CHANGELOG.md +8 -0
  6. data/README.md +7 -7
  7. data/Rakefile +1 -2
  8. data/lib/box2d.jar +0 -0
  9. data/lib/pbox2d/version.rb +1 -1
  10. data/lib/pbox2d.rb +1 -0
  11. data/pbox2d.gemspec +6 -11
  12. data/pom.rb +59 -0
  13. data/pom.xml +82 -73
  14. data/src/org/jbox2d/JBox2D.gwt.xml +12 -0
  15. data/src/org/jbox2d/callbacks/ContactAdaptor.java +27 -0
  16. data/src/org/jbox2d/callbacks/ContactFilter.java +59 -0
  17. data/src/org/jbox2d/callbacks/ContactImpulse.java +42 -0
  18. data/src/org/jbox2d/callbacks/ContactListener.java +87 -0
  19. data/src/org/jbox2d/callbacks/DebugDraw.java +297 -0
  20. data/src/org/jbox2d/callbacks/DestructionListener.java +53 -0
  21. data/src/org/jbox2d/callbacks/PairCallback.java +29 -0
  22. data/src/org/jbox2d/callbacks/ParticleDestructionListener.java +20 -0
  23. data/src/org/jbox2d/callbacks/ParticleQueryCallback.java +19 -0
  24. data/src/org/jbox2d/callbacks/ParticleRaycastCallback.java +19 -0
  25. data/src/org/jbox2d/callbacks/QueryCallback.java +45 -0
  26. data/src/org/jbox2d/callbacks/RayCastCallback.java +55 -0
  27. data/src/org/jbox2d/callbacks/TreeCallback.java +42 -0
  28. data/src/org/jbox2d/callbacks/TreeRayCastCallback.java +44 -0
  29. data/src/org/jbox2d/collision/AABB.java +338 -0
  30. data/src/org/jbox2d/collision/Collision.java +1444 -0
  31. data/src/org/jbox2d/collision/ContactID.java +106 -0
  32. data/src/org/jbox2d/collision/Distance.java +773 -0
  33. data/src/org/jbox2d/collision/DistanceInput.java +41 -0
  34. data/src/org/jbox2d/collision/DistanceOutput.java +43 -0
  35. data/src/org/jbox2d/collision/Manifold.java +116 -0
  36. data/src/org/jbox2d/collision/ManifoldPoint.java +104 -0
  37. data/src/org/jbox2d/collision/RayCastInput.java +47 -0
  38. data/src/org/jbox2d/collision/RayCastOutput.java +46 -0
  39. data/src/org/jbox2d/collision/TimeOfImpact.java +526 -0
  40. data/src/org/jbox2d/collision/WorldManifold.java +200 -0
  41. data/src/org/jbox2d/collision/broadphase/BroadPhase.java +92 -0
  42. data/src/org/jbox2d/collision/broadphase/BroadPhaseStrategy.java +88 -0
  43. data/src/org/jbox2d/collision/broadphase/DefaultBroadPhaseBuffer.java +268 -0
  44. data/src/org/jbox2d/collision/broadphase/DynamicTree.java +883 -0
  45. data/src/org/jbox2d/collision/broadphase/DynamicTreeFlatNodes.java +873 -0
  46. data/src/org/jbox2d/collision/broadphase/DynamicTreeNode.java +54 -0
  47. data/src/org/jbox2d/collision/broadphase/Pair.java +46 -0
  48. data/src/org/jbox2d/collision/shapes/ChainShape.java +264 -0
  49. data/src/org/jbox2d/collision/shapes/CircleShape.java +207 -0
  50. data/src/org/jbox2d/collision/shapes/EdgeShape.java +254 -0
  51. data/src/org/jbox2d/collision/shapes/MassData.java +105 -0
  52. data/src/org/jbox2d/collision/shapes/PolygonShape.java +718 -0
  53. data/src/org/jbox2d/collision/shapes/Shape.java +136 -0
  54. data/src/org/jbox2d/collision/shapes/ShapeType.java +32 -0
  55. data/src/org/jbox2d/common/BufferUtils.java +209 -0
  56. data/src/org/jbox2d/common/Color3f.java +88 -0
  57. data/src/org/jbox2d/common/IViewportTransform.java +133 -0
  58. data/src/org/jbox2d/common/Mat22.java +609 -0
  59. data/src/org/jbox2d/common/Mat33.java +290 -0
  60. data/src/org/jbox2d/common/MathUtils.java +335 -0
  61. data/src/org/jbox2d/common/OBBViewportTransform.java +174 -0
  62. data/src/org/jbox2d/common/PlatformMathUtils.java +46 -0
  63. data/src/org/jbox2d/common/RaycastResult.java +37 -0
  64. data/src/org/jbox2d/common/Rot.java +150 -0
  65. data/src/org/jbox2d/common/Settings.java +246 -0
  66. data/src/org/jbox2d/common/Sweep.java +116 -0
  67. data/src/org/jbox2d/common/Timer.java +46 -0
  68. data/src/org/jbox2d/common/Transform.java +203 -0
  69. data/src/org/jbox2d/common/Vec2.java +388 -0
  70. data/src/org/jbox2d/common/Vec3.java +170 -0
  71. data/src/org/jbox2d/dynamics/Body.java +1246 -0
  72. data/src/org/jbox2d/dynamics/BodyDef.java +382 -0
  73. data/src/org/jbox2d/dynamics/BodyType.java +41 -0
  74. data/src/org/jbox2d/dynamics/ContactManager.java +293 -0
  75. data/src/org/jbox2d/dynamics/Filter.java +62 -0
  76. data/src/org/jbox2d/dynamics/Fixture.java +454 -0
  77. data/src/org/jbox2d/dynamics/FixtureDef.java +214 -0
  78. data/src/org/jbox2d/dynamics/FixtureProxy.java +38 -0
  79. data/src/org/jbox2d/dynamics/Island.java +602 -0
  80. data/src/org/jbox2d/dynamics/Profile.java +97 -0
  81. data/src/org/jbox2d/dynamics/SolverData.java +33 -0
  82. data/src/org/jbox2d/dynamics/TimeStep.java +46 -0
  83. data/src/org/jbox2d/dynamics/World.java +2075 -0
  84. data/src/org/jbox2d/dynamics/contacts/ChainAndCircleContact.java +57 -0
  85. data/src/org/jbox2d/dynamics/contacts/ChainAndPolygonContact.java +57 -0
  86. data/src/org/jbox2d/dynamics/contacts/CircleContact.java +50 -0
  87. data/src/org/jbox2d/dynamics/contacts/Contact.java +365 -0
  88. data/src/org/jbox2d/dynamics/contacts/ContactCreator.java +35 -0
  89. data/src/org/jbox2d/dynamics/contacts/ContactEdge.java +56 -0
  90. data/src/org/jbox2d/dynamics/contacts/ContactPositionConstraint.java +49 -0
  91. data/src/org/jbox2d/dynamics/contacts/ContactRegister.java +31 -0
  92. data/src/org/jbox2d/dynamics/contacts/ContactSolver.java +1104 -0
  93. data/src/org/jbox2d/dynamics/contacts/ContactVelocityConstraint.java +60 -0
  94. data/src/org/jbox2d/dynamics/contacts/EdgeAndCircleContact.java +52 -0
  95. data/src/org/jbox2d/dynamics/contacts/EdgeAndPolygonContact.java +52 -0
  96. data/src/org/jbox2d/dynamics/contacts/PolygonAndCircleContact.java +51 -0
  97. data/src/org/jbox2d/dynamics/contacts/PolygonContact.java +50 -0
  98. data/src/org/jbox2d/dynamics/contacts/Position.java +31 -0
  99. data/src/org/jbox2d/dynamics/contacts/Velocity.java +31 -0
  100. data/src/org/jbox2d/dynamics/joints/ConstantVolumeJoint.java +258 -0
  101. data/src/org/jbox2d/dynamics/joints/ConstantVolumeJointDef.java +75 -0
  102. data/src/org/jbox2d/dynamics/joints/DistanceJoint.java +356 -0
  103. data/src/org/jbox2d/dynamics/joints/DistanceJointDef.java +106 -0
  104. data/src/org/jbox2d/dynamics/joints/FrictionJoint.java +294 -0
  105. data/src/org/jbox2d/dynamics/joints/FrictionJointDef.java +78 -0
  106. data/src/org/jbox2d/dynamics/joints/GearJoint.java +520 -0
  107. data/src/org/jbox2d/dynamics/joints/GearJointDef.java +58 -0
  108. data/src/org/jbox2d/dynamics/joints/Jacobian.java +32 -0
  109. data/src/org/jbox2d/dynamics/joints/Joint.java +235 -0
  110. data/src/org/jbox2d/dynamics/joints/JointDef.java +65 -0
  111. data/src/org/jbox2d/dynamics/joints/JointEdge.java +57 -0
  112. data/src/org/jbox2d/dynamics/joints/JointType.java +28 -0
  113. data/src/org/jbox2d/dynamics/joints/LimitState.java +28 -0
  114. data/src/org/jbox2d/dynamics/joints/MotorJoint.java +339 -0
  115. data/src/org/jbox2d/dynamics/joints/MotorJointDef.java +55 -0
  116. data/src/org/jbox2d/dynamics/joints/MouseJoint.java +262 -0
  117. data/src/org/jbox2d/dynamics/joints/MouseJointDef.java +62 -0
  118. data/src/org/jbox2d/dynamics/joints/PrismaticJoint.java +808 -0
  119. data/src/org/jbox2d/dynamics/joints/PrismaticJointDef.java +120 -0
  120. data/src/org/jbox2d/dynamics/joints/PulleyJoint.java +393 -0
  121. data/src/org/jbox2d/dynamics/joints/PulleyJointDef.java +105 -0
  122. data/src/org/jbox2d/dynamics/joints/RevoluteJoint.java +554 -0
  123. data/src/org/jbox2d/dynamics/joints/RevoluteJointDef.java +137 -0
  124. data/src/org/jbox2d/dynamics/joints/RopeJoint.java +276 -0
  125. data/src/org/jbox2d/dynamics/joints/RopeJointDef.java +34 -0
  126. data/src/org/jbox2d/dynamics/joints/WeldJoint.java +424 -0
  127. data/src/org/jbox2d/dynamics/joints/WeldJointDef.java +85 -0
  128. data/src/org/jbox2d/dynamics/joints/WheelJoint.java +498 -0
  129. data/src/org/jbox2d/dynamics/joints/WheelJointDef.java +98 -0
  130. data/src/org/jbox2d/particle/ParticleBodyContact.java +17 -0
  131. data/src/org/jbox2d/particle/ParticleColor.java +52 -0
  132. data/src/org/jbox2d/particle/ParticleContact.java +14 -0
  133. data/src/org/jbox2d/particle/ParticleDef.java +24 -0
  134. data/src/org/jbox2d/particle/ParticleGroup.java +154 -0
  135. data/src/org/jbox2d/particle/ParticleGroupDef.java +62 -0
  136. data/src/org/jbox2d/particle/ParticleGroupType.java +8 -0
  137. data/src/org/jbox2d/particle/ParticleSystem.java +2172 -0
  138. data/src/org/jbox2d/particle/ParticleType.java +28 -0
  139. data/src/org/jbox2d/particle/StackQueue.java +44 -0
  140. data/src/org/jbox2d/particle/VoronoiDiagram.java +209 -0
  141. data/src/org/jbox2d/pooling/IDynamicStack.java +47 -0
  142. data/src/org/jbox2d/pooling/IOrderedStack.java +57 -0
  143. data/src/org/jbox2d/pooling/IWorldPool.java +101 -0
  144. data/src/org/jbox2d/pooling/arrays/FloatArray.java +50 -0
  145. data/src/org/jbox2d/pooling/arrays/GeneratorArray.java +33 -0
  146. data/src/org/jbox2d/pooling/arrays/IntArray.java +53 -0
  147. data/src/org/jbox2d/pooling/arrays/Vec2Array.java +57 -0
  148. data/src/org/jbox2d/pooling/normal/CircleStack.java +77 -0
  149. data/src/org/jbox2d/pooling/normal/DefaultWorldPool.java +331 -0
  150. data/src/org/jbox2d/pooling/normal/MutableStack.java +72 -0
  151. data/src/org/jbox2d/pooling/normal/OrderedStack.java +73 -0
  152. data/src/org/jbox2d/pooling/stacks/DynamicIntStack.java +60 -0
  153. metadata +161 -14
  154. data/lib/jbox2d-library-2.3.1-SNAPSHOT.jar +0 -0
@@ -0,0 +1,1104 @@
1
+ /*******************************************************************************
2
+ * Copyright (c) 2013, Daniel Murphy
3
+ * All rights reserved.
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without modification,
6
+ * are permitted provided that the following conditions are met:
7
+ * * Redistributions of source code must retain the above copyright notice,
8
+ * this list of conditions and the following disclaimer.
9
+ * * Redistributions in binary form must reproduce the above copyright notice,
10
+ * this list of conditions and the following disclaimer in the documentation
11
+ * and/or other materials provided with the distribution.
12
+ *
13
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
14
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
17
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
19
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
20
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
21
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
22
+ * POSSIBILITY OF SUCH DAMAGE.
23
+ ******************************************************************************/
24
+ package org.jbox2d.dynamics.contacts;
25
+
26
+ import org.jbox2d.collision.Manifold;
27
+ import org.jbox2d.collision.ManifoldPoint;
28
+ import org.jbox2d.collision.WorldManifold;
29
+ import org.jbox2d.collision.shapes.Shape;
30
+ import org.jbox2d.common.Mat22;
31
+ import org.jbox2d.common.MathUtils;
32
+ import org.jbox2d.common.Rot;
33
+ import org.jbox2d.common.Settings;
34
+ import org.jbox2d.common.Transform;
35
+ import org.jbox2d.common.Vec2;
36
+ import org.jbox2d.dynamics.Body;
37
+ import org.jbox2d.dynamics.Fixture;
38
+ import org.jbox2d.dynamics.TimeStep;
39
+ import org.jbox2d.dynamics.contacts.ContactVelocityConstraint.VelocityConstraintPoint;
40
+
41
+ /**
42
+ * @author Daniel
43
+ */
44
+ public class ContactSolver {
45
+
46
+ public static final boolean DEBUG_SOLVER = false;
47
+ public static final float k_errorTol = 1e-3f;
48
+ /**
49
+ * For each solver, this is the initial number of constraints in the array, which expands as
50
+ * needed.
51
+ */
52
+ public static final int INITIAL_NUM_CONSTRAINTS = 256;
53
+
54
+ /**
55
+ * Ensure a reasonable condition number. for the block solver
56
+ */
57
+ public static final float k_maxConditionNumber = 100.0f;
58
+
59
+ public TimeStep m_step;
60
+ public Position[] m_positions;
61
+ public Velocity[] m_velocities;
62
+ public ContactPositionConstraint[] m_positionConstraints;
63
+ public ContactVelocityConstraint[] m_velocityConstraints;
64
+ public Contact[] m_contacts;
65
+ public int m_count;
66
+
67
+ public ContactSolver() {
68
+ m_positionConstraints = new ContactPositionConstraint[INITIAL_NUM_CONSTRAINTS];
69
+ m_velocityConstraints = new ContactVelocityConstraint[INITIAL_NUM_CONSTRAINTS];
70
+ for (int i = 0; i < INITIAL_NUM_CONSTRAINTS; i++) {
71
+ m_positionConstraints[i] = new ContactPositionConstraint();
72
+ m_velocityConstraints[i] = new ContactVelocityConstraint();
73
+ }
74
+ }
75
+
76
+ public final void init(ContactSolverDef def) {
77
+ // System.out.println("Initializing contact solver");
78
+ m_step = def.step;
79
+ m_count = def.count;
80
+
81
+ if (m_positionConstraints.length < m_count) {
82
+ ContactPositionConstraint[] old = m_positionConstraints;
83
+ m_positionConstraints = new ContactPositionConstraint[MathUtils.max(old.length * 2, m_count)];
84
+ System.arraycopy(old, 0, m_positionConstraints, 0, old.length);
85
+ for (int i = old.length; i < m_positionConstraints.length; i++) {
86
+ m_positionConstraints[i] = new ContactPositionConstraint();
87
+ }
88
+ }
89
+
90
+ if (m_velocityConstraints.length < m_count) {
91
+ ContactVelocityConstraint[] old = m_velocityConstraints;
92
+ m_velocityConstraints = new ContactVelocityConstraint[MathUtils.max(old.length * 2, m_count)];
93
+ System.arraycopy(old, 0, m_velocityConstraints, 0, old.length);
94
+ for (int i = old.length; i < m_velocityConstraints.length; i++) {
95
+ m_velocityConstraints[i] = new ContactVelocityConstraint();
96
+ }
97
+ }
98
+
99
+ m_positions = def.positions;
100
+ m_velocities = def.velocities;
101
+ m_contacts = def.contacts;
102
+
103
+ for (int i = 0; i < m_count; ++i) {
104
+ // System.out.println("contacts: " + m_count);
105
+ final Contact contact = m_contacts[i];
106
+
107
+ final Fixture fixtureA = contact.m_fixtureA;
108
+ final Fixture fixtureB = contact.m_fixtureB;
109
+ final Shape shapeA = fixtureA.getShape();
110
+ final Shape shapeB = fixtureB.getShape();
111
+ final float radiusA = shapeA.m_radius;
112
+ final float radiusB = shapeB.m_radius;
113
+ final Body bodyA = fixtureA.getBody();
114
+ final Body bodyB = fixtureB.getBody();
115
+ final Manifold manifold = contact.getManifold();
116
+
117
+ int pointCount = manifold.pointCount;
118
+ assert (pointCount > 0);
119
+
120
+ ContactVelocityConstraint vc = m_velocityConstraints[i];
121
+ vc.friction = contact.m_friction;
122
+ vc.restitution = contact.m_restitution;
123
+ vc.tangentSpeed = contact.m_tangentSpeed;
124
+ vc.indexA = bodyA.m_islandIndex;
125
+ vc.indexB = bodyB.m_islandIndex;
126
+ vc.invMassA = bodyA.m_invMass;
127
+ vc.invMassB = bodyB.m_invMass;
128
+ vc.invIA = bodyA.m_invI;
129
+ vc.invIB = bodyB.m_invI;
130
+ vc.contactIndex = i;
131
+ vc.pointCount = pointCount;
132
+ vc.K.setZero();
133
+ vc.normalMass.setZero();
134
+
135
+ ContactPositionConstraint pc = m_positionConstraints[i];
136
+ pc.indexA = bodyA.m_islandIndex;
137
+ pc.indexB = bodyB.m_islandIndex;
138
+ pc.invMassA = bodyA.m_invMass;
139
+ pc.invMassB = bodyB.m_invMass;
140
+ pc.localCenterA.set(bodyA.m_sweep.localCenter);
141
+ pc.localCenterB.set(bodyB.m_sweep.localCenter);
142
+ pc.invIA = bodyA.m_invI;
143
+ pc.invIB = bodyB.m_invI;
144
+ pc.localNormal.set(manifold.localNormal);
145
+ pc.localPoint.set(manifold.localPoint);
146
+ pc.pointCount = pointCount;
147
+ pc.radiusA = radiusA;
148
+ pc.radiusB = radiusB;
149
+ pc.type = manifold.type;
150
+
151
+ // System.out.println("contact point count: " + pointCount);
152
+ for (int j = 0; j < pointCount; j++) {
153
+ ManifoldPoint cp = manifold.points[j];
154
+ VelocityConstraintPoint vcp = vc.points[j];
155
+
156
+ if (m_step.warmStarting) {
157
+ // assert(cp.normalImpulse == 0);
158
+ // System.out.println("contact normal impulse: " + cp.normalImpulse);
159
+ vcp.normalImpulse = m_step.dtRatio * cp.normalImpulse;
160
+ vcp.tangentImpulse = m_step.dtRatio * cp.tangentImpulse;
161
+ } else {
162
+ vcp.normalImpulse = 0;
163
+ vcp.tangentImpulse = 0;
164
+ }
165
+
166
+ vcp.rA.setZero();
167
+ vcp.rB.setZero();
168
+ vcp.normalMass = 0;
169
+ vcp.tangentMass = 0;
170
+ vcp.velocityBias = 0;
171
+ pc.localPoints[j].x = cp.localPoint.x;
172
+ pc.localPoints[j].y = cp.localPoint.y;
173
+ }
174
+ }
175
+ }
176
+
177
+ public void warmStart() {
178
+ // Warm start.
179
+ for (int i = 0; i < m_count; ++i) {
180
+ final ContactVelocityConstraint vc = m_velocityConstraints[i];
181
+
182
+ int indexA = vc.indexA;
183
+ int indexB = vc.indexB;
184
+ float mA = vc.invMassA;
185
+ float iA = vc.invIA;
186
+ float mB = vc.invMassB;
187
+ float iB = vc.invIB;
188
+ int pointCount = vc.pointCount;
189
+
190
+ Vec2 vA = m_velocities[indexA].v;
191
+ float wA = m_velocities[indexA].w;
192
+ Vec2 vB = m_velocities[indexB].v;
193
+ float wB = m_velocities[indexB].w;
194
+
195
+ Vec2 normal = vc.normal;
196
+ float tangentx = 1.0f * normal.y;
197
+ float tangenty = -1.0f * normal.x;
198
+
199
+ for (int j = 0; j < pointCount; ++j) {
200
+ VelocityConstraintPoint vcp = vc.points[j];
201
+ float Px = tangentx * vcp.tangentImpulse + normal.x * vcp.normalImpulse;
202
+ float Py = tangenty * vcp.tangentImpulse + normal.y * vcp.normalImpulse;
203
+
204
+ wA -= iA * (vcp.rA.x * Py - vcp.rA.y * Px);
205
+ vA.x -= Px * mA;
206
+ vA.y -= Py * mA;
207
+ wB += iB * (vcp.rB.x * Py - vcp.rB.y * Px);
208
+ vB.x += Px * mB;
209
+ vB.y += Py * mB;
210
+ }
211
+ m_velocities[indexA].w = wA;
212
+ m_velocities[indexB].w = wB;
213
+ }
214
+ }
215
+
216
+ // djm pooling, and from above
217
+ private final Transform xfA = new Transform();
218
+ private final Transform xfB = new Transform();
219
+ private final WorldManifold worldManifold = new WorldManifold();
220
+
221
+ public final void initializeVelocityConstraints() {
222
+
223
+ // Warm start.
224
+ for (int i = 0; i < m_count; ++i) {
225
+ ContactVelocityConstraint vc = m_velocityConstraints[i];
226
+ ContactPositionConstraint pc = m_positionConstraints[i];
227
+
228
+ float radiusA = pc.radiusA;
229
+ float radiusB = pc.radiusB;
230
+ Manifold manifold = m_contacts[vc.contactIndex].getManifold();
231
+
232
+ int indexA = vc.indexA;
233
+ int indexB = vc.indexB;
234
+
235
+ float mA = vc.invMassA;
236
+ float mB = vc.invMassB;
237
+ float iA = vc.invIA;
238
+ float iB = vc.invIB;
239
+ Vec2 localCenterA = pc.localCenterA;
240
+ Vec2 localCenterB = pc.localCenterB;
241
+
242
+ Vec2 cA = m_positions[indexA].c;
243
+ float aA = m_positions[indexA].a;
244
+ Vec2 vA = m_velocities[indexA].v;
245
+ float wA = m_velocities[indexA].w;
246
+
247
+ Vec2 cB = m_positions[indexB].c;
248
+ float aB = m_positions[indexB].a;
249
+ Vec2 vB = m_velocities[indexB].v;
250
+ float wB = m_velocities[indexB].w;
251
+
252
+ assert (manifold.pointCount > 0);
253
+
254
+ final Rot xfAq = xfA.q;
255
+ final Rot xfBq = xfB.q;
256
+ xfAq.set(aA);
257
+ xfBq.set(aB);
258
+ xfA.p.x = cA.x - (xfAq.c * localCenterA.x - xfAq.s * localCenterA.y);
259
+ xfA.p.y = cA.y - (xfAq.s * localCenterA.x + xfAq.c * localCenterA.y);
260
+ xfB.p.x = cB.x - (xfBq.c * localCenterB.x - xfBq.s * localCenterB.y);
261
+ xfB.p.y = cB.y - (xfBq.s * localCenterB.x + xfBq.c * localCenterB.y);
262
+
263
+ worldManifold.initialize(manifold, xfA, radiusA, xfB, radiusB);
264
+
265
+ final Vec2 vcnormal = vc.normal;
266
+ vcnormal.x = worldManifold.normal.x;
267
+ vcnormal.y = worldManifold.normal.y;
268
+
269
+ int pointCount = vc.pointCount;
270
+ for (int j = 0; j < pointCount; ++j) {
271
+ VelocityConstraintPoint vcp = vc.points[j];
272
+ Vec2 wmPj = worldManifold.points[j];
273
+ final Vec2 vcprA = vcp.rA;
274
+ final Vec2 vcprB = vcp.rB;
275
+ vcprA.x = wmPj.x - cA.x;
276
+ vcprA.y = wmPj.y - cA.y;
277
+ vcprB.x = wmPj.x - cB.x;
278
+ vcprB.y = wmPj.y - cB.y;
279
+
280
+ float rnA = vcprA.x * vcnormal.y - vcprA.y * vcnormal.x;
281
+ float rnB = vcprB.x * vcnormal.y - vcprB.y * vcnormal.x;
282
+
283
+ float kNormal = mA + mB + iA * rnA * rnA + iB * rnB * rnB;
284
+
285
+ vcp.normalMass = kNormal > 0.0f ? 1.0f / kNormal : 0.0f;
286
+
287
+ float tangentx = 1.0f * vcnormal.y;
288
+ float tangenty = -1.0f * vcnormal.x;
289
+
290
+ float rtA = vcprA.x * tangenty - vcprA.y * tangentx;
291
+ float rtB = vcprB.x * tangenty - vcprB.y * tangentx;
292
+
293
+ float kTangent = mA + mB + iA * rtA * rtA + iB * rtB * rtB;
294
+
295
+ vcp.tangentMass = kTangent > 0.0f ? 1.0f / kTangent : 0.0f;
296
+
297
+ // Setup a velocity bias for restitution.
298
+ vcp.velocityBias = 0.0f;
299
+ float tempx = vB.x + -wB * vcprB.y - vA.x - (-wA * vcprA.y);
300
+ float tempy = vB.y + wB * vcprB.x - vA.y - (wA * vcprA.x);
301
+ float vRel = vcnormal.x * tempx + vcnormal.y * tempy;
302
+ if (vRel < -Settings.velocityThreshold) {
303
+ vcp.velocityBias = -vc.restitution * vRel;
304
+ }
305
+ }
306
+
307
+ // If we have two points, then prepare the block solver.
308
+ if (vc.pointCount == 2) {
309
+ VelocityConstraintPoint vcp1 = vc.points[0];
310
+ VelocityConstraintPoint vcp2 = vc.points[1];
311
+ float rn1A = vcp1.rA.x * vcnormal.y - vcp1.rA.y * vcnormal.x;
312
+ float rn1B = vcp1.rB.x * vcnormal.y - vcp1.rB.y * vcnormal.x;
313
+ float rn2A = vcp2.rA.x * vcnormal.y - vcp2.rA.y * vcnormal.x;
314
+ float rn2B = vcp2.rB.x * vcnormal.y - vcp2.rB.y * vcnormal.x;
315
+
316
+ float k11 = mA + mB + iA * rn1A * rn1A + iB * rn1B * rn1B;
317
+ float k22 = mA + mB + iA * rn2A * rn2A + iB * rn2B * rn2B;
318
+ float k12 = mA + mB + iA * rn1A * rn2A + iB * rn1B * rn2B;
319
+ if (k11 * k11 < k_maxConditionNumber * (k11 * k22 - k12 * k12)) {
320
+ // K is safe to invert.
321
+ vc.K.ex.x = k11;
322
+ vc.K.ex.y = k12;
323
+ vc.K.ey.x = k12;
324
+ vc.K.ey.y = k22;
325
+ vc.K.invertToOut(vc.normalMass);
326
+ } else {
327
+ // The constraints are redundant, just use one.
328
+ // TODO_ERIN use deepest?
329
+ vc.pointCount = 1;
330
+ }
331
+ }
332
+ }
333
+ }
334
+
335
+
336
+ public final void solveVelocityConstraints() {
337
+ for (int i = 0; i < m_count; ++i) {
338
+ final ContactVelocityConstraint vc = m_velocityConstraints[i];
339
+
340
+ int indexA = vc.indexA;
341
+ int indexB = vc.indexB;
342
+
343
+ float mA = vc.invMassA;
344
+ float mB = vc.invMassB;
345
+ float iA = vc.invIA;
346
+ float iB = vc.invIB;
347
+ int pointCount = vc.pointCount;
348
+
349
+ Vec2 vA = m_velocities[indexA].v;
350
+ float wA = m_velocities[indexA].w;
351
+ Vec2 vB = m_velocities[indexB].v;
352
+ float wB = m_velocities[indexB].w;
353
+
354
+ Vec2 normal = vc.normal;
355
+ final float normalx = normal.x;
356
+ final float normaly = normal.y;
357
+ float tangentx = 1.0f * vc.normal.y;
358
+ float tangenty = -1.0f * vc.normal.x;
359
+ final float friction = vc.friction;
360
+
361
+ assert (pointCount == 1 || pointCount == 2);
362
+
363
+ // Solve tangent constraints
364
+ for (int j = 0; j < pointCount; ++j) {
365
+ final VelocityConstraintPoint vcp = vc.points[j];
366
+ final Vec2 a = vcp.rA;
367
+ float dvx = -wB * vcp.rB.y + vB.x - vA.x + wA * a.y;
368
+ float dvy = wB * vcp.rB.x + vB.y - vA.y - wA * a.x;
369
+
370
+ // Compute tangent force
371
+ final float vt = dvx * tangentx + dvy * tangenty - vc.tangentSpeed;
372
+ float lambda = vcp.tangentMass * (-vt);
373
+
374
+ // Clamp the accumulated force
375
+ final float maxFriction = friction * vcp.normalImpulse;
376
+ final float newImpulse =
377
+ MathUtils.clamp(vcp.tangentImpulse + lambda, -maxFriction, maxFriction);
378
+ lambda = newImpulse - vcp.tangentImpulse;
379
+ vcp.tangentImpulse = newImpulse;
380
+
381
+ // Apply contact impulse
382
+ // Vec2 P = lambda * tangent;
383
+
384
+ final float Px = tangentx * lambda;
385
+ final float Py = tangenty * lambda;
386
+
387
+ // vA -= invMassA * P;
388
+ vA.x -= Px * mA;
389
+ vA.y -= Py * mA;
390
+ wA -= iA * (vcp.rA.x * Py - vcp.rA.y * Px);
391
+
392
+ // vB += invMassB * P;
393
+ vB.x += Px * mB;
394
+ vB.y += Py * mB;
395
+ wB += iB * (vcp.rB.x * Py - vcp.rB.y * Px);
396
+ }
397
+
398
+ // Solve normal constraints
399
+ if (vc.pointCount == 1) {
400
+ final VelocityConstraintPoint vcp = vc.points[0];
401
+
402
+ // Relative velocity at contact
403
+ // Vec2 dv = vB + Cross(wB, vcp.rB) - vA - Cross(wA, vcp.rA);
404
+
405
+ float dvx = -wB * vcp.rB.y + vB.x - vA.x + wA * vcp.rA.y;
406
+ float dvy = wB * vcp.rB.x + vB.y - vA.y - wA * vcp.rA.x;
407
+
408
+ // Compute normal impulse
409
+ final float vn = dvx * normalx + dvy * normaly;
410
+ float lambda = -vcp.normalMass * (vn - vcp.velocityBias);
411
+
412
+ // Clamp the accumulated impulse
413
+ float a = vcp.normalImpulse + lambda;
414
+ final float newImpulse = (a > 0.0f ? a : 0.0f);
415
+ lambda = newImpulse - vcp.normalImpulse;
416
+ vcp.normalImpulse = newImpulse;
417
+
418
+ // Apply contact impulse
419
+ float Px = normalx * lambda;
420
+ float Py = normaly * lambda;
421
+
422
+ // vA -= invMassA * P;
423
+ vA.x -= Px * mA;
424
+ vA.y -= Py * mA;
425
+ wA -= iA * (vcp.rA.x * Py - vcp.rA.y * Px);
426
+
427
+ // vB += invMassB * P;
428
+ vB.x += Px * mB;
429
+ vB.y += Py * mB;
430
+ wB += iB * (vcp.rB.x * Py - vcp.rB.y * Px);
431
+ } else {
432
+ // Block solver developed in collaboration with Dirk Gregorius (back in 01/07 on
433
+ // Box2D_Lite).
434
+ // Build the mini LCP for this contact patch
435
+ //
436
+ // vn = A * x + b, vn >= 0, , vn >= 0, x >= 0 and vn_i * x_i = 0 with i = 1..2
437
+ //
438
+ // A = J * W * JT and J = ( -n, -r1 x n, n, r2 x n )
439
+ // b = vn_0 - velocityBias
440
+ //
441
+ // The system is solved using the "Total enumeration method" (s. Murty). The complementary
442
+ // constraint vn_i * x_i
443
+ // implies that we must have in any solution either vn_i = 0 or x_i = 0. So for the 2D
444
+ // contact problem the cases
445
+ // vn1 = 0 and vn2 = 0, x1 = 0 and x2 = 0, x1 = 0 and vn2 = 0, x2 = 0 and vn1 = 0 need to be
446
+ // tested. The first valid
447
+ // solution that satisfies the problem is chosen.
448
+ //
449
+ // In order to account of the accumulated impulse 'a' (because of the iterative nature of
450
+ // the solver which only requires
451
+ // that the accumulated impulse is clamped and not the incremental impulse) we change the
452
+ // impulse variable (x_i).
453
+ //
454
+ // Substitute:
455
+ //
456
+ // x = a + d
457
+ //
458
+ // a := old total impulse
459
+ // x := new total impulse
460
+ // d := incremental impulse
461
+ //
462
+ // For the current iteration we extend the formula for the incremental impulse
463
+ // to compute the new total impulse:
464
+ //
465
+ // vn = A * d + b
466
+ // = A * (x - a) + b
467
+ // = A * x + b - A * a
468
+ // = A * x + b'
469
+ // b' = b - A * a;
470
+
471
+ final VelocityConstraintPoint cp1 = vc.points[0];
472
+ final VelocityConstraintPoint cp2 = vc.points[1];
473
+ final Vec2 cp1rA = cp1.rA;
474
+ final Vec2 cp1rB = cp1.rB;
475
+ final Vec2 cp2rA = cp2.rA;
476
+ final Vec2 cp2rB = cp2.rB;
477
+ float ax = cp1.normalImpulse;
478
+ float ay = cp2.normalImpulse;
479
+
480
+ assert (ax >= 0.0f && ay >= 0.0f);
481
+ // Relative velocity at contact
482
+ // Vec2 dv1 = vB + Cross(wB, cp1.rB) - vA - Cross(wA, cp1.rA);
483
+ float dv1x = -wB * cp1rB.y + vB.x - vA.x + wA * cp1rA.y;
484
+ float dv1y = wB * cp1rB.x + vB.y - vA.y - wA * cp1rA.x;
485
+
486
+ // Vec2 dv2 = vB + Cross(wB, cp2.rB) - vA - Cross(wA, cp2.rA);
487
+ float dv2x = -wB * cp2rB.y + vB.x - vA.x + wA * cp2rA.y;
488
+ float dv2y = wB * cp2rB.x + vB.y - vA.y - wA * cp2rA.x;
489
+
490
+ // Compute normal velocity
491
+ float vn1 = dv1x * normalx + dv1y * normaly;
492
+ float vn2 = dv2x * normalx + dv2y * normaly;
493
+
494
+ float bx = vn1 - cp1.velocityBias;
495
+ float by = vn2 - cp2.velocityBias;
496
+
497
+ // Compute b'
498
+ Mat22 R = vc.K;
499
+ bx -= R.ex.x * ax + R.ey.x * ay;
500
+ by -= R.ex.y * ax + R.ey.y * ay;
501
+
502
+ // final float k_errorTol = 1e-3f;
503
+ // B2_NOT_USED(k_errorTol);
504
+ for (;;) {
505
+ //
506
+ // Case 1: vn = 0
507
+ //
508
+ // 0 = A * x' + b'
509
+ //
510
+ // Solve for x':
511
+ //
512
+ // x' = - inv(A) * b'
513
+ //
514
+ // Vec2 x = - Mul(c.normalMass, b);
515
+ Mat22 R1 = vc.normalMass;
516
+ float xx = R1.ex.x * bx + R1.ey.x * by;
517
+ float xy = R1.ex.y * bx + R1.ey.y * by;
518
+ xx *= -1;
519
+ xy *= -1;
520
+
521
+ if (xx >= 0.0f && xy >= 0.0f) {
522
+ // Get the incremental impulse
523
+ // Vec2 d = x - a;
524
+ float dx = xx - ax;
525
+ float dy = xy - ay;
526
+
527
+ // Apply incremental impulse
528
+ // Vec2 P1 = d.x * normal;
529
+ // Vec2 P2 = d.y * normal;
530
+ float P1x = dx * normalx;
531
+ float P1y = dx * normaly;
532
+ float P2x = dy * normalx;
533
+ float P2y = dy * normaly;
534
+
535
+ /*
536
+ * vA -= invMassA * (P1 + P2); wA -= invIA * (Cross(cp1.rA, P1) + Cross(cp2.rA, P2));
537
+ *
538
+ * vB += invMassB * (P1 + P2); wB += invIB * (Cross(cp1.rB, P1) + Cross(cp2.rB, P2));
539
+ */
540
+
541
+ vA.x -= mA * (P1x + P2x);
542
+ vA.y -= mA * (P1y + P2y);
543
+ vB.x += mB * (P1x + P2x);
544
+ vB.y += mB * (P1y + P2y);
545
+
546
+ wA -= iA * (cp1rA.x * P1y - cp1rA.y * P1x + (cp2rA.x * P2y - cp2rA.y * P2x));
547
+ wB += iB * (cp1rB.x * P1y - cp1rB.y * P1x + (cp2rB.x * P2y - cp2rB.y * P2x));
548
+
549
+ // Accumulate
550
+ cp1.normalImpulse = xx;
551
+ cp2.normalImpulse = xy;
552
+
553
+ /*
554
+ * #if B2_DEBUG_SOLVER == 1 // Postconditions dv1 = vB + Cross(wB, cp1.rB) - vA -
555
+ * Cross(wA, cp1.rA); dv2 = vB + Cross(wB, cp2.rB) - vA - Cross(wA, cp2.rA);
556
+ *
557
+ * // Compute normal velocity vn1 = Dot(dv1, normal); vn2 = Dot(dv2, normal);
558
+ *
559
+ * assert(Abs(vn1 - cp1.velocityBias) < k_errorTol); assert(Abs(vn2 - cp2.velocityBias)
560
+ * < k_errorTol); #endif
561
+ */
562
+ if (DEBUG_SOLVER) {
563
+ // Postconditions
564
+ Vec2 dv1 = vB.add(Vec2.cross(wB, cp1rB).subLocal(vA).subLocal(Vec2.cross(wA, cp1rA)));
565
+ Vec2 dv2 = vB.add(Vec2.cross(wB, cp2rB).subLocal(vA).subLocal(Vec2.cross(wA, cp2rA)));
566
+ // Compute normal velocity
567
+ vn1 = Vec2.dot(dv1, normal);
568
+ vn2 = Vec2.dot(dv2, normal);
569
+
570
+ assert (MathUtils.abs(vn1 - cp1.velocityBias) < k_errorTol);
571
+ assert (MathUtils.abs(vn2 - cp2.velocityBias) < k_errorTol);
572
+ }
573
+ break;
574
+ }
575
+
576
+ //
577
+ // Case 2: vn1 = 0 and x2 = 0
578
+ //
579
+ // 0 = a11 * x1' + a12 * 0 + b1'
580
+ // vn2 = a21 * x1' + a22 * 0 + '
581
+ //
582
+ xx = -cp1.normalMass * bx;
583
+ xy = 0.0f;
584
+ vn1 = 0.0f;
585
+ vn2 = vc.K.ex.y * xx + by;
586
+
587
+ if (xx >= 0.0f && vn2 >= 0.0f) {
588
+ // Get the incremental impulse
589
+ float dx = xx - ax;
590
+ float dy = xy - ay;
591
+
592
+ // Apply incremental impulse
593
+ // Vec2 P1 = d.x * normal;
594
+ // Vec2 P2 = d.y * normal;
595
+ float P1x = normalx * dx;
596
+ float P1y = normaly * dx;
597
+ float P2x = normalx * dy;
598
+ float P2y = normaly * dy;
599
+
600
+ /*
601
+ * Vec2 P1 = d.x * normal; Vec2 P2 = d.y * normal; vA -= invMassA * (P1 + P2); wA -=
602
+ * invIA * (Cross(cp1.rA, P1) + Cross(cp2.rA, P2));
603
+ *
604
+ * vB += invMassB * (P1 + P2); wB += invIB * (Cross(cp1.rB, P1) + Cross(cp2.rB, P2));
605
+ */
606
+
607
+ vA.x -= mA * (P1x + P2x);
608
+ vA.y -= mA * (P1y + P2y);
609
+ vB.x += mB * (P1x + P2x);
610
+ vB.y += mB * (P1y + P2y);
611
+
612
+ wA -= iA * (cp1rA.x * P1y - cp1rA.y * P1x + (cp2rA.x * P2y - cp2rA.y * P2x));
613
+ wB += iB * (cp1rB.x * P1y - cp1rB.y * P1x + (cp2rB.x * P2y - cp2rB.y * P2x));
614
+
615
+ // Accumulate
616
+ cp1.normalImpulse = xx;
617
+ cp2.normalImpulse = xy;
618
+
619
+ /*
620
+ * #if B2_DEBUG_SOLVER == 1 // Postconditions dv1 = vB + Cross(wB, cp1.rB) - vA -
621
+ * Cross(wA, cp1.rA);
622
+ *
623
+ * // Compute normal velocity vn1 = Dot(dv1, normal);
624
+ *
625
+ * assert(Abs(vn1 - cp1.velocityBias) < k_errorTol); #endif
626
+ */
627
+ if (DEBUG_SOLVER) {
628
+ // Postconditions
629
+ Vec2 dv1 = vB.add(Vec2.cross(wB, cp1rB).subLocal(vA).subLocal(Vec2.cross(wA, cp1rA)));
630
+ // Compute normal velocity
631
+ vn1 = Vec2.dot(dv1, normal);
632
+
633
+ assert (MathUtils.abs(vn1 - cp1.velocityBias) < k_errorTol);
634
+ }
635
+ break;
636
+ }
637
+
638
+ //
639
+ // Case 3: wB = 0 and x1 = 0
640
+ //
641
+ // vn1 = a11 * 0 + a12 * x2' + b1'
642
+ // 0 = a21 * 0 + a22 * x2' + '
643
+ //
644
+ xx = 0.0f;
645
+ xy = -cp2.normalMass * by;
646
+ vn1 = vc.K.ey.x * xy + bx;
647
+ vn2 = 0.0f;
648
+
649
+ if (xy >= 0.0f && vn1 >= 0.0f) {
650
+ // Resubstitute for the incremental impulse
651
+ float dx = xx - ax;
652
+ float dy = xy - ay;
653
+
654
+ // Apply incremental impulse
655
+ /*
656
+ * Vec2 P1 = d.x * normal; Vec2 P2 = d.y * normal; vA -= invMassA * (P1 + P2); wA -=
657
+ * invIA * (Cross(cp1.rA, P1) + Cross(cp2.rA, P2));
658
+ *
659
+ * vB += invMassB * (P1 + P2); wB += invIB * (Cross(cp1.rB, P1) + Cross(cp2.rB, P2));
660
+ */
661
+
662
+ float P1x = normalx * dx;
663
+ float P1y = normaly * dx;
664
+ float P2x = normalx * dy;
665
+ float P2y = normaly * dy;
666
+
667
+ vA.x -= mA * (P1x + P2x);
668
+ vA.y -= mA * (P1y + P2y);
669
+ vB.x += mB * (P1x + P2x);
670
+ vB.y += mB * (P1y + P2y);
671
+
672
+ wA -= iA * (cp1rA.x * P1y - cp1rA.y * P1x + (cp2rA.x * P2y - cp2rA.y * P2x));
673
+ wB += iB * (cp1rB.x * P1y - cp1rB.y * P1x + (cp2rB.x * P2y - cp2rB.y * P2x));
674
+
675
+ // Accumulate
676
+ cp1.normalImpulse = xx;
677
+ cp2.normalImpulse = xy;
678
+
679
+ /*
680
+ * #if B2_DEBUG_SOLVER == 1 // Postconditions dv2 = vB + Cross(wB, cp2.rB) - vA -
681
+ * Cross(wA, cp2.rA);
682
+ *
683
+ * // Compute normal velocity vn2 = Dot(dv2, normal);
684
+ *
685
+ * assert(Abs(vn2 - cp2.velocityBias) < k_errorTol); #endif
686
+ */
687
+ if (DEBUG_SOLVER) {
688
+ // Postconditions
689
+ Vec2 dv2 = vB.add(Vec2.cross(wB, cp2rB).subLocal(vA).subLocal(Vec2.cross(wA, cp2rA)));
690
+ // Compute normal velocity
691
+ vn2 = Vec2.dot(dv2, normal);
692
+
693
+ assert (MathUtils.abs(vn2 - cp2.velocityBias) < k_errorTol);
694
+ }
695
+ break;
696
+ }
697
+
698
+ //
699
+ // Case 4: x1 = 0 and x2 = 0
700
+ //
701
+ // vn1 = b1
702
+ // vn2 = ;
703
+ xx = 0.0f;
704
+ xy = 0.0f;
705
+ vn1 = bx;
706
+ vn2 = by;
707
+
708
+ if (vn1 >= 0.0f && vn2 >= 0.0f) {
709
+ // Resubstitute for the incremental impulse
710
+ float dx = xx - ax;
711
+ float dy = xy - ay;
712
+
713
+ // Apply incremental impulse
714
+ /*
715
+ * Vec2 P1 = d.x * normal; Vec2 P2 = d.y * normal; vA -= invMassA * (P1 + P2); wA -=
716
+ * invIA * (Cross(cp1.rA, P1) + Cross(cp2.rA, P2));
717
+ *
718
+ * vB += invMassB * (P1 + P2); wB += invIB * (Cross(cp1.rB, P1) + Cross(cp2.rB, P2));
719
+ */
720
+
721
+ float P1x = normalx * dx;
722
+ float P1y = normaly * dx;
723
+ float P2x = normalx * dy;
724
+ float P2y = normaly * dy;
725
+
726
+ vA.x -= mA * (P1x + P2x);
727
+ vA.y -= mA * (P1y + P2y);
728
+ vB.x += mB * (P1x + P2x);
729
+ vB.y += mB * (P1y + P2y);
730
+
731
+ wA -= iA * (cp1rA.x * P1y - cp1rA.y * P1x + (cp2rA.x * P2y - cp2rA.y * P2x));
732
+ wB += iB * (cp1rB.x * P1y - cp1rB.y * P1x + (cp2rB.x * P2y - cp2rB.y * P2x));
733
+
734
+ // Accumulate
735
+ cp1.normalImpulse = xx;
736
+ cp2.normalImpulse = xy;
737
+
738
+ break;
739
+ }
740
+
741
+ // No solution, give up. This is hit sometimes, but it doesn't seem to matter.
742
+ break;
743
+ }
744
+ }
745
+
746
+ // m_velocities[indexA].v.set(vA);
747
+ m_velocities[indexA].w = wA;
748
+ // m_velocities[indexB].v.set(vB);
749
+ m_velocities[indexB].w = wB;
750
+ }
751
+ }
752
+
753
+ public void storeImpulses() {
754
+ for (int i = 0; i < m_count; i++) {
755
+ final ContactVelocityConstraint vc = m_velocityConstraints[i];
756
+ final Manifold manifold = m_contacts[vc.contactIndex].getManifold();
757
+
758
+ for (int j = 0; j < vc.pointCount; j++) {
759
+ manifold.points[j].normalImpulse = vc.points[j].normalImpulse;
760
+ manifold.points[j].tangentImpulse = vc.points[j].tangentImpulse;
761
+ }
762
+ }
763
+ }
764
+
765
+ /*
766
+ * #if 0 // Sequential solver. bool ContactSolver::SolvePositionConstraints(float baumgarte) {
767
+ * float minSeparation = 0.0f;
768
+ *
769
+ * for (int i = 0; i < m_constraintCount; ++i) { ContactConstraint* c = m_constraints + i; Body*
770
+ * bodyA = c.bodyA; Body* bodyB = c.bodyB; float invMassA = bodyA.m_mass * bodyA.m_invMass; float
771
+ * invIA = bodyA.m_mass * bodyA.m_invI; float invMassB = bodyB.m_mass * bodyB.m_invMass; float
772
+ * invIB = bodyB.m_mass * bodyB.m_invI;
773
+ *
774
+ * Vec2 normal = c.normal;
775
+ *
776
+ * // Solve normal constraints for (int j = 0; j < c.pointCount; ++j) { ContactConstraintPoint*
777
+ * ccp = c.points + j;
778
+ *
779
+ * Vec2 r1 = Mul(bodyA.GetXForm().R, ccp.localAnchorA - bodyA.GetLocalCenter()); Vec2 r2 =
780
+ * Mul(bodyB.GetXForm().R, ccp.localAnchorB - bodyB.GetLocalCenter());
781
+ *
782
+ * Vec2 p1 = bodyA.m_sweep.c + r1; Vec2 p2 = bodyB.m_sweep.c + r2; Vec2 dp = p2 - p1;
783
+ *
784
+ * // Approximate the current separation. float separation = Dot(dp, normal) + ccp.separation;
785
+ *
786
+ * // Track max constraint error. minSeparation = Min(minSeparation, separation);
787
+ *
788
+ * // Prevent large corrections and allow slop. float C = Clamp(baumgarte * (separation +
789
+ * _linearSlop), -_maxLinearCorrection, 0.0f);
790
+ *
791
+ * // Compute normal impulse float impulse = -ccp.equalizedMass * C;
792
+ *
793
+ * Vec2 P = impulse * normal;
794
+ *
795
+ * bodyA.m_sweep.c -= invMassA * P; bodyA.m_sweep.a -= invIA * Cross(r1, P);
796
+ * bodyA.SynchronizeTransform();
797
+ *
798
+ * bodyB.m_sweep.c += invMassB * P; bodyB.m_sweep.a += invIB * Cross(r2, P);
799
+ * bodyB.SynchronizeTransform(); } }
800
+ *
801
+ * // We can't expect minSpeparation >= -_linearSlop because we don't // push the separation above
802
+ * -_linearSlop. return minSeparation >= -1.5f * _linearSlop; }
803
+ */
804
+
805
+ private final PositionSolverManifold psolver = new PositionSolverManifold();
806
+
807
+ /**
808
+ * Sequential solver.
809
+ */
810
+ public final boolean solvePositionConstraints() {
811
+ float minSeparation = 0.0f;
812
+
813
+ for (int i = 0; i < m_count; ++i) {
814
+ ContactPositionConstraint pc = m_positionConstraints[i];
815
+
816
+ int indexA = pc.indexA;
817
+ int indexB = pc.indexB;
818
+
819
+ float mA = pc.invMassA;
820
+ float iA = pc.invIA;
821
+ Vec2 localCenterA = pc.localCenterA;
822
+ final float localCenterAx = localCenterA.x;
823
+ final float localCenterAy = localCenterA.y;
824
+ float mB = pc.invMassB;
825
+ float iB = pc.invIB;
826
+ Vec2 localCenterB = pc.localCenterB;
827
+ final float localCenterBx = localCenterB.x;
828
+ final float localCenterBy = localCenterB.y;
829
+ int pointCount = pc.pointCount;
830
+
831
+ Vec2 cA = m_positions[indexA].c;
832
+ float aA = m_positions[indexA].a;
833
+ Vec2 cB = m_positions[indexB].c;
834
+ float aB = m_positions[indexB].a;
835
+
836
+ // Solve normal constraints
837
+ for (int j = 0; j < pointCount; ++j) {
838
+ final Rot xfAq = xfA.q;
839
+ final Rot xfBq = xfB.q;
840
+ xfAq.set(aA);
841
+ xfBq.set(aB);
842
+ xfA.p.x = cA.x - xfAq.c * localCenterAx + xfAq.s * localCenterAy;
843
+ xfA.p.y = cA.y - xfAq.s * localCenterAx - xfAq.c * localCenterAy;
844
+ xfB.p.x = cB.x - xfBq.c * localCenterBx + xfBq.s * localCenterBy;
845
+ xfB.p.y = cB.y - xfBq.s * localCenterBx - xfBq.c * localCenterBy;
846
+
847
+ final PositionSolverManifold psm = psolver;
848
+ psm.initialize(pc, xfA, xfB, j);
849
+ final Vec2 normal = psm.normal;
850
+ final Vec2 point = psm.point;
851
+ final float separation = psm.separation;
852
+
853
+ float rAx = point.x - cA.x;
854
+ float rAy = point.y - cA.y;
855
+ float rBx = point.x - cB.x;
856
+ float rBy = point.y - cB.y;
857
+
858
+ // Track max constraint error.
859
+ minSeparation = MathUtils.min(minSeparation, separation);
860
+
861
+ // Prevent large corrections and allow slop.
862
+ final float C =
863
+ MathUtils.clamp(Settings.baumgarte * (separation + Settings.linearSlop),
864
+ -Settings.maxLinearCorrection, 0.0f);
865
+
866
+ // Compute the effective mass.
867
+ final float rnA = rAx * normal.y - rAy * normal.x;
868
+ final float rnB = rBx * normal.y - rBy * normal.x;
869
+ final float K = mA + mB + iA * rnA * rnA + iB * rnB * rnB;
870
+
871
+ // Compute normal impulse
872
+ final float impulse = K > 0.0f ? -C / K : 0.0f;
873
+
874
+ float Px = normal.x * impulse;
875
+ float Py = normal.y * impulse;
876
+
877
+ cA.x -= Px * mA;
878
+ cA.y -= Py * mA;
879
+ aA -= iA * (rAx * Py - rAy * Px);
880
+
881
+ cB.x += Px * mB;
882
+ cB.y += Py * mB;
883
+ aB += iB * (rBx * Py - rBy * Px);
884
+ }
885
+
886
+ // m_positions[indexA].c.set(cA);
887
+ m_positions[indexA].a = aA;
888
+
889
+ // m_positions[indexB].c.set(cB);
890
+ m_positions[indexB].a = aB;
891
+ }
892
+
893
+ // We can't expect minSpeparation >= -linearSlop because we don't
894
+ // push the separation above -linearSlop.
895
+ return minSeparation >= -3.0f * Settings.linearSlop;
896
+ }
897
+
898
+ // Sequential position solver for position constraints.
899
+ public boolean solveTOIPositionConstraints(int toiIndexA, int toiIndexB) {
900
+ float minSeparation = 0.0f;
901
+
902
+ for (int i = 0; i < m_count; ++i) {
903
+ ContactPositionConstraint pc = m_positionConstraints[i];
904
+
905
+ int indexA = pc.indexA;
906
+ int indexB = pc.indexB;
907
+ Vec2 localCenterA = pc.localCenterA;
908
+ Vec2 localCenterB = pc.localCenterB;
909
+ final float localCenterAx = localCenterA.x;
910
+ final float localCenterAy = localCenterA.y;
911
+ final float localCenterBx = localCenterB.x;
912
+ final float localCenterBy = localCenterB.y;
913
+ int pointCount = pc.pointCount;
914
+
915
+ float mA = 0.0f;
916
+ float iA = 0.0f;
917
+ if (indexA == toiIndexA || indexA == toiIndexB) {
918
+ mA = pc.invMassA;
919
+ iA = pc.invIA;
920
+ }
921
+
922
+ float mB = 0f;
923
+ float iB = 0f;
924
+ if (indexB == toiIndexA || indexB == toiIndexB) {
925
+ mB = pc.invMassB;
926
+ iB = pc.invIB;
927
+ }
928
+
929
+ Vec2 cA = m_positions[indexA].c;
930
+ float aA = m_positions[indexA].a;
931
+
932
+ Vec2 cB = m_positions[indexB].c;
933
+ float aB = m_positions[indexB].a;
934
+
935
+ // Solve normal constraints
936
+ for (int j = 0; j < pointCount; ++j) {
937
+ final Rot xfAq = xfA.q;
938
+ final Rot xfBq = xfB.q;
939
+ xfAq.set(aA);
940
+ xfBq.set(aB);
941
+ xfA.p.x = cA.x - xfAq.c * localCenterAx + xfAq.s * localCenterAy;
942
+ xfA.p.y = cA.y - xfAq.s * localCenterAx - xfAq.c * localCenterAy;
943
+ xfB.p.x = cB.x - xfBq.c * localCenterBx + xfBq.s * localCenterBy;
944
+ xfB.p.y = cB.y - xfBq.s * localCenterBx - xfBq.c * localCenterBy;
945
+
946
+ final PositionSolverManifold psm = psolver;
947
+ psm.initialize(pc, xfA, xfB, j);
948
+ Vec2 normal = psm.normal;
949
+
950
+ Vec2 point = psm.point;
951
+ float separation = psm.separation;
952
+
953
+ float rAx = point.x - cA.x;
954
+ float rAy = point.y - cA.y;
955
+ float rBx = point.x - cB.x;
956
+ float rBy = point.y - cB.y;
957
+
958
+ // Track max constraint error.
959
+ minSeparation = MathUtils.min(minSeparation, separation);
960
+
961
+ // Prevent large corrections and allow slop.
962
+ float C =
963
+ MathUtils.clamp(Settings.toiBaugarte * (separation + Settings.linearSlop),
964
+ -Settings.maxLinearCorrection, 0.0f);
965
+
966
+ // Compute the effective mass.
967
+ float rnA = rAx * normal.y - rAy * normal.x;
968
+ float rnB = rBx * normal.y - rBy * normal.x;
969
+ float K = mA + mB + iA * rnA * rnA + iB * rnB * rnB;
970
+
971
+ // Compute normal impulse
972
+ float impulse = K > 0.0f ? -C / K : 0.0f;
973
+
974
+ float Px = normal.x * impulse;
975
+ float Py = normal.y * impulse;
976
+
977
+ cA.x -= Px * mA;
978
+ cA.y -= Py * mA;
979
+ aA -= iA * (rAx * Py - rAy * Px);
980
+
981
+ cB.x += Px * mB;
982
+ cB.y += Py * mB;
983
+ aB += iB * (rBx * Py - rBy * Px);
984
+ }
985
+
986
+ // m_positions[indexA].c.set(cA);
987
+ m_positions[indexA].a = aA;
988
+
989
+ // m_positions[indexB].c.set(cB);
990
+ m_positions[indexB].a = aB;
991
+ }
992
+
993
+ // We can't expect minSpeparation >= -_linearSlop because we don't
994
+ // push the separation above -_linearSlop.
995
+ return minSeparation >= -1.5f * Settings.linearSlop;
996
+ }
997
+
998
+ public static class ContactSolverDef {
999
+ public TimeStep step;
1000
+ public Contact[] contacts;
1001
+ public int count;
1002
+ public Position[] positions;
1003
+ public Velocity[] velocities;
1004
+ }
1005
+ }
1006
+
1007
+
1008
+ class PositionSolverManifold {
1009
+
1010
+ public final Vec2 normal = new Vec2();
1011
+ public final Vec2 point = new Vec2();
1012
+ public float separation;
1013
+
1014
+ public void initialize(ContactPositionConstraint pc, Transform xfA, Transform xfB, int index) {
1015
+ assert (pc.pointCount > 0);
1016
+
1017
+ final Rot xfAq = xfA.q;
1018
+ final Rot xfBq = xfB.q;
1019
+ final Vec2 pcLocalPointsI = pc.localPoints[index];
1020
+ switch (pc.type) {
1021
+ case CIRCLES: {
1022
+ // Transform.mulToOutUnsafe(xfA, pc.localPoint, pointA);
1023
+ // Transform.mulToOutUnsafe(xfB, pc.localPoints[0], pointB);
1024
+ // normal.set(pointB).subLocal(pointA);
1025
+ // normal.normalize();
1026
+ //
1027
+ // point.set(pointA).addLocal(pointB).mulLocal(.5f);
1028
+ // temp.set(pointB).subLocal(pointA);
1029
+ // separation = Vec2.dot(temp, normal) - pc.radiusA - pc.radiusB;
1030
+ final Vec2 plocalPoint = pc.localPoint;
1031
+ final Vec2 pLocalPoints0 = pc.localPoints[0];
1032
+ final float pointAx = (xfAq.c * plocalPoint.x - xfAq.s * plocalPoint.y) + xfA.p.x;
1033
+ final float pointAy = (xfAq.s * plocalPoint.x + xfAq.c * plocalPoint.y) + xfA.p.y;
1034
+ final float pointBx = (xfBq.c * pLocalPoints0.x - xfBq.s * pLocalPoints0.y) + xfB.p.x;
1035
+ final float pointBy = (xfBq.s * pLocalPoints0.x + xfBq.c * pLocalPoints0.y) + xfB.p.y;
1036
+ normal.x = pointBx - pointAx;
1037
+ normal.y = pointBy - pointAy;
1038
+ normal.normalize();
1039
+
1040
+ point.x = (pointAx + pointBx) * .5f;
1041
+ point.y = (pointAy + pointBy) * .5f;
1042
+ final float tempx = pointBx - pointAx;
1043
+ final float tempy = pointBy - pointAy;
1044
+ separation = tempx * normal.x + tempy * normal.y - pc.radiusA - pc.radiusB;
1045
+ break;
1046
+ }
1047
+
1048
+ case FACE_A: {
1049
+ // Rot.mulToOutUnsafe(xfAq, pc.localNormal, normal);
1050
+ // Transform.mulToOutUnsafe(xfA, pc.localPoint, planePoint);
1051
+ //
1052
+ // Transform.mulToOutUnsafe(xfB, pc.localPoints[index], clipPoint);
1053
+ // temp.set(clipPoint).subLocal(planePoint);
1054
+ // separation = Vec2.dot(temp, normal) - pc.radiusA - pc.radiusB;
1055
+ // point.set(clipPoint);
1056
+ final Vec2 pcLocalNormal = pc.localNormal;
1057
+ final Vec2 pcLocalPoint = pc.localPoint;
1058
+ normal.x = xfAq.c * pcLocalNormal.x - xfAq.s * pcLocalNormal.y;
1059
+ normal.y = xfAq.s * pcLocalNormal.x + xfAq.c * pcLocalNormal.y;
1060
+ final float planePointx = (xfAq.c * pcLocalPoint.x - xfAq.s * pcLocalPoint.y) + xfA.p.x;
1061
+ final float planePointy = (xfAq.s * pcLocalPoint.x + xfAq.c * pcLocalPoint.y) + xfA.p.y;
1062
+
1063
+ final float clipPointx = (xfBq.c * pcLocalPointsI.x - xfBq.s * pcLocalPointsI.y) + xfB.p.x;
1064
+ final float clipPointy = (xfBq.s * pcLocalPointsI.x + xfBq.c * pcLocalPointsI.y) + xfB.p.y;
1065
+ final float tempx = clipPointx - planePointx;
1066
+ final float tempy = clipPointy - planePointy;
1067
+ separation = tempx * normal.x + tempy * normal.y - pc.radiusA - pc.radiusB;
1068
+ point.x = clipPointx;
1069
+ point.y = clipPointy;
1070
+ break;
1071
+ }
1072
+
1073
+ case FACE_B: {
1074
+ // Rot.mulToOutUnsafe(xfBq, pc.localNormal, normal);
1075
+ // Transform.mulToOutUnsafe(xfB, pc.localPoint, planePoint);
1076
+ //
1077
+ // Transform.mulToOutUnsafe(xfA, pcLocalPointsI, clipPoint);
1078
+ // temp.set(clipPoint).subLocal(planePoint);
1079
+ // separation = Vec2.dot(temp, normal) - pc.radiusA - pc.radiusB;
1080
+ // point.set(clipPoint);
1081
+ //
1082
+ // // Ensure normal points from A to B
1083
+ // normal.negateLocal();
1084
+ final Vec2 pcLocalNormal = pc.localNormal;
1085
+ final Vec2 pcLocalPoint = pc.localPoint;
1086
+ normal.x = xfBq.c * pcLocalNormal.x - xfBq.s * pcLocalNormal.y;
1087
+ normal.y = xfBq.s * pcLocalNormal.x + xfBq.c * pcLocalNormal.y;
1088
+ final float planePointx = (xfBq.c * pcLocalPoint.x - xfBq.s * pcLocalPoint.y) + xfB.p.x;
1089
+ final float planePointy = (xfBq.s * pcLocalPoint.x + xfBq.c * pcLocalPoint.y) + xfB.p.y;
1090
+
1091
+ final float clipPointx = (xfAq.c * pcLocalPointsI.x - xfAq.s * pcLocalPointsI.y) + xfA.p.x;
1092
+ final float clipPointy = (xfAq.s * pcLocalPointsI.x + xfAq.c * pcLocalPointsI.y) + xfA.p.y;
1093
+ final float tempx = clipPointx - planePointx;
1094
+ final float tempy = clipPointy - planePointy;
1095
+ separation = tempx * normal.x + tempy * normal.y - pc.radiusA - pc.radiusB;
1096
+ point.x = clipPointx;
1097
+ point.y = clipPointy;
1098
+ normal.x *= -1;
1099
+ normal.y *= -1;
1100
+ }
1101
+ break;
1102
+ }
1103
+ }
1104
+ }