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.
- checksums.yaml +4 -4
- data/.mvn/extensions.xml +8 -0
- data/.mvn/wrapper/maven-wrapper.properties +1 -0
- data/.travis.yml +23 -0
- data/CHANGELOG.md +8 -0
- data/README.md +7 -7
- data/Rakefile +1 -2
- data/lib/box2d.jar +0 -0
- data/lib/pbox2d/version.rb +1 -1
- data/lib/pbox2d.rb +1 -0
- data/pbox2d.gemspec +6 -11
- data/pom.rb +59 -0
- data/pom.xml +82 -73
- data/src/org/jbox2d/JBox2D.gwt.xml +12 -0
- data/src/org/jbox2d/callbacks/ContactAdaptor.java +27 -0
- data/src/org/jbox2d/callbacks/ContactFilter.java +59 -0
- data/src/org/jbox2d/callbacks/ContactImpulse.java +42 -0
- data/src/org/jbox2d/callbacks/ContactListener.java +87 -0
- data/src/org/jbox2d/callbacks/DebugDraw.java +297 -0
- data/src/org/jbox2d/callbacks/DestructionListener.java +53 -0
- data/src/org/jbox2d/callbacks/PairCallback.java +29 -0
- data/src/org/jbox2d/callbacks/ParticleDestructionListener.java +20 -0
- data/src/org/jbox2d/callbacks/ParticleQueryCallback.java +19 -0
- data/src/org/jbox2d/callbacks/ParticleRaycastCallback.java +19 -0
- data/src/org/jbox2d/callbacks/QueryCallback.java +45 -0
- data/src/org/jbox2d/callbacks/RayCastCallback.java +55 -0
- data/src/org/jbox2d/callbacks/TreeCallback.java +42 -0
- data/src/org/jbox2d/callbacks/TreeRayCastCallback.java +44 -0
- data/src/org/jbox2d/collision/AABB.java +338 -0
- data/src/org/jbox2d/collision/Collision.java +1444 -0
- data/src/org/jbox2d/collision/ContactID.java +106 -0
- data/src/org/jbox2d/collision/Distance.java +773 -0
- data/src/org/jbox2d/collision/DistanceInput.java +41 -0
- data/src/org/jbox2d/collision/DistanceOutput.java +43 -0
- data/src/org/jbox2d/collision/Manifold.java +116 -0
- data/src/org/jbox2d/collision/ManifoldPoint.java +104 -0
- data/src/org/jbox2d/collision/RayCastInput.java +47 -0
- data/src/org/jbox2d/collision/RayCastOutput.java +46 -0
- data/src/org/jbox2d/collision/TimeOfImpact.java +526 -0
- data/src/org/jbox2d/collision/WorldManifold.java +200 -0
- data/src/org/jbox2d/collision/broadphase/BroadPhase.java +92 -0
- data/src/org/jbox2d/collision/broadphase/BroadPhaseStrategy.java +88 -0
- data/src/org/jbox2d/collision/broadphase/DefaultBroadPhaseBuffer.java +268 -0
- data/src/org/jbox2d/collision/broadphase/DynamicTree.java +883 -0
- data/src/org/jbox2d/collision/broadphase/DynamicTreeFlatNodes.java +873 -0
- data/src/org/jbox2d/collision/broadphase/DynamicTreeNode.java +54 -0
- data/src/org/jbox2d/collision/broadphase/Pair.java +46 -0
- data/src/org/jbox2d/collision/shapes/ChainShape.java +264 -0
- data/src/org/jbox2d/collision/shapes/CircleShape.java +207 -0
- data/src/org/jbox2d/collision/shapes/EdgeShape.java +254 -0
- data/src/org/jbox2d/collision/shapes/MassData.java +105 -0
- data/src/org/jbox2d/collision/shapes/PolygonShape.java +718 -0
- data/src/org/jbox2d/collision/shapes/Shape.java +136 -0
- data/src/org/jbox2d/collision/shapes/ShapeType.java +32 -0
- data/src/org/jbox2d/common/BufferUtils.java +209 -0
- data/src/org/jbox2d/common/Color3f.java +88 -0
- data/src/org/jbox2d/common/IViewportTransform.java +133 -0
- data/src/org/jbox2d/common/Mat22.java +609 -0
- data/src/org/jbox2d/common/Mat33.java +290 -0
- data/src/org/jbox2d/common/MathUtils.java +335 -0
- data/src/org/jbox2d/common/OBBViewportTransform.java +174 -0
- data/src/org/jbox2d/common/PlatformMathUtils.java +46 -0
- data/src/org/jbox2d/common/RaycastResult.java +37 -0
- data/src/org/jbox2d/common/Rot.java +150 -0
- data/src/org/jbox2d/common/Settings.java +246 -0
- data/src/org/jbox2d/common/Sweep.java +116 -0
- data/src/org/jbox2d/common/Timer.java +46 -0
- data/src/org/jbox2d/common/Transform.java +203 -0
- data/src/org/jbox2d/common/Vec2.java +388 -0
- data/src/org/jbox2d/common/Vec3.java +170 -0
- data/src/org/jbox2d/dynamics/Body.java +1246 -0
- data/src/org/jbox2d/dynamics/BodyDef.java +382 -0
- data/src/org/jbox2d/dynamics/BodyType.java +41 -0
- data/src/org/jbox2d/dynamics/ContactManager.java +293 -0
- data/src/org/jbox2d/dynamics/Filter.java +62 -0
- data/src/org/jbox2d/dynamics/Fixture.java +454 -0
- data/src/org/jbox2d/dynamics/FixtureDef.java +214 -0
- data/src/org/jbox2d/dynamics/FixtureProxy.java +38 -0
- data/src/org/jbox2d/dynamics/Island.java +602 -0
- data/src/org/jbox2d/dynamics/Profile.java +97 -0
- data/src/org/jbox2d/dynamics/SolverData.java +33 -0
- data/src/org/jbox2d/dynamics/TimeStep.java +46 -0
- data/src/org/jbox2d/dynamics/World.java +2075 -0
- data/src/org/jbox2d/dynamics/contacts/ChainAndCircleContact.java +57 -0
- data/src/org/jbox2d/dynamics/contacts/ChainAndPolygonContact.java +57 -0
- data/src/org/jbox2d/dynamics/contacts/CircleContact.java +50 -0
- data/src/org/jbox2d/dynamics/contacts/Contact.java +365 -0
- data/src/org/jbox2d/dynamics/contacts/ContactCreator.java +35 -0
- data/src/org/jbox2d/dynamics/contacts/ContactEdge.java +56 -0
- data/src/org/jbox2d/dynamics/contacts/ContactPositionConstraint.java +49 -0
- data/src/org/jbox2d/dynamics/contacts/ContactRegister.java +31 -0
- data/src/org/jbox2d/dynamics/contacts/ContactSolver.java +1104 -0
- data/src/org/jbox2d/dynamics/contacts/ContactVelocityConstraint.java +60 -0
- data/src/org/jbox2d/dynamics/contacts/EdgeAndCircleContact.java +52 -0
- data/src/org/jbox2d/dynamics/contacts/EdgeAndPolygonContact.java +52 -0
- data/src/org/jbox2d/dynamics/contacts/PolygonAndCircleContact.java +51 -0
- data/src/org/jbox2d/dynamics/contacts/PolygonContact.java +50 -0
- data/src/org/jbox2d/dynamics/contacts/Position.java +31 -0
- data/src/org/jbox2d/dynamics/contacts/Velocity.java +31 -0
- data/src/org/jbox2d/dynamics/joints/ConstantVolumeJoint.java +258 -0
- data/src/org/jbox2d/dynamics/joints/ConstantVolumeJointDef.java +75 -0
- data/src/org/jbox2d/dynamics/joints/DistanceJoint.java +356 -0
- data/src/org/jbox2d/dynamics/joints/DistanceJointDef.java +106 -0
- data/src/org/jbox2d/dynamics/joints/FrictionJoint.java +294 -0
- data/src/org/jbox2d/dynamics/joints/FrictionJointDef.java +78 -0
- data/src/org/jbox2d/dynamics/joints/GearJoint.java +520 -0
- data/src/org/jbox2d/dynamics/joints/GearJointDef.java +58 -0
- data/src/org/jbox2d/dynamics/joints/Jacobian.java +32 -0
- data/src/org/jbox2d/dynamics/joints/Joint.java +235 -0
- data/src/org/jbox2d/dynamics/joints/JointDef.java +65 -0
- data/src/org/jbox2d/dynamics/joints/JointEdge.java +57 -0
- data/src/org/jbox2d/dynamics/joints/JointType.java +28 -0
- data/src/org/jbox2d/dynamics/joints/LimitState.java +28 -0
- data/src/org/jbox2d/dynamics/joints/MotorJoint.java +339 -0
- data/src/org/jbox2d/dynamics/joints/MotorJointDef.java +55 -0
- data/src/org/jbox2d/dynamics/joints/MouseJoint.java +262 -0
- data/src/org/jbox2d/dynamics/joints/MouseJointDef.java +62 -0
- data/src/org/jbox2d/dynamics/joints/PrismaticJoint.java +808 -0
- data/src/org/jbox2d/dynamics/joints/PrismaticJointDef.java +120 -0
- data/src/org/jbox2d/dynamics/joints/PulleyJoint.java +393 -0
- data/src/org/jbox2d/dynamics/joints/PulleyJointDef.java +105 -0
- data/src/org/jbox2d/dynamics/joints/RevoluteJoint.java +554 -0
- data/src/org/jbox2d/dynamics/joints/RevoluteJointDef.java +137 -0
- data/src/org/jbox2d/dynamics/joints/RopeJoint.java +276 -0
- data/src/org/jbox2d/dynamics/joints/RopeJointDef.java +34 -0
- data/src/org/jbox2d/dynamics/joints/WeldJoint.java +424 -0
- data/src/org/jbox2d/dynamics/joints/WeldJointDef.java +85 -0
- data/src/org/jbox2d/dynamics/joints/WheelJoint.java +498 -0
- data/src/org/jbox2d/dynamics/joints/WheelJointDef.java +98 -0
- data/src/org/jbox2d/particle/ParticleBodyContact.java +17 -0
- data/src/org/jbox2d/particle/ParticleColor.java +52 -0
- data/src/org/jbox2d/particle/ParticleContact.java +14 -0
- data/src/org/jbox2d/particle/ParticleDef.java +24 -0
- data/src/org/jbox2d/particle/ParticleGroup.java +154 -0
- data/src/org/jbox2d/particle/ParticleGroupDef.java +62 -0
- data/src/org/jbox2d/particle/ParticleGroupType.java +8 -0
- data/src/org/jbox2d/particle/ParticleSystem.java +2172 -0
- data/src/org/jbox2d/particle/ParticleType.java +28 -0
- data/src/org/jbox2d/particle/StackQueue.java +44 -0
- data/src/org/jbox2d/particle/VoronoiDiagram.java +209 -0
- data/src/org/jbox2d/pooling/IDynamicStack.java +47 -0
- data/src/org/jbox2d/pooling/IOrderedStack.java +57 -0
- data/src/org/jbox2d/pooling/IWorldPool.java +101 -0
- data/src/org/jbox2d/pooling/arrays/FloatArray.java +50 -0
- data/src/org/jbox2d/pooling/arrays/GeneratorArray.java +33 -0
- data/src/org/jbox2d/pooling/arrays/IntArray.java +53 -0
- data/src/org/jbox2d/pooling/arrays/Vec2Array.java +57 -0
- data/src/org/jbox2d/pooling/normal/CircleStack.java +77 -0
- data/src/org/jbox2d/pooling/normal/DefaultWorldPool.java +331 -0
- data/src/org/jbox2d/pooling/normal/MutableStack.java +72 -0
- data/src/org/jbox2d/pooling/normal/OrderedStack.java +73 -0
- data/src/org/jbox2d/pooling/stacks/DynamicIntStack.java +60 -0
- metadata +161 -14
- data/lib/jbox2d-library-2.3.1-SNAPSHOT.jar +0 -0
@@ -0,0 +1,718 @@
|
|
1
|
+
/**
|
2
|
+
* *****************************************************************************
|
3
|
+
* Copyright (c) 2013, Daniel Murphy
|
4
|
+
* All rights reserved.
|
5
|
+
*
|
6
|
+
* Redistribution and use in source and binary forms, with or without modification,
|
7
|
+
* are permitted provided that the following conditions are met:
|
8
|
+
* * Redistributions of source code must retain the above copyright notice,
|
9
|
+
* this list of conditions and the following disclaimer.
|
10
|
+
* * Redistributions in binary form must reproduce the above copyright notice,
|
11
|
+
* this list of conditions and the following disclaimer in the documentation
|
12
|
+
* and/or other materials provided with the distribution.
|
13
|
+
*
|
14
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
15
|
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
16
|
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
17
|
+
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
18
|
+
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
19
|
+
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
20
|
+
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
21
|
+
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
22
|
+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
23
|
+
* POSSIBILITY OF SUCH DAMAGE.
|
24
|
+
*****************************************************************************
|
25
|
+
*/
|
26
|
+
package org.jbox2d.collision.shapes;
|
27
|
+
|
28
|
+
import org.jbox2d.collision.AABB;
|
29
|
+
import org.jbox2d.collision.RayCastInput;
|
30
|
+
import org.jbox2d.collision.RayCastOutput;
|
31
|
+
import org.jbox2d.common.MathUtils;
|
32
|
+
import org.jbox2d.common.Rot;
|
33
|
+
import org.jbox2d.common.Settings;
|
34
|
+
import org.jbox2d.common.Transform;
|
35
|
+
import org.jbox2d.common.Vec2;
|
36
|
+
import org.jbox2d.pooling.arrays.IntArray;
|
37
|
+
import org.jbox2d.pooling.arrays.Vec2Array;
|
38
|
+
|
39
|
+
/**
|
40
|
+
* A convex polygon shape. Polygons have a maximum number of vertices equal to
|
41
|
+
* _maxPolygonVertices. In most cases you should not need many vertices for a
|
42
|
+
* convex polygon.
|
43
|
+
*/
|
44
|
+
public class PolygonShape extends Shape {
|
45
|
+
|
46
|
+
/**
|
47
|
+
* Dump lots of debug information.
|
48
|
+
*/
|
49
|
+
private final static boolean M_DEBUG = false;
|
50
|
+
|
51
|
+
/**
|
52
|
+
* Local position of the shape centroid in parent body frame.
|
53
|
+
*/
|
54
|
+
public final Vec2 m_centroid = new Vec2();
|
55
|
+
|
56
|
+
/**
|
57
|
+
* The vertices of the shape. Note: use getVertexCount(), not
|
58
|
+
* m_vertices.length, to get number of active vertices.
|
59
|
+
*/
|
60
|
+
public final Vec2 m_vertices[];
|
61
|
+
|
62
|
+
/**
|
63
|
+
* The normals of the shape. Note: use getVertexCount(), not
|
64
|
+
* m_normals.length, to get number of active normals.
|
65
|
+
*/
|
66
|
+
public final Vec2 m_normals[];
|
67
|
+
|
68
|
+
/**
|
69
|
+
* Number of active vertices in the shape.
|
70
|
+
*/
|
71
|
+
public int m_count;
|
72
|
+
|
73
|
+
// pooling
|
74
|
+
private final Vec2 pool1 = new Vec2();
|
75
|
+
private final Vec2 pool2 = new Vec2();
|
76
|
+
private final Vec2 pool3 = new Vec2();
|
77
|
+
private final Vec2 pool4 = new Vec2();
|
78
|
+
private final Transform poolt1 = new Transform();
|
79
|
+
|
80
|
+
public PolygonShape() {
|
81
|
+
super(ShapeType.POLYGON);
|
82
|
+
|
83
|
+
m_count = 0;
|
84
|
+
m_vertices = new Vec2[Settings.maxPolygonVertices];
|
85
|
+
for (int i = 0; i < m_vertices.length; i++) {
|
86
|
+
m_vertices[i] = new Vec2();
|
87
|
+
}
|
88
|
+
m_normals = new Vec2[Settings.maxPolygonVertices];
|
89
|
+
for (int i = 0; i < m_normals.length; i++) {
|
90
|
+
m_normals[i] = new Vec2();
|
91
|
+
}
|
92
|
+
setRadius(Settings.polygonRadius);
|
93
|
+
m_centroid.setZero();
|
94
|
+
}
|
95
|
+
|
96
|
+
@Override
|
97
|
+
public final Shape clone() {
|
98
|
+
PolygonShape shape = new PolygonShape();
|
99
|
+
shape.m_centroid.set(this.m_centroid);
|
100
|
+
for (int i = 0; i < shape.m_normals.length; i++) {
|
101
|
+
shape.m_normals[i].set(m_normals[i]);
|
102
|
+
shape.m_vertices[i].set(m_vertices[i]);
|
103
|
+
}
|
104
|
+
shape.setRadius(this.getRadius());
|
105
|
+
shape.m_count = this.m_count;
|
106
|
+
return shape;
|
107
|
+
}
|
108
|
+
|
109
|
+
/**
|
110
|
+
* Create a convex hull from the given array of points. The count must be in
|
111
|
+
* the range [3, Settings.maxPolygonVertices].
|
112
|
+
*
|
113
|
+
* @param vertices
|
114
|
+
* @param count
|
115
|
+
* @warning the points may be re-ordered, even if they form a convex
|
116
|
+
* polygon.
|
117
|
+
* @warning collinear points are removed.
|
118
|
+
*/
|
119
|
+
public final void set(final Vec2[] vertices, final int count) {
|
120
|
+
set(vertices, count, null, null);
|
121
|
+
}
|
122
|
+
|
123
|
+
/**
|
124
|
+
* Create a convex hull from the given array of points. The count must be in
|
125
|
+
* the range [3, Settings.maxPolygonVertices]. This method takes an
|
126
|
+
* arraypool for pooling.
|
127
|
+
*
|
128
|
+
* @param verts
|
129
|
+
* @param num
|
130
|
+
* @param vecPool
|
131
|
+
* @param intPool
|
132
|
+
* @warning the points may be re-ordered, even if they form a convex
|
133
|
+
* polygon.
|
134
|
+
* @warning collinear points are removed.
|
135
|
+
*/
|
136
|
+
public final void set(final Vec2[] verts, final int num, final Vec2Array vecPool,
|
137
|
+
final IntArray intPool) {
|
138
|
+
assert (3 <= num && num <= Settings.maxPolygonVertices);
|
139
|
+
if (num < 3) {
|
140
|
+
setAsBox(1.0f, 1.0f);
|
141
|
+
return;
|
142
|
+
}
|
143
|
+
|
144
|
+
int n = MathUtils.min(num, Settings.maxPolygonVertices);
|
145
|
+
|
146
|
+
// Perform welding and copy vertices into local buffer.
|
147
|
+
Vec2[] ps
|
148
|
+
= (vecPool != null)
|
149
|
+
? vecPool.get(Settings.maxPolygonVertices)
|
150
|
+
: new Vec2[Settings.maxPolygonVertices];
|
151
|
+
int tempCount = 0;
|
152
|
+
for (int i = 0; i < n; ++i) {
|
153
|
+
Vec2 v = verts[i];
|
154
|
+
boolean unique = true;
|
155
|
+
for (int j = 0; j < tempCount; ++j) {
|
156
|
+
if (MathUtils.distanceSquared(v, ps[j]) < 0.5f * Settings.linearSlop) {
|
157
|
+
unique = false;
|
158
|
+
break;
|
159
|
+
}
|
160
|
+
}
|
161
|
+
|
162
|
+
if (unique) {
|
163
|
+
ps[tempCount++] = v;
|
164
|
+
}
|
165
|
+
}
|
166
|
+
|
167
|
+
n = tempCount;
|
168
|
+
if (n < 3) {
|
169
|
+
// Polygon is degenerate.
|
170
|
+
assert (false);
|
171
|
+
setAsBox(1.0f, 1.0f);
|
172
|
+
return;
|
173
|
+
}
|
174
|
+
|
175
|
+
// Create the convex hull using the Gift wrapping algorithm
|
176
|
+
// http://en.wikipedia.org/wiki/Gift_wrapping_algorithm
|
177
|
+
// Find the right most point on the hull
|
178
|
+
int i0 = 0;
|
179
|
+
float x0 = ps[0].x;
|
180
|
+
for (int i = 1; i < n; ++i) {
|
181
|
+
float x = ps[i].x;
|
182
|
+
if (x > x0 || (x == x0 && ps[i].y < ps[i0].y)) {
|
183
|
+
i0 = i;
|
184
|
+
x0 = x;
|
185
|
+
}
|
186
|
+
}
|
187
|
+
|
188
|
+
int[] hull
|
189
|
+
= (intPool != null)
|
190
|
+
? intPool.get(Settings.maxPolygonVertices)
|
191
|
+
: new int[Settings.maxPolygonVertices];
|
192
|
+
int m = 0;
|
193
|
+
int ih = i0;
|
194
|
+
|
195
|
+
while (true) {
|
196
|
+
hull[m] = ih;
|
197
|
+
|
198
|
+
int ie = 0;
|
199
|
+
for (int j = 1; j < n; ++j) {
|
200
|
+
if (ie == ih) {
|
201
|
+
ie = j;
|
202
|
+
continue;
|
203
|
+
}
|
204
|
+
|
205
|
+
Vec2 r = pool1.set(ps[ie]).subLocal(ps[hull[m]]);
|
206
|
+
Vec2 v = pool2.set(ps[j]).subLocal(ps[hull[m]]);
|
207
|
+
float c = Vec2.cross(r, v);
|
208
|
+
if (c < 0.0f) {
|
209
|
+
ie = j;
|
210
|
+
}
|
211
|
+
|
212
|
+
// Collinearity check
|
213
|
+
if (c == 0.0f && v.lengthSquared() > r.lengthSquared()) {
|
214
|
+
ie = j;
|
215
|
+
}
|
216
|
+
}
|
217
|
+
|
218
|
+
++m;
|
219
|
+
ih = ie;
|
220
|
+
|
221
|
+
if (ie == i0) {
|
222
|
+
break;
|
223
|
+
}
|
224
|
+
}
|
225
|
+
|
226
|
+
this.m_count = m;
|
227
|
+
|
228
|
+
// Copy vertices.
|
229
|
+
for (int i = 0; i < m_count; ++i) {
|
230
|
+
if (m_vertices[i] == null) {
|
231
|
+
m_vertices[i] = new Vec2();
|
232
|
+
}
|
233
|
+
m_vertices[i].set(ps[hull[i]]);
|
234
|
+
}
|
235
|
+
|
236
|
+
final Vec2 edge = pool1;
|
237
|
+
|
238
|
+
// Compute normals. Ensure the edges have non-zero length.
|
239
|
+
for (int i = 0; i < m_count; ++i) {
|
240
|
+
final int i1 = i;
|
241
|
+
final int i2 = i + 1 < m_count ? i + 1 : 0;
|
242
|
+
edge.set(m_vertices[i2]).subLocal(m_vertices[i1]);
|
243
|
+
|
244
|
+
assert (edge.lengthSquared() > Settings.EPSILON * Settings.EPSILON);
|
245
|
+
Vec2.crossToOutUnsafe(edge, 1f, m_normals[i]);
|
246
|
+
m_normals[i].normalize();
|
247
|
+
}
|
248
|
+
|
249
|
+
// Compute the polygon centroid.
|
250
|
+
computeCentroidToOut(m_vertices, m_count, m_centroid);
|
251
|
+
}
|
252
|
+
|
253
|
+
/**
|
254
|
+
* Build vertices to represent an axis-aligned box.
|
255
|
+
*
|
256
|
+
* @param hx the half-width.
|
257
|
+
* @param hy the half-height.
|
258
|
+
*/
|
259
|
+
public final void setAsBox(final float hx, final float hy) {
|
260
|
+
m_count = 4;
|
261
|
+
m_vertices[0].set(-hx, -hy);
|
262
|
+
m_vertices[1].set(hx, -hy);
|
263
|
+
m_vertices[2].set(hx, hy);
|
264
|
+
m_vertices[3].set(-hx, hy);
|
265
|
+
m_normals[0].set(0.0f, -1.0f);
|
266
|
+
m_normals[1].set(1.0f, 0.0f);
|
267
|
+
m_normals[2].set(0.0f, 1.0f);
|
268
|
+
m_normals[3].set(-1.0f, 0.0f);
|
269
|
+
m_centroid.setZero();
|
270
|
+
}
|
271
|
+
|
272
|
+
/**
|
273
|
+
* Build vertices to represent an oriented box.
|
274
|
+
*
|
275
|
+
* @param hx the half-width.
|
276
|
+
* @param hy the half-height.
|
277
|
+
* @param center the center of the box in local coordinates.
|
278
|
+
* @param angle the rotation of the box in local coordinates.
|
279
|
+
*/
|
280
|
+
public final void setAsBox(final float hx, final float hy, final Vec2 center, final float angle) {
|
281
|
+
m_count = 4;
|
282
|
+
m_vertices[0].set(-hx, -hy);
|
283
|
+
m_vertices[1].set(hx, -hy);
|
284
|
+
m_vertices[2].set(hx, hy);
|
285
|
+
m_vertices[3].set(-hx, hy);
|
286
|
+
m_normals[0].set(0.0f, -1.0f);
|
287
|
+
m_normals[1].set(1.0f, 0.0f);
|
288
|
+
m_normals[2].set(0.0f, 1.0f);
|
289
|
+
m_normals[3].set(-1.0f, 0.0f);
|
290
|
+
m_centroid.set(center);
|
291
|
+
|
292
|
+
final Transform xf = poolt1;
|
293
|
+
xf.p.set(center);
|
294
|
+
xf.q.set(angle);
|
295
|
+
|
296
|
+
// Transform vertices and normals.
|
297
|
+
for (int i = 0; i < m_count; ++i) {
|
298
|
+
Transform.mulToOut(xf, m_vertices[i], m_vertices[i]);
|
299
|
+
Rot.mulToOut(xf.q, m_normals[i], m_normals[i]);
|
300
|
+
}
|
301
|
+
}
|
302
|
+
|
303
|
+
@Override
|
304
|
+
public int getChildCount() {
|
305
|
+
return 1;
|
306
|
+
}
|
307
|
+
|
308
|
+
@Override
|
309
|
+
public final boolean testPoint(final Transform xf, final Vec2 p) {
|
310
|
+
float tempx, tempy;
|
311
|
+
final Rot xfq = xf.q;
|
312
|
+
|
313
|
+
tempx = p.x - xf.p.x;
|
314
|
+
tempy = p.y - xf.p.y;
|
315
|
+
final float pLocalx = xfq.c * tempx + xfq.s * tempy;
|
316
|
+
final float pLocaly = -xfq.s * tempx + xfq.c * tempy;
|
317
|
+
|
318
|
+
if (M_DEBUG) {
|
319
|
+
System.out.println("--testPoint debug--");
|
320
|
+
System.out.println("Vertices: ");
|
321
|
+
for (int i = 0; i < m_count; ++i) {
|
322
|
+
System.out.println(m_vertices[i]);
|
323
|
+
}
|
324
|
+
System.out.println("pLocal: " + pLocalx + ", " + pLocaly);
|
325
|
+
}
|
326
|
+
|
327
|
+
for (int i = 0; i < m_count; ++i) {
|
328
|
+
Vec2 vertex = m_vertices[i];
|
329
|
+
Vec2 normal = m_normals[i];
|
330
|
+
tempx = pLocalx - vertex.x;
|
331
|
+
tempy = pLocaly - vertex.y;
|
332
|
+
final float dot = normal.x * tempx + normal.y * tempy;
|
333
|
+
if (dot > 0.0f) {
|
334
|
+
return false;
|
335
|
+
}
|
336
|
+
}
|
337
|
+
|
338
|
+
return true;
|
339
|
+
}
|
340
|
+
|
341
|
+
@Override
|
342
|
+
public final void computeAABB(final AABB aabb, final Transform xf, int childIndex) {
|
343
|
+
final Vec2 lower = aabb.lowerBound;
|
344
|
+
final Vec2 upper = aabb.upperBound;
|
345
|
+
final Vec2 v1 = m_vertices[0];
|
346
|
+
final float xfqc = xf.q.c;
|
347
|
+
final float xfqs = xf.q.s;
|
348
|
+
final float xfpx = xf.p.x;
|
349
|
+
final float xfpy = xf.p.y;
|
350
|
+
lower.x = (xfqc * v1.x - xfqs * v1.y) + xfpx;
|
351
|
+
lower.y = (xfqs * v1.x + xfqc * v1.y) + xfpy;
|
352
|
+
upper.x = lower.x;
|
353
|
+
upper.y = lower.y;
|
354
|
+
|
355
|
+
for (int i = 1; i < m_count; ++i) {
|
356
|
+
Vec2 v2 = m_vertices[i];
|
357
|
+
// Vec2 v = Mul(xf, m_vertices[i]);
|
358
|
+
float vx = (xfqc * v2.x - xfqs * v2.y) + xfpx;
|
359
|
+
float vy = (xfqs * v2.x + xfqc * v2.y) + xfpy;
|
360
|
+
lower.x = lower.x < vx ? lower.x : vx;
|
361
|
+
lower.y = lower.y < vy ? lower.y : vy;
|
362
|
+
upper.x = upper.x > vx ? upper.x : vx;
|
363
|
+
upper.y = upper.y > vy ? upper.y : vy;
|
364
|
+
}
|
365
|
+
|
366
|
+
lower.x -= m_radius;
|
367
|
+
lower.y -= m_radius;
|
368
|
+
upper.x += m_radius;
|
369
|
+
upper.y += m_radius;
|
370
|
+
}
|
371
|
+
|
372
|
+
/**
|
373
|
+
* Get the vertex count.
|
374
|
+
*
|
375
|
+
* @return
|
376
|
+
*/
|
377
|
+
public final int getVertexCount() {
|
378
|
+
return m_count;
|
379
|
+
}
|
380
|
+
|
381
|
+
/**
|
382
|
+
* Get a vertex by index.
|
383
|
+
*
|
384
|
+
* @param index
|
385
|
+
* @return
|
386
|
+
*/
|
387
|
+
public final Vec2 getVertex(final int index) {
|
388
|
+
assert (0 <= index && index < m_count);
|
389
|
+
return m_vertices[index];
|
390
|
+
}
|
391
|
+
|
392
|
+
@Override
|
393
|
+
public float computeDistanceToOut(Transform xf, Vec2 p, int childIndex, Vec2 normalOut) {
|
394
|
+
float xfqc = xf.q.c;
|
395
|
+
float xfqs = xf.q.s;
|
396
|
+
float tx = p.x - xf.p.x;
|
397
|
+
float ty = p.y - xf.p.y;
|
398
|
+
float pLocalx = xfqc * tx + xfqs * ty;
|
399
|
+
float pLocaly = -xfqs * tx + xfqc * ty;
|
400
|
+
|
401
|
+
float maxDistance = -Float.MAX_VALUE;
|
402
|
+
float normalForMaxDistanceX = pLocalx;
|
403
|
+
float normalForMaxDistanceY = pLocaly;
|
404
|
+
|
405
|
+
for (int i = 0; i < m_count; ++i) {
|
406
|
+
Vec2 vertex = m_vertices[i];
|
407
|
+
Vec2 normal = m_normals[i];
|
408
|
+
tx = pLocalx - vertex.x;
|
409
|
+
ty = pLocaly - vertex.y;
|
410
|
+
float dot = normal.x * tx + normal.y * ty;
|
411
|
+
if (dot > maxDistance) {
|
412
|
+
maxDistance = dot;
|
413
|
+
normalForMaxDistanceX = normal.x;
|
414
|
+
normalForMaxDistanceY = normal.y;
|
415
|
+
}
|
416
|
+
}
|
417
|
+
|
418
|
+
float distance;
|
419
|
+
if (maxDistance > 0) {
|
420
|
+
float minDistanceX = normalForMaxDistanceX;
|
421
|
+
float minDistanceY = normalForMaxDistanceY;
|
422
|
+
float minDistance2 = maxDistance * maxDistance;
|
423
|
+
for (int i = 0; i < m_count; ++i) {
|
424
|
+
Vec2 vertex = m_vertices[i];
|
425
|
+
float distanceVecX = pLocalx - vertex.x;
|
426
|
+
float distanceVecY = pLocaly - vertex.y;
|
427
|
+
float distance2 = (distanceVecX * distanceVecX + distanceVecY * distanceVecY);
|
428
|
+
if (minDistance2 > distance2) {
|
429
|
+
minDistanceX = distanceVecX;
|
430
|
+
minDistanceY = distanceVecY;
|
431
|
+
minDistance2 = distance2;
|
432
|
+
}
|
433
|
+
}
|
434
|
+
distance = MathUtils.sqrt(minDistance2);
|
435
|
+
normalOut.x = xfqc * minDistanceX - xfqs * minDistanceY;
|
436
|
+
normalOut.y = xfqs * minDistanceX + xfqc * minDistanceY;
|
437
|
+
normalOut.normalize();
|
438
|
+
} else {
|
439
|
+
distance = maxDistance;
|
440
|
+
normalOut.x = xfqc * normalForMaxDistanceX - xfqs * normalForMaxDistanceY;
|
441
|
+
normalOut.y = xfqs * normalForMaxDistanceX + xfqc * normalForMaxDistanceY;
|
442
|
+
}
|
443
|
+
|
444
|
+
return distance;
|
445
|
+
}
|
446
|
+
|
447
|
+
@Override
|
448
|
+
public final boolean raycast(RayCastOutput output, RayCastInput input, Transform xf,
|
449
|
+
int childIndex) {
|
450
|
+
final float xfqc = xf.q.c;
|
451
|
+
final float xfqs = xf.q.s;
|
452
|
+
final Vec2 xfp = xf.p;
|
453
|
+
float tempx, tempy;
|
454
|
+
// b2Vec2 p1 = b2MulT(xf.q, input.p1 - xf.p);
|
455
|
+
// b2Vec2 p2 = b2MulT(xf.q, input.p2 - xf.p);
|
456
|
+
tempx = input.p1.x - xfp.x;
|
457
|
+
tempy = input.p1.y - xfp.y;
|
458
|
+
final float p1x = xfqc * tempx + xfqs * tempy;
|
459
|
+
final float p1y = -xfqs * tempx + xfqc * tempy;
|
460
|
+
|
461
|
+
tempx = input.p2.x - xfp.x;
|
462
|
+
tempy = input.p2.y - xfp.y;
|
463
|
+
final float p2x = xfqc * tempx + xfqs * tempy;
|
464
|
+
final float p2y = -xfqs * tempx + xfqc * tempy;
|
465
|
+
|
466
|
+
final float dx = p2x - p1x;
|
467
|
+
final float dy = p2y - p1y;
|
468
|
+
|
469
|
+
float lower = 0, upper = input.maxFraction;
|
470
|
+
|
471
|
+
int index = -1;
|
472
|
+
|
473
|
+
for (int i = 0; i < m_count; ++i) {
|
474
|
+
Vec2 normal = m_normals[i];
|
475
|
+
Vec2 vertex = m_vertices[i];
|
476
|
+
// p = p1 + a * d
|
477
|
+
// dot(normal, p - v) = 0
|
478
|
+
// dot(normal, p1 - v) + a * dot(normal, d) = 0
|
479
|
+
float tempxn = vertex.x - p1x;
|
480
|
+
float tempyn = vertex.y - p1y;
|
481
|
+
final float numerator = normal.x * tempxn + normal.y * tempyn;
|
482
|
+
final float denominator = normal.x * dx + normal.y * dy;
|
483
|
+
|
484
|
+
if (denominator == 0.0f) {
|
485
|
+
if (numerator < 0.0f) {
|
486
|
+
return false;
|
487
|
+
}
|
488
|
+
} else // Note: we want this predicate without division:
|
489
|
+
// lower < numerator / denominator, where denominator < 0
|
490
|
+
// Since denominator < 0, we have to flip the inequality:
|
491
|
+
// lower < numerator / denominator <==> denominator * lower >
|
492
|
+
// numerator.
|
493
|
+
{
|
494
|
+
if (denominator < 0.0f && numerator < lower * denominator) {
|
495
|
+
// Increase lower.
|
496
|
+
// The segment enters this half-space.
|
497
|
+
lower = numerator / denominator;
|
498
|
+
index = i;
|
499
|
+
} else if (denominator > 0.0f && numerator < upper * denominator) {
|
500
|
+
// Decrease upper.
|
501
|
+
// The segment exits this half-space.
|
502
|
+
upper = numerator / denominator;
|
503
|
+
}
|
504
|
+
}
|
505
|
+
|
506
|
+
if (upper < lower) {
|
507
|
+
return false;
|
508
|
+
}
|
509
|
+
}
|
510
|
+
|
511
|
+
assert (0.0f <= lower && lower <= input.maxFraction);
|
512
|
+
|
513
|
+
if (index >= 0) {
|
514
|
+
output.fraction = lower;
|
515
|
+
// normal = Mul(xf.R, m_normals[index]);
|
516
|
+
Vec2 normal = m_normals[index];
|
517
|
+
Vec2 out = output.normal;
|
518
|
+
out.x = xfqc * normal.x - xfqs * normal.y;
|
519
|
+
out.y = xfqs * normal.x + xfqc * normal.y;
|
520
|
+
return true;
|
521
|
+
}
|
522
|
+
return false;
|
523
|
+
}
|
524
|
+
|
525
|
+
public final void computeCentroidToOut(final Vec2[] vs, final int count, final Vec2 out) {
|
526
|
+
assert (count >= 3);
|
527
|
+
|
528
|
+
out.set(0.0f, 0.0f);
|
529
|
+
float area = 0.0f;
|
530
|
+
|
531
|
+
// pRef is the reference point for forming triangles.
|
532
|
+
// It's location doesn't change the result (except for rounding error).
|
533
|
+
final Vec2 pRef = pool1;
|
534
|
+
pRef.setZero();
|
535
|
+
|
536
|
+
final Vec2 e1 = pool2;
|
537
|
+
final Vec2 e2 = pool3;
|
538
|
+
|
539
|
+
final float inv3 = 1.0f / 3.0f;
|
540
|
+
|
541
|
+
for (int i = 0; i < count; ++i) {
|
542
|
+
// Triangle vertices.
|
543
|
+
final Vec2 p1 = pRef;
|
544
|
+
final Vec2 p2 = vs[i];
|
545
|
+
final Vec2 p3 = i + 1 < count ? vs[i + 1] : vs[0];
|
546
|
+
|
547
|
+
e1.set(p2).subLocal(p1);
|
548
|
+
e2.set(p3).subLocal(p1);
|
549
|
+
|
550
|
+
final float D = Vec2.cross(e1, e2);
|
551
|
+
|
552
|
+
final float triangleArea = 0.5f * D;
|
553
|
+
area += triangleArea;
|
554
|
+
|
555
|
+
// Area weighted centroid
|
556
|
+
e1.set(p1).addLocal(p2).addLocal(p3).mulLocal(triangleArea * inv3);
|
557
|
+
out.addLocal(e1);
|
558
|
+
}
|
559
|
+
|
560
|
+
// Centroid
|
561
|
+
assert (area > Settings.EPSILON);
|
562
|
+
out.mulLocal(1.0f / area);
|
563
|
+
}
|
564
|
+
|
565
|
+
@Override
|
566
|
+
public void computeMass(final MassData massData, float density) {
|
567
|
+
// Polygon mass, centroid, and inertia.
|
568
|
+
// Let rho be the polygon density in mass per unit area.
|
569
|
+
// Then:
|
570
|
+
// mass = rho * int(dA)
|
571
|
+
// centroid.x = (1/mass) * rho * int(x * dA)
|
572
|
+
// centroid.y = (1/mass) * rho * int(y * dA)
|
573
|
+
// I = rho * int((x*x + y*y) * dA)
|
574
|
+
//
|
575
|
+
// We can compute these integrals by summing all the integrals
|
576
|
+
// for each triangle of the polygon. To evaluate the integral
|
577
|
+
// for a single triangle, we make a change of variables to
|
578
|
+
// the (u,v) coordinates of the triangle:
|
579
|
+
// x = x0 + e1x * u + e2x * v
|
580
|
+
// y = y0 + e1y * u + e2y * v
|
581
|
+
// where 0 <= u && 0 <= v && u + v <= 1.
|
582
|
+
//
|
583
|
+
// We integrate u from [0,1-v] and then v from [0,1].
|
584
|
+
// We also need to use the Jacobian of the transformation:
|
585
|
+
// D = cross(e1, e2)
|
586
|
+
//
|
587
|
+
// Simplification: triangle centroid = (1/3) * (p1 + p2 + p3)
|
588
|
+
//
|
589
|
+
// The rest of the derivation is handled by computer algebra.
|
590
|
+
|
591
|
+
assert (m_count >= 3);
|
592
|
+
|
593
|
+
final Vec2 center = pool1;
|
594
|
+
center.setZero();
|
595
|
+
float area = 0.0f;
|
596
|
+
float I = 0.0f;
|
597
|
+
|
598
|
+
// pRef is the reference point for forming triangles.
|
599
|
+
// It's location doesn't change the result (except for rounding error).
|
600
|
+
final Vec2 s = pool2;
|
601
|
+
s.setZero();
|
602
|
+
// This code would put the reference point inside the polygon.
|
603
|
+
for (int i = 0; i < m_count; ++i) {
|
604
|
+
s.addLocal(m_vertices[i]);
|
605
|
+
}
|
606
|
+
s.mulLocal(1.0f / m_count);
|
607
|
+
|
608
|
+
final float k_inv3 = 1.0f / 3.0f;
|
609
|
+
|
610
|
+
final Vec2 e1 = pool3;
|
611
|
+
final Vec2 e2 = pool4;
|
612
|
+
|
613
|
+
for (int i = 0; i < m_count; ++i) {
|
614
|
+
// Triangle vertices.
|
615
|
+
e1.set(m_vertices[i]).subLocal(s);
|
616
|
+
e2.set(s).negateLocal().addLocal(i + 1 < m_count ? m_vertices[i + 1] : m_vertices[0]);
|
617
|
+
|
618
|
+
final float D = Vec2.cross(e1, e2);
|
619
|
+
|
620
|
+
final float triangleArea = 0.5f * D;
|
621
|
+
area += triangleArea;
|
622
|
+
|
623
|
+
// Area weighted centroid
|
624
|
+
center.x += triangleArea * k_inv3 * (e1.x + e2.x);
|
625
|
+
center.y += triangleArea * k_inv3 * (e1.y + e2.y);
|
626
|
+
|
627
|
+
final float ex1 = e1.x, ey1 = e1.y;
|
628
|
+
final float ex2 = e2.x, ey2 = e2.y;
|
629
|
+
|
630
|
+
float intx2 = ex1 * ex1 + ex2 * ex1 + ex2 * ex2;
|
631
|
+
float inty2 = ey1 * ey1 + ey2 * ey1 + ey2 * ey2;
|
632
|
+
|
633
|
+
I += (0.25f * k_inv3 * D) * (intx2 + inty2);
|
634
|
+
}
|
635
|
+
|
636
|
+
// Total mass
|
637
|
+
massData.mass = density * area;
|
638
|
+
|
639
|
+
// Center of mass
|
640
|
+
assert (area > Settings.EPSILON);
|
641
|
+
center.mulLocal(1.0f / area);
|
642
|
+
massData.center.set(center).addLocal(s);
|
643
|
+
|
644
|
+
// Inertia tensor relative to the local origin (point s)
|
645
|
+
massData.I = I * density;
|
646
|
+
|
647
|
+
// Shift to center of mass then to original body origin.
|
648
|
+
massData.I += massData.mass * (Vec2.dot(massData.center, massData.center));
|
649
|
+
}
|
650
|
+
|
651
|
+
/**
|
652
|
+
* Validate convexity. This is a very time consuming operation.
|
653
|
+
*
|
654
|
+
* @return
|
655
|
+
*/
|
656
|
+
public boolean validate() {
|
657
|
+
for (int i = 0; i < m_count; ++i) {
|
658
|
+
int i1 = i;
|
659
|
+
int i2 = i < m_count - 1 ? i1 + 1 : 0;
|
660
|
+
Vec2 p = m_vertices[i1];
|
661
|
+
Vec2 e = pool1.set(m_vertices[i2]).subLocal(p);
|
662
|
+
|
663
|
+
for (int j = 0; j < m_count; ++j) {
|
664
|
+
if (j == i1 || j == i2) {
|
665
|
+
continue;
|
666
|
+
}
|
667
|
+
|
668
|
+
Vec2 v = pool2.set(m_vertices[j]).subLocal(p);
|
669
|
+
float c = Vec2.cross(e, v);
|
670
|
+
if (c < 0.0f) {
|
671
|
+
return false;
|
672
|
+
}
|
673
|
+
}
|
674
|
+
}
|
675
|
+
|
676
|
+
return true;
|
677
|
+
}
|
678
|
+
|
679
|
+
/**
|
680
|
+
* Get the vertices in local coordinates.
|
681
|
+
*
|
682
|
+
* @return
|
683
|
+
*/
|
684
|
+
public Vec2[] getVertices() {
|
685
|
+
return m_vertices;
|
686
|
+
}
|
687
|
+
|
688
|
+
/**
|
689
|
+
* Get the edge normal vectors. There is one for each vertex.
|
690
|
+
*
|
691
|
+
* @return
|
692
|
+
*/
|
693
|
+
public Vec2[] getNormals() {
|
694
|
+
return m_normals;
|
695
|
+
}
|
696
|
+
|
697
|
+
/**
|
698
|
+
* Get the centroid and apply the supplied transform.
|
699
|
+
*
|
700
|
+
* @param xf
|
701
|
+
* @return
|
702
|
+
*/
|
703
|
+
public Vec2 centroid(final Transform xf) {
|
704
|
+
return Transform.mul(xf, m_centroid);
|
705
|
+
}
|
706
|
+
|
707
|
+
/**
|
708
|
+
* Get the centroid and apply the supplied transform.
|
709
|
+
*
|
710
|
+
* @param xf
|
711
|
+
* @param out
|
712
|
+
* @return
|
713
|
+
*/
|
714
|
+
public Vec2 centroidToOut(final Transform xf, final Vec2 out) {
|
715
|
+
Transform.mulToOutUnsafe(xf, m_centroid, out);
|
716
|
+
return out;
|
717
|
+
}
|
718
|
+
}
|