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,1104 @@
|
|
1
|
+
/*******************************************************************************
|
2
|
+
* Copyright (c) 2013, Daniel Murphy
|
3
|
+
* All rights reserved.
|
4
|
+
*
|
5
|
+
* Redistribution and use in source and binary forms, with or without modification,
|
6
|
+
* are permitted provided that the following conditions are met:
|
7
|
+
* * Redistributions of source code must retain the above copyright notice,
|
8
|
+
* this list of conditions and the following disclaimer.
|
9
|
+
* * Redistributions in binary form must reproduce the above copyright notice,
|
10
|
+
* this list of conditions and the following disclaimer in the documentation
|
11
|
+
* and/or other materials provided with the distribution.
|
12
|
+
*
|
13
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
14
|
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
15
|
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
16
|
+
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
17
|
+
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
18
|
+
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
19
|
+
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
20
|
+
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
21
|
+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
22
|
+
* POSSIBILITY OF SUCH DAMAGE.
|
23
|
+
******************************************************************************/
|
24
|
+
package org.jbox2d.dynamics.contacts;
|
25
|
+
|
26
|
+
import org.jbox2d.collision.Manifold;
|
27
|
+
import org.jbox2d.collision.ManifoldPoint;
|
28
|
+
import org.jbox2d.collision.WorldManifold;
|
29
|
+
import org.jbox2d.collision.shapes.Shape;
|
30
|
+
import org.jbox2d.common.Mat22;
|
31
|
+
import org.jbox2d.common.MathUtils;
|
32
|
+
import org.jbox2d.common.Rot;
|
33
|
+
import org.jbox2d.common.Settings;
|
34
|
+
import org.jbox2d.common.Transform;
|
35
|
+
import org.jbox2d.common.Vec2;
|
36
|
+
import org.jbox2d.dynamics.Body;
|
37
|
+
import org.jbox2d.dynamics.Fixture;
|
38
|
+
import org.jbox2d.dynamics.TimeStep;
|
39
|
+
import org.jbox2d.dynamics.contacts.ContactVelocityConstraint.VelocityConstraintPoint;
|
40
|
+
|
41
|
+
/**
|
42
|
+
* @author Daniel
|
43
|
+
*/
|
44
|
+
public class ContactSolver {
|
45
|
+
|
46
|
+
public static final boolean DEBUG_SOLVER = false;
|
47
|
+
public static final float k_errorTol = 1e-3f;
|
48
|
+
/**
|
49
|
+
* For each solver, this is the initial number of constraints in the array, which expands as
|
50
|
+
* needed.
|
51
|
+
*/
|
52
|
+
public static final int INITIAL_NUM_CONSTRAINTS = 256;
|
53
|
+
|
54
|
+
/**
|
55
|
+
* Ensure a reasonable condition number. for the block solver
|
56
|
+
*/
|
57
|
+
public static final float k_maxConditionNumber = 100.0f;
|
58
|
+
|
59
|
+
public TimeStep m_step;
|
60
|
+
public Position[] m_positions;
|
61
|
+
public Velocity[] m_velocities;
|
62
|
+
public ContactPositionConstraint[] m_positionConstraints;
|
63
|
+
public ContactVelocityConstraint[] m_velocityConstraints;
|
64
|
+
public Contact[] m_contacts;
|
65
|
+
public int m_count;
|
66
|
+
|
67
|
+
public ContactSolver() {
|
68
|
+
m_positionConstraints = new ContactPositionConstraint[INITIAL_NUM_CONSTRAINTS];
|
69
|
+
m_velocityConstraints = new ContactVelocityConstraint[INITIAL_NUM_CONSTRAINTS];
|
70
|
+
for (int i = 0; i < INITIAL_NUM_CONSTRAINTS; i++) {
|
71
|
+
m_positionConstraints[i] = new ContactPositionConstraint();
|
72
|
+
m_velocityConstraints[i] = new ContactVelocityConstraint();
|
73
|
+
}
|
74
|
+
}
|
75
|
+
|
76
|
+
public final void init(ContactSolverDef def) {
|
77
|
+
// System.out.println("Initializing contact solver");
|
78
|
+
m_step = def.step;
|
79
|
+
m_count = def.count;
|
80
|
+
|
81
|
+
if (m_positionConstraints.length < m_count) {
|
82
|
+
ContactPositionConstraint[] old = m_positionConstraints;
|
83
|
+
m_positionConstraints = new ContactPositionConstraint[MathUtils.max(old.length * 2, m_count)];
|
84
|
+
System.arraycopy(old, 0, m_positionConstraints, 0, old.length);
|
85
|
+
for (int i = old.length; i < m_positionConstraints.length; i++) {
|
86
|
+
m_positionConstraints[i] = new ContactPositionConstraint();
|
87
|
+
}
|
88
|
+
}
|
89
|
+
|
90
|
+
if (m_velocityConstraints.length < m_count) {
|
91
|
+
ContactVelocityConstraint[] old = m_velocityConstraints;
|
92
|
+
m_velocityConstraints = new ContactVelocityConstraint[MathUtils.max(old.length * 2, m_count)];
|
93
|
+
System.arraycopy(old, 0, m_velocityConstraints, 0, old.length);
|
94
|
+
for (int i = old.length; i < m_velocityConstraints.length; i++) {
|
95
|
+
m_velocityConstraints[i] = new ContactVelocityConstraint();
|
96
|
+
}
|
97
|
+
}
|
98
|
+
|
99
|
+
m_positions = def.positions;
|
100
|
+
m_velocities = def.velocities;
|
101
|
+
m_contacts = def.contacts;
|
102
|
+
|
103
|
+
for (int i = 0; i < m_count; ++i) {
|
104
|
+
// System.out.println("contacts: " + m_count);
|
105
|
+
final Contact contact = m_contacts[i];
|
106
|
+
|
107
|
+
final Fixture fixtureA = contact.m_fixtureA;
|
108
|
+
final Fixture fixtureB = contact.m_fixtureB;
|
109
|
+
final Shape shapeA = fixtureA.getShape();
|
110
|
+
final Shape shapeB = fixtureB.getShape();
|
111
|
+
final float radiusA = shapeA.m_radius;
|
112
|
+
final float radiusB = shapeB.m_radius;
|
113
|
+
final Body bodyA = fixtureA.getBody();
|
114
|
+
final Body bodyB = fixtureB.getBody();
|
115
|
+
final Manifold manifold = contact.getManifold();
|
116
|
+
|
117
|
+
int pointCount = manifold.pointCount;
|
118
|
+
assert (pointCount > 0);
|
119
|
+
|
120
|
+
ContactVelocityConstraint vc = m_velocityConstraints[i];
|
121
|
+
vc.friction = contact.m_friction;
|
122
|
+
vc.restitution = contact.m_restitution;
|
123
|
+
vc.tangentSpeed = contact.m_tangentSpeed;
|
124
|
+
vc.indexA = bodyA.m_islandIndex;
|
125
|
+
vc.indexB = bodyB.m_islandIndex;
|
126
|
+
vc.invMassA = bodyA.m_invMass;
|
127
|
+
vc.invMassB = bodyB.m_invMass;
|
128
|
+
vc.invIA = bodyA.m_invI;
|
129
|
+
vc.invIB = bodyB.m_invI;
|
130
|
+
vc.contactIndex = i;
|
131
|
+
vc.pointCount = pointCount;
|
132
|
+
vc.K.setZero();
|
133
|
+
vc.normalMass.setZero();
|
134
|
+
|
135
|
+
ContactPositionConstraint pc = m_positionConstraints[i];
|
136
|
+
pc.indexA = bodyA.m_islandIndex;
|
137
|
+
pc.indexB = bodyB.m_islandIndex;
|
138
|
+
pc.invMassA = bodyA.m_invMass;
|
139
|
+
pc.invMassB = bodyB.m_invMass;
|
140
|
+
pc.localCenterA.set(bodyA.m_sweep.localCenter);
|
141
|
+
pc.localCenterB.set(bodyB.m_sweep.localCenter);
|
142
|
+
pc.invIA = bodyA.m_invI;
|
143
|
+
pc.invIB = bodyB.m_invI;
|
144
|
+
pc.localNormal.set(manifold.localNormal);
|
145
|
+
pc.localPoint.set(manifold.localPoint);
|
146
|
+
pc.pointCount = pointCount;
|
147
|
+
pc.radiusA = radiusA;
|
148
|
+
pc.radiusB = radiusB;
|
149
|
+
pc.type = manifold.type;
|
150
|
+
|
151
|
+
// System.out.println("contact point count: " + pointCount);
|
152
|
+
for (int j = 0; j < pointCount; j++) {
|
153
|
+
ManifoldPoint cp = manifold.points[j];
|
154
|
+
VelocityConstraintPoint vcp = vc.points[j];
|
155
|
+
|
156
|
+
if (m_step.warmStarting) {
|
157
|
+
// assert(cp.normalImpulse == 0);
|
158
|
+
// System.out.println("contact normal impulse: " + cp.normalImpulse);
|
159
|
+
vcp.normalImpulse = m_step.dtRatio * cp.normalImpulse;
|
160
|
+
vcp.tangentImpulse = m_step.dtRatio * cp.tangentImpulse;
|
161
|
+
} else {
|
162
|
+
vcp.normalImpulse = 0;
|
163
|
+
vcp.tangentImpulse = 0;
|
164
|
+
}
|
165
|
+
|
166
|
+
vcp.rA.setZero();
|
167
|
+
vcp.rB.setZero();
|
168
|
+
vcp.normalMass = 0;
|
169
|
+
vcp.tangentMass = 0;
|
170
|
+
vcp.velocityBias = 0;
|
171
|
+
pc.localPoints[j].x = cp.localPoint.x;
|
172
|
+
pc.localPoints[j].y = cp.localPoint.y;
|
173
|
+
}
|
174
|
+
}
|
175
|
+
}
|
176
|
+
|
177
|
+
public void warmStart() {
|
178
|
+
// Warm start.
|
179
|
+
for (int i = 0; i < m_count; ++i) {
|
180
|
+
final ContactVelocityConstraint vc = m_velocityConstraints[i];
|
181
|
+
|
182
|
+
int indexA = vc.indexA;
|
183
|
+
int indexB = vc.indexB;
|
184
|
+
float mA = vc.invMassA;
|
185
|
+
float iA = vc.invIA;
|
186
|
+
float mB = vc.invMassB;
|
187
|
+
float iB = vc.invIB;
|
188
|
+
int pointCount = vc.pointCount;
|
189
|
+
|
190
|
+
Vec2 vA = m_velocities[indexA].v;
|
191
|
+
float wA = m_velocities[indexA].w;
|
192
|
+
Vec2 vB = m_velocities[indexB].v;
|
193
|
+
float wB = m_velocities[indexB].w;
|
194
|
+
|
195
|
+
Vec2 normal = vc.normal;
|
196
|
+
float tangentx = 1.0f * normal.y;
|
197
|
+
float tangenty = -1.0f * normal.x;
|
198
|
+
|
199
|
+
for (int j = 0; j < pointCount; ++j) {
|
200
|
+
VelocityConstraintPoint vcp = vc.points[j];
|
201
|
+
float Px = tangentx * vcp.tangentImpulse + normal.x * vcp.normalImpulse;
|
202
|
+
float Py = tangenty * vcp.tangentImpulse + normal.y * vcp.normalImpulse;
|
203
|
+
|
204
|
+
wA -= iA * (vcp.rA.x * Py - vcp.rA.y * Px);
|
205
|
+
vA.x -= Px * mA;
|
206
|
+
vA.y -= Py * mA;
|
207
|
+
wB += iB * (vcp.rB.x * Py - vcp.rB.y * Px);
|
208
|
+
vB.x += Px * mB;
|
209
|
+
vB.y += Py * mB;
|
210
|
+
}
|
211
|
+
m_velocities[indexA].w = wA;
|
212
|
+
m_velocities[indexB].w = wB;
|
213
|
+
}
|
214
|
+
}
|
215
|
+
|
216
|
+
// djm pooling, and from above
|
217
|
+
private final Transform xfA = new Transform();
|
218
|
+
private final Transform xfB = new Transform();
|
219
|
+
private final WorldManifold worldManifold = new WorldManifold();
|
220
|
+
|
221
|
+
public final void initializeVelocityConstraints() {
|
222
|
+
|
223
|
+
// Warm start.
|
224
|
+
for (int i = 0; i < m_count; ++i) {
|
225
|
+
ContactVelocityConstraint vc = m_velocityConstraints[i];
|
226
|
+
ContactPositionConstraint pc = m_positionConstraints[i];
|
227
|
+
|
228
|
+
float radiusA = pc.radiusA;
|
229
|
+
float radiusB = pc.radiusB;
|
230
|
+
Manifold manifold = m_contacts[vc.contactIndex].getManifold();
|
231
|
+
|
232
|
+
int indexA = vc.indexA;
|
233
|
+
int indexB = vc.indexB;
|
234
|
+
|
235
|
+
float mA = vc.invMassA;
|
236
|
+
float mB = vc.invMassB;
|
237
|
+
float iA = vc.invIA;
|
238
|
+
float iB = vc.invIB;
|
239
|
+
Vec2 localCenterA = pc.localCenterA;
|
240
|
+
Vec2 localCenterB = pc.localCenterB;
|
241
|
+
|
242
|
+
Vec2 cA = m_positions[indexA].c;
|
243
|
+
float aA = m_positions[indexA].a;
|
244
|
+
Vec2 vA = m_velocities[indexA].v;
|
245
|
+
float wA = m_velocities[indexA].w;
|
246
|
+
|
247
|
+
Vec2 cB = m_positions[indexB].c;
|
248
|
+
float aB = m_positions[indexB].a;
|
249
|
+
Vec2 vB = m_velocities[indexB].v;
|
250
|
+
float wB = m_velocities[indexB].w;
|
251
|
+
|
252
|
+
assert (manifold.pointCount > 0);
|
253
|
+
|
254
|
+
final Rot xfAq = xfA.q;
|
255
|
+
final Rot xfBq = xfB.q;
|
256
|
+
xfAq.set(aA);
|
257
|
+
xfBq.set(aB);
|
258
|
+
xfA.p.x = cA.x - (xfAq.c * localCenterA.x - xfAq.s * localCenterA.y);
|
259
|
+
xfA.p.y = cA.y - (xfAq.s * localCenterA.x + xfAq.c * localCenterA.y);
|
260
|
+
xfB.p.x = cB.x - (xfBq.c * localCenterB.x - xfBq.s * localCenterB.y);
|
261
|
+
xfB.p.y = cB.y - (xfBq.s * localCenterB.x + xfBq.c * localCenterB.y);
|
262
|
+
|
263
|
+
worldManifold.initialize(manifold, xfA, radiusA, xfB, radiusB);
|
264
|
+
|
265
|
+
final Vec2 vcnormal = vc.normal;
|
266
|
+
vcnormal.x = worldManifold.normal.x;
|
267
|
+
vcnormal.y = worldManifold.normal.y;
|
268
|
+
|
269
|
+
int pointCount = vc.pointCount;
|
270
|
+
for (int j = 0; j < pointCount; ++j) {
|
271
|
+
VelocityConstraintPoint vcp = vc.points[j];
|
272
|
+
Vec2 wmPj = worldManifold.points[j];
|
273
|
+
final Vec2 vcprA = vcp.rA;
|
274
|
+
final Vec2 vcprB = vcp.rB;
|
275
|
+
vcprA.x = wmPj.x - cA.x;
|
276
|
+
vcprA.y = wmPj.y - cA.y;
|
277
|
+
vcprB.x = wmPj.x - cB.x;
|
278
|
+
vcprB.y = wmPj.y - cB.y;
|
279
|
+
|
280
|
+
float rnA = vcprA.x * vcnormal.y - vcprA.y * vcnormal.x;
|
281
|
+
float rnB = vcprB.x * vcnormal.y - vcprB.y * vcnormal.x;
|
282
|
+
|
283
|
+
float kNormal = mA + mB + iA * rnA * rnA + iB * rnB * rnB;
|
284
|
+
|
285
|
+
vcp.normalMass = kNormal > 0.0f ? 1.0f / kNormal : 0.0f;
|
286
|
+
|
287
|
+
float tangentx = 1.0f * vcnormal.y;
|
288
|
+
float tangenty = -1.0f * vcnormal.x;
|
289
|
+
|
290
|
+
float rtA = vcprA.x * tangenty - vcprA.y * tangentx;
|
291
|
+
float rtB = vcprB.x * tangenty - vcprB.y * tangentx;
|
292
|
+
|
293
|
+
float kTangent = mA + mB + iA * rtA * rtA + iB * rtB * rtB;
|
294
|
+
|
295
|
+
vcp.tangentMass = kTangent > 0.0f ? 1.0f / kTangent : 0.0f;
|
296
|
+
|
297
|
+
// Setup a velocity bias for restitution.
|
298
|
+
vcp.velocityBias = 0.0f;
|
299
|
+
float tempx = vB.x + -wB * vcprB.y - vA.x - (-wA * vcprA.y);
|
300
|
+
float tempy = vB.y + wB * vcprB.x - vA.y - (wA * vcprA.x);
|
301
|
+
float vRel = vcnormal.x * tempx + vcnormal.y * tempy;
|
302
|
+
if (vRel < -Settings.velocityThreshold) {
|
303
|
+
vcp.velocityBias = -vc.restitution * vRel;
|
304
|
+
}
|
305
|
+
}
|
306
|
+
|
307
|
+
// If we have two points, then prepare the block solver.
|
308
|
+
if (vc.pointCount == 2) {
|
309
|
+
VelocityConstraintPoint vcp1 = vc.points[0];
|
310
|
+
VelocityConstraintPoint vcp2 = vc.points[1];
|
311
|
+
float rn1A = vcp1.rA.x * vcnormal.y - vcp1.rA.y * vcnormal.x;
|
312
|
+
float rn1B = vcp1.rB.x * vcnormal.y - vcp1.rB.y * vcnormal.x;
|
313
|
+
float rn2A = vcp2.rA.x * vcnormal.y - vcp2.rA.y * vcnormal.x;
|
314
|
+
float rn2B = vcp2.rB.x * vcnormal.y - vcp2.rB.y * vcnormal.x;
|
315
|
+
|
316
|
+
float k11 = mA + mB + iA * rn1A * rn1A + iB * rn1B * rn1B;
|
317
|
+
float k22 = mA + mB + iA * rn2A * rn2A + iB * rn2B * rn2B;
|
318
|
+
float k12 = mA + mB + iA * rn1A * rn2A + iB * rn1B * rn2B;
|
319
|
+
if (k11 * k11 < k_maxConditionNumber * (k11 * k22 - k12 * k12)) {
|
320
|
+
// K is safe to invert.
|
321
|
+
vc.K.ex.x = k11;
|
322
|
+
vc.K.ex.y = k12;
|
323
|
+
vc.K.ey.x = k12;
|
324
|
+
vc.K.ey.y = k22;
|
325
|
+
vc.K.invertToOut(vc.normalMass);
|
326
|
+
} else {
|
327
|
+
// The constraints are redundant, just use one.
|
328
|
+
// TODO_ERIN use deepest?
|
329
|
+
vc.pointCount = 1;
|
330
|
+
}
|
331
|
+
}
|
332
|
+
}
|
333
|
+
}
|
334
|
+
|
335
|
+
|
336
|
+
public final void solveVelocityConstraints() {
|
337
|
+
for (int i = 0; i < m_count; ++i) {
|
338
|
+
final ContactVelocityConstraint vc = m_velocityConstraints[i];
|
339
|
+
|
340
|
+
int indexA = vc.indexA;
|
341
|
+
int indexB = vc.indexB;
|
342
|
+
|
343
|
+
float mA = vc.invMassA;
|
344
|
+
float mB = vc.invMassB;
|
345
|
+
float iA = vc.invIA;
|
346
|
+
float iB = vc.invIB;
|
347
|
+
int pointCount = vc.pointCount;
|
348
|
+
|
349
|
+
Vec2 vA = m_velocities[indexA].v;
|
350
|
+
float wA = m_velocities[indexA].w;
|
351
|
+
Vec2 vB = m_velocities[indexB].v;
|
352
|
+
float wB = m_velocities[indexB].w;
|
353
|
+
|
354
|
+
Vec2 normal = vc.normal;
|
355
|
+
final float normalx = normal.x;
|
356
|
+
final float normaly = normal.y;
|
357
|
+
float tangentx = 1.0f * vc.normal.y;
|
358
|
+
float tangenty = -1.0f * vc.normal.x;
|
359
|
+
final float friction = vc.friction;
|
360
|
+
|
361
|
+
assert (pointCount == 1 || pointCount == 2);
|
362
|
+
|
363
|
+
// Solve tangent constraints
|
364
|
+
for (int j = 0; j < pointCount; ++j) {
|
365
|
+
final VelocityConstraintPoint vcp = vc.points[j];
|
366
|
+
final Vec2 a = vcp.rA;
|
367
|
+
float dvx = -wB * vcp.rB.y + vB.x - vA.x + wA * a.y;
|
368
|
+
float dvy = wB * vcp.rB.x + vB.y - vA.y - wA * a.x;
|
369
|
+
|
370
|
+
// Compute tangent force
|
371
|
+
final float vt = dvx * tangentx + dvy * tangenty - vc.tangentSpeed;
|
372
|
+
float lambda = vcp.tangentMass * (-vt);
|
373
|
+
|
374
|
+
// Clamp the accumulated force
|
375
|
+
final float maxFriction = friction * vcp.normalImpulse;
|
376
|
+
final float newImpulse =
|
377
|
+
MathUtils.clamp(vcp.tangentImpulse + lambda, -maxFriction, maxFriction);
|
378
|
+
lambda = newImpulse - vcp.tangentImpulse;
|
379
|
+
vcp.tangentImpulse = newImpulse;
|
380
|
+
|
381
|
+
// Apply contact impulse
|
382
|
+
// Vec2 P = lambda * tangent;
|
383
|
+
|
384
|
+
final float Px = tangentx * lambda;
|
385
|
+
final float Py = tangenty * lambda;
|
386
|
+
|
387
|
+
// vA -= invMassA * P;
|
388
|
+
vA.x -= Px * mA;
|
389
|
+
vA.y -= Py * mA;
|
390
|
+
wA -= iA * (vcp.rA.x * Py - vcp.rA.y * Px);
|
391
|
+
|
392
|
+
// vB += invMassB * P;
|
393
|
+
vB.x += Px * mB;
|
394
|
+
vB.y += Py * mB;
|
395
|
+
wB += iB * (vcp.rB.x * Py - vcp.rB.y * Px);
|
396
|
+
}
|
397
|
+
|
398
|
+
// Solve normal constraints
|
399
|
+
if (vc.pointCount == 1) {
|
400
|
+
final VelocityConstraintPoint vcp = vc.points[0];
|
401
|
+
|
402
|
+
// Relative velocity at contact
|
403
|
+
// Vec2 dv = vB + Cross(wB, vcp.rB) - vA - Cross(wA, vcp.rA);
|
404
|
+
|
405
|
+
float dvx = -wB * vcp.rB.y + vB.x - vA.x + wA * vcp.rA.y;
|
406
|
+
float dvy = wB * vcp.rB.x + vB.y - vA.y - wA * vcp.rA.x;
|
407
|
+
|
408
|
+
// Compute normal impulse
|
409
|
+
final float vn = dvx * normalx + dvy * normaly;
|
410
|
+
float lambda = -vcp.normalMass * (vn - vcp.velocityBias);
|
411
|
+
|
412
|
+
// Clamp the accumulated impulse
|
413
|
+
float a = vcp.normalImpulse + lambda;
|
414
|
+
final float newImpulse = (a > 0.0f ? a : 0.0f);
|
415
|
+
lambda = newImpulse - vcp.normalImpulse;
|
416
|
+
vcp.normalImpulse = newImpulse;
|
417
|
+
|
418
|
+
// Apply contact impulse
|
419
|
+
float Px = normalx * lambda;
|
420
|
+
float Py = normaly * lambda;
|
421
|
+
|
422
|
+
// vA -= invMassA * P;
|
423
|
+
vA.x -= Px * mA;
|
424
|
+
vA.y -= Py * mA;
|
425
|
+
wA -= iA * (vcp.rA.x * Py - vcp.rA.y * Px);
|
426
|
+
|
427
|
+
// vB += invMassB * P;
|
428
|
+
vB.x += Px * mB;
|
429
|
+
vB.y += Py * mB;
|
430
|
+
wB += iB * (vcp.rB.x * Py - vcp.rB.y * Px);
|
431
|
+
} else {
|
432
|
+
// Block solver developed in collaboration with Dirk Gregorius (back in 01/07 on
|
433
|
+
// Box2D_Lite).
|
434
|
+
// Build the mini LCP for this contact patch
|
435
|
+
//
|
436
|
+
// vn = A * x + b, vn >= 0, , vn >= 0, x >= 0 and vn_i * x_i = 0 with i = 1..2
|
437
|
+
//
|
438
|
+
// A = J * W * JT and J = ( -n, -r1 x n, n, r2 x n )
|
439
|
+
// b = vn_0 - velocityBias
|
440
|
+
//
|
441
|
+
// The system is solved using the "Total enumeration method" (s. Murty). The complementary
|
442
|
+
// constraint vn_i * x_i
|
443
|
+
// implies that we must have in any solution either vn_i = 0 or x_i = 0. So for the 2D
|
444
|
+
// contact problem the cases
|
445
|
+
// vn1 = 0 and vn2 = 0, x1 = 0 and x2 = 0, x1 = 0 and vn2 = 0, x2 = 0 and vn1 = 0 need to be
|
446
|
+
// tested. The first valid
|
447
|
+
// solution that satisfies the problem is chosen.
|
448
|
+
//
|
449
|
+
// In order to account of the accumulated impulse 'a' (because of the iterative nature of
|
450
|
+
// the solver which only requires
|
451
|
+
// that the accumulated impulse is clamped and not the incremental impulse) we change the
|
452
|
+
// impulse variable (x_i).
|
453
|
+
//
|
454
|
+
// Substitute:
|
455
|
+
//
|
456
|
+
// x = a + d
|
457
|
+
//
|
458
|
+
// a := old total impulse
|
459
|
+
// x := new total impulse
|
460
|
+
// d := incremental impulse
|
461
|
+
//
|
462
|
+
// For the current iteration we extend the formula for the incremental impulse
|
463
|
+
// to compute the new total impulse:
|
464
|
+
//
|
465
|
+
// vn = A * d + b
|
466
|
+
// = A * (x - a) + b
|
467
|
+
// = A * x + b - A * a
|
468
|
+
// = A * x + b'
|
469
|
+
// b' = b - A * a;
|
470
|
+
|
471
|
+
final VelocityConstraintPoint cp1 = vc.points[0];
|
472
|
+
final VelocityConstraintPoint cp2 = vc.points[1];
|
473
|
+
final Vec2 cp1rA = cp1.rA;
|
474
|
+
final Vec2 cp1rB = cp1.rB;
|
475
|
+
final Vec2 cp2rA = cp2.rA;
|
476
|
+
final Vec2 cp2rB = cp2.rB;
|
477
|
+
float ax = cp1.normalImpulse;
|
478
|
+
float ay = cp2.normalImpulse;
|
479
|
+
|
480
|
+
assert (ax >= 0.0f && ay >= 0.0f);
|
481
|
+
// Relative velocity at contact
|
482
|
+
// Vec2 dv1 = vB + Cross(wB, cp1.rB) - vA - Cross(wA, cp1.rA);
|
483
|
+
float dv1x = -wB * cp1rB.y + vB.x - vA.x + wA * cp1rA.y;
|
484
|
+
float dv1y = wB * cp1rB.x + vB.y - vA.y - wA * cp1rA.x;
|
485
|
+
|
486
|
+
// Vec2 dv2 = vB + Cross(wB, cp2.rB) - vA - Cross(wA, cp2.rA);
|
487
|
+
float dv2x = -wB * cp2rB.y + vB.x - vA.x + wA * cp2rA.y;
|
488
|
+
float dv2y = wB * cp2rB.x + vB.y - vA.y - wA * cp2rA.x;
|
489
|
+
|
490
|
+
// Compute normal velocity
|
491
|
+
float vn1 = dv1x * normalx + dv1y * normaly;
|
492
|
+
float vn2 = dv2x * normalx + dv2y * normaly;
|
493
|
+
|
494
|
+
float bx = vn1 - cp1.velocityBias;
|
495
|
+
float by = vn2 - cp2.velocityBias;
|
496
|
+
|
497
|
+
// Compute b'
|
498
|
+
Mat22 R = vc.K;
|
499
|
+
bx -= R.ex.x * ax + R.ey.x * ay;
|
500
|
+
by -= R.ex.y * ax + R.ey.y * ay;
|
501
|
+
|
502
|
+
// final float k_errorTol = 1e-3f;
|
503
|
+
// B2_NOT_USED(k_errorTol);
|
504
|
+
for (;;) {
|
505
|
+
//
|
506
|
+
// Case 1: vn = 0
|
507
|
+
//
|
508
|
+
// 0 = A * x' + b'
|
509
|
+
//
|
510
|
+
// Solve for x':
|
511
|
+
//
|
512
|
+
// x' = - inv(A) * b'
|
513
|
+
//
|
514
|
+
// Vec2 x = - Mul(c.normalMass, b);
|
515
|
+
Mat22 R1 = vc.normalMass;
|
516
|
+
float xx = R1.ex.x * bx + R1.ey.x * by;
|
517
|
+
float xy = R1.ex.y * bx + R1.ey.y * by;
|
518
|
+
xx *= -1;
|
519
|
+
xy *= -1;
|
520
|
+
|
521
|
+
if (xx >= 0.0f && xy >= 0.0f) {
|
522
|
+
// Get the incremental impulse
|
523
|
+
// Vec2 d = x - a;
|
524
|
+
float dx = xx - ax;
|
525
|
+
float dy = xy - ay;
|
526
|
+
|
527
|
+
// Apply incremental impulse
|
528
|
+
// Vec2 P1 = d.x * normal;
|
529
|
+
// Vec2 P2 = d.y * normal;
|
530
|
+
float P1x = dx * normalx;
|
531
|
+
float P1y = dx * normaly;
|
532
|
+
float P2x = dy * normalx;
|
533
|
+
float P2y = dy * normaly;
|
534
|
+
|
535
|
+
/*
|
536
|
+
* vA -= invMassA * (P1 + P2); wA -= invIA * (Cross(cp1.rA, P1) + Cross(cp2.rA, P2));
|
537
|
+
*
|
538
|
+
* vB += invMassB * (P1 + P2); wB += invIB * (Cross(cp1.rB, P1) + Cross(cp2.rB, P2));
|
539
|
+
*/
|
540
|
+
|
541
|
+
vA.x -= mA * (P1x + P2x);
|
542
|
+
vA.y -= mA * (P1y + P2y);
|
543
|
+
vB.x += mB * (P1x + P2x);
|
544
|
+
vB.y += mB * (P1y + P2y);
|
545
|
+
|
546
|
+
wA -= iA * (cp1rA.x * P1y - cp1rA.y * P1x + (cp2rA.x * P2y - cp2rA.y * P2x));
|
547
|
+
wB += iB * (cp1rB.x * P1y - cp1rB.y * P1x + (cp2rB.x * P2y - cp2rB.y * P2x));
|
548
|
+
|
549
|
+
// Accumulate
|
550
|
+
cp1.normalImpulse = xx;
|
551
|
+
cp2.normalImpulse = xy;
|
552
|
+
|
553
|
+
/*
|
554
|
+
* #if B2_DEBUG_SOLVER == 1 // Postconditions dv1 = vB + Cross(wB, cp1.rB) - vA -
|
555
|
+
* Cross(wA, cp1.rA); dv2 = vB + Cross(wB, cp2.rB) - vA - Cross(wA, cp2.rA);
|
556
|
+
*
|
557
|
+
* // Compute normal velocity vn1 = Dot(dv1, normal); vn2 = Dot(dv2, normal);
|
558
|
+
*
|
559
|
+
* assert(Abs(vn1 - cp1.velocityBias) < k_errorTol); assert(Abs(vn2 - cp2.velocityBias)
|
560
|
+
* < k_errorTol); #endif
|
561
|
+
*/
|
562
|
+
if (DEBUG_SOLVER) {
|
563
|
+
// Postconditions
|
564
|
+
Vec2 dv1 = vB.add(Vec2.cross(wB, cp1rB).subLocal(vA).subLocal(Vec2.cross(wA, cp1rA)));
|
565
|
+
Vec2 dv2 = vB.add(Vec2.cross(wB, cp2rB).subLocal(vA).subLocal(Vec2.cross(wA, cp2rA)));
|
566
|
+
// Compute normal velocity
|
567
|
+
vn1 = Vec2.dot(dv1, normal);
|
568
|
+
vn2 = Vec2.dot(dv2, normal);
|
569
|
+
|
570
|
+
assert (MathUtils.abs(vn1 - cp1.velocityBias) < k_errorTol);
|
571
|
+
assert (MathUtils.abs(vn2 - cp2.velocityBias) < k_errorTol);
|
572
|
+
}
|
573
|
+
break;
|
574
|
+
}
|
575
|
+
|
576
|
+
//
|
577
|
+
// Case 2: vn1 = 0 and x2 = 0
|
578
|
+
//
|
579
|
+
// 0 = a11 * x1' + a12 * 0 + b1'
|
580
|
+
// vn2 = a21 * x1' + a22 * 0 + '
|
581
|
+
//
|
582
|
+
xx = -cp1.normalMass * bx;
|
583
|
+
xy = 0.0f;
|
584
|
+
vn1 = 0.0f;
|
585
|
+
vn2 = vc.K.ex.y * xx + by;
|
586
|
+
|
587
|
+
if (xx >= 0.0f && vn2 >= 0.0f) {
|
588
|
+
// Get the incremental impulse
|
589
|
+
float dx = xx - ax;
|
590
|
+
float dy = xy - ay;
|
591
|
+
|
592
|
+
// Apply incremental impulse
|
593
|
+
// Vec2 P1 = d.x * normal;
|
594
|
+
// Vec2 P2 = d.y * normal;
|
595
|
+
float P1x = normalx * dx;
|
596
|
+
float P1y = normaly * dx;
|
597
|
+
float P2x = normalx * dy;
|
598
|
+
float P2y = normaly * dy;
|
599
|
+
|
600
|
+
/*
|
601
|
+
* Vec2 P1 = d.x * normal; Vec2 P2 = d.y * normal; vA -= invMassA * (P1 + P2); wA -=
|
602
|
+
* invIA * (Cross(cp1.rA, P1) + Cross(cp2.rA, P2));
|
603
|
+
*
|
604
|
+
* vB += invMassB * (P1 + P2); wB += invIB * (Cross(cp1.rB, P1) + Cross(cp2.rB, P2));
|
605
|
+
*/
|
606
|
+
|
607
|
+
vA.x -= mA * (P1x + P2x);
|
608
|
+
vA.y -= mA * (P1y + P2y);
|
609
|
+
vB.x += mB * (P1x + P2x);
|
610
|
+
vB.y += mB * (P1y + P2y);
|
611
|
+
|
612
|
+
wA -= iA * (cp1rA.x * P1y - cp1rA.y * P1x + (cp2rA.x * P2y - cp2rA.y * P2x));
|
613
|
+
wB += iB * (cp1rB.x * P1y - cp1rB.y * P1x + (cp2rB.x * P2y - cp2rB.y * P2x));
|
614
|
+
|
615
|
+
// Accumulate
|
616
|
+
cp1.normalImpulse = xx;
|
617
|
+
cp2.normalImpulse = xy;
|
618
|
+
|
619
|
+
/*
|
620
|
+
* #if B2_DEBUG_SOLVER == 1 // Postconditions dv1 = vB + Cross(wB, cp1.rB) - vA -
|
621
|
+
* Cross(wA, cp1.rA);
|
622
|
+
*
|
623
|
+
* // Compute normal velocity vn1 = Dot(dv1, normal);
|
624
|
+
*
|
625
|
+
* assert(Abs(vn1 - cp1.velocityBias) < k_errorTol); #endif
|
626
|
+
*/
|
627
|
+
if (DEBUG_SOLVER) {
|
628
|
+
// Postconditions
|
629
|
+
Vec2 dv1 = vB.add(Vec2.cross(wB, cp1rB).subLocal(vA).subLocal(Vec2.cross(wA, cp1rA)));
|
630
|
+
// Compute normal velocity
|
631
|
+
vn1 = Vec2.dot(dv1, normal);
|
632
|
+
|
633
|
+
assert (MathUtils.abs(vn1 - cp1.velocityBias) < k_errorTol);
|
634
|
+
}
|
635
|
+
break;
|
636
|
+
}
|
637
|
+
|
638
|
+
//
|
639
|
+
// Case 3: wB = 0 and x1 = 0
|
640
|
+
//
|
641
|
+
// vn1 = a11 * 0 + a12 * x2' + b1'
|
642
|
+
// 0 = a21 * 0 + a22 * x2' + '
|
643
|
+
//
|
644
|
+
xx = 0.0f;
|
645
|
+
xy = -cp2.normalMass * by;
|
646
|
+
vn1 = vc.K.ey.x * xy + bx;
|
647
|
+
vn2 = 0.0f;
|
648
|
+
|
649
|
+
if (xy >= 0.0f && vn1 >= 0.0f) {
|
650
|
+
// Resubstitute for the incremental impulse
|
651
|
+
float dx = xx - ax;
|
652
|
+
float dy = xy - ay;
|
653
|
+
|
654
|
+
// Apply incremental impulse
|
655
|
+
/*
|
656
|
+
* Vec2 P1 = d.x * normal; Vec2 P2 = d.y * normal; vA -= invMassA * (P1 + P2); wA -=
|
657
|
+
* invIA * (Cross(cp1.rA, P1) + Cross(cp2.rA, P2));
|
658
|
+
*
|
659
|
+
* vB += invMassB * (P1 + P2); wB += invIB * (Cross(cp1.rB, P1) + Cross(cp2.rB, P2));
|
660
|
+
*/
|
661
|
+
|
662
|
+
float P1x = normalx * dx;
|
663
|
+
float P1y = normaly * dx;
|
664
|
+
float P2x = normalx * dy;
|
665
|
+
float P2y = normaly * dy;
|
666
|
+
|
667
|
+
vA.x -= mA * (P1x + P2x);
|
668
|
+
vA.y -= mA * (P1y + P2y);
|
669
|
+
vB.x += mB * (P1x + P2x);
|
670
|
+
vB.y += mB * (P1y + P2y);
|
671
|
+
|
672
|
+
wA -= iA * (cp1rA.x * P1y - cp1rA.y * P1x + (cp2rA.x * P2y - cp2rA.y * P2x));
|
673
|
+
wB += iB * (cp1rB.x * P1y - cp1rB.y * P1x + (cp2rB.x * P2y - cp2rB.y * P2x));
|
674
|
+
|
675
|
+
// Accumulate
|
676
|
+
cp1.normalImpulse = xx;
|
677
|
+
cp2.normalImpulse = xy;
|
678
|
+
|
679
|
+
/*
|
680
|
+
* #if B2_DEBUG_SOLVER == 1 // Postconditions dv2 = vB + Cross(wB, cp2.rB) - vA -
|
681
|
+
* Cross(wA, cp2.rA);
|
682
|
+
*
|
683
|
+
* // Compute normal velocity vn2 = Dot(dv2, normal);
|
684
|
+
*
|
685
|
+
* assert(Abs(vn2 - cp2.velocityBias) < k_errorTol); #endif
|
686
|
+
*/
|
687
|
+
if (DEBUG_SOLVER) {
|
688
|
+
// Postconditions
|
689
|
+
Vec2 dv2 = vB.add(Vec2.cross(wB, cp2rB).subLocal(vA).subLocal(Vec2.cross(wA, cp2rA)));
|
690
|
+
// Compute normal velocity
|
691
|
+
vn2 = Vec2.dot(dv2, normal);
|
692
|
+
|
693
|
+
assert (MathUtils.abs(vn2 - cp2.velocityBias) < k_errorTol);
|
694
|
+
}
|
695
|
+
break;
|
696
|
+
}
|
697
|
+
|
698
|
+
//
|
699
|
+
// Case 4: x1 = 0 and x2 = 0
|
700
|
+
//
|
701
|
+
// vn1 = b1
|
702
|
+
// vn2 = ;
|
703
|
+
xx = 0.0f;
|
704
|
+
xy = 0.0f;
|
705
|
+
vn1 = bx;
|
706
|
+
vn2 = by;
|
707
|
+
|
708
|
+
if (vn1 >= 0.0f && vn2 >= 0.0f) {
|
709
|
+
// Resubstitute for the incremental impulse
|
710
|
+
float dx = xx - ax;
|
711
|
+
float dy = xy - ay;
|
712
|
+
|
713
|
+
// Apply incremental impulse
|
714
|
+
/*
|
715
|
+
* Vec2 P1 = d.x * normal; Vec2 P2 = d.y * normal; vA -= invMassA * (P1 + P2); wA -=
|
716
|
+
* invIA * (Cross(cp1.rA, P1) + Cross(cp2.rA, P2));
|
717
|
+
*
|
718
|
+
* vB += invMassB * (P1 + P2); wB += invIB * (Cross(cp1.rB, P1) + Cross(cp2.rB, P2));
|
719
|
+
*/
|
720
|
+
|
721
|
+
float P1x = normalx * dx;
|
722
|
+
float P1y = normaly * dx;
|
723
|
+
float P2x = normalx * dy;
|
724
|
+
float P2y = normaly * dy;
|
725
|
+
|
726
|
+
vA.x -= mA * (P1x + P2x);
|
727
|
+
vA.y -= mA * (P1y + P2y);
|
728
|
+
vB.x += mB * (P1x + P2x);
|
729
|
+
vB.y += mB * (P1y + P2y);
|
730
|
+
|
731
|
+
wA -= iA * (cp1rA.x * P1y - cp1rA.y * P1x + (cp2rA.x * P2y - cp2rA.y * P2x));
|
732
|
+
wB += iB * (cp1rB.x * P1y - cp1rB.y * P1x + (cp2rB.x * P2y - cp2rB.y * P2x));
|
733
|
+
|
734
|
+
// Accumulate
|
735
|
+
cp1.normalImpulse = xx;
|
736
|
+
cp2.normalImpulse = xy;
|
737
|
+
|
738
|
+
break;
|
739
|
+
}
|
740
|
+
|
741
|
+
// No solution, give up. This is hit sometimes, but it doesn't seem to matter.
|
742
|
+
break;
|
743
|
+
}
|
744
|
+
}
|
745
|
+
|
746
|
+
// m_velocities[indexA].v.set(vA);
|
747
|
+
m_velocities[indexA].w = wA;
|
748
|
+
// m_velocities[indexB].v.set(vB);
|
749
|
+
m_velocities[indexB].w = wB;
|
750
|
+
}
|
751
|
+
}
|
752
|
+
|
753
|
+
public void storeImpulses() {
|
754
|
+
for (int i = 0; i < m_count; i++) {
|
755
|
+
final ContactVelocityConstraint vc = m_velocityConstraints[i];
|
756
|
+
final Manifold manifold = m_contacts[vc.contactIndex].getManifold();
|
757
|
+
|
758
|
+
for (int j = 0; j < vc.pointCount; j++) {
|
759
|
+
manifold.points[j].normalImpulse = vc.points[j].normalImpulse;
|
760
|
+
manifold.points[j].tangentImpulse = vc.points[j].tangentImpulse;
|
761
|
+
}
|
762
|
+
}
|
763
|
+
}
|
764
|
+
|
765
|
+
/*
|
766
|
+
* #if 0 // Sequential solver. bool ContactSolver::SolvePositionConstraints(float baumgarte) {
|
767
|
+
* float minSeparation = 0.0f;
|
768
|
+
*
|
769
|
+
* for (int i = 0; i < m_constraintCount; ++i) { ContactConstraint* c = m_constraints + i; Body*
|
770
|
+
* bodyA = c.bodyA; Body* bodyB = c.bodyB; float invMassA = bodyA.m_mass * bodyA.m_invMass; float
|
771
|
+
* invIA = bodyA.m_mass * bodyA.m_invI; float invMassB = bodyB.m_mass * bodyB.m_invMass; float
|
772
|
+
* invIB = bodyB.m_mass * bodyB.m_invI;
|
773
|
+
*
|
774
|
+
* Vec2 normal = c.normal;
|
775
|
+
*
|
776
|
+
* // Solve normal constraints for (int j = 0; j < c.pointCount; ++j) { ContactConstraintPoint*
|
777
|
+
* ccp = c.points + j;
|
778
|
+
*
|
779
|
+
* Vec2 r1 = Mul(bodyA.GetXForm().R, ccp.localAnchorA - bodyA.GetLocalCenter()); Vec2 r2 =
|
780
|
+
* Mul(bodyB.GetXForm().R, ccp.localAnchorB - bodyB.GetLocalCenter());
|
781
|
+
*
|
782
|
+
* Vec2 p1 = bodyA.m_sweep.c + r1; Vec2 p2 = bodyB.m_sweep.c + r2; Vec2 dp = p2 - p1;
|
783
|
+
*
|
784
|
+
* // Approximate the current separation. float separation = Dot(dp, normal) + ccp.separation;
|
785
|
+
*
|
786
|
+
* // Track max constraint error. minSeparation = Min(minSeparation, separation);
|
787
|
+
*
|
788
|
+
* // Prevent large corrections and allow slop. float C = Clamp(baumgarte * (separation +
|
789
|
+
* _linearSlop), -_maxLinearCorrection, 0.0f);
|
790
|
+
*
|
791
|
+
* // Compute normal impulse float impulse = -ccp.equalizedMass * C;
|
792
|
+
*
|
793
|
+
* Vec2 P = impulse * normal;
|
794
|
+
*
|
795
|
+
* bodyA.m_sweep.c -= invMassA * P; bodyA.m_sweep.a -= invIA * Cross(r1, P);
|
796
|
+
* bodyA.SynchronizeTransform();
|
797
|
+
*
|
798
|
+
* bodyB.m_sweep.c += invMassB * P; bodyB.m_sweep.a += invIB * Cross(r2, P);
|
799
|
+
* bodyB.SynchronizeTransform(); } }
|
800
|
+
*
|
801
|
+
* // We can't expect minSpeparation >= -_linearSlop because we don't // push the separation above
|
802
|
+
* -_linearSlop. return minSeparation >= -1.5f * _linearSlop; }
|
803
|
+
*/
|
804
|
+
|
805
|
+
private final PositionSolverManifold psolver = new PositionSolverManifold();
|
806
|
+
|
807
|
+
/**
|
808
|
+
* Sequential solver.
|
809
|
+
*/
|
810
|
+
public final boolean solvePositionConstraints() {
|
811
|
+
float minSeparation = 0.0f;
|
812
|
+
|
813
|
+
for (int i = 0; i < m_count; ++i) {
|
814
|
+
ContactPositionConstraint pc = m_positionConstraints[i];
|
815
|
+
|
816
|
+
int indexA = pc.indexA;
|
817
|
+
int indexB = pc.indexB;
|
818
|
+
|
819
|
+
float mA = pc.invMassA;
|
820
|
+
float iA = pc.invIA;
|
821
|
+
Vec2 localCenterA = pc.localCenterA;
|
822
|
+
final float localCenterAx = localCenterA.x;
|
823
|
+
final float localCenterAy = localCenterA.y;
|
824
|
+
float mB = pc.invMassB;
|
825
|
+
float iB = pc.invIB;
|
826
|
+
Vec2 localCenterB = pc.localCenterB;
|
827
|
+
final float localCenterBx = localCenterB.x;
|
828
|
+
final float localCenterBy = localCenterB.y;
|
829
|
+
int pointCount = pc.pointCount;
|
830
|
+
|
831
|
+
Vec2 cA = m_positions[indexA].c;
|
832
|
+
float aA = m_positions[indexA].a;
|
833
|
+
Vec2 cB = m_positions[indexB].c;
|
834
|
+
float aB = m_positions[indexB].a;
|
835
|
+
|
836
|
+
// Solve normal constraints
|
837
|
+
for (int j = 0; j < pointCount; ++j) {
|
838
|
+
final Rot xfAq = xfA.q;
|
839
|
+
final Rot xfBq = xfB.q;
|
840
|
+
xfAq.set(aA);
|
841
|
+
xfBq.set(aB);
|
842
|
+
xfA.p.x = cA.x - xfAq.c * localCenterAx + xfAq.s * localCenterAy;
|
843
|
+
xfA.p.y = cA.y - xfAq.s * localCenterAx - xfAq.c * localCenterAy;
|
844
|
+
xfB.p.x = cB.x - xfBq.c * localCenterBx + xfBq.s * localCenterBy;
|
845
|
+
xfB.p.y = cB.y - xfBq.s * localCenterBx - xfBq.c * localCenterBy;
|
846
|
+
|
847
|
+
final PositionSolverManifold psm = psolver;
|
848
|
+
psm.initialize(pc, xfA, xfB, j);
|
849
|
+
final Vec2 normal = psm.normal;
|
850
|
+
final Vec2 point = psm.point;
|
851
|
+
final float separation = psm.separation;
|
852
|
+
|
853
|
+
float rAx = point.x - cA.x;
|
854
|
+
float rAy = point.y - cA.y;
|
855
|
+
float rBx = point.x - cB.x;
|
856
|
+
float rBy = point.y - cB.y;
|
857
|
+
|
858
|
+
// Track max constraint error.
|
859
|
+
minSeparation = MathUtils.min(minSeparation, separation);
|
860
|
+
|
861
|
+
// Prevent large corrections and allow slop.
|
862
|
+
final float C =
|
863
|
+
MathUtils.clamp(Settings.baumgarte * (separation + Settings.linearSlop),
|
864
|
+
-Settings.maxLinearCorrection, 0.0f);
|
865
|
+
|
866
|
+
// Compute the effective mass.
|
867
|
+
final float rnA = rAx * normal.y - rAy * normal.x;
|
868
|
+
final float rnB = rBx * normal.y - rBy * normal.x;
|
869
|
+
final float K = mA + mB + iA * rnA * rnA + iB * rnB * rnB;
|
870
|
+
|
871
|
+
// Compute normal impulse
|
872
|
+
final float impulse = K > 0.0f ? -C / K : 0.0f;
|
873
|
+
|
874
|
+
float Px = normal.x * impulse;
|
875
|
+
float Py = normal.y * impulse;
|
876
|
+
|
877
|
+
cA.x -= Px * mA;
|
878
|
+
cA.y -= Py * mA;
|
879
|
+
aA -= iA * (rAx * Py - rAy * Px);
|
880
|
+
|
881
|
+
cB.x += Px * mB;
|
882
|
+
cB.y += Py * mB;
|
883
|
+
aB += iB * (rBx * Py - rBy * Px);
|
884
|
+
}
|
885
|
+
|
886
|
+
// m_positions[indexA].c.set(cA);
|
887
|
+
m_positions[indexA].a = aA;
|
888
|
+
|
889
|
+
// m_positions[indexB].c.set(cB);
|
890
|
+
m_positions[indexB].a = aB;
|
891
|
+
}
|
892
|
+
|
893
|
+
// We can't expect minSpeparation >= -linearSlop because we don't
|
894
|
+
// push the separation above -linearSlop.
|
895
|
+
return minSeparation >= -3.0f * Settings.linearSlop;
|
896
|
+
}
|
897
|
+
|
898
|
+
// Sequential position solver for position constraints.
|
899
|
+
public boolean solveTOIPositionConstraints(int toiIndexA, int toiIndexB) {
|
900
|
+
float minSeparation = 0.0f;
|
901
|
+
|
902
|
+
for (int i = 0; i < m_count; ++i) {
|
903
|
+
ContactPositionConstraint pc = m_positionConstraints[i];
|
904
|
+
|
905
|
+
int indexA = pc.indexA;
|
906
|
+
int indexB = pc.indexB;
|
907
|
+
Vec2 localCenterA = pc.localCenterA;
|
908
|
+
Vec2 localCenterB = pc.localCenterB;
|
909
|
+
final float localCenterAx = localCenterA.x;
|
910
|
+
final float localCenterAy = localCenterA.y;
|
911
|
+
final float localCenterBx = localCenterB.x;
|
912
|
+
final float localCenterBy = localCenterB.y;
|
913
|
+
int pointCount = pc.pointCount;
|
914
|
+
|
915
|
+
float mA = 0.0f;
|
916
|
+
float iA = 0.0f;
|
917
|
+
if (indexA == toiIndexA || indexA == toiIndexB) {
|
918
|
+
mA = pc.invMassA;
|
919
|
+
iA = pc.invIA;
|
920
|
+
}
|
921
|
+
|
922
|
+
float mB = 0f;
|
923
|
+
float iB = 0f;
|
924
|
+
if (indexB == toiIndexA || indexB == toiIndexB) {
|
925
|
+
mB = pc.invMassB;
|
926
|
+
iB = pc.invIB;
|
927
|
+
}
|
928
|
+
|
929
|
+
Vec2 cA = m_positions[indexA].c;
|
930
|
+
float aA = m_positions[indexA].a;
|
931
|
+
|
932
|
+
Vec2 cB = m_positions[indexB].c;
|
933
|
+
float aB = m_positions[indexB].a;
|
934
|
+
|
935
|
+
// Solve normal constraints
|
936
|
+
for (int j = 0; j < pointCount; ++j) {
|
937
|
+
final Rot xfAq = xfA.q;
|
938
|
+
final Rot xfBq = xfB.q;
|
939
|
+
xfAq.set(aA);
|
940
|
+
xfBq.set(aB);
|
941
|
+
xfA.p.x = cA.x - xfAq.c * localCenterAx + xfAq.s * localCenterAy;
|
942
|
+
xfA.p.y = cA.y - xfAq.s * localCenterAx - xfAq.c * localCenterAy;
|
943
|
+
xfB.p.x = cB.x - xfBq.c * localCenterBx + xfBq.s * localCenterBy;
|
944
|
+
xfB.p.y = cB.y - xfBq.s * localCenterBx - xfBq.c * localCenterBy;
|
945
|
+
|
946
|
+
final PositionSolverManifold psm = psolver;
|
947
|
+
psm.initialize(pc, xfA, xfB, j);
|
948
|
+
Vec2 normal = psm.normal;
|
949
|
+
|
950
|
+
Vec2 point = psm.point;
|
951
|
+
float separation = psm.separation;
|
952
|
+
|
953
|
+
float rAx = point.x - cA.x;
|
954
|
+
float rAy = point.y - cA.y;
|
955
|
+
float rBx = point.x - cB.x;
|
956
|
+
float rBy = point.y - cB.y;
|
957
|
+
|
958
|
+
// Track max constraint error.
|
959
|
+
minSeparation = MathUtils.min(minSeparation, separation);
|
960
|
+
|
961
|
+
// Prevent large corrections and allow slop.
|
962
|
+
float C =
|
963
|
+
MathUtils.clamp(Settings.toiBaugarte * (separation + Settings.linearSlop),
|
964
|
+
-Settings.maxLinearCorrection, 0.0f);
|
965
|
+
|
966
|
+
// Compute the effective mass.
|
967
|
+
float rnA = rAx * normal.y - rAy * normal.x;
|
968
|
+
float rnB = rBx * normal.y - rBy * normal.x;
|
969
|
+
float K = mA + mB + iA * rnA * rnA + iB * rnB * rnB;
|
970
|
+
|
971
|
+
// Compute normal impulse
|
972
|
+
float impulse = K > 0.0f ? -C / K : 0.0f;
|
973
|
+
|
974
|
+
float Px = normal.x * impulse;
|
975
|
+
float Py = normal.y * impulse;
|
976
|
+
|
977
|
+
cA.x -= Px * mA;
|
978
|
+
cA.y -= Py * mA;
|
979
|
+
aA -= iA * (rAx * Py - rAy * Px);
|
980
|
+
|
981
|
+
cB.x += Px * mB;
|
982
|
+
cB.y += Py * mB;
|
983
|
+
aB += iB * (rBx * Py - rBy * Px);
|
984
|
+
}
|
985
|
+
|
986
|
+
// m_positions[indexA].c.set(cA);
|
987
|
+
m_positions[indexA].a = aA;
|
988
|
+
|
989
|
+
// m_positions[indexB].c.set(cB);
|
990
|
+
m_positions[indexB].a = aB;
|
991
|
+
}
|
992
|
+
|
993
|
+
// We can't expect minSpeparation >= -_linearSlop because we don't
|
994
|
+
// push the separation above -_linearSlop.
|
995
|
+
return minSeparation >= -1.5f * Settings.linearSlop;
|
996
|
+
}
|
997
|
+
|
998
|
+
public static class ContactSolverDef {
|
999
|
+
public TimeStep step;
|
1000
|
+
public Contact[] contacts;
|
1001
|
+
public int count;
|
1002
|
+
public Position[] positions;
|
1003
|
+
public Velocity[] velocities;
|
1004
|
+
}
|
1005
|
+
}
|
1006
|
+
|
1007
|
+
|
1008
|
+
class PositionSolverManifold {
|
1009
|
+
|
1010
|
+
public final Vec2 normal = new Vec2();
|
1011
|
+
public final Vec2 point = new Vec2();
|
1012
|
+
public float separation;
|
1013
|
+
|
1014
|
+
public void initialize(ContactPositionConstraint pc, Transform xfA, Transform xfB, int index) {
|
1015
|
+
assert (pc.pointCount > 0);
|
1016
|
+
|
1017
|
+
final Rot xfAq = xfA.q;
|
1018
|
+
final Rot xfBq = xfB.q;
|
1019
|
+
final Vec2 pcLocalPointsI = pc.localPoints[index];
|
1020
|
+
switch (pc.type) {
|
1021
|
+
case CIRCLES: {
|
1022
|
+
// Transform.mulToOutUnsafe(xfA, pc.localPoint, pointA);
|
1023
|
+
// Transform.mulToOutUnsafe(xfB, pc.localPoints[0], pointB);
|
1024
|
+
// normal.set(pointB).subLocal(pointA);
|
1025
|
+
// normal.normalize();
|
1026
|
+
//
|
1027
|
+
// point.set(pointA).addLocal(pointB).mulLocal(.5f);
|
1028
|
+
// temp.set(pointB).subLocal(pointA);
|
1029
|
+
// separation = Vec2.dot(temp, normal) - pc.radiusA - pc.radiusB;
|
1030
|
+
final Vec2 plocalPoint = pc.localPoint;
|
1031
|
+
final Vec2 pLocalPoints0 = pc.localPoints[0];
|
1032
|
+
final float pointAx = (xfAq.c * plocalPoint.x - xfAq.s * plocalPoint.y) + xfA.p.x;
|
1033
|
+
final float pointAy = (xfAq.s * plocalPoint.x + xfAq.c * plocalPoint.y) + xfA.p.y;
|
1034
|
+
final float pointBx = (xfBq.c * pLocalPoints0.x - xfBq.s * pLocalPoints0.y) + xfB.p.x;
|
1035
|
+
final float pointBy = (xfBq.s * pLocalPoints0.x + xfBq.c * pLocalPoints0.y) + xfB.p.y;
|
1036
|
+
normal.x = pointBx - pointAx;
|
1037
|
+
normal.y = pointBy - pointAy;
|
1038
|
+
normal.normalize();
|
1039
|
+
|
1040
|
+
point.x = (pointAx + pointBx) * .5f;
|
1041
|
+
point.y = (pointAy + pointBy) * .5f;
|
1042
|
+
final float tempx = pointBx - pointAx;
|
1043
|
+
final float tempy = pointBy - pointAy;
|
1044
|
+
separation = tempx * normal.x + tempy * normal.y - pc.radiusA - pc.radiusB;
|
1045
|
+
break;
|
1046
|
+
}
|
1047
|
+
|
1048
|
+
case FACE_A: {
|
1049
|
+
// Rot.mulToOutUnsafe(xfAq, pc.localNormal, normal);
|
1050
|
+
// Transform.mulToOutUnsafe(xfA, pc.localPoint, planePoint);
|
1051
|
+
//
|
1052
|
+
// Transform.mulToOutUnsafe(xfB, pc.localPoints[index], clipPoint);
|
1053
|
+
// temp.set(clipPoint).subLocal(planePoint);
|
1054
|
+
// separation = Vec2.dot(temp, normal) - pc.radiusA - pc.radiusB;
|
1055
|
+
// point.set(clipPoint);
|
1056
|
+
final Vec2 pcLocalNormal = pc.localNormal;
|
1057
|
+
final Vec2 pcLocalPoint = pc.localPoint;
|
1058
|
+
normal.x = xfAq.c * pcLocalNormal.x - xfAq.s * pcLocalNormal.y;
|
1059
|
+
normal.y = xfAq.s * pcLocalNormal.x + xfAq.c * pcLocalNormal.y;
|
1060
|
+
final float planePointx = (xfAq.c * pcLocalPoint.x - xfAq.s * pcLocalPoint.y) + xfA.p.x;
|
1061
|
+
final float planePointy = (xfAq.s * pcLocalPoint.x + xfAq.c * pcLocalPoint.y) + xfA.p.y;
|
1062
|
+
|
1063
|
+
final float clipPointx = (xfBq.c * pcLocalPointsI.x - xfBq.s * pcLocalPointsI.y) + xfB.p.x;
|
1064
|
+
final float clipPointy = (xfBq.s * pcLocalPointsI.x + xfBq.c * pcLocalPointsI.y) + xfB.p.y;
|
1065
|
+
final float tempx = clipPointx - planePointx;
|
1066
|
+
final float tempy = clipPointy - planePointy;
|
1067
|
+
separation = tempx * normal.x + tempy * normal.y - pc.radiusA - pc.radiusB;
|
1068
|
+
point.x = clipPointx;
|
1069
|
+
point.y = clipPointy;
|
1070
|
+
break;
|
1071
|
+
}
|
1072
|
+
|
1073
|
+
case FACE_B: {
|
1074
|
+
// Rot.mulToOutUnsafe(xfBq, pc.localNormal, normal);
|
1075
|
+
// Transform.mulToOutUnsafe(xfB, pc.localPoint, planePoint);
|
1076
|
+
//
|
1077
|
+
// Transform.mulToOutUnsafe(xfA, pcLocalPointsI, clipPoint);
|
1078
|
+
// temp.set(clipPoint).subLocal(planePoint);
|
1079
|
+
// separation = Vec2.dot(temp, normal) - pc.radiusA - pc.radiusB;
|
1080
|
+
// point.set(clipPoint);
|
1081
|
+
//
|
1082
|
+
// // Ensure normal points from A to B
|
1083
|
+
// normal.negateLocal();
|
1084
|
+
final Vec2 pcLocalNormal = pc.localNormal;
|
1085
|
+
final Vec2 pcLocalPoint = pc.localPoint;
|
1086
|
+
normal.x = xfBq.c * pcLocalNormal.x - xfBq.s * pcLocalNormal.y;
|
1087
|
+
normal.y = xfBq.s * pcLocalNormal.x + xfBq.c * pcLocalNormal.y;
|
1088
|
+
final float planePointx = (xfBq.c * pcLocalPoint.x - xfBq.s * pcLocalPoint.y) + xfB.p.x;
|
1089
|
+
final float planePointy = (xfBq.s * pcLocalPoint.x + xfBq.c * pcLocalPoint.y) + xfB.p.y;
|
1090
|
+
|
1091
|
+
final float clipPointx = (xfAq.c * pcLocalPointsI.x - xfAq.s * pcLocalPointsI.y) + xfA.p.x;
|
1092
|
+
final float clipPointy = (xfAq.s * pcLocalPointsI.x + xfAq.c * pcLocalPointsI.y) + xfA.p.y;
|
1093
|
+
final float tempx = clipPointx - planePointx;
|
1094
|
+
final float tempy = clipPointy - planePointy;
|
1095
|
+
separation = tempx * normal.x + tempy * normal.y - pc.radiusA - pc.radiusB;
|
1096
|
+
point.x = clipPointx;
|
1097
|
+
point.y = clipPointy;
|
1098
|
+
normal.x *= -1;
|
1099
|
+
normal.y *= -1;
|
1100
|
+
}
|
1101
|
+
break;
|
1102
|
+
}
|
1103
|
+
}
|
1104
|
+
}
|