public static void createBody(World world, SceneElement e, ValueMap valueMap) { float x = valueMap.getValue(e, SceneElement.VAR_X, 0f) / WORLD_SCALE; float y = valueMap.getValue(e, SceneElement.VAR_Y, 0f) / WORLD_SCALE; float width = valueMap.getValue(e, SceneElement.VAR_WIDTH, 1) / WORLD_SCALE; float height = valueMap.getValue(e, SceneElement.VAR_HEIGHT, 1) / WORLD_SCALE; // TODO what if corner is not center? PhType phType = valueMap.getValue(e, PhysicsEf.VAR_PH_TYPE, PhType.DYNAMIC); PhShape phShape = valueMap.getValue(e, PhysicsEf.VAR_PH_SHAPE, PhShape.RECTANGULAR); Shape s = null; switch (phShape) { case CIRCULAR: s = new CircleShape(); s.setRadius(width / 2); break; default: s = new PolygonShape(); ((PolygonShape) s).setAsBox(width / 2, height / 2); } BodyDef bd = new BodyDef(); switch (phType) { case STATIC: bd.type = BodyType.StaticBody; break; case DYNAMIC: bd.type = BodyType.DynamicBody; break; } bd.position.set(x, y); bd.angle = valueMap.getValue(e, SceneElement.VAR_ROTATION, 0); FixtureDef fixture = new FixtureDef(); fixture.shape = s; fixture.density = valueMap.getValue(e, PhysicsEf.VAR_PH_DENSITY, 1f); fixture.friction = valueMap.getValue(e, PhysicsEf.VAR_PH_FRICTION, 1f); fixture.restitution = valueMap.getValue(e, PhysicsEf.VAR_PH_RESTITUTION, 1f); Body body = world.createBody(bd); body.createFixture(fixture); body.resetMassData(); valueMap.setValue(e.getId(), VAR_PH_BODY, body); }
/** * @param f - fixture that is affected * @return true if force was applied, false otherwise. */ private boolean ApplyToFixture(Fixture f) { float shapeDensity = mUseDensity ? f.getDensity() : mFluidDensity; // don't bother with buoyancy on sensors or fixtures with no density if (f.isSensor() || (shapeDensity == 0)) { return false; } Body body = f.getBody(); mAreac.set(Vector2.Zero); mMassc.set(Vector2.Zero); float area = 0; // Get shape for displacement area calculations Shape shape = f.getShape(); mSC.set(Vector2.Zero); float sarea; switch (shape.getType()) { case Circle: sarea = B2ShapeExtensions.ComputeSubmergedArea( (CircleShape) shape, mSurfaceNormal, mSurfaceHeight, body.getTransform(), mSC); break; case Chain: sarea = B2ShapeExtensions.ComputeSubmergedArea( (ChainShape) shape, mSurfaceNormal, mSurfaceHeight, body.getTransform(), mSC); break; case Edge: sarea = B2ShapeExtensions.ComputeSubmergedArea( (EdgeShape) shape, mSurfaceNormal, mSurfaceHeight, body.getTransform(), mSC); break; case Polygon: sarea = B2ShapeExtensions.ComputeSubmergedArea( (PolygonShape) shape, mSurfaceNormal, mSurfaceHeight, body.getTransform(), mSC); break; default: sarea = 0; break; } area += sarea; mAreac.x += sarea * mSC.x; mAreac.y += sarea * mSC.y; float mass = sarea * shapeDensity; mMassc.x += sarea * mSC.x * shapeDensity; mMassc.y += sarea * mSC.y * shapeDensity; mAreac.x /= area; mAreac.y /= area; mMassc.x /= mass; mMassc.y /= mass; if (area < Float.MIN_VALUE) { return false; } if (DEBUG_BUOYANCY) { // Run debug w/HCR to see the effects of different fluid densities / linear drag mFluidDensity = 2f; mLinearDrag = 5; mAngularDrag = 2; } // buoyancy force. mTmp.set(mGravity).scl(-mFluidDensity * area); body.applyForce(mTmp, mMassc, true); // multiply by -density to invert gravity // linear drag. mTmp.set( body.getLinearVelocityFromWorldPoint(mAreac).sub(mFluidVelocity).mul(-mLinearDrag * area)); body.applyForce(mTmp, mAreac, true); // angular drag. float bodyMass = body.getMass(); if (bodyMass < 1) // prevent a huge torque from being generated... { bodyMass = 1; } float torque = -body.getInertia() / bodyMass * area * body.getAngularVelocity() * mAngularDrag; body.applyTorque(torque, true); return true; }