예제 #1
0
  public AABB getBounds() {
    Vector3f mins = Vector3f.MAX_VALUE;
    Vector3f maxs = Vector3f.MIN_VALUE;

    for (Vector3f vert : verts) {
      mins = mins.min(vert);
      maxs = maxs.max(vert);
    }

    return new AABB(mins, maxs);
  }
예제 #2
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());
  }
예제 #3
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;
  }
예제 #4
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);
  }
예제 #5
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);
  }
예제 #6
0
  /**
   * Checks if a point is inside this winding.
   *
   * @param pt point to test
   * @return true if the point lies inside this winding
   */
  public boolean isInside(Vector3f pt) {
    if (isEmpty() || size() < 2) {
      // "Is not possible!"
      return false;
    }

    // get the first normal to test
    Vector3f toPt = pt.sub(get(0));
    Vector3f edge = get(1).sub(get(0));
    Vector3f testCross = edge.cross(toPt).normalize();
    Vector3f cross;

    int size = size();

    for (int i = 1; i < size; i++) {
      toPt = pt.sub(get(i));
      edge = get((i + 1) % size).sub(get(i));
      cross = edge.cross(toPt).normalize();

      if (cross.dot(testCross) < 0) {
        return false;
      }
    }

    return true;
  }
예제 #7
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;
  }
예제 #8
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);
  }
예제 #9
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);
  }
예제 #10
0
  @Override
  public void write(DataWriter out) throws IOException {
    Vector3f.write(out, startPos);
    out.writeInt(dispVertStart);
    out.writeInt(dispTriStart);
    out.writeInt(power);
    out.writeFloat(smoothingAngle);
    out.writeInt(unknown);
    out.writeInt(contents);
    out.writeUnsignedShort(mapFace);
    out.writeInt(lightmapAlphaStart);
    out.writeInt(lightmapSamplePositionStart);
    out.writeBytes(neighborsVin);

    for (int i = 0; i < allowedVerts.length; i++) {
      out.writeInt(allowedVerts[i]);
    }
  }
예제 #11
0
  @Override
  public void read(DataReader in) throws IOException {
    startPos = Vector3f.read(in);
    dispVertStart = in.readInt();
    dispTriStart = in.readInt();
    power = in.readInt();
    smoothingAngle = in.readFloat();
    unknown = in.readInt();
    contents = in.readInt();
    mapFace = in.readUnsignedShort();
    lightmapAlphaStart = in.readInt();
    lightmapSamplePositionStart = in.readInt();
    in.readBytes(neighborsVin);

    for (int i = 0; i < allowedVerts.length; i++) {
      allowedVerts[i] = in.readInt();
    }
  }
예제 #12
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);
  }