Beispiel #1
0
 public boolean processGestureEvent(MTGestureEvent ge) {
   DragEvent de = (DragEvent) ge;
   try {
     Body body = (Body) comp.getUserData("box2d");
     MouseJoint mouseJoint;
     Vector3D to = new Vector3D(de.getTo());
     // Un-scale position from mt4j to box2d
     PhysicsHelper.scaleDown(to, scale);
     switch (de.getId()) {
       case DragEvent.GESTURE_STARTED:
         comp.sendToFront();
         body.wakeUp();
         body.setXForm(new Vec2(to.x, to.y), body.getAngle());
         mouseJoint = PhysicsHelper.createDragJoint(world, body, to.x, to.y);
         comp.setUserData(comp.getID(), mouseJoint);
         break;
       case DragEvent.GESTURE_UPDATED:
         mouseJoint = (MouseJoint) comp.getUserData(comp.getID());
         if (mouseJoint != null) {
           boolean onCorrectGameSide =
               ((MTComponent) de.getTarget()).containsPointGlobal(de.getTo());
           // System.out.println(((MTComponent)de.getTargetComponent()).getName()  + " Contains
           // " + to + " -> " + contains);
           if (onCorrectGameSide) {
             mouseJoint.setTarget(new Vec2(to.x, to.y));
           }
         }
         break;
       case DragEvent.GESTURE_ENDED:
         mouseJoint = (MouseJoint) comp.getUserData(comp.getID());
         if (mouseJoint != null) {
           comp.setUserData(comp.getID(), null);
           // Only destroy the joint if it isnt already (go through joint list and check)
           for (Joint joint = world.getJointList(); joint != null; joint = joint.getNext()) {
             JointType type = joint.getType();
             switch (type) {
               case MOUSE_JOINT:
                 MouseJoint mj = (MouseJoint) joint;
                 if (body.equals(mj.getBody1()) || body.equals(mj.getBody2())) {
                   if (mj.equals(mouseJoint)) {
                     world.destroyJoint(mj);
                   }
                 }
                 break;
               default:
                 break;
             }
           }
         }
         mouseJoint = null;
         break;
       default:
         break;
     }
   } catch (Exception e) {
     System.err.println(e.getMessage());
   }
   return false;
 }
Beispiel #2
0
  public void step(float dt, int iterations) {
    if (joint != null) {
      Vec2 force = joint.getReactionForce();
      float forceAngle = PhysicsUtils.angle(force);
      float forceMag = force.length();

      if (forceMag > reactionThreshold) {
        /*
         * First, check for direction.
         */
        if (angleLo == angleHi || (forceAngle >= angleLo && forceAngle <= angleHi)) {
          // Ok, this one's done with. Kill it.
          joint.getBody1().getWorld().destroyJoint(joint);
          joint = null;
          joint.getBody1().getWorld().unregisterPostStep(this);
        }
      }
    }
  }
Beispiel #3
0
  /**
   * create a joint to constrain bodies together. No reference to the definition is retained. This
   * may cause the connected bodies to cease colliding.
   *
   * @warning This function is locked during callbacks.
   * @param def
   * @return
   */
  public Joint createJoint(JointDef def) {
    assert (isLocked() == false);
    if (isLocked()) {
      return null;
    }

    Joint j = Joint.create(this, def);

    // Connect to the world list.
    j.m_prev = null;
    j.m_next = m_jointList;
    if (m_jointList != null) {
      m_jointList.m_prev = j;
    }
    m_jointList = j;
    ++m_jointCount;

    // Connect to the bodies' doubly linked lists.
    j.m_edgeA.joint = j;
    j.m_edgeA.other = j.m_bodyB;
    j.m_edgeA.prev = null;
    j.m_edgeA.next = j.m_bodyA.m_jointList;
    if (j.m_bodyA.m_jointList != null) {
      j.m_bodyA.m_jointList.prev = j.m_edgeA;
    }
    j.m_bodyA.m_jointList = j.m_edgeA;

    j.m_edgeB.joint = j;
    j.m_edgeB.other = j.m_bodyA;
    j.m_edgeB.prev = null;
    j.m_edgeB.next = j.m_bodyB.m_jointList;
    if (j.m_bodyB.m_jointList != null) {
      j.m_bodyB.m_jointList.prev = j.m_edgeB;
    }
    j.m_bodyB.m_jointList = j.m_edgeB;

    Body bodyA = def.bodyA;
    Body bodyB = def.bodyB;

    // If the joint prevents collisions, then flag any contacts for filtering.
    if (def.collideConnected == false) {
      ContactEdge edge = bodyB.getContactList();
      while (edge != null) {
        if (edge.other == bodyA) {
          // Flag the contact for filtering at the next time step (where either
          // body is awake).
          edge.contact.flagForFiltering();
        }

        edge = edge.next;
      }
    }

    // Note: creating a joint doesn't wake the bodies.

    return j;
  }
Beispiel #4
0
  private void drawJoint(Joint joint) {
    Body bodyA = joint.getBodyA();
    Body bodyB = joint.getBodyB();
    Transform xf1 = bodyA.getTransform();
    Transform xf2 = bodyB.getTransform();
    Vec2 x1 = xf1.p;
    Vec2 x2 = xf2.p;
    Vec2 p1 = pool.popVec2();
    Vec2 p2 = pool.popVec2();
    joint.getAnchorA(p1);
    joint.getAnchorB(p2);

    color.set(0.5f, 0.8f, 0.8f);

    switch (joint.getType()) {
        // TODO djm write after writing joints
      case DISTANCE:
        m_debugDraw.drawSegment(p1, p2, color);
        break;

      case PULLEY:
        {
          PulleyJoint pulley = (PulleyJoint) joint;
          Vec2 s1 = pulley.getGroundAnchorA();
          Vec2 s2 = pulley.getGroundAnchorB();
          m_debugDraw.drawSegment(s1, p1, color);
          m_debugDraw.drawSegment(s2, p2, color);
          m_debugDraw.drawSegment(s1, s2, color);
        }
        break;
      case CONSTANT_VOLUME:
      case MOUSE:
        // don't draw this
        break;
      default:
        m_debugDraw.drawSegment(x1, p1, color);
        m_debugDraw.drawSegment(p1, p2, color);
        m_debugDraw.drawSegment(x2, p2, color);
    }
    pool.pushVec2(2);
  }
