pbox2d 0.6.0-java → 0.8.0-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. checksums.yaml +4 -4
  2. data/.mvn/extensions.xml +8 -0
  3. data/.mvn/wrapper/maven-wrapper.properties +1 -0
  4. data/.travis.yml +23 -0
  5. data/CHANGELOG.md +8 -0
  6. data/README.md +7 -7
  7. data/Rakefile +1 -2
  8. data/lib/box2d.jar +0 -0
  9. data/lib/pbox2d/version.rb +1 -1
  10. data/lib/pbox2d.rb +1 -0
  11. data/pbox2d.gemspec +6 -11
  12. data/pom.rb +59 -0
  13. data/pom.xml +82 -73
  14. data/src/org/jbox2d/JBox2D.gwt.xml +12 -0
  15. data/src/org/jbox2d/callbacks/ContactAdaptor.java +27 -0
  16. data/src/org/jbox2d/callbacks/ContactFilter.java +59 -0
  17. data/src/org/jbox2d/callbacks/ContactImpulse.java +42 -0
  18. data/src/org/jbox2d/callbacks/ContactListener.java +87 -0
  19. data/src/org/jbox2d/callbacks/DebugDraw.java +297 -0
  20. data/src/org/jbox2d/callbacks/DestructionListener.java +53 -0
  21. data/src/org/jbox2d/callbacks/PairCallback.java +29 -0
  22. data/src/org/jbox2d/callbacks/ParticleDestructionListener.java +20 -0
  23. data/src/org/jbox2d/callbacks/ParticleQueryCallback.java +19 -0
  24. data/src/org/jbox2d/callbacks/ParticleRaycastCallback.java +19 -0
  25. data/src/org/jbox2d/callbacks/QueryCallback.java +45 -0
  26. data/src/org/jbox2d/callbacks/RayCastCallback.java +55 -0
  27. data/src/org/jbox2d/callbacks/TreeCallback.java +42 -0
  28. data/src/org/jbox2d/callbacks/TreeRayCastCallback.java +44 -0
  29. data/src/org/jbox2d/collision/AABB.java +338 -0
  30. data/src/org/jbox2d/collision/Collision.java +1444 -0
  31. data/src/org/jbox2d/collision/ContactID.java +106 -0
  32. data/src/org/jbox2d/collision/Distance.java +773 -0
  33. data/src/org/jbox2d/collision/DistanceInput.java +41 -0
  34. data/src/org/jbox2d/collision/DistanceOutput.java +43 -0
  35. data/src/org/jbox2d/collision/Manifold.java +116 -0
  36. data/src/org/jbox2d/collision/ManifoldPoint.java +104 -0
  37. data/src/org/jbox2d/collision/RayCastInput.java +47 -0
  38. data/src/org/jbox2d/collision/RayCastOutput.java +46 -0
  39. data/src/org/jbox2d/collision/TimeOfImpact.java +526 -0
  40. data/src/org/jbox2d/collision/WorldManifold.java +200 -0
  41. data/src/org/jbox2d/collision/broadphase/BroadPhase.java +92 -0
  42. data/src/org/jbox2d/collision/broadphase/BroadPhaseStrategy.java +88 -0
  43. data/src/org/jbox2d/collision/broadphase/DefaultBroadPhaseBuffer.java +268 -0
  44. data/src/org/jbox2d/collision/broadphase/DynamicTree.java +883 -0
  45. data/src/org/jbox2d/collision/broadphase/DynamicTreeFlatNodes.java +873 -0
  46. data/src/org/jbox2d/collision/broadphase/DynamicTreeNode.java +54 -0
  47. data/src/org/jbox2d/collision/broadphase/Pair.java +46 -0
  48. data/src/org/jbox2d/collision/shapes/ChainShape.java +264 -0
  49. data/src/org/jbox2d/collision/shapes/CircleShape.java +207 -0
  50. data/src/org/jbox2d/collision/shapes/EdgeShape.java +254 -0
  51. data/src/org/jbox2d/collision/shapes/MassData.java +105 -0
  52. data/src/org/jbox2d/collision/shapes/PolygonShape.java +718 -0
  53. data/src/org/jbox2d/collision/shapes/Shape.java +136 -0
  54. data/src/org/jbox2d/collision/shapes/ShapeType.java +32 -0
  55. data/src/org/jbox2d/common/BufferUtils.java +209 -0
  56. data/src/org/jbox2d/common/Color3f.java +88 -0
  57. data/src/org/jbox2d/common/IViewportTransform.java +133 -0
  58. data/src/org/jbox2d/common/Mat22.java +609 -0
  59. data/src/org/jbox2d/common/Mat33.java +290 -0
  60. data/src/org/jbox2d/common/MathUtils.java +335 -0
  61. data/src/org/jbox2d/common/OBBViewportTransform.java +174 -0
  62. data/src/org/jbox2d/common/PlatformMathUtils.java +46 -0
  63. data/src/org/jbox2d/common/RaycastResult.java +37 -0
  64. data/src/org/jbox2d/common/Rot.java +150 -0
  65. data/src/org/jbox2d/common/Settings.java +246 -0
  66. data/src/org/jbox2d/common/Sweep.java +116 -0
  67. data/src/org/jbox2d/common/Timer.java +46 -0
  68. data/src/org/jbox2d/common/Transform.java +203 -0
  69. data/src/org/jbox2d/common/Vec2.java +388 -0
  70. data/src/org/jbox2d/common/Vec3.java +170 -0
  71. data/src/org/jbox2d/dynamics/Body.java +1246 -0
  72. data/src/org/jbox2d/dynamics/BodyDef.java +382 -0
  73. data/src/org/jbox2d/dynamics/BodyType.java +41 -0
  74. data/src/org/jbox2d/dynamics/ContactManager.java +293 -0
  75. data/src/org/jbox2d/dynamics/Filter.java +62 -0
  76. data/src/org/jbox2d/dynamics/Fixture.java +454 -0
  77. data/src/org/jbox2d/dynamics/FixtureDef.java +214 -0
  78. data/src/org/jbox2d/dynamics/FixtureProxy.java +38 -0
  79. data/src/org/jbox2d/dynamics/Island.java +602 -0
  80. data/src/org/jbox2d/dynamics/Profile.java +97 -0
  81. data/src/org/jbox2d/dynamics/SolverData.java +33 -0
  82. data/src/org/jbox2d/dynamics/TimeStep.java +46 -0
  83. data/src/org/jbox2d/dynamics/World.java +2075 -0
  84. data/src/org/jbox2d/dynamics/contacts/ChainAndCircleContact.java +57 -0
  85. data/src/org/jbox2d/dynamics/contacts/ChainAndPolygonContact.java +57 -0
  86. data/src/org/jbox2d/dynamics/contacts/CircleContact.java +50 -0
  87. data/src/org/jbox2d/dynamics/contacts/Contact.java +365 -0
  88. data/src/org/jbox2d/dynamics/contacts/ContactCreator.java +35 -0
  89. data/src/org/jbox2d/dynamics/contacts/ContactEdge.java +56 -0
  90. data/src/org/jbox2d/dynamics/contacts/ContactPositionConstraint.java +49 -0
  91. data/src/org/jbox2d/dynamics/contacts/ContactRegister.java +31 -0
  92. data/src/org/jbox2d/dynamics/contacts/ContactSolver.java +1104 -0
  93. data/src/org/jbox2d/dynamics/contacts/ContactVelocityConstraint.java +60 -0
  94. data/src/org/jbox2d/dynamics/contacts/EdgeAndCircleContact.java +52 -0
  95. data/src/org/jbox2d/dynamics/contacts/EdgeAndPolygonContact.java +52 -0
  96. data/src/org/jbox2d/dynamics/contacts/PolygonAndCircleContact.java +51 -0
  97. data/src/org/jbox2d/dynamics/contacts/PolygonContact.java +50 -0
  98. data/src/org/jbox2d/dynamics/contacts/Position.java +31 -0
  99. data/src/org/jbox2d/dynamics/contacts/Velocity.java +31 -0
  100. data/src/org/jbox2d/dynamics/joints/ConstantVolumeJoint.java +258 -0
  101. data/src/org/jbox2d/dynamics/joints/ConstantVolumeJointDef.java +75 -0
  102. data/src/org/jbox2d/dynamics/joints/DistanceJoint.java +356 -0
  103. data/src/org/jbox2d/dynamics/joints/DistanceJointDef.java +106 -0
  104. data/src/org/jbox2d/dynamics/joints/FrictionJoint.java +294 -0
  105. data/src/org/jbox2d/dynamics/joints/FrictionJointDef.java +78 -0
  106. data/src/org/jbox2d/dynamics/joints/GearJoint.java +520 -0
  107. data/src/org/jbox2d/dynamics/joints/GearJointDef.java +58 -0
  108. data/src/org/jbox2d/dynamics/joints/Jacobian.java +32 -0
  109. data/src/org/jbox2d/dynamics/joints/Joint.java +235 -0
  110. data/src/org/jbox2d/dynamics/joints/JointDef.java +65 -0
  111. data/src/org/jbox2d/dynamics/joints/JointEdge.java +57 -0
  112. data/src/org/jbox2d/dynamics/joints/JointType.java +28 -0
  113. data/src/org/jbox2d/dynamics/joints/LimitState.java +28 -0
  114. data/src/org/jbox2d/dynamics/joints/MotorJoint.java +339 -0
  115. data/src/org/jbox2d/dynamics/joints/MotorJointDef.java +55 -0
  116. data/src/org/jbox2d/dynamics/joints/MouseJoint.java +262 -0
  117. data/src/org/jbox2d/dynamics/joints/MouseJointDef.java +62 -0
  118. data/src/org/jbox2d/dynamics/joints/PrismaticJoint.java +808 -0
  119. data/src/org/jbox2d/dynamics/joints/PrismaticJointDef.java +120 -0
  120. data/src/org/jbox2d/dynamics/joints/PulleyJoint.java +393 -0
  121. data/src/org/jbox2d/dynamics/joints/PulleyJointDef.java +105 -0
  122. data/src/org/jbox2d/dynamics/joints/RevoluteJoint.java +554 -0
  123. data/src/org/jbox2d/dynamics/joints/RevoluteJointDef.java +137 -0
  124. data/src/org/jbox2d/dynamics/joints/RopeJoint.java +276 -0
  125. data/src/org/jbox2d/dynamics/joints/RopeJointDef.java +34 -0
  126. data/src/org/jbox2d/dynamics/joints/WeldJoint.java +424 -0
  127. data/src/org/jbox2d/dynamics/joints/WeldJointDef.java +85 -0
  128. data/src/org/jbox2d/dynamics/joints/WheelJoint.java +498 -0
  129. data/src/org/jbox2d/dynamics/joints/WheelJointDef.java +98 -0
  130. data/src/org/jbox2d/particle/ParticleBodyContact.java +17 -0
  131. data/src/org/jbox2d/particle/ParticleColor.java +52 -0
  132. data/src/org/jbox2d/particle/ParticleContact.java +14 -0
  133. data/src/org/jbox2d/particle/ParticleDef.java +24 -0
  134. data/src/org/jbox2d/particle/ParticleGroup.java +154 -0
  135. data/src/org/jbox2d/particle/ParticleGroupDef.java +62 -0
  136. data/src/org/jbox2d/particle/ParticleGroupType.java +8 -0
  137. data/src/org/jbox2d/particle/ParticleSystem.java +2172 -0
  138. data/src/org/jbox2d/particle/ParticleType.java +28 -0
  139. data/src/org/jbox2d/particle/StackQueue.java +44 -0
  140. data/src/org/jbox2d/particle/VoronoiDiagram.java +209 -0
  141. data/src/org/jbox2d/pooling/IDynamicStack.java +47 -0
  142. data/src/org/jbox2d/pooling/IOrderedStack.java +57 -0
  143. data/src/org/jbox2d/pooling/IWorldPool.java +101 -0
  144. data/src/org/jbox2d/pooling/arrays/FloatArray.java +50 -0
  145. data/src/org/jbox2d/pooling/arrays/GeneratorArray.java +33 -0
  146. data/src/org/jbox2d/pooling/arrays/IntArray.java +53 -0
  147. data/src/org/jbox2d/pooling/arrays/Vec2Array.java +57 -0
  148. data/src/org/jbox2d/pooling/normal/CircleStack.java +77 -0
  149. data/src/org/jbox2d/pooling/normal/DefaultWorldPool.java +331 -0
  150. data/src/org/jbox2d/pooling/normal/MutableStack.java +72 -0
  151. data/src/org/jbox2d/pooling/normal/OrderedStack.java +73 -0
  152. data/src/org/jbox2d/pooling/stacks/DynamicIntStack.java +60 -0
  153. metadata +161 -14
  154. data/lib/jbox2d-library-2.3.1-SNAPSHOT.jar +0 -0
@@ -0,0 +1,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
+ }