public void setPrevEdge(
     final EdgeShape edge, final Vec2 core, final Vec2 cornerDir, final boolean convex) {
   m_prevEdge = edge;
   m_coreV1.set(core);
   m_cornerDir1.set(cornerDir);
   m_cornerConvex1 = convex;
 }
  @Override
  public final boolean testPoint(final Transform xf, final Vec2 p) {

    final Vec2 pLocal = pool1;
    final Vec2 temp = pool2;

    pLocal.set(p).subLocal(xf.p);
    Rot.mulTransUnsafe(xf.q, pLocal, temp);
    pLocal.set(temp);

    if (m_debug) {
      System.out.println("--testPoint debug--");
      System.out.println("Vertices: ");
      for (int i = 0; i < m_count; ++i) {
        System.out.println(m_vertices[i]);
      }
      System.out.println("pLocal: " + pLocal);
    }

    for (int i = 0; i < m_count; ++i) {
      temp.set(pLocal).subLocal(m_vertices[i]);
      final float dot = Vec2.dot(m_normals[i], temp);
      if (dot > 0.0f) {
        return false;
      }
    }

    return true;
  }
 public void setNextEdge(
     final EdgeShape edge, final Vec2 core, final Vec2 cornerDir, final boolean convex) {
   // djm note: the vec2s are probably pooled, don't use them
   m_nextEdge = edge;
   m_coreV2.set(core);
   m_cornerDir2.set(cornerDir);
   m_cornerConvex2 = convex;
 }
  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);
  }
Example #5
0
  /**
   * Construct a world object.
   *
   * @param gravity the world gravity vector.
   * @param doSleep improve performance by not simulating inactive bodies.
   */
  public World(Vec2 gravity, IWorldPool argPool) {
    pool = argPool;
    m_destructionListener = null;
    m_debugDraw = null;

    m_bodyList = null;
    m_jointList = null;

    m_bodyCount = 0;
    m_jointCount = 0;

    m_warmStarting = true;
    m_continuousPhysics = true;
    m_subStepping = false;
    m_stepComplete = true;

    m_allowSleep = true;
    m_gravity.set(gravity);

    m_flags = CLEAR_FORCES;

    m_inv_dt0 = 0f;

    m_contactManager = new ContactManager(this);
    m_profile = new Profile();

    initializeRegisters();
  }
Example #6
0
  protected RevoluteJoint(IWorldPool argWorld, RevoluteJointDef def) {
    super(argWorld, def);
    m_localAnchorA.set(def.localAnchorA);
    m_localAnchorB.set(def.localAnchorB);
    m_referenceAngle = def.referenceAngle;

    m_motorImpulse = 0;

    m_lowerAngle = def.lowerAngle;
    m_upperAngle = def.upperAngle;
    m_maxMotorTorque = def.maxMotorTorque;
    m_motorSpeed = def.motorSpeed;
    m_enableLimit = def.enableLimit;
    m_enableMotor = def.enableMotor;
    m_limitState = LimitState.INACTIVE;
  }
  @Override
  public final void computeAABB(final AABB aabb, final Transform xf, int childIndex) {
    final Vec2 v = pool1;
    final Vec2 lower = aabb.lowerBound;
    final Vec2 upper = aabb.upperBound;
    final Vec2 v1 = m_vertices[0];
    lower.x = (xf.q.c * v1.x - xf.q.s * v1.y) + xf.p.x;
    lower.y = (xf.q.s * v1.x + xf.q.c * v1.y) + xf.p.y;
    upper.set(lower);

    for (int i = 1; i < m_count; ++i) {
      Vec2 v2 = m_vertices[i];
      v.x = (xf.q.c * v2.x - xf.q.s * v2.y) + xf.p.x;
      v.y = (xf.q.s * v2.x + xf.q.c * v2.y) + xf.p.y;
      // Vec2 v = Mul(xf, m_vertices[i]);
      Vec2.minToOut(lower, v, lower);
      Vec2.maxToOut(upper, v, upper);
    }

    // Vec2 r(m_radius, m_radius);
    // aabb.lowerBound = lower - r;
    // aabb.upperBound = upper + r;

    aabb.lowerBound.x -= m_radius;
    aabb.lowerBound.y -= m_radius;
    aabb.upperBound.x += m_radius;
    aabb.upperBound.y += m_radius;
  }
