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,873 @@
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.broadphase;
25
+
26
+ import org.jbox2d.callbacks.DebugDraw;
27
+ import org.jbox2d.callbacks.TreeCallback;
28
+ import org.jbox2d.callbacks.TreeRayCastCallback;
29
+ import org.jbox2d.collision.AABB;
30
+ import org.jbox2d.collision.RayCastInput;
31
+ import org.jbox2d.common.BufferUtils;
32
+ import org.jbox2d.common.Color3f;
33
+ import org.jbox2d.common.MathUtils;
34
+ import org.jbox2d.common.Settings;
35
+ import org.jbox2d.common.Vec2;
36
+
37
+ public class DynamicTreeFlatNodes implements BroadPhaseStrategy {
38
+ public static final int MAX_STACK_SIZE = 64;
39
+ public static final int NULL_NODE = -1;
40
+ public static final int INITIAL_BUFFER_LENGTH = 16;
41
+
42
+ public int m_root;
43
+ public AABB[] m_aabb;
44
+ public Object[] m_userData;
45
+ protected int[] m_parent;
46
+ protected int[] m_child1;
47
+ protected int[] m_child2;
48
+ protected int[] m_height;
49
+
50
+ private int m_nodeCount;
51
+ private int m_nodeCapacity;
52
+
53
+ private int m_freeList;
54
+
55
+ private final Vec2[] drawVecs = new Vec2[4];
56
+
57
+ public DynamicTreeFlatNodes() {
58
+ m_root = NULL_NODE;
59
+ m_nodeCount = 0;
60
+ m_nodeCapacity = 16;
61
+ expandBuffers(0, m_nodeCapacity);
62
+
63
+ for (int i = 0; i < drawVecs.length; i++) {
64
+ drawVecs[i] = new Vec2();
65
+ }
66
+ }
67
+
68
+ private void expandBuffers(int oldSize, int newSize) {
69
+ m_aabb = BufferUtils.reallocateBuffer(AABB.class, m_aabb, oldSize, newSize);
70
+ m_userData = BufferUtils.reallocateBuffer(Object.class, m_userData, oldSize, newSize);
71
+ m_parent = BufferUtils.reallocateBuffer(m_parent, oldSize, newSize);
72
+ m_child1 = BufferUtils.reallocateBuffer(m_child1, oldSize, newSize);
73
+ m_child2 = BufferUtils.reallocateBuffer(m_child2, oldSize, newSize);
74
+ m_height = BufferUtils.reallocateBuffer(m_height, oldSize, newSize);
75
+
76
+ // Build a linked list for the free list.
77
+ for (int i = oldSize; i < newSize; i++) {
78
+ m_aabb[i] = new AABB();
79
+ m_parent[i] = (i == newSize - 1) ? NULL_NODE : i + 1;
80
+ m_height[i] = -1;
81
+ m_child1[i] = -1;
82
+ m_child2[i] = -1;
83
+ }
84
+ m_freeList = oldSize;
85
+ }
86
+
87
+ @Override
88
+ public final int createProxy(final AABB aabb, Object userData) {
89
+ final int node = allocateNode();
90
+ // Fatten the aabb
91
+ final AABB nodeAABB = m_aabb[node];
92
+ nodeAABB.lowerBound.x = aabb.lowerBound.x - Settings.aabbExtension;
93
+ nodeAABB.lowerBound.y = aabb.lowerBound.y - Settings.aabbExtension;
94
+ nodeAABB.upperBound.x = aabb.upperBound.x + Settings.aabbExtension;
95
+ nodeAABB.upperBound.y = aabb.upperBound.y + Settings.aabbExtension;
96
+ m_userData[node] = userData;
97
+
98
+ insertLeaf(node);
99
+
100
+ return node;
101
+ }
102
+
103
+ @Override
104
+ public final void destroyProxy(int proxyId) {
105
+ assert (0 <= proxyId && proxyId < m_nodeCapacity);
106
+ assert (m_child1[proxyId] == NULL_NODE);
107
+
108
+ removeLeaf(proxyId);
109
+ freeNode(proxyId);
110
+ }
111
+
112
+ @Override
113
+ public final boolean moveProxy(int proxyId, final AABB aabb, Vec2 displacement) {
114
+ assert (0 <= proxyId && proxyId < m_nodeCapacity);
115
+ final int node = proxyId;
116
+ assert (m_child1[node] == NULL_NODE);
117
+
118
+ final AABB nodeAABB = m_aabb[node];
119
+ // if (nodeAABB.contains(aabb)) {
120
+ if (nodeAABB.lowerBound.x <= aabb.lowerBound.x && nodeAABB.lowerBound.y <= aabb.lowerBound.y
121
+ && aabb.upperBound.x <= nodeAABB.upperBound.x && aabb.upperBound.y <= nodeAABB.upperBound.y) {
122
+ return false;
123
+ }
124
+
125
+ removeLeaf(node);
126
+
127
+ // Extend AABB
128
+ final Vec2 lowerBound = nodeAABB.lowerBound;
129
+ final Vec2 upperBound = nodeAABB.upperBound;
130
+ lowerBound.x = aabb.lowerBound.x - Settings.aabbExtension;
131
+ lowerBound.y = aabb.lowerBound.y - Settings.aabbExtension;
132
+ upperBound.x = aabb.upperBound.x + Settings.aabbExtension;
133
+ upperBound.y = aabb.upperBound.y + Settings.aabbExtension;
134
+
135
+ // Predict AABB displacement.
136
+ final float dx = displacement.x * Settings.aabbMultiplier;
137
+ final float dy = displacement.y * Settings.aabbMultiplier;
138
+ if (dx < 0.0f) {
139
+ lowerBound.x += dx;
140
+ } else {
141
+ upperBound.x += dx;
142
+ }
143
+
144
+ if (dy < 0.0f) {
145
+ lowerBound.y += dy;
146
+ } else {
147
+ upperBound.y += dy;
148
+ }
149
+
150
+ insertLeaf(proxyId);
151
+ return true;
152
+ }
153
+
154
+ @Override
155
+ public final Object getUserData(int proxyId) {
156
+ assert (0 <= proxyId && proxyId < m_nodeCount);
157
+ return m_userData[proxyId];
158
+ }
159
+
160
+ @Override
161
+ public final AABB getFatAABB(int proxyId) {
162
+ assert (0 <= proxyId && proxyId < m_nodeCount);
163
+ return m_aabb[proxyId];
164
+ }
165
+
166
+ private int[] nodeStack = new int[20];
167
+ private int nodeStackIndex;
168
+
169
+ @Override
170
+ public final void query(TreeCallback callback, AABB aabb) {
171
+ nodeStackIndex = 0;
172
+ nodeStack[nodeStackIndex++] = m_root;
173
+
174
+ while (nodeStackIndex > 0) {
175
+ int node = nodeStack[--nodeStackIndex];
176
+ if (node == NULL_NODE) {
177
+ continue;
178
+ }
179
+
180
+ if (AABB.testOverlap(m_aabb[node], aabb)) {
181
+ int child1 = m_child1[node];
182
+ if (child1 == NULL_NODE) {
183
+ boolean proceed = callback.treeCallback(node);
184
+ if (!proceed) {
185
+ return;
186
+ }
187
+ } else {
188
+ if (nodeStack.length - nodeStackIndex - 2 <= 0) {
189
+ nodeStack =
190
+ BufferUtils.reallocateBuffer(nodeStack, nodeStack.length, nodeStack.length * 2);
191
+ }
192
+ nodeStack[nodeStackIndex++] = child1;
193
+ nodeStack[nodeStackIndex++] = m_child2[node];
194
+ }
195
+ }
196
+ }
197
+ }
198
+
199
+ private final Vec2 r = new Vec2();
200
+ private final AABB aabb = new AABB();
201
+ private final RayCastInput subInput = new RayCastInput();
202
+
203
+ @Override
204
+ public void raycast(TreeRayCastCallback callback, RayCastInput input) {
205
+ final Vec2 p1 = input.p1;
206
+ final Vec2 p2 = input.p2;
207
+ float p1x = p1.x, p2x = p2.x, p1y = p1.y, p2y = p2.y;
208
+ float vx, vy;
209
+ float rx, ry;
210
+ float absVx, absVy;
211
+ float cx, cy;
212
+ float hx, hy;
213
+ float tempx, tempy;
214
+ r.x = p2x - p1x;
215
+ r.y = p2y - p1y;
216
+ assert ((r.x * r.x + r.y * r.y) > 0f);
217
+ r.normalize();
218
+ rx = r.x;
219
+ ry = r.y;
220
+
221
+ // v is perpendicular to the segment.
222
+ vx = -1f * ry;
223
+ vy = 1f * rx;
224
+ absVx = MathUtils.abs(vx);
225
+ absVy = MathUtils.abs(vy);
226
+
227
+ // Separating axis for segment (Gino, p80).
228
+ // |dot(v, p1 - c)| > dot(|v|, h)
229
+
230
+ float maxFraction = input.maxFraction;
231
+
232
+ // Build a bounding box for the segment.
233
+ final AABB segAABB = aabb;
234
+ // Vec2 t = p1 + maxFraction * (p2 - p1);
235
+ // before inline
236
+ // temp.set(p2).subLocal(p1).mulLocal(maxFraction).addLocal(p1);
237
+ // Vec2.minToOut(p1, temp, segAABB.lowerBound);
238
+ // Vec2.maxToOut(p1, temp, segAABB.upperBound);
239
+ tempx = (p2x - p1x) * maxFraction + p1x;
240
+ tempy = (p2y - p1y) * maxFraction + p1y;
241
+ segAABB.lowerBound.x = p1x < tempx ? p1x : tempx;
242
+ segAABB.lowerBound.y = p1y < tempy ? p1y : tempy;
243
+ segAABB.upperBound.x = p1x > tempx ? p1x : tempx;
244
+ segAABB.upperBound.y = p1y > tempy ? p1y : tempy;
245
+ // end inline
246
+
247
+ nodeStackIndex = 0;
248
+ nodeStack[nodeStackIndex++] = m_root;
249
+ while (nodeStackIndex > 0) {
250
+ int node = nodeStack[--nodeStackIndex] = m_root;
251
+ if (node == NULL_NODE) {
252
+ continue;
253
+ }
254
+
255
+ final AABB nodeAABB = m_aabb[node];
256
+ if (!AABB.testOverlap(nodeAABB, segAABB)) {
257
+ continue;
258
+ }
259
+
260
+ // Separating axis for segment (Gino, p80).
261
+ // |dot(v, p1 - c)| > dot(|v|, h)
262
+ // node.aabb.getCenterToOut(c);
263
+ // node.aabb.getExtentsToOut(h);
264
+ cx = (nodeAABB.lowerBound.x + nodeAABB.upperBound.x) * .5f;
265
+ cy = (nodeAABB.lowerBound.y + nodeAABB.upperBound.y) * .5f;
266
+ hx = (nodeAABB.upperBound.x - nodeAABB.lowerBound.x) * .5f;
267
+ hy = (nodeAABB.upperBound.y - nodeAABB.lowerBound.y) * .5f;
268
+ tempx = p1x - cx;
269
+ tempy = p1y - cy;
270
+ float separation = MathUtils.abs(vx * tempx + vy * tempy) - (absVx * hx + absVy * hy);
271
+ if (separation > 0.0f) {
272
+ continue;
273
+ }
274
+
275
+ int child1 = m_child1[node];
276
+ if (child1 == NULL_NODE) {
277
+ subInput.p1.x = p1x;
278
+ subInput.p1.y = p1y;
279
+ subInput.p2.x = p2x;
280
+ subInput.p2.y = p2y;
281
+ subInput.maxFraction = maxFraction;
282
+
283
+ float value = callback.raycastCallback(subInput, node);
284
+
285
+ if (value == 0.0f) {
286
+ // The client has terminated the ray cast.
287
+ return;
288
+ }
289
+
290
+ if (value > 0.0f) {
291
+ // Update segment bounding box.
292
+ maxFraction = value;
293
+ // temp.set(p2).subLocal(p1).mulLocal(maxFraction).addLocal(p1);
294
+ // Vec2.minToOut(p1, temp, segAABB.lowerBound);
295
+ // Vec2.maxToOut(p1, temp, segAABB.upperBound);
296
+ tempx = (p2x - p1x) * maxFraction + p1x;
297
+ tempy = (p2y - p1y) * maxFraction + p1y;
298
+ segAABB.lowerBound.x = p1x < tempx ? p1x : tempx;
299
+ segAABB.lowerBound.y = p1y < tempy ? p1y : tempy;
300
+ segAABB.upperBound.x = p1x > tempx ? p1x : tempx;
301
+ segAABB.upperBound.y = p1y > tempy ? p1y : tempy;
302
+ }
303
+ } else {
304
+ nodeStack[nodeStackIndex++] = child1;
305
+ nodeStack[nodeStackIndex++] = m_child2[node];
306
+ }
307
+ }
308
+ }
309
+
310
+ @Override
311
+ public final int computeHeight() {
312
+ return computeHeight(m_root);
313
+ }
314
+
315
+ private final int computeHeight(int node) {
316
+ assert (0 <= node && node < m_nodeCapacity);
317
+
318
+ if (m_child1[node] == NULL_NODE) {
319
+ return 0;
320
+ }
321
+ int height1 = computeHeight(m_child1[node]);
322
+ int height2 = computeHeight(m_child2[node]);
323
+ return 1 + MathUtils.max(height1, height2);
324
+ }
325
+
326
+ /**
327
+ * Validate this tree. For testing.
328
+ */
329
+ public void validate() {
330
+ validateStructure(m_root);
331
+ validateMetrics(m_root);
332
+
333
+ int freeCount = 0;
334
+ int freeNode = m_freeList;
335
+ while (freeNode != NULL_NODE) {
336
+ assert (0 <= freeNode && freeNode < m_nodeCapacity);
337
+ freeNode = m_parent[freeNode];
338
+ ++freeCount;
339
+ }
340
+
341
+ assert (getHeight() == computeHeight());
342
+ assert (m_nodeCount + freeCount == m_nodeCapacity);
343
+ }
344
+
345
+ @Override
346
+ public int getHeight() {
347
+ if (m_root == NULL_NODE) {
348
+ return 0;
349
+ }
350
+ return m_height[m_root];
351
+ }
352
+
353
+ @Override
354
+ public int getMaxBalance() {
355
+ int maxBalance = 0;
356
+ for (int i = 0; i < m_nodeCapacity; ++i) {
357
+ if (m_height[i] <= 1) {
358
+ continue;
359
+ }
360
+
361
+ assert (m_child1[i] != NULL_NODE);
362
+
363
+ int child1 = m_child1[i];
364
+ int child2 = m_child2[i];
365
+ int balance = MathUtils.abs(m_height[child2] - m_height[child1]);
366
+ maxBalance = MathUtils.max(maxBalance, balance);
367
+ }
368
+
369
+ return maxBalance;
370
+ }
371
+
372
+ @Override
373
+ public float getAreaRatio() {
374
+ if (m_root == NULL_NODE) {
375
+ return 0.0f;
376
+ }
377
+
378
+ final int root = m_root;
379
+ float rootArea = m_aabb[root].getPerimeter();
380
+
381
+ float totalArea = 0.0f;
382
+ for (int i = 0; i < m_nodeCapacity; ++i) {
383
+ if (m_height[i] < 0) {
384
+ // Free node in pool
385
+ continue;
386
+ }
387
+
388
+ totalArea += m_aabb[i].getPerimeter();
389
+ }
390
+
391
+ return totalArea / rootArea;
392
+ }
393
+
394
+ // /**
395
+ // * Build an optimal tree. Very expensive. For testing.
396
+ // */
397
+ // public void rebuildBottomUp() {
398
+ // int[] nodes = new int[m_nodeCount];
399
+ // int count = 0;
400
+ //
401
+ // // Build array of leaves. Free the rest.
402
+ // for (int i = 0; i < m_nodeCapacity; ++i) {
403
+ // if (m_nodes[i].height < 0) {
404
+ // // free node in pool
405
+ // continue;
406
+ // }
407
+ //
408
+ // DynamicTreeNode node = m_nodes[i];
409
+ // if (node.isLeaf()) {
410
+ // node.parent = null;
411
+ // nodes[count] = i;
412
+ // ++count;
413
+ // } else {
414
+ // freeNode(node);
415
+ // }
416
+ // }
417
+ //
418
+ // AABB b = new AABB();
419
+ // while (count > 1) {
420
+ // float minCost = Float.MAX_VALUE;
421
+ // int iMin = -1, jMin = -1;
422
+ // for (int i = 0; i < count; ++i) {
423
+ // AABB aabbi = m_nodes[nodes[i]].aabb;
424
+ //
425
+ // for (int j = i + 1; j < count; ++j) {
426
+ // AABB aabbj = m_nodes[nodes[j]].aabb;
427
+ // b.combine(aabbi, aabbj);
428
+ // float cost = b.getPerimeter();
429
+ // if (cost < minCost) {
430
+ // iMin = i;
431
+ // jMin = j;
432
+ // minCost = cost;
433
+ // }
434
+ // }
435
+ // }
436
+ //
437
+ // int index1 = nodes[iMin];
438
+ // int index2 = nodes[jMin];
439
+ // DynamicTreeNode child1 = m_nodes[index1];
440
+ // DynamicTreeNode child2 = m_nodes[index2];
441
+ //
442
+ // DynamicTreeNode parent = allocateNode();
443
+ // parent.child1 = child1;
444
+ // parent.child2 = child2;
445
+ // parent.height = 1 + MathUtils.max(child1.height, child2.height);
446
+ // parent.aabb.combine(child1.aabb, child2.aabb);
447
+ // parent.parent = null;
448
+ //
449
+ // child1.parent = parent;
450
+ // child2.parent = parent;
451
+ //
452
+ // nodes[jMin] = nodes[count - 1];
453
+ // nodes[iMin] = parent.id;
454
+ // --count;
455
+ // }
456
+ //
457
+ // m_root = m_nodes[nodes[0]];
458
+ //
459
+ // validate();
460
+ // }
461
+
462
+ private final int allocateNode() {
463
+ if (m_freeList == NULL_NODE) {
464
+ assert (m_nodeCount == m_nodeCapacity);
465
+ m_nodeCapacity *= 2;
466
+ expandBuffers(m_nodeCount, m_nodeCapacity);
467
+ }
468
+ assert (m_freeList != NULL_NODE);
469
+ int node = m_freeList;
470
+ m_freeList = m_parent[node];
471
+ m_parent[node] = NULL_NODE;
472
+ m_child1[node] = NULL_NODE;
473
+ m_height[node] = 0;
474
+ ++m_nodeCount;
475
+ return node;
476
+ }
477
+
478
+ /**
479
+ * returns a node to the pool
480
+ */
481
+ private final void freeNode(int node) {
482
+ assert (node != NULL_NODE);
483
+ assert (0 < m_nodeCount);
484
+ m_parent[node] = m_freeList != NULL_NODE ? m_freeList : NULL_NODE;
485
+ m_height[node] = -1;
486
+ m_freeList = node;
487
+ m_nodeCount--;
488
+ }
489
+
490
+ private final AABB combinedAABB = new AABB();
491
+
492
+ private final void insertLeaf(int leaf) {
493
+ if (m_root == NULL_NODE) {
494
+ m_root = leaf;
495
+ m_parent[m_root] = NULL_NODE;
496
+ return;
497
+ }
498
+
499
+ // find the best sibling
500
+ AABB leafAABB = m_aabb[leaf];
501
+ int index = m_root;
502
+ while (m_child1[index] != NULL_NODE) {
503
+ final int node = index;
504
+ int child1 = m_child1[node];
505
+ int child2 = m_child2[node];
506
+ final AABB nodeAABB = m_aabb[node];
507
+ float area = nodeAABB.getPerimeter();
508
+
509
+ combinedAABB.combine(nodeAABB, leafAABB);
510
+ float combinedArea = combinedAABB.getPerimeter();
511
+
512
+ // Cost of creating a new parent for this node and the new leaf
513
+ float cost = 2.0f * combinedArea;
514
+
515
+ // Minimum cost of pushing the leaf further down the tree
516
+ float inheritanceCost = 2.0f * (combinedArea - area);
517
+
518
+ // Cost of descending into child1
519
+ float cost1;
520
+ AABB child1AABB = m_aabb[child1];
521
+ if (m_child1[child1] == NULL_NODE) {
522
+ combinedAABB.combine(leafAABB, child1AABB);
523
+ cost1 = combinedAABB.getPerimeter() + inheritanceCost;
524
+ } else {
525
+ combinedAABB.combine(leafAABB, child1AABB);
526
+ float oldArea = child1AABB.getPerimeter();
527
+ float newArea = combinedAABB.getPerimeter();
528
+ cost1 = (newArea - oldArea) + inheritanceCost;
529
+ }
530
+
531
+ // Cost of descending into child2
532
+ float cost2;
533
+ AABB child2AABB = m_aabb[child2];
534
+ if (m_child1[child2] == NULL_NODE) {
535
+ combinedAABB.combine(leafAABB, child2AABB);
536
+ cost2 = combinedAABB.getPerimeter() + inheritanceCost;
537
+ } else {
538
+ combinedAABB.combine(leafAABB, child2AABB);
539
+ float oldArea = child2AABB.getPerimeter();
540
+ float newArea = combinedAABB.getPerimeter();
541
+ cost2 = newArea - oldArea + inheritanceCost;
542
+ }
543
+
544
+ // Descend according to the minimum cost.
545
+ if (cost < cost1 && cost < cost2) {
546
+ break;
547
+ }
548
+
549
+ // Descend
550
+ if (cost1 < cost2) {
551
+ index = child1;
552
+ } else {
553
+ index = child2;
554
+ }
555
+ }
556
+
557
+ int sibling = index;
558
+ int oldParent = m_parent[sibling];
559
+ final int newParent = allocateNode();
560
+ m_parent[newParent] = oldParent;
561
+ m_userData[newParent] = null;
562
+ m_aabb[newParent].combine(leafAABB, m_aabb[sibling]);
563
+ m_height[newParent] = m_height[sibling] + 1;
564
+
565
+ if (oldParent != NULL_NODE) {
566
+ // The sibling was not the root.
567
+ if (m_child1[oldParent] == sibling) {
568
+ m_child1[oldParent] = newParent;
569
+ } else {
570
+ m_child2[oldParent] = newParent;
571
+ }
572
+
573
+ m_child1[newParent] = sibling;
574
+ m_child2[newParent] = leaf;
575
+ m_parent[sibling] = newParent;
576
+ m_parent[leaf] = newParent;
577
+ } else {
578
+ // The sibling was the root.
579
+ m_child1[newParent] = sibling;
580
+ m_child2[newParent] = leaf;
581
+ m_parent[sibling] = newParent;
582
+ m_parent[leaf] = newParent;
583
+ m_root = newParent;
584
+ }
585
+
586
+ // Walk back up the tree fixing heights and AABBs
587
+ index = m_parent[leaf];
588
+ while (index != NULL_NODE) {
589
+ index = balance(index);
590
+
591
+ int child1 = m_child1[index];
592
+ int child2 = m_child2[index];
593
+
594
+ assert (child1 != NULL_NODE);
595
+ assert (child2 != NULL_NODE);
596
+
597
+ m_height[index] = 1 + MathUtils.max(m_height[child1], m_height[child2]);
598
+ m_aabb[index].combine(m_aabb[child1], m_aabb[child2]);
599
+
600
+ index = m_parent[index];
601
+ }
602
+ // validate();
603
+ }
604
+
605
+ private final void removeLeaf(int leaf) {
606
+ if (leaf == m_root) {
607
+ m_root = NULL_NODE;
608
+ return;
609
+ }
610
+
611
+ int parent = m_parent[leaf];
612
+ int grandParent = m_parent[parent];
613
+ int parentChild1 = m_child1[parent];
614
+ int parentChild2 = m_child2[parent];
615
+ int sibling;
616
+ if (parentChild1 == leaf) {
617
+ sibling = parentChild2;
618
+ } else {
619
+ sibling = parentChild1;
620
+ }
621
+
622
+ if (grandParent != NULL_NODE) {
623
+ // Destroy parent and connect sibling to grandParent.
624
+ if (m_child1[grandParent] == parent) {
625
+ m_child1[grandParent] = sibling;
626
+ } else {
627
+ m_child2[grandParent] = sibling;
628
+ }
629
+ m_parent[sibling] = grandParent;
630
+ freeNode(parent);
631
+
632
+ // Adjust ancestor bounds.
633
+ int index = grandParent;
634
+ while (index != NULL_NODE) {
635
+ index = balance(index);
636
+
637
+ int child1 = m_child1[index];
638
+ int child2 = m_child2[index];
639
+
640
+ m_aabb[index].combine(m_aabb[child1], m_aabb[child2]);
641
+ m_height[index] = 1 + MathUtils.max(m_height[child1], m_height[child2]);
642
+
643
+ index = m_parent[index];
644
+ }
645
+ } else {
646
+ m_root = sibling;
647
+ m_parent[sibling] = NULL_NODE;
648
+ freeNode(parent);
649
+ }
650
+
651
+ // validate();
652
+ }
653
+
654
+ // Perform a left or right rotation if node A is imbalanced.
655
+ // Returns the new root index.
656
+ private int balance(int iA) {
657
+ assert (iA != NULL_NODE);
658
+
659
+ int A = iA;
660
+ if (m_child1[A] == NULL_NODE || m_height[A] < 2) {
661
+ return iA;
662
+ }
663
+
664
+ int iB = m_child1[A];
665
+ int iC = m_child2[A];
666
+ assert (0 <= iB && iB < m_nodeCapacity);
667
+ assert (0 <= iC && iC < m_nodeCapacity);
668
+
669
+ int B = iB;
670
+ int C = iC;
671
+
672
+ int balance = m_height[C] - m_height[B];
673
+
674
+ // Rotate C up
675
+ if (balance > 1) {
676
+ int iF = m_child1[C];
677
+ int iG = m_child2[C];
678
+ int F = iF;
679
+ int G = iG;
680
+ // assert (F != null);
681
+ // assert (G != null);
682
+ assert (0 <= iF && iF < m_nodeCapacity);
683
+ assert (0 <= iG && iG < m_nodeCapacity);
684
+
685
+ // Swap A and C
686
+ m_child1[C] = iA;
687
+ int cParent = m_parent[C] = m_parent[A];
688
+ m_parent[A] = iC;
689
+
690
+ // A's old parent should point to C
691
+ if (cParent != NULL_NODE) {
692
+ if (m_child1[cParent] == iA) {
693
+ m_child1[cParent] = iC;
694
+ } else {
695
+ assert (m_child2[cParent] == iA);
696
+ m_child2[cParent] = iC;
697
+ }
698
+ } else {
699
+ m_root = iC;
700
+ }
701
+
702
+ // Rotate
703
+ if (m_height[F] > m_height[G]) {
704
+ m_child2[C] = iF;
705
+ m_child2[A] = iG;
706
+ m_parent[G] = iA;
707
+ m_aabb[A].combine(m_aabb[B], m_aabb[G]);
708
+ m_aabb[C].combine(m_aabb[A], m_aabb[F]);
709
+
710
+ m_height[A] = 1 + MathUtils.max(m_height[B], m_height[G]);
711
+ m_height[C] = 1 + MathUtils.max(m_height[A], m_height[F]);
712
+ } else {
713
+ m_child2[C] = iG;
714
+ m_child2[A] = iF;
715
+ m_parent[F] = iA;
716
+ m_aabb[A].combine(m_aabb[B], m_aabb[F]);
717
+ m_aabb[C].combine(m_aabb[A], m_aabb[G]);
718
+
719
+ m_height[A] = 1 + MathUtils.max(m_height[B], m_height[F]);
720
+ m_height[C] = 1 + MathUtils.max(m_height[A], m_height[G]);
721
+ }
722
+
723
+ return iC;
724
+ }
725
+
726
+ // Rotate B up
727
+ if (balance < -1) {
728
+ int iD = m_child1[B];
729
+ int iE = m_child2[B];
730
+ int D = iD;
731
+ int E = iE;
732
+ assert (0 <= iD && iD < m_nodeCapacity);
733
+ assert (0 <= iE && iE < m_nodeCapacity);
734
+
735
+ // Swap A and B
736
+ m_child1[B] = iA;
737
+ int Bparent = m_parent[B] = m_parent[A];
738
+ m_parent[A] = iB;
739
+
740
+ // A's old parent should point to B
741
+ if (Bparent != NULL_NODE) {
742
+ if (m_child1[Bparent] == iA) {
743
+ m_child1[Bparent] = iB;
744
+ } else {
745
+ assert (m_child2[Bparent] == iA);
746
+ m_child2[Bparent] = iB;
747
+ }
748
+ } else {
749
+ m_root = iB;
750
+ }
751
+
752
+ // Rotate
753
+ if (m_height[D] > m_height[E]) {
754
+ m_child2[B] = iD;
755
+ m_child1[A] = iE;
756
+ m_parent[E] = iA;
757
+ m_aabb[A].combine(m_aabb[C], m_aabb[E]);
758
+ m_aabb[B].combine(m_aabb[A], m_aabb[D]);
759
+
760
+ m_height[A] = 1 + MathUtils.max(m_height[C], m_height[E]);
761
+ m_height[B] = 1 + MathUtils.max(m_height[A], m_height[D]);
762
+ } else {
763
+ m_child2[B] = iE;
764
+ m_child1[A] = iD;
765
+ m_parent[D] = iA;
766
+ m_aabb[A].combine(m_aabb[C], m_aabb[D]);
767
+ m_aabb[B].combine(m_aabb[A], m_aabb[E]);
768
+
769
+ m_height[A] = 1 + MathUtils.max(m_height[C], m_height[D]);
770
+ m_height[B] = 1 + MathUtils.max(m_height[A], m_height[E]);
771
+ }
772
+
773
+ return iB;
774
+ }
775
+
776
+ return iA;
777
+ }
778
+
779
+ private void validateStructure(int node) {
780
+ if (node == NULL_NODE) {
781
+ return;
782
+ }
783
+
784
+ if (node == m_root) {
785
+ assert (m_parent[node] == NULL_NODE);
786
+ }
787
+
788
+ int child1 = m_child1[node];
789
+ int child2 = m_child2[node];
790
+
791
+ if (child1 == NULL_NODE) {
792
+ assert (child1 == NULL_NODE);
793
+ assert (child2 == NULL_NODE);
794
+ assert (m_height[node] == 0);
795
+ return;
796
+ }
797
+
798
+ assert (child1 != NULL_NODE && 0 <= child1 && child1 < m_nodeCapacity);
799
+ assert (child2 != NULL_NODE && 0 <= child2 && child2 < m_nodeCapacity);
800
+
801
+ assert (m_parent[child1] == node);
802
+ assert (m_parent[child2] == node);
803
+
804
+ validateStructure(child1);
805
+ validateStructure(child2);
806
+ }
807
+
808
+ private void validateMetrics(int node) {
809
+ if (node == NULL_NODE) {
810
+ return;
811
+ }
812
+
813
+ int child1 = m_child1[node];
814
+ int child2 = m_child2[node];
815
+
816
+ if (child1 == NULL_NODE) {
817
+ assert (child1 == NULL_NODE);
818
+ assert (child2 == NULL_NODE);
819
+ assert (m_height[node] == 0);
820
+ return;
821
+ }
822
+
823
+ assert (child1 != NULL_NODE && 0 <= child1 && child1 < m_nodeCapacity);
824
+ assert (child2 != child1 && 0 <= child2 && child2 < m_nodeCapacity);
825
+
826
+ int height1 = m_height[child1];
827
+ int height2 = m_height[child2];
828
+ int height;
829
+ height = 1 + MathUtils.max(height1, height2);
830
+ assert (m_height[node] == height);
831
+
832
+ AABB aabb = new AABB();
833
+ aabb.combine(m_aabb[child1], m_aabb[child2]);
834
+
835
+ assert (aabb.lowerBound.equals(m_aabb[node].lowerBound));
836
+ assert (aabb.upperBound.equals(m_aabb[node].upperBound));
837
+
838
+ validateMetrics(child1);
839
+ validateMetrics(child2);
840
+ }
841
+
842
+ @Override
843
+ public void drawTree(DebugDraw argDraw) {
844
+ if (m_root == NULL_NODE) {
845
+ return;
846
+ }
847
+ int height = computeHeight();
848
+ drawTree(argDraw, m_root, 0, height);
849
+ }
850
+
851
+ private final Color3f color = new Color3f();
852
+ private final Vec2 textVec = new Vec2();
853
+
854
+ public void drawTree(DebugDraw argDraw, int node, int spot, int height) {
855
+ AABB a = m_aabb[node];
856
+ a.getVertices(drawVecs);
857
+
858
+ color.set(1, (height - spot) * 1f / height, (height - spot) * 1f / height);
859
+ argDraw.drawPolygon(drawVecs, 4, color);
860
+
861
+ argDraw.getViewportTranform().getWorldToScreen(a.upperBound, textVec);
862
+ argDraw.drawString(textVec.x, textVec.y, node + "-" + (spot + 1) + "/" + height, color);
863
+
864
+ int c1 = m_child1[node];
865
+ int c2 = m_child2[node];
866
+ if (c1 != NULL_NODE) {
867
+ drawTree(argDraw, c1, spot + 1, height);
868
+ }
869
+ if (c2 != NULL_NODE) {
870
+ drawTree(argDraw, c2, spot + 1, height);
871
+ }
872
+ }
873
+ }