Beispiel #5
0
  private void solve(TimeStep step) {
    m_profile.solveInit = 0;
    m_profile.solveVelocity = 0;
    m_profile.solvePosition = 0;

    // Size the island for the worst case.
    island.init(
        m_bodyCount,
        m_contactManager.m_contactCount,
        m_jointCount,
        m_contactManager.m_contactListener);

    // Clear all the island flags.
    for (Body b = m_bodyList; b != null; b = b.m_next) {
      b.m_flags &= ~Body.e_islandFlag;
    }
    for (Contact c = m_contactManager.m_contactList; c != null; c = c.m_next) {
      c.m_flags &= ~Contact.ISLAND_FLAG;
    }
    for (Joint j = m_jointList; j != null; j = j.m_next) {
      j.m_islandFlag = false;
    }

    // Build and simulate all awake islands.
    int stackSize = m_bodyCount;
    if (stack.length < stackSize) {
      stack = new Body[stackSize];
    }
    for (Body seed = m_bodyList; seed != null; seed = seed.m_next) {
      if ((seed.m_flags & Body.e_islandFlag) == Body.e_islandFlag) {
        continue;
      }

      if (seed.isAwake() == false || seed.isActive() == false) {
        continue;
      }

      // The seed can be dynamic or kinematic.
      if (seed.getType() == BodyType.STATIC) {
        continue;
      }

      // Reset island and stack.
      island.clear();
      int stackCount = 0;
      stack[stackCount++] = seed;
      seed.m_flags |= Body.e_islandFlag;

      // Perform a depth first search (DFS) on the constraint graph.
      while (stackCount > 0) {
        // Grab the next body off the stack and add it to the island.
        Body b = stack[--stackCount];
        assert (b.isActive() == true);
        island.add(b);

        // Make sure the body is awake.
        b.setAwake(true);

        // To keep islands as small as possible, we don't
        // propagate islands across static bodies.
        if (b.getType() == BodyType.STATIC) {
          continue;
        }

        // Search all contacts connected to this body.
        for (ContactEdge ce = b.m_contactList; ce != null; ce = ce.next) {
          Contact contact = ce.contact;

          // Has this contact already been added to an island?
          if ((contact.m_flags & Contact.ISLAND_FLAG) == Contact.ISLAND_FLAG) {
            continue;
          }

          // Is this contact solid and touching?
          if (contact.isEnabled() == false || contact.isTouching() == false) {
            continue;
          }

          // Skip sensors.
          boolean sensorA = contact.m_fixtureA.m_isSensor;
          boolean sensorB = contact.m_fixtureB.m_isSensor;
          if (sensorA || sensorB) {
            continue;
          }

          island.add(contact);
          contact.m_flags |= Contact.ISLAND_FLAG;

          Body other = ce.other;

          // Was the other body already added to this island?
          if ((other.m_flags & Body.e_islandFlag) == Body.e_islandFlag) {
            continue;
          }

          assert (stackCount < stackSize);
          stack[stackCount++] = other;
          other.m_flags |= Body.e_islandFlag;
        }

        // Search all joints connect to this body.
        for (JointEdge je = b.m_jointList; je != null; je = je.next) {
          if (je.joint.m_islandFlag == true) {
            continue;
          }

          Body other = je.other;

          // Don't simulate joints connected to inactive bodies.
          if (other.isActive() == false) {
            continue;
          }

          island.add(je.joint);
          je.joint.m_islandFlag = true;

          if ((other.m_flags & Body.e_islandFlag) == Body.e_islandFlag) {
            continue;
          }

          assert (stackCount < stackSize);
          stack[stackCount++] = other;
          other.m_flags |= Body.e_islandFlag;
        }
      }
      island.solve(islandProfile, step, m_gravity, m_allowSleep);
      m_profile.solveInit += islandProfile.solveInit;
      m_profile.solveVelocity += islandProfile.solveVelocity;
      m_profile.solvePosition += islandProfile.solvePosition;

      // Post solve cleanup.
      for (int i = 0; i < island.m_bodyCount; ++i) {
        // Allow static bodies to participate in other islands.
        Body b = island.m_bodies[i];
        if (b.getType() == BodyType.STATIC) {
          b.m_flags &= ~Body.e_islandFlag;
        }
      }
    }

    broadphaseTimer.reset();
    // Synchronize fixtures, check for out of range bodies.
    for (Body b = m_bodyList; b != null; b = b.getNext()) {
      // If a body was not in an island then it did not move.
      if ((b.m_flags & Body.e_islandFlag) == 0) {
        continue;
      }

      if (b.getType() == BodyType.STATIC) {
        continue;
      }

      // Update fixtures (for broad-phase).
      b.synchronizeFixtures();
    }

    // Look for new contacts.
    m_contactManager.findNewContacts();
    m_profile.broadphase = broadphaseTimer.getMilliseconds();
  }
Beispiel #6
0
  /** Call this to draw shapes and other debug draw data. */
  public void drawDebugData() {
    if (m_debugDraw == null) {
      return;
    }

    int flags = m_debugDraw.getFlags();

    if ((flags & DebugDraw.e_shapeBit) == DebugDraw.e_shapeBit) {
      for (Body b = m_bodyList; b != null; b = b.getNext()) {
        xf.set(b.getTransform());
        for (Fixture f = b.getFixtureList(); f != null; f = f.getNext()) {
          if (b.isActive() == false) {
            color.set(0.5f, 0.5f, 0.3f);
            drawShape(f, xf, color);
          } else if (b.getType() == BodyType.STATIC) {
            color.set(0.5f, 0.9f, 0.3f);
            drawShape(f, xf, color);
          } else if (b.getType() == BodyType.KINEMATIC) {
            color.set(0.5f, 0.5f, 0.9f);
            drawShape(f, xf, color);
          } else if (b.isAwake() == false) {
            color.set(0.5f, 0.5f, 0.5f);
            drawShape(f, xf, color);
          } else {
            color.set(0.9f, 0.7f, 0.7f);
            drawShape(f, xf, color);
          }
        }
      }
    }

    if ((flags & DebugDraw.e_jointBit) == DebugDraw.e_jointBit) {
      for (Joint j = m_jointList; j != null; j = j.getNext()) {
        drawJoint(j);
      }
    }

    if ((flags & DebugDraw.e_pairBit) == DebugDraw.e_pairBit) {
      color.set(0.3f, 0.9f, 0.9f);
      for (Contact c = m_contactManager.m_contactList; c != null; c = c.getNext()) {
        // Fixture fixtureA = c.getFixtureA();
        // Fixture fixtureB = c.getFixtureB();
        //
        // fixtureA.getAABB(childIndex).getCenterToOut(cA);
        // fixtureB.getAABB().getCenterToOut(cB);
        //
        // m_debugDraw.drawSegment(cA, cB, color);
      }
    }

    if ((flags & DebugDraw.e_aabbBit) == DebugDraw.e_aabbBit) {
      color.set(0.9f, 0.3f, 0.9f);

      for (Body b = m_bodyList; b != null; b = b.getNext()) {
        if (b.isActive() == false) {
          continue;
        }

        for (Fixture f = b.getFixtureList(); f != null; f = f.getNext()) {

          for (int i = 0; i < f.m_proxyCount; ++i) {
            FixtureProxy proxy = f.m_proxies[i];
            AABB aabb = m_contactManager.m_broadPhase.getFatAABB(proxy.proxyId);
            Vec2[] vs = avs.get(4);
            vs[0].set(aabb.lowerBound.x, aabb.lowerBound.y);
            vs[1].set(aabb.upperBound.x, aabb.lowerBound.y);
            vs[2].set(aabb.upperBound.x, aabb.upperBound.y);
            vs[3].set(aabb.lowerBound.x, aabb.upperBound.y);

            m_debugDraw.drawPolygon(vs, 4, color);
          }
        }
      }
    }

    if ((flags & DebugDraw.e_centerOfMassBit) == DebugDraw.e_centerOfMassBit) {
      for (Body b = m_bodyList; b != null; b = b.getNext()) {
        xf.set(b.getTransform());
        xf.p.set(b.getWorldCenter());
        m_debugDraw.drawTransform(xf);
      }
    }

    if ((flags & DebugDraw.e_dynamicTreeBit) == DebugDraw.e_dynamicTreeBit) {
      m_contactManager.m_broadPhase.drawTree(m_debugDraw);
    }
  }
