Example #1
0
  public Winding addBackface() {
    if (verts.isEmpty()) {
      return this;
    }

    List<Vector3f> vertsNew = new ArrayList<>();

    final int size = verts.size();

    for (int i = 0; i < size; i++) {
      if (i != 0) {
        vertsNew.add(verts.get(i));
      }
      if (i != size) {
        vertsNew.add(verts.get(i));
      }
    }

    return new Winding(vertsNew);
  }
Example #2
0
  /**
   * Clips this winding to a plane defined by a normal and distance, removing all vertices in front
   * or behind it.
   *
   * <p>Equals ClipWindingEpsilon() in polylib.cpp
   *
   * @param normal plane normal
   * @param dist plane distance to origin
   * @param eps clipping epsilon
   * @param back keep vertices behind the plane?
   */
  public Winding clipEpsilon(Vector3f normal, float dist, float eps, boolean back) {
    // counts number of front, back and on vertices
    int[] counts = new int[] {0, 0, 0};
    final int size = verts.size();
    float[] dists = new float[size + 1];
    int[] sides = new int[size + 1];

    // determine sides for each point
    for (int i = 0; i < size; i++) {
      // distance along norm-dirn from origin to vertex
      float dot = verts.get(i).dot(normal);

      // distance along norm-dirn from clip plane to vertex
      dot -= dist;

      // store it
      dists[i] = dot;

      if (dot > eps) {
        // vertex in front of plane
        sides[i] = SIDE_FRONT;
      } else if (dot < -eps) {
        // vertex behind plane
        sides[i] = SIDE_BACK;
      } else {
        // vertex on plane (within epsilon)
        sides[i] = SIDE_ON;
      }

      // count relative vertex positions
      counts[sides[i]]++;
    }

    sides[size] = sides[0]; // loop around to 0'th
    dists[size] = dists[0];

    if (counts[SIDE_FRONT] == 0) {
      // no vertices in front - all behind clip plane
      if (!back) {
        return EMPTY;
      } else {
        return this;
      }
    }
    if (counts[SIDE_BACK] == 0) {
      // no vertices in back - all in front of clip plane
      if (back) {
        return EMPTY;
      } else {
        return this;
      }
    }

    List<Vector3f> vertsNew = new ArrayList<Vector3f>();

    for (int i = 0; i < size; i++) {
      // get i'th vertex
      Vector3f p1 = verts.get(i);

      if (sides[i] == SIDE_ON) {
        vertsNew.add(p1);
        continue;
      }

      if (sides[i] == SIDE_FRONT && !back) {
        // add copy the current vertex
        vertsNew.add(p1);
      }

      if (sides[i] == SIDE_BACK && back) {
        // add copy the current vertex
        vertsNew.add(p1);
      }

      if (sides[i + 1] == SIDE_ON) {
        // next vertex is on the plane, so go to next vertex stat
        continue;
      }

      if (sides[i + 1] == sides[i]) {
        // next vertex does not change side, so go to next vertex stat
        continue;
      }

      // otherwise, we are crossing the clip plane between this vertex and the next
      // so generate a split point

      // will contain the next vertex position
      Vector3f p2;

      if (i == size - 1) {
        // we're the last vertex in the winding
        // next vertex is the 0'th one
        p2 = verts.get(0);
      } else {
        // else get the next vertex
        p2 = verts.get(i + 1);
      }

      // dot is fractional position of clip plane between
      // this vertex and the next
      float dot = dists[i] / (dists[i] - dists[i + 1]);

      // vector of the split vertex
      Vector3f mv = Vector3f.NULL;

      for (int j = 0; j < normal.size; j++) {
        // avoid round off error when possible
        if (normal.get(j) == 1) {
          mv = mv.set(j, dist);
        } else if (normal.get(j) == -1) {
          mv = mv.set(j, -dist);
        } else {
          // check it! MSH
          mv = mv.set(j, p1.get(j) + dot * (p2.get(j) - p1.get(j)));
        }
      }

      // write the output vertex
      vertsNew.add(mv);
    }

    return new Winding(vertsNew);
  }