public float computeSubmergedArea(final Vec2 normal, float offset, XForm xf, Vec2 c) {
    final Vec2 v0 = tlV0.get();
    final Vec2 v1 = tlV1.get();
    final Vec2 v2 = tlV2.get();
    final Vec2 temp = tlTemp.get();

    // Note that v0 is independent of any details of the specific edge
    // We are relying on v0 being consistent between multiple edges of the same body
    v0.set(normal).mul(offset);
    // b2Vec2 v0 = xf.position + (offset - b2Dot(normal, xf.position)) * normal;

    XForm.mulToOut(xf, m_v1, v1);
    XForm.mulToOut(xf, m_v2, v2);

    float d1 = Vec2.dot(normal, v1) - offset;
    float d2 = Vec2.dot(normal, v2) - offset;

    if (d1 > 0.0f) {
      if (d2 > 0.0f) {
        return 0.0f;
      } else {
        temp.set(v2).mulLocal(d1 / (d1 - d2));
        v1.mulLocal(-d2 / (d1 - d2)).addLocal(temp);
      }
    } else {
      if (d2 > 0.0f) {
        temp.set(v1).mulLocal(-d2 / (d1 - d2));
        v2.mulLocal(d1 / (d1 - d2)).addLocal(temp);
      } else {
        // Nothing
      }
    }

    final Vec2 e1 = tlE1.get();
    final Vec2 e2 = tlE2.get();

    // v0,v1,v2 represents a fully submerged triangle
    float k_inv3 = 1.0f / 3.0f;

    // Area weighted centroid
    c.x = k_inv3 * (v0.x + v1.x + v2.x);
    c.y = k_inv3 * (v0.y + v1.y + v2.y);

    e1.set(v1).subLocal(v0);
    e2.set(v2).subLocal(v0);

    return 0.5f * Vec2.cross(e1, e2);
  }
Esempio n. 2
0
  /**
   * Apply force to the center of the planetoid
   *
   * @param force
   */
  public void applyThrust(Vec2 force) {

    force = force.mul(1 / Globals.PHYS_RATIO);

    // Nasty hack to change player speed
    if (this.forceFactor > 0) {
      force = force.mulLocal(this.forceFactor);
    }
    this.getBody().applyForce(force, this.getBody().getWorldCenter());
  }
  public final void computeCentroidToOut(final Vec2[] vs, final int count, final Vec2 out) {
    assert (count >= 3);

    out.set(0.0f, 0.0f);
    float area = 0.0f;

    // pRef is the reference point for forming triangles.
    // It's location doesn't change the result (except for rounding error).
    final Vec2 pRef = pool1;
    pRef.setZero();

    final Vec2 e1 = pool2;
    final Vec2 e2 = pool3;

    final float inv3 = 1.0f / 3.0f;

    for (int i = 0; i < count; ++i) {
      // Triangle vertices.
      final Vec2 p1 = pRef;
      final Vec2 p2 = vs[i];
      final Vec2 p3 = i + 1 < count ? vs[i + 1] : vs[0];

      e1.set(p2).subLocal(p1);
      e2.set(p3).subLocal(p1);

      final float D = Vec2.cross(e1, e2);

      final float triangleArea = 0.5f * D;
      area += triangleArea;

      // Area weighted centroid
      e1.set(p1).addLocal(p2).addLocal(p3).mulLocal(triangleArea * inv3);
      out.addLocal(e1);
    }

    // Centroid
    assert (area > Settings.EPSILON);
    out.mulLocal(1.0f / area);
  }
Esempio n. 4
0
  @Override
  public void solveVelocityConstraints(TimeStep step) {
    Body b = m_bodyB;

    Vec2 r = pool.popVec2();

    r.set(m_localAnchor).subLocal(b.getLocalCenter());
    Mat22.mulToOut(b.getTransform().R, r, r);

    // Cdot = v + cross(w, r)
    Vec2 Cdot = pool.popVec2();
    Vec2.crossToOut(b.m_angularVelocity, r, Cdot);
    Cdot.addLocal(b.m_linearVelocity);

    Vec2 impulse = pool.popVec2();
    Vec2 temp = pool.popVec2();

    // Mul(m_mass, -(Cdot + m_beta * m_C + m_gamma * m_impulse));
    impulse.set(m_C).mulLocal(m_beta);
    temp.set(m_impulse).mulLocal(m_gamma);
    temp.addLocal(impulse).addLocal(Cdot).mulLocal(-1);
    Mat22.mulToOut(m_mass, temp, impulse);

    Vec2 oldImpulse = temp;
    oldImpulse.set(m_impulse);
    m_impulse.addLocal(impulse);
    float maxImpulse = step.dt * m_maxForce;
    if (m_impulse.lengthSquared() > maxImpulse * maxImpulse) {
      m_impulse.mulLocal(maxImpulse / m_impulse.length());
    }
    impulse.set(m_impulse).subLocal(oldImpulse);

    // pooling
    oldImpulse.set(impulse).mulLocal(b.m_invMass);
    b.m_linearVelocity.addLocal(oldImpulse);
    b.m_angularVelocity += b.m_invI * Vec2.cross(r, impulse);

    pool.pushVec2(4);
  }
Esempio n. 5
0
  /**
   * GameLoop provides the accurate delta time we need to step our entities
   *
   * @param delta
   */
  public void gameInteration(float delta) {
    // Check if Rule and Rulette have met
    if (rule.getBounds().intersects(rulette.getBounds()) || gameStatus == GAMESTATUS_WON) {

      gameWon();
      return;
    } else if (rule.isDead() || rulette.isDead() || gameStatus == GAMESTATUS_FAILED) {

      // If we have died
      gameLost();
      return;
    }

    Vec2 move = new Vec2();
    if (Input.isKeyDown(KeyEvent.VK_A)) move.x -= 1;
    if (Input.isKeyDown(KeyEvent.VK_D)) move.x += 1;
    move.mulLocal(speed);

    this.selectedCharacter.setVelocityX(move.x);

    move.x = -move.x;

    this.getNotSelectedCharacter().setVelocityX(move.x);

    if (Input.isKeyDown(KeyEvent.VK_SPACE)) {
      Input.removeKey(KeyEvent.VK_SPACE);
      if (selectedCharacter.touching > 0) {
        Sound.playSound(R.sound.effects.jump);
        selectedCharacter
            .getBody()
            .applyLinearImpulse(
                new Vec2(0, -jumpspeed), selectedCharacter.getBody().getLocalCenter());
      }
      if (getNotSelectedCharacter().touching > 0) {
        Sound.playSound(R.sound.effects.jump);
        getNotSelectedCharacter()
            .getBody()
            .applyLinearImpulse(
                new Vec2(0, -jumpspeed), selectedCharacter.getBody().getLocalCenter());
      }
    }

    // Move all the tokens
    for (int i = 0; i < gameObjects.size(); i++) {
      Entity e = gameObjects.get(i);
      e.update(delta);
    }

    // SOUND
    if (Input.isKeyDownOnce(KeyEvent.VK_PAGE_UP)) {
      Sound.increaseClipVolume();
    } else if (Input.isKeyDownOnce(KeyEvent.VK_PAGE_DOWN)) {
      Sound.decreaseClipVolume();
    } else if (Input.isKeyDownOnce(KeyEvent.VK_HOME)) {
      Sound.increaseMusicVolume();
    } else if (Input.isKeyDownOnce(KeyEvent.VK_END)) {
      Sound.decreaseMusicVolume();
    } else if (Input.isKeyDownOnce(KeyEvent.VK_INSERT)) {
      if (Sound.isMusicMuted()) Sound.unmuteMusic();
      else Sound.muteMusic();
    } else if (Input.isKeyDownOnce(KeyEvent.VK_DELETE)) {
      if (Sound.isClipsMuted()) Sound.unmuteClips();
      else Sound.muteClips();
    }

    // Reset Game
    if (Input.isKeyDownOnce(KeyEvent.VK_R)) {
      resetLevel();
    }
  }
  public void computeMass(final MassData massData, float density) {
    // Polygon mass, centroid, and inertia.
    // Let rho be the polygon density in mass per unit area.
    // Then:
    // mass = rho * int(dA)
    // centroid.x = (1/mass) * rho * int(x * dA)
    // centroid.y = (1/mass) * rho * int(y * dA)
    // I = rho * int((x*x + y*y) * dA)
    //
    // We can compute these integrals by summing all the integrals
    // for each triangle of the polygon. To evaluate the integral
    // for a single triangle, we make a change of variables to
    // the (u,v) coordinates of the triangle:
    // x = x0 + e1x * u + e2x * v
    // y = y0 + e1y * u + e2y * v
    // where 0 <= u && 0 <= v && u + v <= 1.
    //
    // We integrate u from [0,1-v] and then v from [0,1].
    // We also need to use the Jacobian of the transformation:
    // D = cross(e1, e2)
    //
    // Simplification: triangle centroid = (1/3) * (p1 + p2 + p3)
    //
    // The rest of the derivation is handled by computer algebra.

    assert (m_count >= 3);

    final Vec2 center = pool1;
    center.setZero();
    float area = 0.0f;
    float I = 0.0f;

    // pRef is the reference point for forming triangles.
    // It's location doesn't change the result (except for rounding error).
    final Vec2 s = pool2;
    s.setZero();
    // This code would put the reference point inside the polygon.
    for (int i = 0; i < m_count; ++i) {
      s.addLocal(m_vertices[i]);
    }
    s.mulLocal(1.0f / m_count);

    final float k_inv3 = 1.0f / 3.0f;

    final Vec2 e1 = pool3;
    final Vec2 e2 = pool4;

    for (int i = 0; i < m_count; ++i) {
      // Triangle vertices.
      e1.set(m_vertices[i]).subLocal(s);
      e2.set(s).negateLocal().addLocal(i + 1 < m_count ? m_vertices[i + 1] : m_vertices[0]);

      final float D = Vec2.cross(e1, e2);

      final float triangleArea = 0.5f * D;
      area += triangleArea;

      // Area weighted centroid
      center.x += triangleArea * k_inv3 * (e1.x + e2.x);
      center.y += triangleArea * k_inv3 * (e1.y + e2.y);

      final float ex1 = e1.x, ey1 = e1.y;
      final float ex2 = e2.x, ey2 = e2.y;

      float intx2 = ex1 * ex1 + ex2 * ex1 + ex2 * ex2;
      float inty2 = ey1 * ey1 + ey2 * ey1 + ey2 * ey2;

      I += (0.25f * k_inv3 * D) * (intx2 + inty2);
    }

    // Total mass
    massData.mass = density * area;

    // Center of mass
    assert (area > Settings.EPSILON);
    center.mulLocal(1.0f / area);
    massData.center.set(center).addLocal(s);

    // Inertia tensor relative to the local origin (point s)
    massData.I = I * density;

    // Shift to center of mass then to original body origin.
    massData.I += massData.mass * (Vec2.dot(massData.center, massData.center));
  }
Esempio n. 7
0
  private void drawShape(Fixture fixture, Transform xf, Color3f color) {
    switch (fixture.getType()) {
      case CIRCLE:
        {
          CircleShape circle = (CircleShape) fixture.getShape();

          // Vec2 center = Mul(xf, circle.m_p);
          Transform.mulToOutUnsafe(xf, circle.m_p, center);
          float radius = circle.m_radius;
          xf.q.getXAxis(axis);

          if (fixture.getUserData() != null && fixture.getUserData().equals(LIQUID_INT)) {
            Body b = fixture.getBody();
            liquidOffset.set(b.m_linearVelocity);
            float linVelLength = b.m_linearVelocity.length();
            if (averageLinearVel == -1) {
              averageLinearVel = linVelLength;
            } else {
              averageLinearVel = .98f * averageLinearVel + .02f * linVelLength;
            }
            liquidOffset.mulLocal(liquidLength / averageLinearVel / 2);
            circCenterMoved.set(center).addLocal(liquidOffset);
            center.subLocal(liquidOffset);
            m_debugDraw.drawSegment(center, circCenterMoved, liquidColor);
            return;
          }

          m_debugDraw.drawSolidCircle(center, radius, axis, color);
        }
        break;

      case POLYGON:
        {
          PolygonShape poly = (PolygonShape) fixture.getShape();
          int vertexCount = poly.m_count;
          assert (vertexCount <= Settings.maxPolygonVertices);
          Vec2[] vertices = tlvertices.get(Settings.maxPolygonVertices);

          for (int i = 0; i < vertexCount; ++i) {
            // vertices[i] = Mul(xf, poly.m_vertices[i]);
            Transform.mulToOutUnsafe(xf, poly.m_vertices[i], vertices[i]);
          }

          m_debugDraw.drawSolidPolygon(vertices, vertexCount, color);
        }
        break;
      case EDGE:
        {
          EdgeShape edge = (EdgeShape) fixture.getShape();
          Transform.mulToOutUnsafe(xf, edge.m_vertex1, v1);
          Transform.mulToOutUnsafe(xf, edge.m_vertex2, v2);
          m_debugDraw.drawSegment(v1, v2, color);
        }
        break;

      case CHAIN:
        {
          ChainShape chain = (ChainShape) fixture.getShape();
          int count = chain.m_count;
          Vec2[] vertices = chain.m_vertices;

          Transform.mulToOutUnsafe(xf, vertices[0], v1);
          for (int i = 1; i < count; ++i) {
            Transform.mulToOutUnsafe(xf, vertices[i], v2);
            m_debugDraw.drawSegment(v1, v2, color);
            m_debugDraw.drawCircle(v1, 0.05f, color);
            v1.set(v2);
          }
        }
        break;
      default:
        break;
    }
  }
