
com.almasb.fxgl.physics.box2d.dynamics.Body Maven / Gradle / Ivy
/*
* FXGL - JavaFX Game Library. The MIT License (MIT).
* Copyright (c) AlmasB ([email protected]).
* See LICENSE for details.
*/
package com.almasb.fxgl.physics.box2d.dynamics;
import com.almasb.fxgl.core.math.Vec2;
import com.almasb.fxgl.entity.Entity;
import com.almasb.fxgl.physics.box2d.collision.broadphase.BroadPhase;
import com.almasb.fxgl.physics.box2d.collision.shapes.MassData;
import com.almasb.fxgl.physics.box2d.collision.shapes.Shape;
import com.almasb.fxgl.physics.box2d.common.Rotation;
import com.almasb.fxgl.physics.box2d.common.Sweep;
import com.almasb.fxgl.physics.box2d.common.Transform;
import com.almasb.fxgl.physics.box2d.dynamics.contacts.Contact;
import com.almasb.fxgl.physics.box2d.dynamics.contacts.ContactEdge;
import com.almasb.fxgl.physics.box2d.dynamics.joints.JointEdge;
import java.util.ArrayList;
import java.util.List;
/**
* A rigid body.
* These are created via World.createBody.
*
* @author Daniel Murphy
*/
public final class Body {
static final int e_islandFlag = 0x0001;
private static final int e_awakeFlag = 0x0002;
private static final int e_autoSleepFlag = 0x0004;
private static final int e_bulletFlag = 0x0008;
private static final int e_fixedRotationFlag = 0x0010;
private static final int e_activeFlag = 0x0020;
private final World world;
private BodyType type;
private List fixtures = new ArrayList<>();
public JointEdge m_jointList = null;
public ContactEdge m_contactList = null;
public int m_flags = 0;
public int m_islandIndex;
/**
* The body origin transform.
*/
public final Transform m_xf = new Transform();
/**
* The previous transform for particle simulation
*/
public final Transform m_xf0 = new Transform();
/**
* The swept motion for CCD
*/
public final Sweep m_sweep = new Sweep();
private final Vec2 linearVelocity = new Vec2();
private float angularVelocity;
private final Vec2 m_force = new Vec2();
private float m_torque = 0;
private float m_mass;
public float m_invMass;
// Rotational inertia about the center of mass.
private float m_I = 0;
public float m_invI = 0;
private float linearDamping;
private float angularDamping;
private float gravityScale;
private float sleepTime = 0;
private final BroadPhase broadPhase;
private Object userData;
private Entity entity;
Body(BodyDef bd, World world) {
checkValid(bd);
this.world = world;
broadPhase = world.getContactManager().broadPhase;
userData = bd.getUserData();
if (bd.isBullet()) {
m_flags |= e_bulletFlag;
}
if (bd.isFixedRotation()) {
m_flags |= e_fixedRotationFlag;
}
if (bd.isAllowSleep()) {
m_flags |= e_autoSleepFlag;
}
if (bd.isAwake()) {
m_flags |= e_awakeFlag;
}
if (bd.isActive()) {
m_flags |= e_activeFlag;
}
m_xf.p.set(bd.getPosition());
m_xf.q.set(bd.getAngle());
m_sweep.localCenter.setZero();
m_sweep.c0.set(m_xf.p);
m_sweep.c.set(m_xf.p);
m_sweep.a0 = bd.getAngle();
m_sweep.a = bd.getAngle();
m_sweep.alpha0 = 0.0f;
linearVelocity.set(bd.getLinearVelocity());
angularVelocity = bd.getAngularVelocity();
linearDamping = bd.getLinearDamping();
angularDamping = bd.getAngularDamping();
gravityScale = bd.getGravityScale();
type = bd.getType();
if (type == BodyType.DYNAMIC) {
m_mass = 1f;
m_invMass = 1f;
} else {
m_mass = 0f;
m_invMass = 0f;
}
}
private void checkValid(BodyDef def) {
if (def.getGravityScale() < 0)
throw new IllegalArgumentException("Gravity scale is invalid");
if (def.getAngularDamping() < 0)
throw new IllegalArgumentException("Angular damping is invalid");
if (def.getLinearDamping() < 0)
throw new IllegalArgumentException("Linear damping is invalid");
}
public float getTorque() {
return m_torque;
}
public void setTorque(float torque) {
m_torque = torque;
}
/**
* Set entity to which this body belongs.
*/
public void setEntity(Entity entity) {
this.entity = entity;
}
/**
* @return entity to which this body belongs
*/
public Entity getEntity() {
return entity;
}
/**
* @return reference to the underlying list of fixtures attached to this body
*/
public List getFixtures() {
return fixtures;
}
/**
* Creates a fixture and attach it to this body.
* Use this function if you need to set some fixture parameters, like friction.
* Otherwise you can create the fixture directly from a shape.
* If the density is non-zero, this function automatically updates the mass of the body.
* Contacts are not created until the next time step.
* Note: This function is locked during callbacks.
*
* @param def the fixture definition
*/
public Fixture createFixture(FixtureDef def) {
world.assertNotLocked();
Fixture fixture = new Fixture(this, def);
if ((m_flags & e_activeFlag) == e_activeFlag) {
fixture.createProxies(broadPhase, m_xf);
}
fixtures.add(fixture);
// Adjust mass properties if needed.
if (fixture.getDensity() > 0) {
resetMassData();
}
// Let the world know we have a new fixture. This will cause new contacts
// to be created at the beginning of the next time step.
world.notifyNewFixture();
return fixture;
}
private final FixtureDef fixDef = new FixtureDef();
/**
* Creates a fixture from a shape and attach it to this body.
* This is a convenience function.
* Use FixtureDef if you need to set parameters like friction, restitution, user data, or filtering.
* If the density is non-zero, this function automatically updates the mass of the body.
* Note: this function is locked during callbacks.
*
*
* @param shape the shape to be cloned.
* @param density the shape density (set to zero for static bodies).
*/
public Fixture createFixture(Shape shape, float density) {
fixDef.setShape(shape);
fixDef.setDensity(density);
return createFixture(fixDef);
}
/**
* Destroy a fixture.
* This removes the fixture from the broad-phase and destroys all contacts
* associated with this fixture.
* This will automatically adjust the mass of the body if the body
* is dynamic and the fixture has positive density.
* All fixtures attached to a body are implicitly destroyed when the body is destroyed.
* Note: this function is locked during callbacks.
*
* @param fixture the fixture to be removed
*/
public void destroyFixture(Fixture fixture) {
world.assertNotLocked();
fixtures.remove(fixture);
// Destroy any contacts associated with the fixture.
ContactEdge edge = m_contactList;
while (edge != null) {
Contact c = edge.contact;
edge = edge.next;
if (fixture == c.getFixtureA() || fixture == c.getFixtureB()) {
// This destroys the contact and removes it from this body's contact list.
world.getContactManager().destroy(c);
}
}
if ((m_flags & e_activeFlag) == e_activeFlag) {
fixture.destroyProxies(broadPhase);
}
fixture.destroy();
resetMassData();
}
/**
* Set the position of the body's origin and rotation.
* This breaks any contacts and wakes the other bodies.
* Manipulating a body's transform may cause non-physical behavior.
* Note: contacts are updated on the next call to World.step().
*
* @param position the world position of the body's local origin
* @param angle the world rotation in radians
*/
public void setTransform(Vec2 position, float angle) {
world.assertNotLocked();
m_xf.q.set(angle);
m_xf.p.set(position);
// m_sweep.c0 = m_sweep.c = Mul(m_xf, m_sweep.localCenter);
Transform.mulToOutUnsafe(m_xf, m_sweep.localCenter, m_sweep.c);
m_sweep.a = angle;
m_sweep.c0.set(m_sweep.c);
m_sweep.a0 = m_sweep.a;
for (Fixture f : fixtures) {
f.synchronize(broadPhase, m_xf, m_xf);
}
}
/**
* @return the world transform of the body's origin.
*/
public Transform getTransform() {
return m_xf;
}
/**
* Get the world body origin position. Do not modify.
*
* @return the world position of the body's origin.
*/
public Vec2 getPosition() {
return m_xf.p;
}
/**
* Get the angle in radians.
*
* @return the current world rotation angle in radians.
*/
public float getAngle() {
return m_sweep.a;
}
/**
* Get the world position of the center of mass. Do not modify.
*/
public Vec2 getWorldCenter() {
return m_sweep.c;
}
/**
* Get the local position of the center of mass. Do not modify.
*/
public Vec2 getLocalCenter() {
return m_sweep.localCenter;
}
/**
* Set the linear velocity of the center of mass.
*
* @param v the new linear velocity of the center of mass.
*/
public void setLinearVelocity(Vec2 v) {
if (type == BodyType.STATIC) {
return;
}
if (Vec2.dot(v, v) > 0) {
setAwake(true);
}
linearVelocity.set(v);
}
void setLinearVelocityDirectly(float vx, float vy) {
linearVelocity.set(vx, vy);
}
/**
* Get the linear velocity of the center of mass. Do not modify, instead use
* {@link #setLinearVelocity(Vec2)}.
*
* @return the linear velocity of the center of mass.
*/
public Vec2 getLinearVelocity() {
return linearVelocity;
}
/**
* Set the angular velocity.
*
* @param w the new angular velocity in radians/second.
*/
public void setAngularVelocity(float w) {
if (type == BodyType.STATIC) {
return;
}
if (w * w > 0f) {
setAwake(true);
}
angularVelocity = w;
}
void setAngularVelocityDirectly(float angularVelocity) {
this.angularVelocity = angularVelocity;
}
/**
* Get the angular velocity.
*
* @return the angular velocity in radians/second.
*/
public float getAngularVelocity() {
return angularVelocity;
}
/**
* @return the gravity scale of the body
*/
public float getGravityScale() {
return gravityScale;
}
/**
* Set the gravity scale of the body.
*
* @param gravityScale gravity scale
*/
public void setGravityScale(float gravityScale) {
this.gravityScale = gravityScale;
}
/**
* Apply a force at a world point.
* If the force is not applied at the center of mass, it will generate a torque and affect the angular velocity.
* This wakes up the body.
*
* @param force the world force vector, usually in Newtons (N)
* @param point the world position of the point of application
*/
public void applyForce(Vec2 force, Vec2 point) {
applyForceToCenter(force);
m_torque += (point.x - m_sweep.c.x) * force.y - (point.y - m_sweep.c.y) * force.x;
}
/**
* Apply a force to the center of mass.
* This wakes up the body.
*
* @param force the world force vector, usually in Newtons (N)
*/
public void applyForceToCenter(Vec2 force) {
if (type != BodyType.DYNAMIC) {
return;
}
if (!isAwake()) {
setAwake(true);
}
m_force.addLocal(force);
}
/**
* Apply a torque.
* This affects the angular velocity without affecting the linear velocity of the center of mass.
* This wakes up the body.
*
* @param torque about the z-axis (out of the screen), usually in N-m
*/
public void applyTorque(float torque) {
if (type != BodyType.DYNAMIC) {
return;
}
if (!isAwake()) {
setAwake(true);
}
m_torque += torque;
}
/**
* Apply an impulse at a point.
* This immediately modifies the velocity.
* It also modifies the angular velocity if the point of application is not at the center of mass.
* This wakes up the body if 'wake' is set to true.
* If the body is sleeping and 'wake' is false, then there is no effect.
*
* @param impulse the world impulse vector, usually in N-seconds or kg-m/s
* @param point the world position of the point of application
* @param wake also wake up the body
*/
public void applyLinearImpulse(Vec2 impulse, Vec2 point, boolean wake) {
if (type != BodyType.DYNAMIC) {
return;
}
if (!isAwake()) {
if (wake) {
setAwake(true);
} else {
return;
}
}
linearVelocity.x += impulse.x * m_invMass;
linearVelocity.y += impulse.y * m_invMass;
angularVelocity += m_invI * ((point.x - m_sweep.c.x) * impulse.y - (point.y - m_sweep.c.y) * impulse.x);
}
/**
* Apply an angular impulse.
*
* @param impulse the angular impulse in units of kg*m*m/s
*/
public void applyAngularImpulse(float impulse) {
if (type != BodyType.DYNAMIC) {
return;
}
if (!isAwake()) {
setAwake(true);
}
angularVelocity += m_invI * impulse;
}
/**
* @return total mass of the body, usually in kilograms (kg)
*/
public float getMass() {
return m_mass;
}
/**
* @return central rotational inertia of the body, usually in kg-m^2
*/
public float getInertia() {
return m_I + m_mass * Vec2.dot(m_sweep.localCenter, m_sweep.localCenter);
}
/**
* Get the mass data of the body.
* The rotational inertia is relative to the center of mass.
* Fills in a struct containing the mass, inertia and center of the body.
*/
public void getMassData(MassData data) {
data.mass = m_mass;
data.I = getInertia();
data.center.set(m_sweep.localCenter);
}
/**
* Set the mass properties to override the mass properties of the fixtures.
* Note that this changes the center of mass position.
* Note that creating or destroying fixtures can also alter the mass.
* This function has no effect if the body isn't dynamic.
*
* @param massData the mass properties.
*/
public void setMassData(MassData massData) {
world.assertNotLocked();
if (type != BodyType.DYNAMIC) {
return;
}
m_I = 0;
m_invI = 0;
m_mass = massData.mass;
if (m_mass <= 0) {
m_mass = 1;
}
m_invMass = 1.0f / m_mass;
if (massData.I > 0 && (m_flags & e_fixedRotationFlag) == 0) {
m_I = massData.I - m_mass * Vec2.dot(massData.center, massData.center);
assert m_I > 0;
m_invI = 1.0f / m_I;
}
final Vec2 oldCenter = world.getPool().popVec2();
// Move center of mass.
oldCenter.set(m_sweep.c);
m_sweep.localCenter.set(massData.center);
// m_sweep.c0 = m_sweep.c = Mul(m_xf, m_sweep.localCenter);
Transform.mulToOutUnsafe(m_xf, m_sweep.localCenter, m_sweep.c0);
m_sweep.c.set(m_sweep.c0);
// Update center of mass velocity.
// m_linearVelocity += Cross(m_angularVelocity, m_sweep.c - oldCenter);
final Vec2 temp = world.getPool().popVec2();
temp.set(m_sweep.c).subLocal(oldCenter);
// crossToOut(m_angularVelocity, temp, temp);
final float tempY = angularVelocity * temp.x;
temp.x = -angularVelocity * temp.y;
temp.y = tempY;
linearVelocity.addLocal(temp);
world.getPool().pushVec2(2);
}
private final MassData pmd = new MassData();
/**
* This resets the mass properties to the sum of the mass properties of the fixtures.
* This normally does not need to be called unless you called setMassData to override the mass and you
* later want to reset the mass.
*/
public void resetMassData() {
// Compute mass data from shapes. Each shape has its own density.
m_mass = 0;
m_invMass = 0;
m_I = 0;
m_invI = 0;
m_sweep.localCenter.setZero();
// Static and kinematic bodies have zero mass.
if (type == BodyType.STATIC || type == BodyType.KINEMATIC) {
m_sweep.c0.set(m_xf.p);
m_sweep.c.set(m_xf.p);
m_sweep.a0 = m_sweep.a;
return;
}
// Accumulate mass over all fixtures.
final Vec2 localCenter = world.getPool().popVec2();
localCenter.setZero();
final Vec2 temp = world.getPool().popVec2();
final MassData massData = pmd;
for (Fixture f : fixtures) {
if (f.getDensity() == 0.0f) {
continue;
}
f.getMassData(massData);
m_mass += massData.mass;
// center += massData.mass * massData.center;
temp.set(massData.center).mulLocal(massData.mass);
localCenter.addLocal(temp);
m_I += massData.I;
}
// Compute center of mass.
if (m_mass > 0.0f) {
m_invMass = 1.0f / m_mass;
localCenter.mulLocal(m_invMass);
} else {
// Force all dynamic bodies to have a positive mass.
m_mass = 1.0f;
m_invMass = 1.0f;
}
if (m_I > 0.0f && (m_flags & e_fixedRotationFlag) == 0) {
// Center the inertia about the center of mass.
m_I -= m_mass * Vec2.dot(localCenter, localCenter);
assert m_I > 0.0f;
m_invI = 1.0f / m_I;
} else {
m_I = 0.0f;
m_invI = 0.0f;
}
Vec2 oldCenter = world.getPool().popVec2();
// Move center of mass.
oldCenter.set(m_sweep.c);
m_sweep.localCenter.set(localCenter);
// m_sweep.c0 = m_sweep.c = Mul(m_xf, m_sweep.localCenter);
Transform.mulToOutUnsafe(m_xf, m_sweep.localCenter, m_sweep.c0);
m_sweep.c.set(m_sweep.c0);
// Update center of mass velocity.
// m_linearVelocity += Cross(m_angularVelocity, m_sweep.c - oldCenter);
temp.set(m_sweep.c).subLocal(oldCenter);
final Vec2 temp2 = oldCenter;
Vec2.crossToOutUnsafe(angularVelocity, temp, temp2);
linearVelocity.addLocal(temp2);
world.getPool().pushVec2(3);
}
/**
* Get the world coordinates of a point given the local coordinates.
*
* @param localPoint a point on the body measured relative the the body's origin.
* @return the same point expressed in world coordinates.
*/
public Vec2 getWorldPoint(Vec2 localPoint) {
Vec2 v = new Vec2();
getWorldPointToOut(localPoint, v);
return v;
}
public void getWorldPointToOut(Vec2 localPoint, Vec2 out) {
Transform.mulToOut(m_xf, localPoint, out);
}
/**
* Get the world coordinates of a vector given the local coordinates.
*
* @param localVector a vector fixed in the body.
* @return the same vector expressed in world coordinates.
*/
public Vec2 getWorldVector(Vec2 localVector) {
Vec2 out = new Vec2();
getWorldVectorToOut(localVector, out);
return out;
}
public void getWorldVectorToOut(Vec2 localVector, Vec2 out) {
Rotation.mulToOut(m_xf.q, localVector, out);
}
public void getWorldVectorToOutUnsafe(Vec2 localVector, Vec2 out) {
Rotation.mulToOutUnsafe(m_xf.q, localVector, out);
}
/**
* Gets a local point relative to the body's origin given a world point.
*
* @param worldPoint point in world coordinates.
* @return the corresponding local point relative to the body's origin.
*/
public Vec2 getLocalPoint(Vec2 worldPoint) {
Vec2 out = new Vec2();
getLocalPointToOut(worldPoint, out);
return out;
}
public void getLocalPointToOut(Vec2 worldPoint, Vec2 out) {
Transform.mulTransToOut(m_xf, worldPoint, out);
}
/**
* Gets a local vector given a world vector.
*
* @param worldVector vector in world coordinates.
* @return the corresponding local vector.
*/
public Vec2 getLocalVector(Vec2 worldVector) {
Vec2 out = new Vec2();
getLocalVectorToOut(worldVector, out);
return out;
}
public void getLocalVectorToOut(Vec2 worldVector, Vec2 out) {
Rotation.mulTrans(m_xf.q, worldVector, out);
}
public void getLocalVectorToOutUnsafe(Vec2 worldVector, Vec2 out) {
Rotation.mulTransUnsafe(m_xf.q, worldVector, out);
}
/**
* Get the world linear velocity of a world point attached to this body.
*
* @param worldPoint point in world coordinates.
* @return the world velocity of a point.
*/
public Vec2 getLinearVelocityFromWorldPoint(Vec2 worldPoint) {
Vec2 out = new Vec2();
getLinearVelocityFromWorldPointToOut(worldPoint, out);
return out;
}
public void getLinearVelocityFromWorldPointToOut(Vec2 worldPoint, Vec2 out) {
final float tempX = worldPoint.x - m_sweep.c.x;
final float tempY = worldPoint.y - m_sweep.c.y;
out.x = -angularVelocity * tempY + linearVelocity.x;
out.y = angularVelocity * tempX + linearVelocity.y;
}
/**
* Get the world velocity of a local point.
*
* @param localPoint point in local coordinates.
* @return the world velocity of a point.
*/
public Vec2 getLinearVelocityFromLocalPoint(Vec2 localPoint) {
Vec2 out = new Vec2();
getLinearVelocityFromLocalPointToOut(localPoint, out);
return out;
}
public void getLinearVelocityFromLocalPointToOut(Vec2 localPoint, Vec2 out) {
getWorldPointToOut(localPoint, out);
getLinearVelocityFromWorldPointToOut(out, out);
}
/**
* Get the linear damping of the body.
**/
public float getLinearDamping() {
return linearDamping;
}
/**
* Set the linear damping of the body.
**/
public void setLinearDamping(float linearDamping) {
this.linearDamping = linearDamping;
}
/**
* Get the angular damping of the body.
**/
public float getAngularDamping() {
return angularDamping;
}
/**
* Set the angular damping of the body.
**/
public void setAngularDamping(float angularDamping) {
this.angularDamping = angularDamping;
}
public float getSleepTime() {
return sleepTime;
}
void setSleepTime(float sleepTime) {
this.sleepTime = sleepTime;
}
/**
* @return body type
*/
public BodyType getType() {
return type;
}
/**
* Set the type of this body.
* This may alter the mass and velocity.
*
* @param type body type
*/
public void setType(BodyType type) {
world.assertNotLocked();
if (this.type == type) {
return;
}
this.type = type;
resetMassData();
if (this.type == BodyType.STATIC) {
linearVelocity.setZero();
angularVelocity = 0.0f;
m_sweep.a0 = m_sweep.a;
m_sweep.c0.set(m_sweep.c);
synchronizeFixtures();
}
setAwake(true);
clearForces();
destroyAttachedContacts();
// Touch the proxies so that new contacts will be created (when appropriate)
for (Fixture f : fixtures) {
int proxyCount = f.getProxyCount();
for (int i = 0; i < proxyCount; ++i) {
broadPhase.touchProxy(f.getProxyId(i));
}
}
}
void clearForces() {
m_force.setZero();
m_torque = 0.0f;
}
Vec2 getForce() {
return m_force;
}
void destroy() {
destroyAttachedJoints();
destroyAttachedContacts();
destroyFixtures();
}
private void destroyAttachedJoints() {
JointEdge je = this.m_jointList;
while (je != null) {
JointEdge je0 = je;
je = je.next;
if (world.getDestructionListener() != null) {
world.getDestructionListener().onDestroy(je0.joint);
}
world.destroyJoint(je0.joint);
this.m_jointList = je;
}
this.m_jointList = null;
}
private void destroyAttachedContacts() {
// Delete the attached contacts.
ContactEdge ce = m_contactList;
while (ce != null) {
ContactEdge ce0 = ce;
ce = ce.next;
world.getContactManager().destroy(ce0.contact);
}
m_contactList = null;
}
private void destroyFixtures() {
for (Fixture f : getFixtures()) {
if (world.getDestructionListener() != null) {
world.getDestructionListener().onDestroy(f);
}
f.destroyProxies(broadPhase);
f.destroy();
// jbox2dTODO djm recycle fixtures (here or in that destroy method)
}
getFixtures().clear();
}
/**
* @return is this body treated like a bullet for continuous collision detection?
**/
public boolean isBullet() {
return (m_flags & e_bulletFlag) == e_bulletFlag;
}
/**
* Should this body be treated like a bullet for continuous collision detection?
**/
public void setBullet(boolean flag) {
if (flag) {
m_flags |= e_bulletFlag;
} else {
m_flags &= ~e_bulletFlag;
}
}
/**
* You can disable sleeping on this body.
* If you disable sleeping, the body will be woken.
*
* @param flag sleep flag
*/
public void setSleepingAllowed(boolean flag) {
if (flag) {
m_flags |= e_autoSleepFlag;
} else {
m_flags &= ~e_autoSleepFlag;
setAwake(true);
}
}
/**
* @return whether this body is allowed to sleep
*/
public boolean isSleepingAllowed() {
return (m_flags & e_autoSleepFlag) == e_autoSleepFlag;
}
/**
* Set the sleep state of the body.
* A sleeping body has very low CPU cost.
*
* @param flag set to true to put body to sleep, false to wake it
*/
public void setAwake(boolean flag) {
if (flag) {
if ((m_flags & e_awakeFlag) == 0) {
m_flags |= e_awakeFlag;
sleepTime = 0.0f;
}
} else {
m_flags &= ~e_awakeFlag;
sleepTime = 0.0f;
linearVelocity.setZero();
angularVelocity = 0.0f;
clearForces();
}
}
/**
* Get the sleeping state of this body.
*
* @return true if the body is awake.
*/
public boolean isAwake() {
return (m_flags & e_awakeFlag) == e_awakeFlag;
}
/**
* Set the active state of the body.
* An inactive body is not simulated and cannot be collided with or woken up.
* If you pass a flag of true, all fixtures will be added to the broad-phase.
* If you pass a flag of false, all fixtures will be removed from the broad-phase and all contacts will be destroyed.
* Fixtures and joints are otherwise unaffected.
* You may continue to create/destroy fixtures and joints on inactive bodies.
* Fixtures on an inactive body are implicitly inactive
* and will not participate in collisions, ray-casts, or queries.
* Joints connected to an inactive body are implicitly inactive.
* An inactive body is still owned by a World object and remains in the body list.
*
* @param flag active flag
*/
public void setActive(boolean flag) {
world.assertNotLocked();
if (flag == isActive()) {
return;
}
if (flag) {
m_flags |= e_activeFlag;
// Create all proxies.
for (Fixture f : fixtures) {
f.createProxies(broadPhase, m_xf);
}
// Contacts are created the next time step.
} else {
m_flags &= ~e_activeFlag;
// Destroy all proxies.
for (Fixture f : fixtures) {
f.destroyProxies(broadPhase);
}
destroyAttachedContacts();
}
}
/**
* @return the active state of the body
*/
public boolean isActive() {
return (m_flags & e_activeFlag) == e_activeFlag;
}
/**
* Set this body to have fixed rotation. This causes the mass to be reset.
*
* @param flag fixed rotation flag
*/
public void setFixedRotation(boolean flag) {
if (flag) {
m_flags |= e_fixedRotationFlag;
} else {
m_flags &= ~e_fixedRotationFlag;
}
resetMassData();
}
/**
* @return does this body have fixed rotation
*/
public boolean isFixedRotation() {
return (m_flags & e_fixedRotationFlag) == e_fixedRotationFlag;
}
/**
* Get the list of all joints attached to this body.
**/
public JointEdge getJointList() {
return m_jointList;
}
/**
* Get the list of all contacts attached to this body.
* Note: this list changes during the time step and you may miss some collisions if you don't
* use ContactListener.
*/
public ContactEdge getContactList() {
return m_contactList;
}
/**
* Get the user data pointer that was provided in the body definition.
**/
public Object getUserData() {
return userData;
}
/**
* Set the user data. Use this to store your application specific data.
*/
public void setUserData(Object data) {
userData = data;
}
/**
* Get the parent world of this body.
*/
public World getWorld() {
return world;
}
// djm pooling
private final Transform pxf = new Transform();
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;
// end inline
for (Fixture f : fixtures) {
f.synchronize(broadPhase, xf1, m_xf);
}
}
void synchronizeTransform() {
// m_xf.position = m_sweep.c - Mul(m_xf.R, m_sweep.localCenter);
// Rot.mulToOutUnsafe(m_xf.q, m_sweep.localCenter, m_xf.p);
// m_xf.p.mulLocal(-1).addLocal(m_sweep.c);
m_xf.q.set(m_sweep.a);
Rotation q = m_xf.q;
Vec2 v = m_sweep.localCenter;
m_xf.p.x = m_sweep.c.x - q.c * v.x + q.s * v.y;
m_xf.p.y = m_sweep.c.y - q.s * v.x - q.c * v.y;
}
/**
* This is used to prevent connected bodies from colliding.
* It may lie, depending on the collideConnected flag.
*
* @param other other body
* @return if they should collide
*/
public boolean shouldCollide(Body other) {
// At least one body should be dynamic.
if (type != BodyType.DYNAMIC && other.type != BodyType.DYNAMIC) {
return false;
}
// Does a joint prevent collision?
for (JointEdge jn = m_jointList; jn != null; jn = jn.next) {
if (jn.other == other && !jn.joint.getCollideConnected()) {
return false;
}
}
return true;
}
void advance(float t) {
// Advance to the new safe time. This doesn't sync the broad-phase.
m_sweep.advance(t);
m_sweep.c.set(m_sweep.c0);
m_sweep.a = m_sweep.a0;
m_xf.q.set(m_sweep.a);
// m_xf.position = m_sweep.c - Mul(m_xf.R, m_sweep.localCenter);
Rotation.mulToOutUnsafe(m_xf.q, m_sweep.localCenter, m_xf.p);
m_xf.p.mulLocal(-1).addLocal(m_sweep.c);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy