Example #1
0
  /**
   * Compare two windings, taking into account that start points may not match
   *
   * @param that other winding
   * @return true if it matches this winding
   */
  public boolean matches(Winding that) {
    final int size = verts.size();

    // if windings have different number of points, trivially fail
    if (size != that.verts.size()) {
      return false;
    }

    // minimum match distance
    float min = 1e6f;

    for (int i = 0; i < size; i++) {
      float mdist = 0;

      // get the aggregate distance at offset i
      for (int j = 0; j < size; j++) {
        // wrap index if greater than size
        int k = (j + i) % size;

        // distance between vertex j of this and k of that
        mdist += verts.get(j).sub(that.verts.get(k)).length();
      }

      // update minimum match distance
      min = Math.min(min, mdist);
    }

    // check if match was close enough
    return min < EPS_COMP;
  }
Example #2
0
  /**
   * Returns the total area of this winding.
   *
   * @return total area
   */
  public float getArea() {
    float total = 0;
    final int size = verts.size();

    for (int i = 2; i < size; i++) {
      Vector3f v1 = verts.get(i - 1).sub(verts.get(0));
      Vector3f v2 = verts.get(i).sub(verts.get(0));
      total += v1.cross(v2).length();
    }

    return total * 0.5f;
  }
Example #3
0
  /**
   * Returns the center point (barycenter) of this winding.
   *
   * <p>Equals WindingCenter() in polylib.cpp
   *
   * @return
   */
  public Vector3f getCenter() {
    Vector3f sum = Vector3f.NULL;

    // add all verts
    for (Vector3f vert : verts) {
      sum = sum.add(vert);
    }

    // average vertex position
    return sum.scalar(1f / verts.size());
  }
Example #4
0
  /**
   * Checks if this winding contains any duplicate vertices.
   *
   * @return true if this winding contains duplicate vertices
   */
  public boolean hasDuplicates() {
    final int size = verts.size();

    for (int i = 0; i < size; i++) {
      for (int j = 0; j < size; j++) {
        if (i == j) {
          continue;
        }

        Vector3f v1 = verts.get(i);
        Vector3f v2 = verts.get(j);

        if (v1.equals(v2)) {
          return true;
        }
      }
    }

    return false;
  }
Example #5
0
  /**
   * Removes degenerated vertices from this winding. A vertex is degenerated when its distance to
   * the previous vertex is smaller than {@link EPS_DEGEN}.
   *
   * @return number of removed vertices
   */
  public Winding removeDegenerated() {
    if (verts.isEmpty()) {
      return this;
    }

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

    final int size = verts.size();

    for (int i = 0; i < size; i++) {
      int j = (i + 1) % size;
      Vector3f v1 = verts.get(i);
      Vector3f v2 = verts.get(j);

      if (v1.sub(v2).length() > EPS_DEGEN) {
        vertsNew.add(v1);
      }
    }

    return new Winding(vertsNew);
  }
Example #6
0
  /**
   * Removes collinear vertices from this winding.
   *
   * @return number of removed vertices
   */
  public Winding removeCollinear() {
    if (verts.isEmpty()) {
      return this;
    }

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

    final int size = verts.size();

    for (int i = 0; i < size; i++) {
      int j = (i + 1) % size;
      int k = (i + size - 1) % size;
      Vector3f v1 = verts.get(j).sub(verts.get(i)).normalize();
      Vector3f v2 = verts.get(i).sub(verts.get(k)).normalize();

      if (v1.dot(v2) < 0.999) {
        vertsNew.add(verts.get(i));
      }
    }

    return new Winding(vertsNew);
  }
Example #7
0
  /**
   * Rotates all vertices in this winding by the given euler angles.
   *
   * @param angles rotation angles
   */
  public Winding rotate(Vector3f angles) {
    if (verts.isEmpty()) {
      return this;
    }

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

    for (Vector3f vert : verts) {
      vertsNew.add(vert.rotate(angles));
    }

    return new Winding(vertsNew);
  }
Example #8
0
  public Winding translate(Vector3f offset) {
    if (verts.isEmpty()) {
      return this;
    }

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

    for (Vector3f vert : verts) {
      vertsNew.add(vert.add(offset));
    }

    return new Winding(vertsNew);
  }
Example #9
0
  /**
   * Returns the plane points of this winding in form of a triangle.
   *
   * @return Vector3f array with three points of the triangle
   */
  public Vector3f[] buildPlane() {
    Vector3f[] vertsNew = new Vector3f[verts.size()];
    Vector3f[] plane = new Vector3f[3];

    // 1st vert is always base vertex
    plane[0] = get(0);

    // build vector list
    for (int i = 0; i < vertsNew.length; i++) {
      // the vector from start vertex to i'th
      vertsNew[i] = get(i).sub(plane[0]);
    }

    // the largest modulus of cross product found between ixj
    float maxmcp = -1;
    // the i index of largest cp
    int imax = -1;
    // the j index of largest cp
    int jmax = -1;

    // loop through all i x j combinations
    for (int i = 1; i < vertsNew.length; i++) {
      // ensures j>i
      for (int j = i + 1; j < vertsNew.length; j++) {
        float mcp = vertsNew[i].cross(vertsNew[j]).length();
        if (mcp > maxmcp) {
          maxmcp = mcp;
          imax = i;
          jmax = j;
        }
      }
    }

    // choose other two such that cross product is maximum
    plane[1] = get(imax);
    plane[2] = get(jmax);

    return plane;
  }
Example #10
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 #11
0
 @Override
 public int indexOf(Object o) {
   return verts.indexOf(o);
 }
Example #12
0
 @Override
 public Vector3f get(int index) {
   return verts.get(index);
 }
Example #13
0
 @Override
 public boolean containsAll(Collection<?> c) {
   return verts.containsAll(c);
 }
Example #14
0
 @Override
 public <T> T[] toArray(T[] a) {
   return verts.toArray(a);
 }
Example #15
0
 @Override
 public Object[] toArray() {
   return verts.toArray();
 }
Example #16
0
 @Override
 public Iterator<Vector3f> iterator() {
   return verts.iterator();
 }
Example #17
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);
  }
Example #18
0
 @Override
 public ListIterator<Vector3f> listIterator(int index) {
   return verts.listIterator(index);
 }
Example #19
0
 @Override
 public int lastIndexOf(Object o) {
   return verts.lastIndexOf(o);
 }
Example #20
0
 @Override
 public ListIterator<Vector3f> listIterator() {
   return verts.listIterator();
 }
Example #21
0
 @Override
 public int size() {
   return verts.size();
 }
Example #22
0
 @Override
 public List<Vector3f> subList(int fromIndex, int toIndex) {
   return verts.subList(fromIndex, toIndex);
 }
Example #23
0
 @Override
 public boolean isEmpty() {
   return verts.isEmpty();
 }
Example #24
0
 @Override
 public String toString() {
   return verts.toString();
 }
Example #25
0
 @Override
 public boolean contains(Object o) {
   return verts.contains(o);
 }