Esempio n. 8
0
  @Override
  public void initVelocityConstraints(TimeStep step) {
    Body b = m_bodyB;

    float mass = b.getMass();

    // Frequency
    float omega = 2.0f * MathUtils.PI * m_frequencyHz;

    // Damping coefficient
    float d = 2.0f * mass * m_dampingRatio * omega;

    // Spring stiffness
    float k = mass * (omega * omega);

    // magic formulas
    // gamma has units of inverse mass.
    // beta has units of inverse time.
    assert (d + step.dt * k > Settings.EPSILON);
    m_gamma = step.dt * (d + step.dt * k);
    if (m_gamma != 0.0f) {
      m_gamma = 1.0f / m_gamma;
    }
    m_beta = step.dt * k * m_gamma;

    Vec2 r = pool.popVec2();

    // Compute the effective mass matrix.
    // Vec2 r = Mul(b.getTransform().R, m_localAnchor - b.getLocalCenter());
    r.set(m_localAnchor).subLocal(b.getLocalCenter());
    Mat22.mulToOut(b.getTransform().R, r, r);

    // K    = [(1/m1 + 1/m2) * eye(2) - skew(r1) * invI1 * skew(r1) - skew(r2) * invI2 * skew(r2)]
    //      = [1/m1+1/m2     0    ] + invI1 * [r1.y*r1.y -r1.x*r1.y] + invI2 * [r1.y*r1.y
    // -r1.x*r1.y]
    //        [    0     1/m1+1/m2]           [-r1.x*r1.y r1.x*r1.x]           [-r1.x*r1.y
    // r1.x*r1.x]
    float invMass = b.m_invMass;
    float invI = b.m_invI;

    Mat22 K1 = pool.popMat22();
    K1.m11 = invMass;
    K1.m21 = 0.0f;
    K1.m12 = 0.0f;
    K1.m22 = invMass;

    Mat22 K2 = pool.popMat22();
    K2.m11 = invI * r.y * r.y;
    K2.m21 = -invI * r.x * r.y;
    K2.m12 = -invI * r.x * r.y;
    K2.m22 = invI * r.x * r.x;

    Mat22 K = pool.popMat22();
    K.set(K1).addLocal(K2);
    K.m11 += m_gamma;
    K.m22 += m_gamma;

    K.invertToOut(m_mass);

    m_C.set(b.m_sweep.c).addLocal(r).subLocal(m_target);

    // Cheat with some damping
    b.m_angularVelocity *= 0.98f;

    // Warm starting.
    m_impulse.mulLocal(step.dtRatio);
    // pool
    Vec2 temp = pool.popVec2();
    temp.set(m_impulse).mulLocal(invMass);
    b.m_linearVelocity.addLocal(temp);
    b.m_angularVelocity += invI * Vec2.cross(r, m_impulse);

    pool.pushVec2(2);
    pool.pushMat22(3);
  }
