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,1444 @@
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.collision;
25
+
26
+ import org.jbox2d.collision.Distance.SimplexCache;
27
+ import org.jbox2d.collision.Manifold.ManifoldType;
28
+ import org.jbox2d.collision.shapes.CircleShape;
29
+ import org.jbox2d.collision.shapes.EdgeShape;
30
+ import org.jbox2d.collision.shapes.PolygonShape;
31
+ import org.jbox2d.collision.shapes.Shape;
32
+ import org.jbox2d.common.MathUtils;
33
+ import org.jbox2d.common.Rot;
34
+ import org.jbox2d.common.Settings;
35
+ import org.jbox2d.common.Transform;
36
+ import org.jbox2d.common.Vec2;
37
+ import org.jbox2d.pooling.IWorldPool;
38
+
39
+ /**
40
+ * Functions used for computing contact points, distance queries, and TOI queries. Collision methods
41
+ * are non-static for pooling speed, retrieve a collision object from the {@link SingletonPool}.
42
+ * Should not be finalructed.
43
+ *
44
+ * @author Daniel Murphy
45
+ */
46
+ public class Collision {
47
+ public static final int NULL_FEATURE = Integer.MAX_VALUE;
48
+
49
+ private final IWorldPool pool;
50
+
51
+ public Collision(IWorldPool argPool) {
52
+ incidentEdge[0] = new ClipVertex();
53
+ incidentEdge[1] = new ClipVertex();
54
+ clipPoints1[0] = new ClipVertex();
55
+ clipPoints1[1] = new ClipVertex();
56
+ clipPoints2[0] = new ClipVertex();
57
+ clipPoints2[1] = new ClipVertex();
58
+ pool = argPool;
59
+ }
60
+
61
+ private final DistanceInput input = new DistanceInput();
62
+ private final SimplexCache cache = new SimplexCache();
63
+ private final DistanceOutput output = new DistanceOutput();
64
+
65
+ /**
66
+ * Determine if two generic shapes overlap.
67
+ *
68
+ * @param shapeA
69
+ * @param shapeB
70
+ * @param xfA
71
+ * @param xfB
72
+ * @return
73
+ */
74
+ public final boolean testOverlap(Shape shapeA, int indexA, Shape shapeB, int indexB,
75
+ Transform xfA, Transform xfB) {
76
+ input.proxyA.set(shapeA, indexA);
77
+ input.proxyB.set(shapeB, indexB);
78
+ input.transformA.set(xfA);
79
+ input.transformB.set(xfB);
80
+ input.useRadii = true;
81
+
82
+ cache.count = 0;
83
+
84
+ pool.getDistance().distance(output, cache, input);
85
+ // djm note: anything significant about 10.0f?
86
+ return output.distance < 10.0f * Settings.EPSILON;
87
+ }
88
+
89
+ /**
90
+ * Compute the point states given two manifolds. The states pertain to the transition from
91
+ * manifold1 to manifold2. So state1 is either persist or remove while state2 is either add or
92
+ * persist.
93
+ *
94
+ * @param state1
95
+ * @param state2
96
+ * @param manifold1
97
+ * @param manifold2
98
+ */
99
+ public static final void getPointStates(final PointState[] state1, final PointState[] state2,
100
+ final Manifold manifold1, final Manifold manifold2) {
101
+
102
+ for (int i = 0; i < Settings.maxManifoldPoints; i++) {
103
+ state1[i] = PointState.NULL_STATE;
104
+ state2[i] = PointState.NULL_STATE;
105
+ }
106
+
107
+ // Detect persists and removes.
108
+ for (int i = 0; i < manifold1.pointCount; i++) {
109
+ ContactID id = manifold1.points[i].id;
110
+
111
+ state1[i] = PointState.REMOVE_STATE;
112
+
113
+ for (int j = 0; j < manifold2.pointCount; j++) {
114
+ if (manifold2.points[j].id.isEqual(id)) {
115
+ state1[i] = PointState.PERSIST_STATE;
116
+ break;
117
+ }
118
+ }
119
+ }
120
+
121
+ // Detect persists and adds
122
+ for (int i = 0; i < manifold2.pointCount; i++) {
123
+ ContactID id = manifold2.points[i].id;
124
+
125
+ state2[i] = PointState.ADD_STATE;
126
+
127
+ for (int j = 0; j < manifold1.pointCount; j++) {
128
+ if (manifold1.points[j].id.isEqual(id)) {
129
+ state2[i] = PointState.PERSIST_STATE;
130
+ break;
131
+ }
132
+ }
133
+ }
134
+ }
135
+
136
+ /**
137
+ * Clipping for contact manifolds. Sutherland-Hodgman clipping.
138
+ *
139
+ * @param vOut
140
+ * @param vIn
141
+ * @param normal
142
+ * @param offset
143
+ * @return
144
+ */
145
+ public static final int clipSegmentToLine(final ClipVertex[] vOut, final ClipVertex[] vIn,
146
+ final Vec2 normal, float offset, int vertexIndexA) {
147
+
148
+ // Start with no output points
149
+ int numOut = 0;
150
+ final ClipVertex vIn0 = vIn[0];
151
+ final ClipVertex vIn1 = vIn[1];
152
+ final Vec2 vIn0v = vIn0.v;
153
+ final Vec2 vIn1v = vIn1.v;
154
+
155
+ // Calculate the distance of end points to the line
156
+ float distance0 = Vec2.dot(normal, vIn0v) - offset;
157
+ float distance1 = Vec2.dot(normal, vIn1v) - offset;
158
+
159
+ // If the points are behind the plane
160
+ if (distance0 <= 0.0f) {
161
+ vOut[numOut++].set(vIn0);
162
+ }
163
+ if (distance1 <= 0.0f) {
164
+ vOut[numOut++].set(vIn1);
165
+ }
166
+
167
+ // If the points are on different sides of the plane
168
+ if (distance0 * distance1 < 0.0f) {
169
+ // Find intersection point of edge and plane
170
+ float interp = distance0 / (distance0 - distance1);
171
+
172
+ ClipVertex vOutNO = vOut[numOut];
173
+ // vOut[numOut].v = vIn[0].v + interp * (vIn[1].v - vIn[0].v);
174
+ vOutNO.v.x = vIn0v.x + interp * (vIn1v.x - vIn0v.x);
175
+ vOutNO.v.y = vIn0v.y + interp * (vIn1v.y - vIn0v.y);
176
+
177
+ // VertexA is hitting edgeB.
178
+ vOutNO.id.indexA = (byte) vertexIndexA;
179
+ vOutNO.id.indexB = vIn0.id.indexB;
180
+ vOutNO.id.typeA = (byte) ContactID.Type.VERTEX.ordinal();
181
+ vOutNO.id.typeB = (byte) ContactID.Type.FACE.ordinal();
182
+ ++numOut;
183
+ }
184
+
185
+ return numOut;
186
+ }
187
+
188
+ // #### COLLISION STUFF (not from collision.h or collision.cpp) ####
189
+
190
+ // djm pooling
191
+ private static Vec2 d = new Vec2();
192
+
193
+ /**
194
+ * Compute the collision manifold between two circles.
195
+ *
196
+ * @param manifold
197
+ * @param circle1
198
+ * @param xfA
199
+ * @param circle2
200
+ * @param xfB
201
+ */
202
+ public final void collideCircles(Manifold manifold, final CircleShape circle1,
203
+ final Transform xfA, final CircleShape circle2, final Transform xfB) {
204
+ manifold.pointCount = 0;
205
+ // before inline:
206
+ // Transform.mulToOut(xfA, circle1.m_p, pA);
207
+ // Transform.mulToOut(xfB, circle2.m_p, pB);
208
+ // d.set(pB).subLocal(pA);
209
+ // float distSqr = d.x * d.x + d.y * d.y;
210
+
211
+ // after inline:
212
+ Vec2 circle1p = circle1.m_p;
213
+ Vec2 circle2p = circle2.m_p;
214
+ float pAx = (xfA.q.c * circle1p.x - xfA.q.s * circle1p.y) + xfA.p.x;
215
+ float pAy = (xfA.q.s * circle1p.x + xfA.q.c * circle1p.y) + xfA.p.y;
216
+ float pBx = (xfB.q.c * circle2p.x - xfB.q.s * circle2p.y) + xfB.p.x;
217
+ float pBy = (xfB.q.s * circle2p.x + xfB.q.c * circle2p.y) + xfB.p.y;
218
+ float dx = pBx - pAx;
219
+ float dy = pBy - pAy;
220
+ float distSqr = dx * dx + dy * dy;
221
+ // end inline
222
+
223
+ final float radius = circle1.m_radius + circle2.m_radius;
224
+ if (distSqr > radius * radius) {
225
+ return;
226
+ }
227
+
228
+ manifold.type = ManifoldType.CIRCLES;
229
+ manifold.localPoint.set(circle1p);
230
+ manifold.localNormal.setZero();
231
+ manifold.pointCount = 1;
232
+
233
+ manifold.points[0].localPoint.set(circle2p);
234
+ manifold.points[0].id.zero();
235
+ }
236
+
237
+ // djm pooling, and from above
238
+
239
+ /**
240
+ * Compute the collision manifold between a polygon and a circle.
241
+ *
242
+ * @param manifold
243
+ * @param polygon
244
+ * @param xfA
245
+ * @param circle
246
+ * @param xfB
247
+ */
248
+ public final void collidePolygonAndCircle(Manifold manifold, final PolygonShape polygon,
249
+ final Transform xfA, final CircleShape circle, final Transform xfB) {
250
+ manifold.pointCount = 0;
251
+ // Vec2 v = circle.m_p;
252
+
253
+ // Compute circle position in the frame of the polygon.
254
+ // before inline:
255
+ // Transform.mulToOutUnsafe(xfB, circle.m_p, c);
256
+ // Transform.mulTransToOut(xfA, c, cLocal);
257
+ // final float cLocalx = cLocal.x;
258
+ // final float cLocaly = cLocal.y;
259
+ // after inline:
260
+ final Vec2 circlep = circle.m_p;
261
+ final Rot xfBq = xfB.q;
262
+ final Rot xfAq = xfA.q;
263
+ final float cx = (xfBq.c * circlep.x - xfBq.s * circlep.y) + xfB.p.x;
264
+ final float cy = (xfBq.s * circlep.x + xfBq.c * circlep.y) + xfB.p.y;
265
+ final float px = cx - xfA.p.x;
266
+ final float py = cy - xfA.p.y;
267
+ final float cLocalx = (xfAq.c * px + xfAq.s * py);
268
+ final float cLocaly = (-xfAq.s * px + xfAq.c * py);
269
+ // end inline
270
+
271
+ // Find the min separating edge.
272
+ int normalIndex = 0;
273
+ float separation = -Float.MAX_VALUE;
274
+ final float radius = polygon.m_radius + circle.m_radius;
275
+ final int vertexCount = polygon.m_count;
276
+ float s;
277
+ final Vec2[] vertices = polygon.m_vertices;
278
+ final Vec2[] normals = polygon.m_normals;
279
+
280
+ for (int i = 0; i < vertexCount; i++) {
281
+ // before inline
282
+ // temp.set(cLocal).subLocal(vertices[i]);
283
+ // float s = Vec2.dot(normals[i], temp);
284
+ // after inline
285
+ final Vec2 vertex = vertices[i];
286
+ final float tempx = cLocalx - vertex.x;
287
+ final float tempy = cLocaly - vertex.y;
288
+ s = normals[i].x * tempx + normals[i].y * tempy;
289
+
290
+
291
+ if (s > radius) {
292
+ // early out
293
+ return;
294
+ }
295
+
296
+ if (s > separation) {
297
+ separation = s;
298
+ normalIndex = i;
299
+ }
300
+ }
301
+
302
+ // Vertices that subtend the incident face.
303
+ final int vertIndex1 = normalIndex;
304
+ final int vertIndex2 = vertIndex1 + 1 < vertexCount ? vertIndex1 + 1 : 0;
305
+ final Vec2 v1 = vertices[vertIndex1];
306
+ final Vec2 v2 = vertices[vertIndex2];
307
+
308
+ // If the center is inside the polygon ...
309
+ if (separation < Settings.EPSILON) {
310
+ manifold.pointCount = 1;
311
+ manifold.type = ManifoldType.FACE_A;
312
+
313
+ // before inline:
314
+ // manifold.localNormal.set(normals[normalIndex]);
315
+ // manifold.localPoint.set(v1).addLocal(v2).mulLocal(.5f);
316
+ // manifold.points[0].localPoint.set(circle.m_p);
317
+ // after inline:
318
+ final Vec2 normal = normals[normalIndex];
319
+ manifold.localNormal.x = normal.x;
320
+ manifold.localNormal.y = normal.y;
321
+ manifold.localPoint.x = (v1.x + v2.x) * .5f;
322
+ manifold.localPoint.y = (v1.y + v2.y) * .5f;
323
+ final ManifoldPoint mpoint = manifold.points[0];
324
+ mpoint.localPoint.x = circlep.x;
325
+ mpoint.localPoint.y = circlep.y;
326
+ mpoint.id.zero();
327
+ // end inline
328
+
329
+ return;
330
+ }
331
+
332
+ // Compute barycentric coordinates
333
+ // before inline:
334
+ // temp.set(cLocal).subLocal(v1);
335
+ // temp2.set(v2).subLocal(v1);
336
+ // float u1 = Vec2.dot(temp, temp2);
337
+ // temp.set(cLocal).subLocal(v2);
338
+ // temp2.set(v1).subLocal(v2);
339
+ // float u2 = Vec2.dot(temp, temp2);
340
+ // after inline:
341
+ final float tempX = cLocalx - v1.x;
342
+ final float tempY = cLocaly - v1.y;
343
+ final float temp2X = v2.x - v1.x;
344
+ final float temp2Y = v2.y - v1.y;
345
+ final float u1 = tempX * temp2X + tempY * temp2Y;
346
+
347
+ final float temp3X = cLocalx - v2.x;
348
+ final float temp3Y = cLocaly - v2.y;
349
+ final float temp4X = v1.x - v2.x;
350
+ final float temp4Y = v1.y - v2.y;
351
+ final float u2 = temp3X * temp4X + temp3Y * temp4Y;
352
+ // end inline
353
+
354
+ if (u1 <= 0f) {
355
+ // inlined
356
+ final float dx = cLocalx - v1.x;
357
+ final float dy = cLocaly - v1.y;
358
+ if (dx * dx + dy * dy > radius * radius) {
359
+ return;
360
+ }
361
+
362
+ manifold.pointCount = 1;
363
+ manifold.type = ManifoldType.FACE_A;
364
+ // before inline:
365
+ // manifold.localNormal.set(cLocal).subLocal(v1);
366
+ // after inline:
367
+ manifold.localNormal.x = cLocalx - v1.x;
368
+ manifold.localNormal.y = cLocaly - v1.y;
369
+ // end inline
370
+ manifold.localNormal.normalize();
371
+ manifold.localPoint.set(v1);
372
+ manifold.points[0].localPoint.set(circlep);
373
+ manifold.points[0].id.zero();
374
+ } else if (u2 <= 0.0f) {
375
+ // inlined
376
+ final float dx = cLocalx - v2.x;
377
+ final float dy = cLocaly - v2.y;
378
+ if (dx * dx + dy * dy > radius * radius) {
379
+ return;
380
+ }
381
+
382
+ manifold.pointCount = 1;
383
+ manifold.type = ManifoldType.FACE_A;
384
+ // before inline:
385
+ // manifold.localNormal.set(cLocal).subLocal(v2);
386
+ // after inline:
387
+ manifold.localNormal.x = cLocalx - v2.x;
388
+ manifold.localNormal.y = cLocaly - v2.y;
389
+ // end inline
390
+ manifold.localNormal.normalize();
391
+ manifold.localPoint.set(v2);
392
+ manifold.points[0].localPoint.set(circlep);
393
+ manifold.points[0].id.zero();
394
+ } else {
395
+ // Vec2 faceCenter = 0.5f * (v1 + v2);
396
+ // (temp is faceCenter)
397
+ // before inline:
398
+ // temp.set(v1).addLocal(v2).mulLocal(.5f);
399
+ //
400
+ // temp2.set(cLocal).subLocal(temp);
401
+ // separation = Vec2.dot(temp2, normals[vertIndex1]);
402
+ // if (separation > radius) {
403
+ // return;
404
+ // }
405
+ // after inline:
406
+ final float fcx = (v1.x + v2.x) * .5f;
407
+ final float fcy = (v1.y + v2.y) * .5f;
408
+
409
+ final float tx = cLocalx - fcx;
410
+ final float ty = cLocaly - fcy;
411
+ final Vec2 normal = normals[vertIndex1];
412
+ separation = tx * normal.x + ty * normal.y;
413
+ if (separation > radius) {
414
+ return;
415
+ }
416
+ // end inline
417
+
418
+ manifold.pointCount = 1;
419
+ manifold.type = ManifoldType.FACE_A;
420
+ manifold.localNormal.set(normals[vertIndex1]);
421
+ manifold.localPoint.x = fcx; // (faceCenter)
422
+ manifold.localPoint.y = fcy;
423
+ manifold.points[0].localPoint.set(circlep);
424
+ manifold.points[0].id.zero();
425
+ }
426
+ }
427
+
428
+ // djm pooling, and from above
429
+ private final Vec2 temp = new Vec2();
430
+ private final Transform xf = new Transform();
431
+ private final Vec2 n = new Vec2();
432
+ private final Vec2 v1 = new Vec2();
433
+
434
+ /**
435
+ * Find the max separation between poly1 and poly2 using edge normals from poly1.
436
+ *
437
+ * @param edgeIndex
438
+ * @param poly1
439
+ * @param xf1
440
+ * @param poly2
441
+ * @param xf2
442
+ * @return
443
+ */
444
+ public final void findMaxSeparation(EdgeResults results, final PolygonShape poly1,
445
+ final Transform xf1, final PolygonShape poly2, final Transform xf2) {
446
+ int count1 = poly1.m_count;
447
+ int count2 = poly2.m_count;
448
+ Vec2[] n1s = poly1.m_normals;
449
+ Vec2[] v1s = poly1.m_vertices;
450
+ Vec2[] v2s = poly2.m_vertices;
451
+
452
+ Transform.mulTransToOutUnsafe(xf2, xf1, xf);
453
+ final Rot xfq = xf.q;
454
+
455
+ int bestIndex = 0;
456
+ float maxSeparation = -Float.MAX_VALUE;
457
+ for (int i = 0; i < count1; i++) {
458
+ // Get poly1 normal in frame2.
459
+ Rot.mulToOutUnsafe(xfq, n1s[i], n);
460
+ Transform.mulToOutUnsafe(xf, v1s[i], v1);
461
+
462
+ // Find deepest point for normal i.
463
+ float si = Float.MAX_VALUE;
464
+ for (int j = 0; j < count2; ++j) {
465
+ Vec2 v2sj = v2s[j];
466
+ float sij = n.x * (v2sj.x - v1.x) + n.y * (v2sj.y - v1.y);
467
+ if (sij < si) {
468
+ si = sij;
469
+ }
470
+ }
471
+
472
+ if (si > maxSeparation) {
473
+ maxSeparation = si;
474
+ bestIndex = i;
475
+ }
476
+ }
477
+
478
+ results.edgeIndex = bestIndex;
479
+ results.separation = maxSeparation;
480
+ }
481
+
482
+ public final void findIncidentEdge(final ClipVertex[] c, final PolygonShape poly1,
483
+ final Transform xf1, int edge1, final PolygonShape poly2, final Transform xf2) {
484
+ int count1 = poly1.m_count;
485
+ final Vec2[] normals1 = poly1.m_normals;
486
+
487
+ int count2 = poly2.m_count;
488
+ final Vec2[] vertices2 = poly2.m_vertices;
489
+ final Vec2[] normals2 = poly2.m_normals;
490
+
491
+ assert (0 <= edge1 && edge1 < count1);
492
+
493
+ final ClipVertex c0 = c[0];
494
+ final ClipVertex c1 = c[1];
495
+ final Rot xf1q = xf1.q;
496
+ final Rot xf2q = xf2.q;
497
+
498
+ // Get the normal of the reference edge in poly2's frame.
499
+ // Vec2 normal1 = MulT(xf2.R, Mul(xf1.R, normals1[edge1]));
500
+ // before inline:
501
+ // Rot.mulToOutUnsafe(xf1.q, normals1[edge1], normal1); // temporary
502
+ // Rot.mulTrans(xf2.q, normal1, normal1);
503
+ // after inline:
504
+ final Vec2 v = normals1[edge1];
505
+ final float tempx = xf1q.c * v.x - xf1q.s * v.y;
506
+ final float tempy = xf1q.s * v.x + xf1q.c * v.y;
507
+ final float normal1x = xf2q.c * tempx + xf2q.s * tempy;
508
+ final float normal1y = -xf2q.s * tempx + xf2q.c * tempy;
509
+
510
+ // end inline
511
+
512
+ // Find the incident edge on poly2.
513
+ int index = 0;
514
+ float minDot = Float.MAX_VALUE;
515
+ for (int i = 0; i < count2; ++i) {
516
+ Vec2 b = normals2[i];
517
+ float dot = normal1x * b.x + normal1y * b.y;
518
+ if (dot < minDot) {
519
+ minDot = dot;
520
+ index = i;
521
+ }
522
+ }
523
+
524
+ // Build the clip vertices for the incident edge.
525
+ int i1 = index;
526
+ int i2 = i1 + 1 < count2 ? i1 + 1 : 0;
527
+
528
+ // c0.v = Mul(xf2, vertices2[i1]);
529
+ Vec2 v1 = vertices2[i1];
530
+ Vec2 out = c0.v;
531
+ out.x = (xf2q.c * v1.x - xf2q.s * v1.y) + xf2.p.x;
532
+ out.y = (xf2q.s * v1.x + xf2q.c * v1.y) + xf2.p.y;
533
+ c0.id.indexA = (byte) edge1;
534
+ c0.id.indexB = (byte) i1;
535
+ c0.id.typeA = (byte) ContactID.Type.FACE.ordinal();
536
+ c0.id.typeB = (byte) ContactID.Type.VERTEX.ordinal();
537
+
538
+ // c1.v = Mul(xf2, vertices2[i2]);
539
+ Vec2 v2 = vertices2[i2];
540
+ Vec2 out1 = c1.v;
541
+ out1.x = (xf2q.c * v2.x - xf2q.s * v2.y) + xf2.p.x;
542
+ out1.y = (xf2q.s * v2.x + xf2q.c * v2.y) + xf2.p.y;
543
+ c1.id.indexA = (byte) edge1;
544
+ c1.id.indexB = (byte) i2;
545
+ c1.id.typeA = (byte) ContactID.Type.FACE.ordinal();
546
+ c1.id.typeB = (byte) ContactID.Type.VERTEX.ordinal();
547
+ }
548
+
549
+ private final EdgeResults results1 = new EdgeResults();
550
+ private final EdgeResults results2 = new EdgeResults();
551
+ private final ClipVertex[] incidentEdge = new ClipVertex[2];
552
+ private final Vec2 localTangent = new Vec2();
553
+ private final Vec2 localNormal = new Vec2();
554
+ private final Vec2 planePoint = new Vec2();
555
+ private final Vec2 tangent = new Vec2();
556
+ private final Vec2 v11 = new Vec2();
557
+ private final Vec2 v12 = new Vec2();
558
+ private final ClipVertex[] clipPoints1 = new ClipVertex[2];
559
+ private final ClipVertex[] clipPoints2 = new ClipVertex[2];
560
+
561
+ /**
562
+ * Compute the collision manifold between two polygons.
563
+ *
564
+ * @param manifold
565
+ * @param polygon1
566
+ * @param xf1
567
+ * @param polygon2
568
+ * @param xf2
569
+ */
570
+ public final void collidePolygons(Manifold manifold, final PolygonShape polyA,
571
+ final Transform xfA, final PolygonShape polyB, final Transform xfB) {
572
+ // Find edge normal of max separation on A - return if separating axis is found
573
+ // Find edge normal of max separation on B - return if separation axis is found
574
+ // Choose reference edge as min(minA, minB)
575
+ // Find incident edge
576
+ // Clip
577
+
578
+ // The normal points from 1 to 2
579
+
580
+ manifold.pointCount = 0;
581
+ float totalRadius = polyA.m_radius + polyB.m_radius;
582
+
583
+ findMaxSeparation(results1, polyA, xfA, polyB, xfB);
584
+ if (results1.separation > totalRadius) {
585
+ return;
586
+ }
587
+
588
+ findMaxSeparation(results2, polyB, xfB, polyA, xfA);
589
+ if (results2.separation > totalRadius) {
590
+ return;
591
+ }
592
+
593
+ final PolygonShape poly1; // reference polygon
594
+ final PolygonShape poly2; // incident polygon
595
+ Transform xf1, xf2;
596
+ int edge1; // reference edge
597
+ boolean flip;
598
+ final float k_tol = 0.1f * Settings.linearSlop;
599
+
600
+ if (results2.separation > results1.separation + k_tol) {
601
+ poly1 = polyB;
602
+ poly2 = polyA;
603
+ xf1 = xfB;
604
+ xf2 = xfA;
605
+ edge1 = results2.edgeIndex;
606
+ manifold.type = ManifoldType.FACE_B;
607
+ flip = true;
608
+ } else {
609
+ poly1 = polyA;
610
+ poly2 = polyB;
611
+ xf1 = xfA;
612
+ xf2 = xfB;
613
+ edge1 = results1.edgeIndex;
614
+ manifold.type = ManifoldType.FACE_A;
615
+ flip = false;
616
+ }
617
+ final Rot xf1q = xf1.q;
618
+
619
+ findIncidentEdge(incidentEdge, poly1, xf1, edge1, poly2, xf2);
620
+
621
+ int count1 = poly1.m_count;
622
+ final Vec2[] vertices1 = poly1.m_vertices;
623
+
624
+ final int iv1 = edge1;
625
+ final int iv2 = edge1 + 1 < count1 ? edge1 + 1 : 0;
626
+ v11.set(vertices1[iv1]);
627
+ v12.set(vertices1[iv2]);
628
+ localTangent.x = v12.x - v11.x;
629
+ localTangent.y = v12.y - v11.y;
630
+ localTangent.normalize();
631
+
632
+ // Vec2 localNormal = Vec2.cross(dv, 1.0f);
633
+ localNormal.x = 1f * localTangent.y;
634
+ localNormal.y = -1f * localTangent.x;
635
+
636
+ // Vec2 planePoint = 0.5f * (v11+ v12);
637
+ planePoint.x = (v11.x + v12.x) * .5f;
638
+ planePoint.y = (v11.y + v12.y) * .5f;
639
+
640
+ // Rot.mulToOutUnsafe(xf1.q, localTangent, tangent);
641
+ tangent.x = xf1q.c * localTangent.x - xf1q.s * localTangent.y;
642
+ tangent.y = xf1q.s * localTangent.x + xf1q.c * localTangent.y;
643
+
644
+ // Vec2.crossToOutUnsafe(tangent, 1f, normal);
645
+ final float normalx = 1f * tangent.y;
646
+ final float normaly = -1f * tangent.x;
647
+
648
+
649
+ Transform.mulToOut(xf1, v11, v11);
650
+ Transform.mulToOut(xf1, v12, v12);
651
+ // v11 = Mul(xf1, v11);
652
+ // v12 = Mul(xf1, v12);
653
+
654
+ // Face offset
655
+ // float frontOffset = Vec2.dot(normal, v11);
656
+ float frontOffset = normalx * v11.x + normaly * v11.y;
657
+
658
+ // Side offsets, extended by polytope skin thickness.
659
+ // float sideOffset1 = -Vec2.dot(tangent, v11) + totalRadius;
660
+ // float sideOffset2 = Vec2.dot(tangent, v12) + totalRadius;
661
+ float sideOffset1 = -(tangent.x * v11.x + tangent.y * v11.y) + totalRadius;
662
+ float sideOffset2 = tangent.x * v12.x + tangent.y * v12.y + totalRadius;
663
+
664
+ // Clip incident edge against extruded edge1 side edges.
665
+ // ClipVertex clipPoints1[2];
666
+ // ClipVertex clipPoints2[2];
667
+ int np;
668
+
669
+ // Clip to box side 1
670
+ // np = ClipSegmentToLine(clipPoints1, incidentEdge, -sideNormal, sideOffset1);
671
+ tangent.negateLocal();
672
+ np = clipSegmentToLine(clipPoints1, incidentEdge, tangent, sideOffset1, iv1);
673
+ tangent.negateLocal();
674
+
675
+ if (np < 2) {
676
+ return;
677
+ }
678
+
679
+ // Clip to negative box side 1
680
+ np = clipSegmentToLine(clipPoints2, clipPoints1, tangent, sideOffset2, iv2);
681
+
682
+ if (np < 2) {
683
+ return;
684
+ }
685
+
686
+ // Now clipPoints2 contains the clipped points.
687
+ manifold.localNormal.set(localNormal);
688
+ manifold.localPoint.set(planePoint);
689
+
690
+ int pointCount = 0;
691
+ for (int i = 0; i < Settings.maxManifoldPoints; ++i) {
692
+ // float separation = Vec2.dot(normal, clipPoints2[i].v) - frontOffset;
693
+ float separation = normalx * clipPoints2[i].v.x + normaly * clipPoints2[i].v.y - frontOffset;
694
+
695
+ if (separation <= totalRadius) {
696
+ ManifoldPoint cp = manifold.points[pointCount];
697
+ // cp.m_localPoint = MulT(xf2, clipPoints2[i].v);
698
+ Vec2 out = cp.localPoint;
699
+ final float px = clipPoints2[i].v.x - xf2.p.x;
700
+ final float py = clipPoints2[i].v.y - xf2.p.y;
701
+ out.x = (xf2.q.c * px + xf2.q.s * py);
702
+ out.y = (-xf2.q.s * px + xf2.q.c * py);
703
+ cp.id.set(clipPoints2[i].id);
704
+ if (flip) {
705
+ // Swap features
706
+ cp.id.flip();
707
+ }
708
+ ++pointCount;
709
+ }
710
+ }
711
+
712
+ manifold.pointCount = pointCount;
713
+ }
714
+
715
+ private final Vec2 Q = new Vec2();
716
+ private final Vec2 e = new Vec2();
717
+ private final ContactID cf = new ContactID();
718
+ private final Vec2 e1 = new Vec2();
719
+ private final Vec2 P = new Vec2();
720
+
721
+ // Compute contact points for edge versus circle.
722
+ // This accounts for edge connectivity.
723
+ public void collideEdgeAndCircle(Manifold manifold, final EdgeShape edgeA, final Transform xfA,
724
+ final CircleShape circleB, final Transform xfB) {
725
+ manifold.pointCount = 0;
726
+
727
+
728
+ // Compute circle in frame of edge
729
+ // Vec2 Q = MulT(xfA, Mul(xfB, circleB.m_p));
730
+ Transform.mulToOutUnsafe(xfB, circleB.m_p, temp);
731
+ Transform.mulTransToOutUnsafe(xfA, temp, Q);
732
+
733
+ final Vec2 A = edgeA.m_vertex1;
734
+ final Vec2 B = edgeA.m_vertex2;
735
+ e.set(B).subLocal(A);
736
+
737
+ // Barycentric coordinates
738
+ float u = Vec2.dot(e, temp.set(B).subLocal(Q));
739
+ float v = Vec2.dot(e, temp.set(Q).subLocal(A));
740
+
741
+ float radius = edgeA.m_radius + circleB.m_radius;
742
+
743
+ // ContactFeature cf;
744
+ cf.indexB = 0;
745
+ cf.typeB = (byte) ContactID.Type.VERTEX.ordinal();
746
+
747
+ // Region A
748
+ if (v <= 0.0f) {
749
+ final Vec2 P = A;
750
+ d.set(Q).subLocal(P);
751
+ float dd = Vec2.dot(d, d);
752
+ if (dd > radius * radius) {
753
+ return;
754
+ }
755
+
756
+ // Is there an edge connected to A?
757
+ if (edgeA.m_hasVertex0) {
758
+ final Vec2 A1 = edgeA.m_vertex0;
759
+ final Vec2 B1 = A;
760
+ e1.set(B1).subLocal(A1);
761
+ float u1 = Vec2.dot(e1, temp.set(B1).subLocal(Q));
762
+
763
+ // Is the circle in Region AB of the previous edge?
764
+ if (u1 > 0.0f) {
765
+ return;
766
+ }
767
+ }
768
+
769
+ cf.indexA = 0;
770
+ cf.typeA = (byte) ContactID.Type.VERTEX.ordinal();
771
+ manifold.pointCount = 1;
772
+ manifold.type = Manifold.ManifoldType.CIRCLES;
773
+ manifold.localNormal.setZero();
774
+ manifold.localPoint.set(P);
775
+ // manifold.points[0].id.key = 0;
776
+ manifold.points[0].id.set(cf);
777
+ manifold.points[0].localPoint.set(circleB.m_p);
778
+ return;
779
+ }
780
+
781
+ // Region B
782
+ if (u <= 0.0f) {
783
+ Vec2 P = B;
784
+ d.set(Q).subLocal(P);
785
+ float dd = Vec2.dot(d, d);
786
+ if (dd > radius * radius) {
787
+ return;
788
+ }
789
+
790
+ // Is there an edge connected to B?
791
+ if (edgeA.m_hasVertex3) {
792
+ final Vec2 B2 = edgeA.m_vertex3;
793
+ final Vec2 A2 = B;
794
+ final Vec2 e2 = e1;
795
+ e2.set(B2).subLocal(A2);
796
+ float v2 = Vec2.dot(e2, temp.set(Q).subLocal(A2));
797
+
798
+ // Is the circle in Region AB of the next edge?
799
+ if (v2 > 0.0f) {
800
+ return;
801
+ }
802
+ }
803
+
804
+ cf.indexA = 1;
805
+ cf.typeA = (byte) ContactID.Type.VERTEX.ordinal();
806
+ manifold.pointCount = 1;
807
+ manifold.type = Manifold.ManifoldType.CIRCLES;
808
+ manifold.localNormal.setZero();
809
+ manifold.localPoint.set(P);
810
+ // manifold.points[0].id.key = 0;
811
+ manifold.points[0].id.set(cf);
812
+ manifold.points[0].localPoint.set(circleB.m_p);
813
+ return;
814
+ }
815
+
816
+ // Region AB
817
+ float den = Vec2.dot(e, e);
818
+ assert (den > 0.0f);
819
+
820
+ // Vec2 P = (1.0f / den) * (u * A + v * B);
821
+ P.set(A).mulLocal(u).addLocal(temp.set(B).mulLocal(v));
822
+ P.mulLocal(1.0f / den);
823
+ d.set(Q).subLocal(P);
824
+ float dd = Vec2.dot(d, d);
825
+ if (dd > radius * radius) {
826
+ return;
827
+ }
828
+
829
+ n.x = -e.y;
830
+ n.y = e.x;
831
+ if (Vec2.dot(n, temp.set(Q).subLocal(A)) < 0.0f) {
832
+ n.set(-n.x, -n.y);
833
+ }
834
+ n.normalize();
835
+
836
+ cf.indexA = 0;
837
+ cf.typeA = (byte) ContactID.Type.FACE.ordinal();
838
+ manifold.pointCount = 1;
839
+ manifold.type = Manifold.ManifoldType.FACE_A;
840
+ manifold.localNormal.set(n);
841
+ manifold.localPoint.set(A);
842
+ // manifold.points[0].id.key = 0;
843
+ manifold.points[0].id.set(cf);
844
+ manifold.points[0].localPoint.set(circleB.m_p);
845
+ }
846
+
847
+ private final EPCollider collider = new EPCollider();
848
+
849
+ public void collideEdgeAndPolygon(Manifold manifold, final EdgeShape edgeA, final Transform xfA,
850
+ final PolygonShape polygonB, final Transform xfB) {
851
+ collider.collide(manifold, edgeA, xfA, polygonB, xfB);
852
+ }
853
+
854
+
855
+
856
+ /**
857
+ * Java-specific class for returning edge results
858
+ */
859
+ private static class EdgeResults {
860
+ public float separation;
861
+ public int edgeIndex;
862
+ }
863
+
864
+ /**
865
+ * Used for computing contact manifolds.
866
+ */
867
+ public static class ClipVertex {
868
+ public final Vec2 v;
869
+ public final ContactID id;
870
+
871
+ public ClipVertex() {
872
+ v = new Vec2();
873
+ id = new ContactID();
874
+ }
875
+
876
+ public void set(final ClipVertex cv) {
877
+ Vec2 v1 = cv.v;
878
+ v.x = v1.x;
879
+ v.y = v1.y;
880
+ ContactID c = cv.id;
881
+ id.indexA = c.indexA;
882
+ id.indexB = c.indexB;
883
+ id.typeA = c.typeA;
884
+ id.typeB = c.typeB;
885
+ }
886
+ }
887
+
888
+ /**
889
+ * This is used for determining the state of contact points.
890
+ *
891
+ * @author Daniel Murphy
892
+ */
893
+ public static enum PointState {
894
+ /**
895
+ * point does not exist
896
+ */
897
+ NULL_STATE,
898
+ /**
899
+ * point was added in the update
900
+ */
901
+ ADD_STATE,
902
+ /**
903
+ * point persisted across the update
904
+ */
905
+ PERSIST_STATE,
906
+ /**
907
+ * point was removed in the update
908
+ */
909
+ REMOVE_STATE
910
+ }
911
+
912
+ /**
913
+ * This structure is used to keep track of the best separating axis.
914
+ */
915
+ static class EPAxis {
916
+ enum Type {
917
+ UNKNOWN, EDGE_A, EDGE_B
918
+ }
919
+
920
+ Type type;
921
+ int index;
922
+ float separation;
923
+ }
924
+
925
+ /**
926
+ * This holds polygon B expressed in frame A.
927
+ */
928
+ static class TempPolygon {
929
+ final Vec2[] vertices = new Vec2[Settings.maxPolygonVertices];
930
+ final Vec2[] normals = new Vec2[Settings.maxPolygonVertices];
931
+ int count;
932
+
933
+ public TempPolygon() {
934
+ for (int i = 0; i < vertices.length; i++) {
935
+ vertices[i] = new Vec2();
936
+ normals[i] = new Vec2();
937
+ }
938
+ }
939
+ }
940
+
941
+ /**
942
+ * Reference face used for clipping
943
+ */
944
+ static class ReferenceFace {
945
+ int i1, i2;
946
+ final Vec2 v1 = new Vec2();
947
+ final Vec2 v2 = new Vec2();
948
+ final Vec2 normal = new Vec2();
949
+
950
+ final Vec2 sideNormal1 = new Vec2();
951
+ float sideOffset1;
952
+
953
+ final Vec2 sideNormal2 = new Vec2();
954
+ float sideOffset2;
955
+ }
956
+
957
+ /**
958
+ * This class collides and edge and a polygon, taking into account edge adjacency.
959
+ */
960
+ static class EPCollider {
961
+ enum VertexType {
962
+ ISOLATED, CONCAVE, CONVEX
963
+ }
964
+
965
+ final TempPolygon m_polygonB = new TempPolygon();
966
+
967
+ final Transform m_xf = new Transform();
968
+ final Vec2 m_centroidB = new Vec2();
969
+ Vec2 m_v0 = new Vec2();
970
+ Vec2 m_v1 = new Vec2();
971
+ Vec2 m_v2 = new Vec2();
972
+ Vec2 m_v3 = new Vec2();
973
+ final Vec2 m_normal0 = new Vec2();
974
+ final Vec2 m_normal1 = new Vec2();
975
+ final Vec2 m_normal2 = new Vec2();
976
+ final Vec2 m_normal = new Vec2();
977
+
978
+ VertexType m_type1, m_type2;
979
+
980
+ final Vec2 m_lowerLimit = new Vec2();
981
+ final Vec2 m_upperLimit = new Vec2();
982
+ float m_radius;
983
+ boolean m_front;
984
+
985
+ public EPCollider() {
986
+ for (int i = 0; i < 2; i++) {
987
+ ie[i] = new ClipVertex();
988
+ clipPoints1[i] = new ClipVertex();
989
+ clipPoints2[i] = new ClipVertex();
990
+ }
991
+ }
992
+
993
+ private final Vec2 edge1 = new Vec2();
994
+ private final Vec2 temp = new Vec2();
995
+ private final Vec2 edge0 = new Vec2();
996
+ private final Vec2 edge2 = new Vec2();
997
+ private final ClipVertex[] ie = new ClipVertex[2];
998
+ private final ClipVertex[] clipPoints1 = new ClipVertex[2];
999
+ private final ClipVertex[] clipPoints2 = new ClipVertex[2];
1000
+ private final ReferenceFace rf = new ReferenceFace();
1001
+ private final EPAxis edgeAxis = new EPAxis();
1002
+ private final EPAxis polygonAxis = new EPAxis();
1003
+
1004
+ public void collide(Manifold manifold, final EdgeShape edgeA, final Transform xfA,
1005
+ final PolygonShape polygonB, final Transform xfB) {
1006
+
1007
+ Transform.mulTransToOutUnsafe(xfA, xfB, m_xf);
1008
+ Transform.mulToOutUnsafe(m_xf, polygonB.m_centroid, m_centroidB);
1009
+
1010
+ m_v0 = edgeA.m_vertex0;
1011
+ m_v1 = edgeA.m_vertex1;
1012
+ m_v2 = edgeA.m_vertex2;
1013
+ m_v3 = edgeA.m_vertex3;
1014
+
1015
+ boolean hasVertex0 = edgeA.m_hasVertex0;
1016
+ boolean hasVertex3 = edgeA.m_hasVertex3;
1017
+
1018
+ edge1.set(m_v2).subLocal(m_v1);
1019
+ edge1.normalize();
1020
+ m_normal1.set(edge1.y, -edge1.x);
1021
+ float offset1 = Vec2.dot(m_normal1, temp.set(m_centroidB).subLocal(m_v1));
1022
+ float offset0 = 0.0f, offset2 = 0.0f;
1023
+ boolean convex1 = false, convex2 = false;
1024
+
1025
+ // Is there a preceding edge?
1026
+ if (hasVertex0) {
1027
+ edge0.set(m_v1).subLocal(m_v0);
1028
+ edge0.normalize();
1029
+ m_normal0.set(edge0.y, -edge0.x);
1030
+ convex1 = Vec2.cross(edge0, edge1) >= 0.0f;
1031
+ offset0 = Vec2.dot(m_normal0, temp.set(m_centroidB).subLocal(m_v0));
1032
+ }
1033
+
1034
+ // Is there a following edge?
1035
+ if (hasVertex3) {
1036
+ edge2.set(m_v3).subLocal(m_v2);
1037
+ edge2.normalize();
1038
+ m_normal2.set(edge2.y, -edge2.x);
1039
+ convex2 = Vec2.cross(edge1, edge2) > 0.0f;
1040
+ offset2 = Vec2.dot(m_normal2, temp.set(m_centroidB).subLocal(m_v2));
1041
+ }
1042
+
1043
+ // Determine front or back collision. Determine collision normal limits.
1044
+ if (hasVertex0 && hasVertex3) {
1045
+ if (convex1 && convex2) {
1046
+ m_front = offset0 >= 0.0f || offset1 >= 0.0f || offset2 >= 0.0f;
1047
+ if (m_front) {
1048
+ m_normal.x = m_normal1.x;
1049
+ m_normal.y = m_normal1.y;
1050
+ m_lowerLimit.x = m_normal0.x;
1051
+ m_lowerLimit.y = m_normal0.y;
1052
+ m_upperLimit.x = m_normal2.x;
1053
+ m_upperLimit.y = m_normal2.y;
1054
+ } else {
1055
+ m_normal.x = -m_normal1.x;
1056
+ m_normal.y = -m_normal1.y;
1057
+ m_lowerLimit.x = -m_normal1.x;
1058
+ m_lowerLimit.y = -m_normal1.y;
1059
+ m_upperLimit.x = -m_normal1.x;
1060
+ m_upperLimit.y = -m_normal1.y;
1061
+ }
1062
+ } else if (convex1) {
1063
+ m_front = offset0 >= 0.0f || (offset1 >= 0.0f && offset2 >= 0.0f);
1064
+ if (m_front) {
1065
+ m_normal.x = m_normal1.x;
1066
+ m_normal.y = m_normal1.y;
1067
+ m_lowerLimit.x = m_normal0.x;
1068
+ m_lowerLimit.y = m_normal0.y;
1069
+ m_upperLimit.x = m_normal1.x;
1070
+ m_upperLimit.y = m_normal1.y;
1071
+ } else {
1072
+ m_normal.x = -m_normal1.x;
1073
+ m_normal.y = -m_normal1.y;
1074
+ m_lowerLimit.x = -m_normal2.x;
1075
+ m_lowerLimit.y = -m_normal2.y;
1076
+ m_upperLimit.x = -m_normal1.x;
1077
+ m_upperLimit.y = -m_normal1.y;
1078
+ }
1079
+ } else if (convex2) {
1080
+ m_front = offset2 >= 0.0f || (offset0 >= 0.0f && offset1 >= 0.0f);
1081
+ if (m_front) {
1082
+ m_normal.x = m_normal1.x;
1083
+ m_normal.y = m_normal1.y;
1084
+ m_lowerLimit.x = m_normal1.x;
1085
+ m_lowerLimit.y = m_normal1.y;
1086
+ m_upperLimit.x = m_normal2.x;
1087
+ m_upperLimit.y = m_normal2.y;
1088
+ } else {
1089
+ m_normal.x = -m_normal1.x;
1090
+ m_normal.y = -m_normal1.y;
1091
+ m_lowerLimit.x = -m_normal1.x;
1092
+ m_lowerLimit.y = -m_normal1.y;
1093
+ m_upperLimit.x = -m_normal0.x;
1094
+ m_upperLimit.y = -m_normal0.y;
1095
+ }
1096
+ } else {
1097
+ m_front = offset0 >= 0.0f && offset1 >= 0.0f && offset2 >= 0.0f;
1098
+ if (m_front) {
1099
+ m_normal.x = m_normal1.x;
1100
+ m_normal.y = m_normal1.y;
1101
+ m_lowerLimit.x = m_normal1.x;
1102
+ m_lowerLimit.y = m_normal1.y;
1103
+ m_upperLimit.x = m_normal1.x;
1104
+ m_upperLimit.y = m_normal1.y;
1105
+ } else {
1106
+ m_normal.x = -m_normal1.x;
1107
+ m_normal.y = -m_normal1.y;
1108
+ m_lowerLimit.x = -m_normal2.x;
1109
+ m_lowerLimit.y = -m_normal2.y;
1110
+ m_upperLimit.x = -m_normal0.x;
1111
+ m_upperLimit.y = -m_normal0.y;
1112
+ }
1113
+ }
1114
+ } else if (hasVertex0) {
1115
+ if (convex1) {
1116
+ m_front = offset0 >= 0.0f || offset1 >= 0.0f;
1117
+ if (m_front) {
1118
+ m_normal.x = m_normal1.x;
1119
+ m_normal.y = m_normal1.y;
1120
+ m_lowerLimit.x = m_normal0.x;
1121
+ m_lowerLimit.y = m_normal0.y;
1122
+ m_upperLimit.x = -m_normal1.x;
1123
+ m_upperLimit.y = -m_normal1.y;
1124
+ } else {
1125
+ m_normal.x = -m_normal1.x;
1126
+ m_normal.y = -m_normal1.y;
1127
+ m_lowerLimit.x = m_normal1.x;
1128
+ m_lowerLimit.y = m_normal1.y;
1129
+ m_upperLimit.x = -m_normal1.x;
1130
+ m_upperLimit.y = -m_normal1.y;
1131
+ }
1132
+ } else {
1133
+ m_front = offset0 >= 0.0f && offset1 >= 0.0f;
1134
+ if (m_front) {
1135
+ m_normal.x = m_normal1.x;
1136
+ m_normal.y = m_normal1.y;
1137
+ m_lowerLimit.x = m_normal1.x;
1138
+ m_lowerLimit.y = m_normal1.y;
1139
+ m_upperLimit.x = -m_normal1.x;
1140
+ m_upperLimit.y = -m_normal1.y;
1141
+ } else {
1142
+ m_normal.x = -m_normal1.x;
1143
+ m_normal.y = -m_normal1.y;
1144
+ m_lowerLimit.x = m_normal1.x;
1145
+ m_lowerLimit.y = m_normal1.y;
1146
+ m_upperLimit.x = -m_normal0.x;
1147
+ m_upperLimit.y = -m_normal0.y;
1148
+ }
1149
+ }
1150
+ } else if (hasVertex3) {
1151
+ if (convex2) {
1152
+ m_front = offset1 >= 0.0f || offset2 >= 0.0f;
1153
+ if (m_front) {
1154
+ m_normal.x = m_normal1.x;
1155
+ m_normal.y = m_normal1.y;
1156
+ m_lowerLimit.x = -m_normal1.x;
1157
+ m_lowerLimit.y = -m_normal1.y;
1158
+ m_upperLimit.x = m_normal2.x;
1159
+ m_upperLimit.y = m_normal2.y;
1160
+ } else {
1161
+ m_normal.x = -m_normal1.x;
1162
+ m_normal.y = -m_normal1.y;
1163
+ m_lowerLimit.x = -m_normal1.x;
1164
+ m_lowerLimit.y = -m_normal1.y;
1165
+ m_upperLimit.x = m_normal1.x;
1166
+ m_upperLimit.y = m_normal1.y;
1167
+ }
1168
+ } else {
1169
+ m_front = offset1 >= 0.0f && offset2 >= 0.0f;
1170
+ if (m_front) {
1171
+ m_normal.x = m_normal1.x;
1172
+ m_normal.y = m_normal1.y;
1173
+ m_lowerLimit.x = -m_normal1.x;
1174
+ m_lowerLimit.y = -m_normal1.y;
1175
+ m_upperLimit.x = m_normal1.x;
1176
+ m_upperLimit.y = m_normal1.y;
1177
+ } else {
1178
+ m_normal.x = -m_normal1.x;
1179
+ m_normal.y = -m_normal1.y;
1180
+ m_lowerLimit.x = -m_normal2.x;
1181
+ m_lowerLimit.y = -m_normal2.y;
1182
+ m_upperLimit.x = m_normal1.x;
1183
+ m_upperLimit.y = m_normal1.y;
1184
+ }
1185
+ }
1186
+ } else {
1187
+ m_front = offset1 >= 0.0f;
1188
+ if (m_front) {
1189
+ m_normal.x = m_normal1.x;
1190
+ m_normal.y = m_normal1.y;
1191
+ m_lowerLimit.x = -m_normal1.x;
1192
+ m_lowerLimit.y = -m_normal1.y;
1193
+ m_upperLimit.x = -m_normal1.x;
1194
+ m_upperLimit.y = -m_normal1.y;
1195
+ } else {
1196
+ m_normal.x = -m_normal1.x;
1197
+ m_normal.y = -m_normal1.y;
1198
+ m_lowerLimit.x = m_normal1.x;
1199
+ m_lowerLimit.y = m_normal1.y;
1200
+ m_upperLimit.x = m_normal1.x;
1201
+ m_upperLimit.y = m_normal1.y;
1202
+ }
1203
+ }
1204
+
1205
+ // Get polygonB in frameA
1206
+ m_polygonB.count = polygonB.m_count;
1207
+ for (int i = 0; i < polygonB.m_count; ++i) {
1208
+ Transform.mulToOutUnsafe(m_xf, polygonB.m_vertices[i], m_polygonB.vertices[i]);
1209
+ Rot.mulToOutUnsafe(m_xf.q, polygonB.m_normals[i], m_polygonB.normals[i]);
1210
+ }
1211
+
1212
+ m_radius = 2.0f * Settings.polygonRadius;
1213
+
1214
+ manifold.pointCount = 0;
1215
+
1216
+ computeEdgeSeparation(edgeAxis);
1217
+
1218
+ // If no valid normal can be found than this edge should not collide.
1219
+ if (edgeAxis.type == EPAxis.Type.UNKNOWN) {
1220
+ return;
1221
+ }
1222
+
1223
+ if (edgeAxis.separation > m_radius) {
1224
+ return;
1225
+ }
1226
+
1227
+ computePolygonSeparation(polygonAxis);
1228
+ if (polygonAxis.type != EPAxis.Type.UNKNOWN && polygonAxis.separation > m_radius) {
1229
+ return;
1230
+ }
1231
+
1232
+ // Use hysteresis for jitter reduction.
1233
+ final float k_relativeTol = 0.98f;
1234
+ final float k_absoluteTol = 0.001f;
1235
+
1236
+ EPAxis primaryAxis;
1237
+ if (polygonAxis.type == EPAxis.Type.UNKNOWN) {
1238
+ primaryAxis = edgeAxis;
1239
+ } else if (polygonAxis.separation > k_relativeTol * edgeAxis.separation + k_absoluteTol) {
1240
+ primaryAxis = polygonAxis;
1241
+ } else {
1242
+ primaryAxis = edgeAxis;
1243
+ }
1244
+
1245
+ final ClipVertex ie0 = ie[0];
1246
+ final ClipVertex ie1 = ie[1];
1247
+
1248
+ if (primaryAxis.type == EPAxis.Type.EDGE_A) {
1249
+ manifold.type = Manifold.ManifoldType.FACE_A;
1250
+
1251
+ // Search for the polygon normal that is most anti-parallel to the edge normal.
1252
+ int bestIndex = 0;
1253
+ float bestValue = Vec2.dot(m_normal, m_polygonB.normals[0]);
1254
+ for (int i = 1; i < m_polygonB.count; ++i) {
1255
+ float value = Vec2.dot(m_normal, m_polygonB.normals[i]);
1256
+ if (value < bestValue) {
1257
+ bestValue = value;
1258
+ bestIndex = i;
1259
+ }
1260
+ }
1261
+
1262
+ int i1 = bestIndex;
1263
+ int i2 = i1 + 1 < m_polygonB.count ? i1 + 1 : 0;
1264
+
1265
+ ie0.v.set(m_polygonB.vertices[i1]);
1266
+ ie0.id.indexA = 0;
1267
+ ie0.id.indexB = (byte) i1;
1268
+ ie0.id.typeA = (byte) ContactID.Type.FACE.ordinal();
1269
+ ie0.id.typeB = (byte) ContactID.Type.VERTEX.ordinal();
1270
+
1271
+ ie1.v.set(m_polygonB.vertices[i2]);
1272
+ ie1.id.indexA = 0;
1273
+ ie1.id.indexB = (byte) i2;
1274
+ ie1.id.typeA = (byte) ContactID.Type.FACE.ordinal();
1275
+ ie1.id.typeB = (byte) ContactID.Type.VERTEX.ordinal();
1276
+
1277
+ if (m_front) {
1278
+ rf.i1 = 0;
1279
+ rf.i2 = 1;
1280
+ rf.v1.set(m_v1);
1281
+ rf.v2.set(m_v2);
1282
+ rf.normal.set(m_normal1);
1283
+ } else {
1284
+ rf.i1 = 1;
1285
+ rf.i2 = 0;
1286
+ rf.v1.set(m_v2);
1287
+ rf.v2.set(m_v1);
1288
+ rf.normal.set(m_normal1).negateLocal();
1289
+ }
1290
+ } else {
1291
+ manifold.type = Manifold.ManifoldType.FACE_B;
1292
+
1293
+ ie0.v.set(m_v1);
1294
+ ie0.id.indexA = 0;
1295
+ ie0.id.indexB = (byte) primaryAxis.index;
1296
+ ie0.id.typeA = (byte) ContactID.Type.VERTEX.ordinal();
1297
+ ie0.id.typeB = (byte) ContactID.Type.FACE.ordinal();
1298
+
1299
+ ie1.v.set(m_v2);
1300
+ ie1.id.indexA = 0;
1301
+ ie1.id.indexB = (byte) primaryAxis.index;
1302
+ ie1.id.typeA = (byte) ContactID.Type.VERTEX.ordinal();
1303
+ ie1.id.typeB = (byte) ContactID.Type.FACE.ordinal();
1304
+
1305
+ rf.i1 = primaryAxis.index;
1306
+ rf.i2 = rf.i1 + 1 < m_polygonB.count ? rf.i1 + 1 : 0;
1307
+ rf.v1.set(m_polygonB.vertices[rf.i1]);
1308
+ rf.v2.set(m_polygonB.vertices[rf.i2]);
1309
+ rf.normal.set(m_polygonB.normals[rf.i1]);
1310
+ }
1311
+
1312
+ rf.sideNormal1.set(rf.normal.y, -rf.normal.x);
1313
+ rf.sideNormal2.set(rf.sideNormal1).negateLocal();
1314
+ rf.sideOffset1 = Vec2.dot(rf.sideNormal1, rf.v1);
1315
+ rf.sideOffset2 = Vec2.dot(rf.sideNormal2, rf.v2);
1316
+
1317
+ // Clip incident edge against extruded edge1 side edges.
1318
+ int np;
1319
+
1320
+ // Clip to box side 1
1321
+ np = clipSegmentToLine(clipPoints1, ie, rf.sideNormal1, rf.sideOffset1, rf.i1);
1322
+
1323
+ if (np < Settings.maxManifoldPoints) {
1324
+ return;
1325
+ }
1326
+
1327
+ // Clip to negative box side 1
1328
+ np = clipSegmentToLine(clipPoints2, clipPoints1, rf.sideNormal2, rf.sideOffset2, rf.i2);
1329
+
1330
+ if (np < Settings.maxManifoldPoints) {
1331
+ return;
1332
+ }
1333
+
1334
+ // Now clipPoints2 contains the clipped points.
1335
+ if (primaryAxis.type == EPAxis.Type.EDGE_A) {
1336
+ manifold.localNormal.set(rf.normal);
1337
+ manifold.localPoint.set(rf.v1);
1338
+ } else {
1339
+ manifold.localNormal.set(polygonB.m_normals[rf.i1]);
1340
+ manifold.localPoint.set(polygonB.m_vertices[rf.i1]);
1341
+ }
1342
+
1343
+ int pointCount = 0;
1344
+ for (int i = 0; i < Settings.maxManifoldPoints; ++i) {
1345
+ float separation;
1346
+
1347
+ separation = Vec2.dot(rf.normal, temp.set(clipPoints2[i].v).subLocal(rf.v1));
1348
+
1349
+ if (separation <= m_radius) {
1350
+ ManifoldPoint cp = manifold.points[pointCount];
1351
+
1352
+ if (primaryAxis.type == EPAxis.Type.EDGE_A) {
1353
+ // cp.localPoint = MulT(m_xf, clipPoints2[i].v);
1354
+ Transform.mulTransToOutUnsafe(m_xf, clipPoints2[i].v, cp.localPoint);
1355
+ cp.id.set(clipPoints2[i].id);
1356
+ } else {
1357
+ cp.localPoint.set(clipPoints2[i].v);
1358
+ cp.id.typeA = clipPoints2[i].id.typeB;
1359
+ cp.id.typeB = clipPoints2[i].id.typeA;
1360
+ cp.id.indexA = clipPoints2[i].id.indexB;
1361
+ cp.id.indexB = clipPoints2[i].id.indexA;
1362
+ }
1363
+
1364
+ ++pointCount;
1365
+ }
1366
+ }
1367
+
1368
+ manifold.pointCount = pointCount;
1369
+ }
1370
+
1371
+
1372
+ public void computeEdgeSeparation(EPAxis axis) {
1373
+ axis.type = EPAxis.Type.EDGE_A;
1374
+ axis.index = m_front ? 0 : 1;
1375
+ axis.separation = Float.MAX_VALUE;
1376
+ float nx = m_normal.x;
1377
+ float ny = m_normal.y;
1378
+
1379
+ for (int i = 0; i < m_polygonB.count; ++i) {
1380
+ Vec2 v = m_polygonB.vertices[i];
1381
+ float tempx = v.x - m_v1.x;
1382
+ float tempy = v.y - m_v1.y;
1383
+ float s = nx * tempx + ny * tempy;
1384
+ if (s < axis.separation) {
1385
+ axis.separation = s;
1386
+ }
1387
+ }
1388
+ }
1389
+
1390
+ private final Vec2 perp = new Vec2();
1391
+ private final Vec2 n = new Vec2();
1392
+
1393
+ public void computePolygonSeparation(EPAxis axis) {
1394
+ axis.type = EPAxis.Type.UNKNOWN;
1395
+ axis.index = -1;
1396
+ axis.separation = -Float.MAX_VALUE;
1397
+
1398
+ perp.x = -m_normal.y;
1399
+ perp.y = m_normal.x;
1400
+
1401
+ for (int i = 0; i < m_polygonB.count; ++i) {
1402
+ Vec2 normalB = m_polygonB.normals[i];
1403
+ Vec2 vB = m_polygonB.vertices[i];
1404
+ n.x = -normalB.x;
1405
+ n.y = -normalB.y;
1406
+
1407
+ // float s1 = Vec2.dot(n, temp.set(vB).subLocal(m_v1));
1408
+ // float s2 = Vec2.dot(n, temp.set(vB).subLocal(m_v2));
1409
+ float tempx = vB.x - m_v1.x;
1410
+ float tempy = vB.y - m_v1.y;
1411
+ float s1 = n.x * tempx + n.y * tempy;
1412
+ tempx = vB.x - m_v2.x;
1413
+ tempy = vB.y - m_v2.y;
1414
+ float s2 = n.x * tempx + n.y * tempy;
1415
+ float s = MathUtils.min(s1, s2);
1416
+
1417
+ if (s > m_radius) {
1418
+ // No collision
1419
+ axis.type = EPAxis.Type.EDGE_B;
1420
+ axis.index = i;
1421
+ axis.separation = s;
1422
+ return;
1423
+ }
1424
+
1425
+ // Adjacency
1426
+ if (n.x * perp.x + n.y * perp.y >= 0.0f) {
1427
+ if (Vec2.dot(temp.set(n).subLocal(m_upperLimit), m_normal) < -Settings.angularSlop) {
1428
+ continue;
1429
+ }
1430
+ } else {
1431
+ if (Vec2.dot(temp.set(n).subLocal(m_lowerLimit), m_normal) < -Settings.angularSlop) {
1432
+ continue;
1433
+ }
1434
+ }
1435
+
1436
+ if (s > axis.separation) {
1437
+ axis.type = EPAxis.Type.EDGE_B;
1438
+ axis.index = i;
1439
+ axis.separation = s;
1440
+ }
1441
+ }
1442
+ }
1443
+ }
1444
+ }