Example #8
0
 public Vec2
     getProjectileSpawnPoint() { // TODO move to an interface like IProjectileParent or something
   mProjectileSpawnPoint.set(
       mPhysics.getX() + 3,
       mPhysics.getY()); // TODO change arguments to mPhysics.getProjectileSpawn
   return mProjectileSpawnPoint;
 }
Example #9
0
  /**
   * Compute the collision manifold between two circles.
   *
   * @param manifold
   * @param circle1
   * @param xfA
   * @param circle2
   * @param xfB
   */
  public final void collideCircles(
      Manifold manifold,
      final CircleShape circle1,
      final Transform xfA,
      final CircleShape circle2,
      final Transform xfB) {
    manifold.pointCount = 0;

    Transform.mulToOut(xfA, circle1.m_p, pA);
    Transform.mulToOut(xfB, circle2.m_p, pB);

    d.set(pB).subLocal(pA);
    float distSqr = Vec2.dot(d, d);
    float radius = circle1.m_radius + circle2.m_radius;
    if (distSqr > radius * radius) {
      return;
    }

    manifold.type = ManifoldType.CIRCLES;
    manifold.localPoint.set(circle1.m_p);
    manifold.localNormal.setZero();
    manifold.pointCount = 1;

    manifold.points[0].localPoint.set(circle2.m_p);
    manifold.points[0].id.zero();
  }
Example #10
0
  public float raycastCallback(RayCastInput input, int nodeId) {
    Object userData = broadPhase.getUserData(nodeId);
    FixtureProxy proxy = (FixtureProxy) userData;
    Fixture fixture = proxy.fixture;
    int index = proxy.childIndex;
    boolean hit = fixture.raycast(output, input, index);

    if (hit) {
      float fraction = output.fraction;
      // Vec2 point = (1.0f - fraction) * input.p1 + fraction * input.p2;
      temp.set(input.p2).mulLocal(fraction);
      point.set(input.p1).mulLocal(1 - fraction).addLocal(temp);
      return callback.reportFixture(fixture, point, output.normal, fraction);
    }

    return input.maxFraction;
  }
  /** @see SupportsGenericDistance#support(Vec2, XForm, Vec2) */
  public void support(final Vec2 dest, final XForm xf, final Vec2 d) {
    final Vec2 supportV1 = tlSupportV1.get();
    final Vec2 supportV2 = tlSupportV2.get();

    XForm.mulToOut(xf, m_coreV1, supportV1);
    XForm.mulToOut(xf, m_coreV2, supportV2);
    dest.set(Vec2.dot(supportV1, d) > Vec2.dot(supportV2, d) ? supportV1 : supportV2);
  }
