use of com.almasb.fxgl.physics.box2d.common.Transform in project FXGL by AlmasB.
the class Contact method update.
public void update(ContactListener listener) {
oldManifold.set(m_manifold);
// Re-enable this contact.
m_flags |= ENABLED_FLAG;
boolean wasTouching = (m_flags & TOUCHING_FLAG) == TOUCHING_FLAG;
boolean sensorA = m_fixtureA.isSensor();
boolean sensorB = m_fixtureB.isSensor();
boolean sensor = sensorA || sensorB;
Body bodyA = m_fixtureA.getBody();
Body bodyB = m_fixtureB.getBody();
Transform xfA = bodyA.getTransform();
Transform xfB = bodyB.getTransform();
boolean touching;
if (sensor) {
Shape shapeA = m_fixtureA.getShape();
Shape shapeB = m_fixtureB.getShape();
touching = GenericCollision.testOverlap(pool, shapeA, m_indexA, shapeB, m_indexB, xfA, xfB);
// Sensors don't generate manifolds.
m_manifold.pointCount = 0;
} else {
evaluate(m_manifold, xfA, xfB);
touching = m_manifold.pointCount > 0;
// stored impulses to warm start the solver.
for (int i = 0; i < m_manifold.pointCount; ++i) {
ManifoldPoint mp2 = m_manifold.points[i];
mp2.normalImpulse = 0.0f;
mp2.tangentImpulse = 0.0f;
ContactID id2 = mp2.id;
for (int j = 0; j < oldManifold.pointCount; ++j) {
ManifoldPoint mp1 = oldManifold.points[j];
if (mp1.id.isEqual(id2)) {
mp2.normalImpulse = mp1.normalImpulse;
mp2.tangentImpulse = mp1.tangentImpulse;
break;
}
}
}
if (touching != wasTouching) {
bodyA.setAwake(true);
bodyB.setAwake(true);
}
}
if (touching) {
m_flags |= TOUCHING_FLAG;
} else {
m_flags &= ~TOUCHING_FLAG;
}
if (listener == null) {
return;
}
if (!wasTouching && touching) {
listener.beginContact(this);
}
if (wasTouching && !touching) {
listener.endContact(this);
}
if (!sensor && touching) {
listener.preSolve(this, oldManifold);
}
}
use of com.almasb.fxgl.physics.box2d.common.Transform in project FXGL by AlmasB.
the class Distance method distance.
/**
* Compute the closest points between two shapes. Supports any combination of: CircleShape and
* PolygonShape. The simplex cache is input/output. On the first call set SimplexCache.count to
* zero.
*/
@SuppressWarnings("PMD.EmptyIfStmt")
public final void distance(final DistanceOutput output, final SimplexCache cache, final DistanceInput input) {
final DistanceProxy proxyA = input.proxyA;
final DistanceProxy proxyB = input.proxyB;
Transform transformA = input.transformA;
Transform transformB = input.transformB;
// Initialize the simplex.
simplex.readCache(cache, proxyA, transformA, proxyB, transformB);
// Get simplex vertices as an array.
SimplexVertex[] vertices = simplex.vertices;
// These store the vertices of the last simplex so that we
// can check for duplicates and prevent cycling.
// (pooled above)
int saveCount = 0;
simplex.getClosestPoint(closestPoint);
float distanceSqr1 = closestPoint.lengthSquared();
float distanceSqr2 = distanceSqr1;
// Main iteration loop
int iter = 0;
while (iter < MAX_ITERS) {
// Copy simplex so we can identify duplicates.
saveCount = simplex.m_count;
for (int i = 0; i < saveCount; i++) {
saveA[i] = vertices[i].indexA;
saveB[i] = vertices[i].indexB;
}
switch(simplex.m_count) {
case 1:
break;
case 2:
simplex.solve2();
break;
case 3:
simplex.solve3();
break;
default:
assert false;
}
// If we have 3 points, then the origin is in the corresponding triangle.
if (simplex.m_count == 3) {
break;
}
// Compute closest point.
simplex.getClosestPoint(closestPoint);
distanceSqr2 = closestPoint.lengthSquared();
// ensure progress
if (distanceSqr2 >= distanceSqr1) {
// break;
}
distanceSqr1 = distanceSqr2;
// get search direction;
simplex.getSearchDirection(d);
// Ensure the search direction is numerically fit.
if (d.lengthSquared() < JBoxSettings.EPSILON * JBoxSettings.EPSILON) {
// to determine if the origin is contained in the CSO or very close to it.
break;
}
/*
* SimplexVertex* vertex = vertices + simplex.m_count; vertex.indexA =
* proxyA.GetSupport(MulT(transformA.R, -d)); vertex.wA = Mul(transformA,
* proxyA.GetVertex(vertex.indexA)); Vec2 wBLocal; vertex.indexB =
* proxyB.GetSupport(MulT(transformB.R, d)); vertex.wB = Mul(transformB,
* proxyB.GetVertex(vertex.indexB)); vertex.w = vertex.wB - vertex.wA;
*/
// Compute a tentative new simplex vertex using support points.
SimplexVertex vertex = vertices[simplex.m_count];
Rotation.mulTransUnsafe(transformA.q, d.negateLocal(), temp);
vertex.indexA = proxyA.getSupport(temp);
Transform.mulToOutUnsafe(transformA, proxyA.getVertex(vertex.indexA), vertex.wA);
// Vec2 wBLocal;
Rotation.mulTransUnsafe(transformB.q, d.negateLocal(), temp);
vertex.indexB = proxyB.getSupport(temp);
Transform.mulToOutUnsafe(transformB, proxyB.getVertex(vertex.indexB), vertex.wB);
vertex.w.set(vertex.wB).subLocal(vertex.wA);
// Iteration count is equated to the number of support point calls.
++iter;
// Check for duplicate support points. This is the main termination criteria.
boolean duplicate = false;
for (int i = 0; i < saveCount; ++i) {
if (vertex.indexA == saveA[i] && vertex.indexB == saveB[i]) {
duplicate = true;
break;
}
}
// If we found a duplicate support point we must exit to avoid cycling.
if (duplicate) {
break;
}
// New vertex is ok and needed.
++simplex.m_count;
}
// Prepare output.
simplex.getWitnessPoints(output.pointA, output.pointB);
output.distance = output.pointA.distanceF(output.pointB);
output.iterations = iter;
// Cache the simplex.
simplex.writeCache(cache);
// Apply radii if requested.
if (input.useRadii) {
float rA = proxyA.m_radius;
float rB = proxyB.m_radius;
if (output.distance > rA + rB && output.distance > JBoxSettings.EPSILON) {
// Shapes are still no overlapped.
// Move the witness points to the outer surface.
output.distance -= rA + rB;
normal.set(output.pointB).subLocal(output.pointA);
normal.getLengthAndNormalize();
temp.set(normal).mulLocal(rA);
output.pointA.addLocal(temp);
temp.set(normal).mulLocal(rB);
output.pointB.subLocal(temp);
} else {
// Shapes are overlapped when radii are considered.
// Move the witness points to the middle.
// Vec2 p = 0.5f * (output.pointA + output.pointB);
output.pointA.addLocal(output.pointB).mulLocal(.5f);
output.pointB.set(output.pointA);
output.distance = 0.0f;
}
}
}
use of com.almasb.fxgl.physics.box2d.common.Transform in project FXGL by AlmasB.
the class ParticleSystem method solveRigid.
private void solveRigid(final TimeStep step) {
for (ParticleGroup group = m_groupList; group != null; group = group.getNext()) {
if ((group.m_groupFlags & ParticleGroupType.b2_rigidParticleGroup) != 0) {
group.updateStatistics();
Vec2 temp = tempVec;
Vec2 cross = tempVec2;
Rotation rotation = tempRotation;
rotation.set(step.dt * group.m_angularVelocity);
Rotation.mulToOutUnsafe(rotation, group.m_center, cross);
temp.set(group.m_linearVelocity).mulLocal(step.dt).addLocal(group.m_center).subLocal(cross);
tempXf.p.set(temp);
tempXf.q.set(rotation);
Transform.mulToOut(tempXf, group.m_transform, group.m_transform);
final Transform velocityTransform = tempXf2;
velocityTransform.p.x = step.inv_dt * tempXf.p.x;
velocityTransform.p.y = step.inv_dt * tempXf.p.y;
velocityTransform.q.s = step.inv_dt * tempXf.q.s;
velocityTransform.q.c = step.inv_dt * (tempXf.q.c - 1);
for (int i = group.m_firstIndex; i < group.m_lastIndex; i++) {
Transform.mulToOutUnsafe(velocityTransform, m_positionBuffer.data[i], m_velocityBuffer.data[i]);
}
}
}
}
use of com.almasb.fxgl.physics.box2d.common.Transform in project FXGL by AlmasB.
the class ParticleSystem method createParticleGroup.
@SuppressWarnings("PMD.DontUseFloatTypeForLoopIndices")
public ParticleGroup createParticleGroup(ParticleGroupDef groupDef) {
float stride = getParticleStride();
final Transform identity = tempTransform;
identity.setIdentity();
Transform transform = tempTransform2;
transform.setIdentity();
int firstIndex = m_count;
if (groupDef.getShape() != null) {
final ParticleDef particleDef = tempParticleDef;
particleDef.setTypeFlags(groupDef.getTypeFlags());
particleDef.color = groupDef.getColor();
particleDef.setUserData(groupDef.getUserData());
Shape shape = groupDef.getShape();
transform.set(groupDef.getPosition(), groupDef.getAngle());
AABB aabb = temp;
int childCount = shape.getChildCount();
for (int childIndex = 0; childIndex < childCount; childIndex++) {
if (childIndex == 0) {
shape.computeAABB(aabb, identity, childIndex);
} else {
AABB childAABB = temp2;
shape.computeAABB(childAABB, identity, childIndex);
aabb.combine(childAABB);
}
}
final float upperBoundY = aabb.upperBound.y;
final float upperBoundX = aabb.upperBound.x;
for (float y = FXGLMath.floor(aabb.lowerBound.y / stride) * stride; y < upperBoundY; y += stride) {
for (float x = FXGLMath.floor(aabb.lowerBound.x / stride) * stride; x < upperBoundX; x += stride) {
Vec2 p = tempVec;
p.x = x;
p.y = y;
if (shape.containsPoint(identity, p)) {
Transform.mulToOut(transform, p, p);
particleDef.position.x = p.x;
particleDef.position.y = p.y;
p.subLocal(groupDef.getPosition());
Vec2.crossToOutUnsafe(groupDef.getAngularVelocity(), p, particleDef.velocity);
particleDef.velocity.addLocal(groupDef.getLinearVelocity());
createParticle(particleDef);
}
}
}
}
int lastIndex = m_count;
ParticleGroup group = new ParticleGroup();
group.m_system = this;
group.m_firstIndex = firstIndex;
group.m_lastIndex = lastIndex;
group.m_groupFlags = groupDef.getGroupFlags();
group.m_strength = groupDef.getStrength();
group.m_userData = groupDef.getUserData();
group.m_transform.set(transform);
group.m_destroyAutomatically = groupDef.isDestroyAutomatically();
group.m_prev = null;
group.m_next = m_groupList;
if (m_groupList != null) {
m_groupList.m_prev = group;
}
m_groupList = group;
++m_groupCount;
for (int i = firstIndex; i < lastIndex; i++) {
m_groupBuffer[i] = group;
}
updateContacts(true);
if ((groupDef.getTypeFlags() & k_pairFlags) != 0) {
for (int k = 0; k < m_contactCount; k++) {
ParticleContact contact = m_contactBuffer[k];
int a = contact.indexA;
int b = contact.indexB;
if (a > b) {
int temp = a;
a = b;
b = temp;
}
if (firstIndex <= a && b < lastIndex) {
if (m_pairCount >= m_pairCapacity) {
int oldCapacity = m_pairCapacity;
int newCapacity = m_pairCount != 0 ? 2 * m_pairCount : JBoxSettings.minParticleBufferCapacity;
m_pairBuffer = reallocateBuffer(Pair.class, m_pairBuffer, oldCapacity, newCapacity);
m_pairCapacity = newCapacity;
}
Pair pair = m_pairBuffer[m_pairCount];
pair.indexA = a;
pair.indexB = b;
pair.flags = contact.flags;
pair.strength = groupDef.getStrength();
pair.distance = m_positionBuffer.data[a].distanceF(m_positionBuffer.data[b]);
m_pairCount++;
}
}
}
if ((groupDef.getTypeFlags() & k_triadFlags) != 0) {
VoronoiDiagram diagram = new VoronoiDiagram(lastIndex - firstIndex);
for (int i = firstIndex; i < lastIndex; i++) {
diagram.addGenerator(m_positionBuffer.data[i], i);
}
diagram.generate(stride / 2);
createParticleGroupCallback.system = this;
createParticleGroupCallback.def = groupDef;
createParticleGroupCallback.firstIndex = firstIndex;
diagram.getNodes(createParticleGroupCallback);
}
if ((groupDef.getGroupFlags() & ParticleGroupType.b2_solidParticleGroup) != 0) {
computeDepthForGroup(group);
}
return group;
}
use of com.almasb.fxgl.physics.box2d.common.Transform in project FXGL by AlmasB.
the class Body method synchronizeFixtures.
void synchronizeFixtures() {
final Transform xf1 = pxf;
// xf1.position = m_sweep.c0 - Mul(xf1.R, m_sweep.localCenter);
// xf1.q.set(m_sweep.a0);
// Rot.mulToOutUnsafe(xf1.q, m_sweep.localCenter, xf1.p);
// xf1.p.mulLocal(-1).addLocal(m_sweep.c0);
// inlined:
xf1.q.set(m_sweep.a0);
xf1.p.x = m_sweep.c0.x - xf1.q.c * m_sweep.localCenter.x + xf1.q.s * m_sweep.localCenter.y;
xf1.p.y = m_sweep.c0.y - xf1.q.s * m_sweep.localCenter.x - xf1.q.c * m_sweep.localCenter.y;
for (Fixture f : fixtures) {
f.synchronize(world.getContactManager().broadPhase, xf1, m_xf);
}
}
Aggregations