Beispiel #7
0
  /**
   * destroy a joint. This may cause the connected bodies to begin colliding.
   *
   * @warning This function is locked during callbacks.
   * @param joint
   */
  public void destroyJoint(Joint j) {
    assert (isLocked() == false);
    if (isLocked()) {
      return;
    }

    boolean collideConnected = j.m_collideConnected;

    // Remove from the doubly linked list.
    if (j.m_prev != null) {
      j.m_prev.m_next = j.m_next;
    }

    if (j.m_next != null) {
      j.m_next.m_prev = j.m_prev;
    }

    if (j == m_jointList) {
      m_jointList = j.m_next;
    }

    // Disconnect from island graph.
    Body bodyA = j.m_bodyA;
    Body bodyB = j.m_bodyB;

    // Wake up connected bodies.
    bodyA.setAwake(true);
    bodyB.setAwake(true);

    // Remove from body 1.
    if (j.m_edgeA.prev != null) {
      j.m_edgeA.prev.next = j.m_edgeA.next;
    }

    if (j.m_edgeA.next != null) {
      j.m_edgeA.next.prev = j.m_edgeA.prev;
    }

    if (j.m_edgeA == bodyA.m_jointList) {
      bodyA.m_jointList = j.m_edgeA.next;
    }

    j.m_edgeA.prev = null;
    j.m_edgeA.next = null;

    // Remove from body 2
    if (j.m_edgeB.prev != null) {
      j.m_edgeB.prev.next = j.m_edgeB.next;
    }

    if (j.m_edgeB.next != null) {
      j.m_edgeB.next.prev = j.m_edgeB.prev;
    }

    if (j.m_edgeB == bodyB.m_jointList) {
      bodyB.m_jointList = j.m_edgeB.next;
    }

    j.m_edgeB.prev = null;
    j.m_edgeB.next = null;

    Joint.destroy(j);

    assert (m_jointCount > 0);
    --m_jointCount;

    // If the joint prevents collisions, then flag any contacts for filtering.
    if (collideConnected == false) {
      ContactEdge edge = bodyB.getContactList();
      while (edge != null) {
        if (edge.other == bodyA) {
          // Flag the contact for filtering at the next time step (where either
          // body is awake).
          edge.contact.flagForFiltering();
        }

        edge = edge.next;
      }
    }
  }
Beispiel #8
0
 // ewjordan: I've added a Destroy method because although
 // these usually just deallocate memory, it is possible that
 // Erin may alter them to do more nontrivial things, and we
 // should be prepared for this possibility.
 // Note: this now happens in ConstantVolumeJoint, because
 // it contains distance joints that also need to be destroyed.
 public static void destroy(final Joint j) {
   j.destructor();
   return;
 }