/**
   * Creates and applies the fixtures defined in the editor. The name parameter is used to retrieve
   * the right fixture from the loaded file. <br>
   * <br>
   * The body reference point (the red cross in the tool) is by default located at the bottom left
   * corner of the image. This reference point will be put right over the BodyDef position point.
   * Therefore, you should place this reference point carefully to let you place your body in your
   * world easily with its BodyDef.position point. Note that to draw an image at the position of
   * your body, you will need to know this reference point (see {@link #getOrigin(java.lang.String,
   * float)}. <br>
   * <br>
   * Also, saved shapes are normalized. As shown in the tool, the width of the image is considered
   * to be always 1 meter. Thus, you need to provide a scale factor so the polygons get resized
   * according to your needs (not every body is 1 meter large in your game, I guess).
   *
   * @param body The Box2d body you want to attach the fixture to.
   * @param name The name of the fixture you want to load.
   * @param def The fixture parameters to apply to the created body fixture.
   * @param scale The desired scale of the body. The default width is 1.
   */
  public void attachFixture(Body body, String name, FixtureDef def, float scale) {
    RigidBodyModel rbModel = this.MODEL.RIGIDBODIES.get(name);
    if (rbModel == null) throw new RuntimeException("Name '" + name + "' was not found.");

    Vector2 origin = this.VEC.set(rbModel.ORIGIN).scl(scale);

    for (int i = 0, n = rbModel.POLYGONS.size(); i < n; i++) {
      PolygonModel polygon = rbModel.POLYGONS.get(i);
      Vector2[] vertices = polygon.buffer;

      for (int j = 0, n2 = vertices.length; j < n2; j++) {
        vertices[j] = newVec().set(polygon.VERTICES.get(j)).scl(scale);
        vertices[j].sub(origin);
      }

      this.POLYGONSHAPE.set(vertices);
      def.shape = this.POLYGONSHAPE;
      body.createFixture(def);

      for (int j = 0, n2 = vertices.length; j < n2; j++) {
        free(vertices[j]);
      }
    }

    for (int i = 0, n = rbModel.CIRCLES.size(); i < n; i++) {
      CircleModel circle = rbModel.CIRCLES.get(i);
      Vector2 center = newVec().set(circle.CENTER).scl(scale);
      float radius = circle.radius * scale;

      this.CIRCLESHAPE.setPosition(center);
      this.CIRCLESHAPE.setRadius(radius);
      def.shape = this.CIRCLESHAPE;
      body.createFixture(def);

      free(center);
    }
  }
  private RigidBodyModel readRigidBody(JsonValue bodyElem) {
    RigidBodyModel rbModel = new RigidBodyModel();
    rbModel.name = bodyElem.getString("name");
    rbModel.imagePath = bodyElem.getString("imagePath");

    JsonValue originElem = bodyElem.get("origin");
    rbModel.ORIGIN.x = originElem.getFloat("x");
    rbModel.ORIGIN.y = originElem.getFloat("y");

    // polygons
    JsonValue polygonsElem = bodyElem.getChild("polygons");
    for (; polygonsElem != null; polygonsElem = polygonsElem.next()) {
      PolygonModel polygon = new PolygonModel();
      rbModel.POLYGONS.add(polygon);

      JsonValue vertexElem = polygonsElem.child();
      for (; vertexElem != null; vertexElem = vertexElem.next()) {
        float x = vertexElem.getFloat("x");
        float y = vertexElem.getFloat("y");
        polygon.VERTICES.add(new Vector2(x, y));
      }

      polygon.buffer = new Vector2[polygon.VERTICES.size()];
    }

    // circles
    JsonValue circleElem = bodyElem.getChild("circles");

    for (; circleElem != null; circleElem = circleElem.next()) {
      CircleModel circle = new CircleModel();
      rbModel.CIRCLES.add(circle);

      circle.CENTER.x = circleElem.getFloat("cx");
      circle.CENTER.y = circleElem.getFloat("cy");
      circle.radius = circleElem.getFloat("r");
    }

    return rbModel;
  }