Example #12
0
  /**
   * 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 final void setMassData(MassData massData) {
    // TODO_ERIN adjust linear velocity and torque to account for movement of center.
    assert (m_world.isLocked() == false);
    if (m_world.isLocked() == true) {
      return;
    }

    if (m_type != BodyType.DYNAMIC) {
      return;
    }

    m_invMass = 0.0f;
    m_I = 0.0f;
    m_invI = 0.0f;

    m_mass = massData.mass;
    if (m_mass <= 0.0f) {
      m_mass = 1f;
    }

    m_invMass = 1.0f / m_mass;

    if (massData.I > 0.0f && (m_flags & e_fixedRotationFlag) == 0) {
      m_I = massData.I - m_mass * Vec2.dot(massData.center, massData.center);
      assert (m_I > 0.0f);
      m_invI = 1.0f / m_I;
    }

    final Vec2 oldCenter = m_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.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);
    final Vec2 temp = m_world.getPool().popVec2();
    temp.set(m_sweep.c).subLocal(oldCenter);
    Vec2.crossToOut(m_angularVelocity, temp, temp);
    m_linearVelocity.addLocal(temp);

    m_world.getPool().pushVec2(2);
  }
Example #13
0
  /**
   * Set the linear velocity of the center of mass.
   *
   * @param v the new linear velocity of the center of mass.
   */
  public final void setLinearVelocity(Vec2 v) {
    if (m_type == BodyType.STATIC) {
      return;
    }

    if (Vec2.dot(v, v) > 0.0f) {
      setAwake(true);
    }

    m_linearVelocity.set(v);
  }
 /**
  * Set this as a single edge.
  *
  * @param v1
  * @param v2
  * @deprecated
  */
 public final void setAsEdge(final Vec2 v1, final Vec2 v2) {
   m_count = 2;
   m_vertices[0].set(v1);
   m_vertices[1].set(v2);
   m_centroid.set(v1).addLocal(v2).mulLocal(0.5f);
   // = 0.5f * (v1 + v2);
   m_normals[0].set(v2).subLocal(v1);
   Vec2.crossToOut(m_normals[0], 1f, m_normals[0]);
   // m_normals[0] = Cross(v2 - v1, 1.0f);
   m_normals[0].normalize();
   m_normals[1].set(m_normals[0]).negateLocal();
 }
  @Override
  public void move(Body body) {
    Objects.requireNonNull(body);

    Vec2 v2 = new Vec2(2f, 0f);
    switch (nbCall) {
      case -1:
        nbCall++;
        break;
      case 0:
        if (body.getPosition().y * EscapeWorld.SCALE > (FrontApplication.WIDTH / 3 - 120)) {
          return;
        }
        v2.set(2f, 0f);
        break;
      case 1:
        if (body.getPosition().x * EscapeWorld.SCALE < (FrontApplication.WIDTH / 3)) {
          return;
        }
        v2.set(0f, 2f);
        break;
      case 2:
        if (body.getPosition().y * EscapeWorld.SCALE < (FrontApplication.WIDTH / 3)) {
          return;
        }
        v2.set(-2f, 0f);
        break;
      case 3:
        if (body.getPosition().x * EscapeWorld.SCALE > (FrontApplication.WIDTH / 3 - 120)) {
          return;
        }
        v2.set(0f, -2f);
        break;
      default:
        throw new AssertionError();
    }

    body.setLinearVelocity(v2);
    nbCall = (nbCall + 1) % 4;
  }
  /** @see Shape#testSegment(XForm, RaycastResult, Segment, float) */
  @Override
  public SegmentCollide testSegment(
      final XForm xf, final RaycastResult out, final Segment segment, final float maxLambda) {
    final Vec2 r = tlR.get();
    final Vec2 v1 = tlV1.get();
    final Vec2 d = tlD.get();
    final Vec2 n = tlN.get();
    final Vec2 b = tlB.get();

    r.set(segment.p2).subLocal(segment.p1);
    XForm.mulToOut(xf, m_v1, v1);
    XForm.mulToOut(xf, m_v2, d);
    d.subLocal(v1);
    Vec2.crossToOut(d, 1.0f, n);

    final float k_slop = 100.0f * Settings.EPSILON;
    final float denom = -Vec2.dot(r, n);

    // Cull back facing collision and ignore parallel segments.
    if (denom > k_slop) {
      // Does the segment intersect the infinite line associated with this segment?
      b.set(segment.p1).subLocal(v1);
      float a = Vec2.dot(b, n);

      if (0.0f <= a && a <= maxLambda * denom) {
        final float mu2 = -r.x * b.y + r.y * b.x;

        // Does the segment intersect this segment?
        if (-k_slop * denom <= mu2 && mu2 <= denom * (1.0f + k_slop)) {
          a /= denom;
          n.normalize();
          out.lambda = a;
          out.normal.set(n);
          return SegmentCollide.HIT_COLLIDE;
        }
      }
    }

    return SegmentCollide.MISS_COLLIDE;
  }
  /**
   * Validate convexity. This is a very time consuming operation.
   *
   * @return
   */
  public boolean validate() {
    for (int i = 0; i < m_count; ++i) {
      int i1 = i;
      int i2 = i < m_count - 1 ? i1 + 1 : 0;
      Vec2 p = m_vertices[i1];
      Vec2 e = pool1.set(m_vertices[i2]).subLocal(p);

      for (int j = 0; j < m_count; ++j) {
        if (j == i1 || j == i2) {
          continue;
        }

        Vec2 v = pool2.set(m_vertices[j]).subLocal(p);
        float c = Vec2.cross(e, v);
        if (c < 0.0f) {
          return false;
        }
      }
    }

    return true;
  }
  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);
  }
