private void aabbCompute() {
    float minX = Integer.MAX_VALUE,
        minY = Integer.MAX_VALUE,
        maxX = Integer.MIN_VALUE,
        maxY = Integer.MIN_VALUE;

    for (final FloatArray polygon : polygons) {
      float[] vertices = polygon.elements();

      for (int vertexIndex = 0, vertexCount = polygon.size();
          vertexIndex < vertexCount;
          vertexIndex += 2) {
        final float x = vertices[vertexIndex];
        final float y = vertices[vertexIndex + 1];
        minX = Math.min(minX, x);
        minY = Math.min(minY, y);
        maxX = Math.max(maxX, x);
        maxY = Math.max(maxY, y);
      }
    }

    this.minX = minX;
    this.minY = minY;
    this.maxX = maxX;
    this.maxY = maxY;
  }
  /** Returns true if the polygon contains the line segment. */
  public boolean intersectsSegment(
      @Nonnull final FloatArray polygon,
      final float x1,
      final float y1,
      final float x2,
      final float y2) {
    final float[] vertices = polygon.elements();
    final int vertexCount = polygon.size();

    float width12 = x1 - x2, height12 = y1 - y2;
    float det1 = x1 * y2 - y1 * x2;
    float x3 = vertices[vertexCount - 2], y3 = vertices[vertexCount - 1];
    for (int vertexIndex = 0; vertexIndex < vertexCount; vertexIndex += 2) {
      float x4 = vertices[vertexIndex], y4 = vertices[vertexIndex + 1];
      float det2 = x3 * y4 - y3 * x4;
      float width34 = x3 - x4, height34 = y3 - y4;
      float det3 = width12 * height34 - height12 * width34;
      float x = (det1 * width34 - width12 * det2) / det3;
      if (((x >= x3 && x <= x4) || (x >= x4 && x <= x3))
          && ((x >= x1 && x <= x2) || (x >= x2 && x <= x1))) {
        float y = (det1 * height34 - height12 * det2) / det3;
        if (((y >= y3 && y <= y4) || (y >= y4 && y <= y3))
            && ((y >= y1 && y <= y2) || (y >= y2 && y <= y1))) return true;
      }
      x3 = x4;
      y3 = y4;
    }
    return false;
  }
  public void update(Skeleton skeleton, boolean updateAabb) {
    final Array<BoundingBoxAttachment> boundingBoxes = this.boundingBoxes;
    final Array<FloatArray> polygons = this.polygons;
    final Array<Slot> slots = skeleton.slots;

    boundingBoxes.clear();
    polygonPool.retAll(polygons);
    polygons.clear();

    for (final Slot slot : slots) {
      final Attachment attachment = slot.attachment;

      if (attachment instanceof BoundingBoxAttachment) {
        final BoundingBoxAttachment boundingBox = (BoundingBoxAttachment) attachment;
        boundingBoxes.push(boundingBox);

        final FloatArray polygon = polygonPool.get();

        polygons.push(polygon);

        final int vertexCount = boundingBox.vertices().length;

        polygon.size(vertexCount);

        boundingBox.computeWorldVertices(slot.bone, polygon.elements());
      }
    }

    if (updateAabb) {
      aabbCompute();
    }
  }
  /** Returns true if the polygon contains the point. */
  public boolean containsPoint(@Nonnull final FloatArray polygon, final float x, final float y) {
    final float[] vertices = polygon.elements();
    final int vertexCount = polygon.size();

    int prevIndex = vertexCount - 2;
    boolean inside = false;

    for (int vertexIndex = 0; vertexIndex < vertexCount; vertexIndex += 2) {
      final float vertexY = vertices[vertexIndex + 1];
      final float prevY = vertices[prevIndex + 1];

      if ((vertexY < y && prevY >= y) || (prevY < y && vertexY >= y)) {
        final float vertexX = vertices[vertexIndex];

        if (vertexX + (y - vertexY) / (prevY - vertexY) * (vertices[prevIndex] - vertexX) < x) {
          inside = !inside;
        }
      }

      prevIndex = vertexIndex;
    }
    return inside;
  }