Esempio n. 9
0
  /**
   * 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 final void resetMassData() {
    // Compute mass data from shapes. Each shape has its own density.
    m_mass = 0.0f;
    m_invMass = 0.0f;
    m_I = 0.0f;
    m_invI = 0.0f;
    m_sweep.localCenter.setZero();

    // Static and kinematic bodies have zero mass.
    if (m_type == BodyType.STATIC || m_type == BodyType.KINEMATIC) {
      // m_sweep.c0 = m_sweep.c = m_xf.position;
      m_sweep.c.set(m_xf.position);
      m_sweep.c0.set(m_xf.position);
      return;
    }

    assert (m_type == BodyType.DYNAMIC);

    // Accumulate mass over all fixtures.
    final Vec2 center = m_world.getPool().popVec2();
    center.setZero();
    final Vec2 temp = m_world.getPool().popVec2();
    final MassData massData = pmd;
    for (Fixture f = m_fixtureList; f != null; f = f.m_next) {
      if (f.m_density == 0.0f) {
        continue;
      }
      f.getMassData(massData);
      m_mass += massData.mass;
      // center += massData.mass * massData.center;
      temp.set(massData.center).mulLocal(massData.mass);
      center.addLocal(temp);
      m_I += massData.I;
    }

    // Compute center of mass.
    if (m_mass > 0.0f) {
      m_invMass = 1.0f / m_mass;
      center.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(center, center);
      assert (m_I > 0.0f);
      m_invI = 1.0f / m_I;
    } else {
      m_I = 0.0f;
      m_invI = 0.0f;
    }

    Vec2 oldCenter = m_world.getPool().popVec2();
    // Move center of mass.
    oldCenter.set(m_sweep.c);
    m_sweep.localCenter.set(center);
    // m_sweep.c0 = m_sweep.c = Mul(m_xf, m_sweep.localCenter);
    Transform.mulToOut(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);
    Vec2.crossToOut(m_angularVelocity, temp, temp);
    m_linearVelocity.addLocal(temp);

    m_world.getPool().pushVec2(3);
  }
Esempio n. 10
0
  /**
   * Rozbije objekt. Upravi objekt world tak, ze vymaze triesteny objekt a nahradi ho fragmentami na
   * zaklade nastaveneho materialu a clenskych premennych.
   *
   * @param dt casova dlzka framu
   */
  public void smash(float dt) {
    if (contact == null) { // riesi sa staticky prvok, ktory ma priliz maly obsah
      b1.setType(BodyType.DYNAMIC);
      return;
    }

    World w = b1.m_world;
    Shape s = f1.m_shape;
    Polygon p = f1.m_polygon;

    if (p == null) {
      switch (s.m_type) {
        case POLYGON:
          PolygonShape ps = (PolygonShape) s;
          Vec2[] vertices = ps.m_vertices;
          p = new Polygon();
          for (int i = 0; i < ps.m_count; ++i) {
            p.add(vertices[ps.m_count - i - 1]);
          }
          break;
        case CIRCLE:
          CircleShape cs = (CircleShape) s;
          p = new Polygon();
          float radius = cs.m_radius;

          double u = Math.PI * 2 / CIRCLEVERTICES;
          radius =
              (float) Math.sqrt(u / Math.sin(u))
                  * radius; // upravim radius tak, aby bola zachovana velkost obsahu

          Vec2 center = cs.m_p;
          for (int i = 0; i < CIRCLEVERTICES; ++i) {
            double j = u * i; // uhol
            float sin = (float) Math.sin(j);
            float cos = (float) Math.cos(j);
            Vec2 v = new Vec2(sin, cos).mulLocal(radius).addLocal(center);
            p.add(v);
          }
          break;
        default:
          throw new RuntimeException("Dany typ tvaru nepodporuje stiepenie");
      }
    }

    float mConst = f1.m_material.m_rigidity / normalImpulse; // sila v zavislosti na pevnosti telesa

    boolean fixA = f1 == contact.m_fixtureA; // true, ak f2 je v objekte contact ako m_fixtureA
    float oldAngularVelocity =
        fixA ? contact.m_angularVelocity_bodyA : contact.m_angularVelocity_bodyB;
    Vec2 oldLinearVelocity = fixA ? contact.m_linearVelocity_bodyA : contact.m_linearVelocity_bodyB;
    b1.setAngularVelocity(
        (b1.m_angularVelocity - oldAngularVelocity) * mConst + oldAngularVelocity);
    b1.setLinearVelocity(
        b1.m_linearVelocity.sub(oldLinearVelocity).mulLocal(mConst).addLocal(oldLinearVelocity));
    if (!w.isFractured(f2)
        && b2.m_type == BodyType.DYNAMIC
        && !b2.m_fractureTransformUpdate) { // ak sa druhy objekt nerozbija, tak sa jej nahodia
      // povodne hodnoty (TREBA MODIFIKOVAT POHYB OBJEKTU,
      // KTORY SPOSOBUJE ROZPAD)
      oldAngularVelocity =
          !fixA ? contact.m_angularVelocity_bodyA : contact.m_angularVelocity_bodyB;
      oldLinearVelocity = !fixA ? contact.m_linearVelocity_bodyA : contact.m_linearVelocity_bodyB;
      b2.setAngularVelocity(
          (b2.m_angularVelocity - oldAngularVelocity) * mConst + oldAngularVelocity);
      b2.setLinearVelocity(
          b2.m_linearVelocity.sub(oldLinearVelocity).mulLocal(mConst).addLocal(oldLinearVelocity));
      b2.setTransform(
          b2.m_xf0.p.add(b2.m_linearVelocity.mul(dt)),
          b2.m_xf0.q.getAngle()); // osetruje jbox2d od posuvania telesa pri rieseni kolizie
      b2.m_fractureTransformUpdate = true;
    }

    Vec2 localPoint = Transform.mulTrans(b1.m_xf, point);
    Vec2 b1Vec = b1.getLinearVelocityFromWorldPoint(point);
    Vec2 b2Vec = b2.getLinearVelocityFromWorldPoint(point);
    Vec2 localVector = b2Vec.subLocal(b1Vec);

    localVector.mulLocal(dt);
    Polygon[] fragment;
    try {
      fragment = m.split(p, localPoint, localVector, normalImpulse); // rodeli to
    } catch (RuntimeException ex) {
      return;
    }

    if (fragment.length == 1) { // nerozbilo to na ziadne fragmenty
      return;
    }

    // definuje tela fragmentov - tie maju vsetky rovnaku definiciu (preberaju parametre z povodneho
    // objektu)
    BodyDef bodyDef = new BodyDef();
    bodyDef.position.set(b1.m_xf.p); // pozicia
    bodyDef.angle = b1.m_xf.q.getAngle(); // otocenie
    bodyDef.fixedRotation = b1.isFixedRotation();
    bodyDef.angularDamping = b1.m_angularDamping;
    bodyDef.allowSleep = b1.isSleepingAllowed();

    FixtureDef fd = new FixtureDef();
    fd.friction = f1.m_friction; // trenie
    fd.restitution = f1.m_restitution; // odrazivost
    fd.isSensor = f1.m_isSensor;
    fd.density = f1.m_density;

    // odstrani fragmentacne predmety/cele teleso
    ArrayList<Fixture> fixtures = new ArrayList<>();
    if (f1.m_polygon != null) {
      for (Fixture f = b1.m_fixtureList; f != null; f = f.m_next) {
        if (f.m_polygon == f1.m_polygon) {
          fixtures.add(f);
        }
      }
    } else {
      fixtures.add(f1);
    }

    for (Fixture f : fixtures) {
      b1.destroyFixture(f);
    }

    if (b1.m_fixtureCount == 0) {
      w.destroyBody(b1);
    }

    // prida fragmenty do simulacie
    MyList<Body> newbodies = new MyList<>();
    for (Polygon pg : fragment) { // vytvori tela, prida fixtury, poriesi konvexnu dekompoziciu
      if (pg.isCorrect()) {
        if (pg instanceof Fragment) {
          Polygon[] convex = pg.convexDecomposition();
          bodyDef.type = BodyType.DYNAMIC;
          for (Polygon pgx : convex) {
            Body f_body = w.createBody(bodyDef);
            pgx.flip();
            PolygonShape ps = new PolygonShape();
            ps.set(pgx.getArray(), pgx.size());
            fd.shape = ps;
            fd.polygon = null;
            fd.material = f1.m_material.m_fragments; // rekurzivne stiepenie

            f_body.createFixture(fd);
            f_body.setAngularVelocity(b1.m_angularVelocity);
            f_body.setLinearVelocity(b1.getLinearVelocityFromLocalPoint(f_body.getLocalCenter()));
            newbodies.add(f_body);
          }

        } else {
          fd.material = f1.m_material.m_fragments; // rekurzivne stiepenie
          bodyDef.type = b1.getType();
          Body f_body = w.createBody(bodyDef);
          PolygonFixture pf = new PolygonFixture(pg);

          f_body.createFixture(pf, fd);
          f_body.setLinearVelocity(b1.getLinearVelocityFromLocalPoint(f_body.getLocalCenter()));
          f_body.setAngularVelocity(b1.m_angularVelocity);
          newbodies.add(f_body);
        }
      }
    }

    // zavola sa funkcia z fraction listeneru (pokial je nadefinovany)
    FractureListener fl = w.getContactManager().m_fractureListener;
    if (fl != null) {
      fl.action(m, normalImpulse, newbodies);
    }
  }