Example #19
0
  protected MouseJoint(IWorldPool argWorld, MouseJointDef def) {
    super(argWorld, def);
    assert (def.target.isValid());
    assert (def.maxForce >= 0);
    assert (def.frequencyHz >= 0);
    assert (def.dampingRatio >= 0);

    m_target.set(def.target);
    Transform.mulTransToOut(m_bodyB.getTransform(), m_target, m_localAnchor);

    m_maxForce = def.maxForce;
    m_impulse.setZero();

    m_frequencyHz = def.frequencyHz;
    m_dampingRatio = def.dampingRatio;

    m_beta = 0;
    m_gamma = 0;
  }
  /**
   * Build vertices to represent an oriented box.
   *
   * @param hx the half-width.
   * @param hy the half-height.
   * @param center the center of the box in local coordinates.
   * @param angle the rotation of the box in local coordinates.
   */
  public final void setAsBox(final float hx, final float hy, final Vec2 center, final float angle) {
    m_count = 4;
    m_vertices[0].set(-hx, -hy);
    m_vertices[1].set(hx, -hy);
    m_vertices[2].set(hx, hy);
    m_vertices[3].set(-hx, hy);
    m_normals[0].set(0.0f, -1.0f);
    m_normals[1].set(1.0f, 0.0f);
    m_normals[2].set(0.0f, 1.0f);
    m_normals[3].set(-1.0f, 0.0f);
    m_centroid.set(center);

    final Transform xf = poolt1;
    xf.p.set(center);
    xf.q.set(angle);

    // Transform vertices and normals.
    for (int i = 0; i < m_count; ++i) {
      Transform.mulToOut(xf, m_vertices[i], m_vertices[i]);
      Rot.mulToOut(xf.q, m_normals[i], m_normals[i]);
    }
  }
Example #21
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);
  }
Example #22
0
  /**
   * Compute the collision manifold between a polygon and a circle.
   *
   * @param manifold
   * @param polygon
   * @param xfA
   * @param circle
   * @param xfB
   */
  public final void collidePolygonAndCircle(
      Manifold manifold,
      final PolygonShape polygon,
      final Transform xfA,
      final CircleShape circle,
      final Transform xfB) {
    manifold.pointCount = 0;

    // Compute circle position in the frame of the polygon.
    Transform.mulToOut(xfB, circle.m_p, c);
    Transform.mulTransToOut(xfA, c, cLocal);

    // Find the min separating edge.
    int normalIndex = 0;
    float separation = Float.MIN_VALUE;
    float radius = polygon.m_radius + circle.m_radius;
    int vertexCount = polygon.m_vertexCount;

    Vec2[] vertices = polygon.m_vertices;
    Vec2[] normals = polygon.m_normals;

    for (int i = 0; i < vertexCount; i++) {
      temp.set(cLocal).subLocal(vertices[i]);
      float s = Vec2.dot(normals[i], temp);

      if (s > radius) {
        // early out
        return;
      }

      if (s > separation) {
        separation = s;
        normalIndex = i;
      }
    }

    // Vertices that subtend the incident face.
    int vertIndex1 = normalIndex;
    int vertIndex2 = vertIndex1 + 1 < vertexCount ? vertIndex1 + 1 : 0;
    Vec2 v1 = vertices[vertIndex1];
    Vec2 v2 = vertices[vertIndex2];

    // If the center is inside the polygon ...
    if (separation < Settings.EPSILON) {
      manifold.pointCount = 1;
      manifold.type = ManifoldType.FACE_A;
      manifold.localNormal.set(normals[normalIndex]);
      manifold.localPoint.set(v1).addLocal(v2).mulLocal(.5f);
      manifold.points[0].localPoint.set(circle.m_p);
      manifold.points[0].id.zero();
      return;
    }

    // Compute barycentric coordinates
    temp.set(cLocal).subLocal(v1);
    temp2.set(v2).subLocal(v1);
    float u1 = Vec2.dot(temp, temp2);
    temp.set(cLocal).subLocal(v2);
    temp2.set(v1).subLocal(v2);
    float u2 = Vec2.dot(temp, temp2);

    if (u1 <= 0f) {
      if (MathUtils.distanceSquared(cLocal, v1) > radius * radius) {
        return;
      }

      manifold.pointCount = 1;
      manifold.type = ManifoldType.FACE_A;
      manifold.localNormal.set(cLocal).subLocal(v1);
      manifold.localNormal.normalize();
      manifold.localPoint.set(v1);
      manifold.points[0].localPoint.set(circle.m_p);
      manifold.points[0].id.zero();
    } else if (u2 <= 0.0f) {
      if (MathUtils.distanceSquared(cLocal, v2) > radius * radius) {
        return;
      }

      manifold.pointCount = 1;
      manifold.type = ManifoldType.FACE_A;
      manifold.localNormal.set(cLocal).subLocal(v2);
      manifold.localNormal.normalize();
      manifold.localPoint.set(v2);
      manifold.points[0].localPoint.set(circle.m_p);
      manifold.points[0].id.zero();
    } else {
      // Vec2 faceCenter = 0.5f * (v1 + v2);
      // (temp is faceCenter)
      temp.set(v1).addLocal(v2).mulLocal(.5f);

      temp2.set(cLocal).subLocal(temp);
      separation = Vec2.dot(temp2, normals[vertIndex1]);
      if (separation > radius) {
        return;
      }

      manifold.pointCount = 1;
      manifold.type = ManifoldType.FACE_A;
      manifold.localNormal.set(normals[vertIndex1]);
      manifold.localPoint.set(temp); // (faceCenter)
      manifold.points[0].localPoint.set(circle.m_p);
      manifold.points[0].id.zero();
    }
  }
  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));
  }
Example #24
0
 /**
  * Change the global gravity vector.
  *
  * @param gravity
  */
 public void setGravity(Vec2 gravity) {
   m_gravity.set(gravity);
 }
Example #25
0
 @Override
 public void getReactionForce(float inv_dt, Vec2 argOut) {
   argOut.set(m_impulse.x, m_impulse.y).mulLocal(inv_dt);
 }
  /**
   * Create a convex hull from the given array of points. The count must be in the range [3,
   * Settings.maxPolygonVertices]. This method takes an arraypool for pooling
   *
   * @warning the points may be re-ordered, even if they form a convex polygon
   * @warning collinear points are handled but not removed. Collinear points may lead to poor
   *     stacking behavior.
   */
  public final void set(
      final Vec2[] verts, final int num, final Vec2Array vecPool, final IntArray intPool) {
    assert (3 <= num && num <= Settings.maxPolygonVertices);
    if (num < 3) {
      setAsBox(1.0f, 1.0f);
      return;
    }

    int n = MathUtils.min(num, Settings.maxPolygonVertices);

    // Copy the vertices into a local buffer
    Vec2[] ps = (vecPool != null) ? vecPool.get(n) : new Vec2[n];
    for (int i = 0; i < n; ++i) {
      ps[i] = verts[i];
    }

    // Create the convex hull using the Gift wrapping algorithm
    // http://en.wikipedia.org/wiki/Gift_wrapping_algorithm

    // Find the right most point on the hull
    int i0 = 0;
    float x0 = ps[0].x;
    for (int i = 1; i < num; ++i) {
      float x = ps[i].x;
      if (x > x0 || (x == x0 && ps[i].y < ps[i0].y)) {
        i0 = i;
        x0 = x;
      }
    }

    int[] hull =
        (intPool != null)
            ? intPool.get(Settings.maxPolygonVertices)
            : new int[Settings.maxPolygonVertices];
    int m = 0;
    int ih = i0;

    while (true) {
      hull[m] = ih;

      int ie = 0;
      for (int j = 1; j < n; ++j) {
        if (ie == ih) {
          ie = j;
          continue;
        }

        Vec2 r = pool1.set(ps[ie]).subLocal(ps[hull[m]]);
        Vec2 v = pool2.set(ps[j]).subLocal(ps[hull[m]]);
        float c = Vec2.cross(r, v);
        if (c < 0.0f) {
          ie = j;
        }

        // Collinearity check
        if (c == 0.0f && v.lengthSquared() > r.lengthSquared()) {
          ie = j;
        }
      }

      ++m;
      ih = ie;

      if (ie == i0) {
        break;
      }
    }

    this.m_count = m;

    // Copy vertices.
    for (int i = 0; i < m_count; ++i) {
      if (m_vertices[i] == null) {
        m_vertices[i] = new Vec2();
      }
      m_vertices[i].set(ps[hull[i]]);
    }

    final Vec2 edge = pool1;

    // Compute normals. Ensure the edges have non-zero length.
    for (int i = 0; i < m_count; ++i) {
      final int i1 = i;
      final int i2 = i + 1 < m_count ? i + 1 : 0;
      edge.set(m_vertices[i2]).subLocal(m_vertices[i1]);

      assert (edge.lengthSquared() > Settings.EPSILON * Settings.EPSILON);
      Vec2.crossToOutUnsafe(edge, 1f, m_normals[i]);
      m_normals[i].normalize();
    }

    // Compute the polygon centroid.
    computeCentroidToOut(m_vertices, m_count, m_centroid);
  }
Example #27
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;
    }
  }
Example #28
0
  /**
   * Compute the collision manifold between two polygons.
   *
   * @param manifold
   * @param polygon1
   * @param xf1
   * @param polygon2
   * @param xf2
   */
  public final void collidePolygons(
      Manifold manifold,
      final PolygonShape polyA,
      final Transform xfA,
      final PolygonShape polyB,
      final Transform xfB) {
    // Find edge normal of max separation on A - return if separating axis is found
    // Find edge normal of max separation on B - return if separation axis is found
    // Choose reference edge as min(minA, minB)
    // Find incident edge
    // Clip

    // The normal points from 1 to 2

    manifold.pointCount = 0;
    float totalRadius = polyA.m_radius + polyB.m_radius;

    findMaxSeparation(results1, polyA, xfA, polyB, xfB);
    if (results1.separation > totalRadius) {
      return;
    }

    findMaxSeparation(results2, polyB, xfB, polyA, xfA);
    if (results2.separation > totalRadius) {
      return;
    }

    final PolygonShape poly1; // reference polygon
    final PolygonShape poly2; // incident polygon
    Transform xf1, xf2;
    int edge1; // reference edge
    int flip;
    final float k_relativeTol = 0.98f;
    final float k_absoluteTol = 0.001f;

    if (results2.separation > k_relativeTol * results1.separation + k_absoluteTol) {
      poly1 = polyB;
      poly2 = polyA;
      xf1 = xfB;
      xf2 = xfA;
      edge1 = results2.edgeIndex;
      manifold.type = ManifoldType.FACE_B;
      flip = 1;
    } else {
      poly1 = polyA;
      poly2 = polyB;
      xf1 = xfA;
      xf2 = xfB;
      edge1 = results1.edgeIndex;
      manifold.type = ManifoldType.FACE_A;
      flip = 0;
    }

    findIncidentEdge(incidentEdge, poly1, xf1, edge1, poly2, xf2);

    int count1 = poly1.m_vertexCount;
    final Vec2[] vertices1 = poly1.m_vertices;

    v11.set(vertices1[edge1]);
    v12.set(edge1 + 1 < count1 ? vertices1[edge1 + 1] : vertices1[0]);

    localTangent.set(v12).subLocal(v11);
    localTangent.normalize();

    Vec2.crossToOut(localTangent, 1f, localNormal); // Vec2 localNormal = Cross(dv,
    // 1.0f);

    planePoint.set(v11).addLocal(v12).mulLocal(.5f); // Vec2 planePoint = 0.5f * (v11
    // + v12);

    Mat22.mulToOut(xf1.R, localTangent, tangent); // Vec2 sideNormal = Mul(xf1.R, v12
    // - v11);
    Vec2.crossToOut(tangent, 1f, normal); // Vec2 frontNormal = Cross(sideNormal,
    // 1.0f);

    Transform.mulToOut(xf1, v11, v11);
    Transform.mulToOut(xf1, v12, v12);
    // v11 = Mul(xf1, v11);
    // v12 = Mul(xf1, v12);

    // Face offset
    float frontOffset = Vec2.dot(normal, v11);

    // Side offsets, extended by polytope skin thickness.
    float sideOffset1 = -Vec2.dot(tangent, v11) + totalRadius;
    float sideOffset2 = Vec2.dot(tangent, v12) + totalRadius;

    // Clip incident edge against extruded edge1 side edges.
    // ClipVertex clipPoints1[2];
    // ClipVertex clipPoints2[2];
    int np;

    // Clip to box side 1
    // np = ClipSegmentToLine(clipPoints1, incidentEdge, -sideNormal, sideOffset1);
    tangent.negateLocal();
    np = clipSegmentToLine(clipPoints1, incidentEdge, tangent, sideOffset1);
    tangent.negateLocal();

    if (np < 2) {
      return;
    }

    // Clip to negative box side 1
    np = clipSegmentToLine(clipPoints2, clipPoints1, tangent, sideOffset2);

    if (np < 2) {
      return;
    }

    // Now clipPoints2 contains the clipped points.
    manifold.localNormal.set(localNormal);
    manifold.localPoint.set(planePoint);

    int pointCount = 0;
    for (int i = 0; i < Settings.maxManifoldPoints; ++i) {
      float separation = Vec2.dot(normal, clipPoints2[i].v) - frontOffset;

      if (separation <= totalRadius) {
        ManifoldPoint cp = manifold.points[pointCount];
        Transform.mulTransToOut(xf2, clipPoints2[i].v, cp.localPoint);
        // cp.m_localPoint = MulT(xf2, clipPoints2[i].v);
        cp.id.set(clipPoints2[i].id);
        cp.id.features.flip = flip;
        ++pointCount;
      }
    }

    manifold.pointCount = pointCount;
  }
Example #29
0
 public void set(final ClipVertex cv) {
   v.set(cv.v);
   id.set(cv.id);
 }
  @Override
  public final boolean raycast(
      RayCastOutput output, RayCastInput input, Transform xf, int childIndex) {
    final Vec2 p1 = pool1;
    final Vec2 p2 = pool2;
    final Vec2 d = pool3;
    final Vec2 temp = pool4;

    p1.set(input.p1).subLocal(xf.p);
    Rot.mulTrans(xf.q, p1, p1);
    p2.set(input.p2).subLocal(xf.p);
    Rot.mulTrans(xf.q, p2, p2);
    d.set(p2).subLocal(p1);

    // if (count == 2) {

    // } else {

    float lower = 0, upper = input.maxFraction;

    int index = -1;

    for (int i = 0; i < m_count; ++i) {
      // p = p1 + a * d
      // dot(normal, p - v) = 0
      // dot(normal, p1 - v) + a * dot(normal, d) = 0
      temp.set(m_vertices[i]).subLocal(p1);
      final float numerator = Vec2.dot(m_normals[i], temp);
      final float denominator = Vec2.dot(m_normals[i], d);

      if (denominator == 0.0f) {
        if (numerator < 0.0f) {
          return false;
        }
      } else {
        // Note: we want this predicate without division:
        // lower < numerator / denominator, where denominator < 0
        // Since denominator < 0, we have to flip the inequality:
        // lower < numerator / denominator <==> denominator * lower >
        // numerator.
        if (denominator < 0.0f && numerator < lower * denominator) {
          // Increase lower.
          // The segment enters this half-space.
          lower = numerator / denominator;
          index = i;
        } else if (denominator > 0.0f && numerator < upper * denominator) {
          // Decrease upper.
          // The segment exits this half-space.
          upper = numerator / denominator;
        }
      }

      if (upper < lower) {
        return false;
      }
    }

    assert (0.0f <= lower && lower <= input.maxFraction);

    if (index >= 0) {
      output.fraction = lower;
      Rot.mulToOutUnsafe(xf.q, m_normals[index], output.normal);
      // normal = Mul(xf.R, m_normals[index]);
      return true;
    }
    return false;
  }