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;
  }