pbox2d 0.6.0-java → 0.8.0-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ }