Пример #1
0
  public static void findTrianglePick(
      final Mesh mesh, final Ray3 toTest, final List<PrimitiveKey> results) {
    if (mesh.getWorldBound() == null
        || !mesh.getSceneHints().isPickingHintEnabled(PickingHint.Pickable)) {
      return;
    }

    if (mesh.getWorldBound().intersects(toTest)) {
      final CollisionTree ct = CollisionTreeManager.getInstance().getCollisionTree(mesh);
      if (ct != null) {
        ct.getBounds().transform(mesh.getWorldTransform(), ct.getWorldBounds());
        ct.intersect(toTest, results);
      }
    }
  }
Пример #2
0
  protected void splitMesh(
      final Mesh mesh, final int sectionStart, final int sectionEnd, final boolean doSort) {
    _mesh = makeRef(mesh);

    // Split range in half
    final int rangeSize = sectionEnd - sectionStart;
    final int halfRange = rangeSize / 2; // odd number will give +1 to right.

    // left half:
    // if half size == 1, create as regular CollisionTree
    if (halfRange == 1) {
      // compute section
      final int section = sectionStart;

      // create the left child
      _left = new CollisionTree(_type);

      _left._primitiveIndices = new int[mesh.getMeshData().getPrimitiveCount(section)];
      for (int i = 0; i < _left._primitiveIndices.length; i++) {
        _left._primitiveIndices[i] = i;
      }
      _left._mesh = _mesh;
      _left.createTree(section, 0, _left._primitiveIndices.length, doSort);
    } else {
      // otherwise, make an empty collision tree and call split with new range
      _left = new CollisionTree(_type);
      _left.splitMesh(mesh, sectionStart, sectionStart + halfRange, doSort);
    }

    // right half:
    // if rangeSize - half size == 1, create as regular CollisionTree
    if (rangeSize - halfRange == 1) {
      // compute section
      final int section = sectionStart + 1;

      // create the left child
      _right = new CollisionTree(_type);

      _right._primitiveIndices = new int[mesh.getMeshData().getPrimitiveCount(section)];
      for (int i = 0; i < _right._primitiveIndices.length; i++) {
        _right._primitiveIndices[i] = i;
      }
      _right._mesh = _mesh;
      _right.createTree(section, 0, _right._primitiveIndices.length, doSort);
    } else {
      // otherwise, make an empty collision tree and call split with new range
      _right = new CollisionTree(_type);
      _right.splitMesh(mesh, sectionStart + halfRange, sectionEnd, doSort);
    }

    // Ok, now since we technically have no primitives, we need our bounds to be the merging of our
    // children bounds
    // instead:
    _bounds = _left._bounds.clone(_bounds);
    _bounds.mergeLocal(_right._bounds);
    _worldBounds = _bounds.clone(_worldBounds);
  }
Пример #3
0
  /**
   * This function checks for intersection between this mesh and the given one. On the first
   * intersection, true is returned.
   *
   * @param toCheck The intersection testing mesh.
   * @return True if they intersect.
   */
  public static boolean hasTriangleCollision(final Mesh testMesh, final Mesh toCheck) {
    if (!testMesh.getSceneHints().isPickingHintEnabled(PickingHint.Collidable)
        || !toCheck.getSceneHints().isPickingHintEnabled(PickingHint.Collidable)) {
      return false;
    }

    final CollisionTree thisCT = CollisionTreeManager.getInstance().getCollisionTree(testMesh);
    final CollisionTree checkCT = CollisionTreeManager.getInstance().getCollisionTree(toCheck);

    if (thisCT == null || checkCT == null) {
      return false;
    }

    final ReadOnlyTransform worldTransform = testMesh.getWorldTransform();
    thisCT.getBounds().transform(worldTransform, thisCT.getWorldBounds());
    return thisCT.intersect(checkCT);
  }
Пример #4
0
  /**
   * intersect checks for collisions between this collision tree and a provided Ray. Any collisions
   * are stored in a provided list as primitive index values. The ray is assumed to have a
   * normalized direction for accurate calculations.
   *
   * @param ray the ray to test for intersections.
   * @param store a list to fill with the index values of the primitive hit. if null, a new List is
   *     created.
   * @return the list.
   */
  public List<PrimitiveKey> intersect(final Ray3 ray, final List<PrimitiveKey> store) {
    List<PrimitiveKey> result = store;
    if (result == null) {
      result = new ArrayList<PrimitiveKey>();
    }

    // if our ray doesn't hit the bounds, then it must not hit a primitive.
    if (!_worldBounds.intersects(ray)) {
      return result;
    }

    // This is not a leaf node, therefore, check each child (left/right) for intersection with the
    // ray.
    if (_left != null) {
      _left._worldBounds =
          _left._bounds.transform(getMesh().getWorldTransform(), _left._worldBounds);
      _left.intersect(ray, result);
    }

    if (_right != null) {
      _right._worldBounds =
          _right._bounds.transform(getMesh().getWorldTransform(), _right._worldBounds);
      _right.intersect(ray, result);
    } else if (_left == null) {
      // This is a leaf node. We can therefore check each primitive this node contains. If an
      // intersection occurs,
      // place it in the list.

      final MeshData data = getMesh().getMeshData();
      final ReadOnlyTransform transform = getMesh().getWorldTransform();

      Vector3[] points = null;
      for (int i = _start; i < _end; i++) {
        points = data.getPrimitiveVertices(_primitiveIndices[i], _section, points);
        for (int t = 0; t < points.length; t++) {
          transform.applyForward(points[t]);
        }
        if (ray.intersects(points, null)) {
          result.add(new PrimitiveKey(_primitiveIndices[i], _section));
        }
      }
    }
    return result;
  }
Пример #5
0
  /**
   * This function finds all intersections between this mesh and the checking one. The intersections
   * are stored as Integer objects of Triangle indexes in each of the parameters.
   *
   * @param toCheck The Mesh to check.
   * @param testIndex The array of triangle indexes intersecting in this mesh.
   * @param otherIndex The array of triangle indexes intersecting in the given mesh.
   */
  public static void findPrimitiveCollision(
      final Mesh testMesh,
      final Mesh toCheck,
      final List<PrimitiveKey> testIndex,
      final List<PrimitiveKey> otherIndex) {
    if (!testMesh.getSceneHints().isPickingHintEnabled(PickingHint.Collidable)
        || !toCheck.getSceneHints().isPickingHintEnabled(PickingHint.Collidable)) {
      return;
    }

    final CollisionTree myTree = CollisionTreeManager.getInstance().getCollisionTree(testMesh);
    final CollisionTree otherTree = CollisionTreeManager.getInstance().getCollisionTree(toCheck);

    if (myTree == null || otherTree == null) {
      return;
    }

    myTree.getBounds().transform(testMesh.getWorldTransform(), myTree.getWorldBounds());

    myTree.intersect(otherTree, testIndex, otherIndex);
  }
Пример #6
0
  /**
   * Creates a Collision Tree by recursively creating children nodes, splitting the primitives this
   * node is responsible for in half until the desired primitive count is reached.
   *
   * @param start The start index of the primitivesArray, inclusive.
   * @param end The end index of the primitivesArray, exclusive.
   * @param doSort True if the primitives should be sorted at each level, false otherwise.
   */
  public void createTree(final int section, final int start, final int end, final boolean doSort) {
    _section = section;
    _start = start;
    _end = end;

    if (_primitiveIndices == null) {
      return;
    }

    createBounds();

    // the bounds at this level should contain all the primitives this level is responsible for.
    _bounds.computeFromPrimitives(
        getMesh().getMeshData(), _section, _primitiveIndices, _start, _end);

    // check to see if we are a leaf, if the number of primitives we reference is less than or equal
    // to the maximum
    // defined by the CollisionTreeManager we are done.
    if (_end - _start + 1 <= CollisionTreeManager.getInstance().getMaxPrimitivesPerLeaf()) {
      return;
    }

    // if doSort is set we need to attempt to optimize the referenced primitives. optimizing the
    // sorting of the
    // primitives will help group them spatially in the left/right children better.
    if (doSort) {
      sortPrimitives();
    }

    // create the left child
    if (_left == null) {
      _left = new CollisionTree(_type);
    }

    _left._primitiveIndices = _primitiveIndices;
    _left._mesh = _mesh;
    _left.createTree(_section, _start, (_start + _end) / 2, doSort);

    // create the right child
    if (_right == null) {
      _right = new CollisionTree(_type);
    }
    _right._primitiveIndices = _primitiveIndices;
    _right._mesh = _mesh;
    _right.createTree(_section, (_start + _end) / 2, _end, doSort);
  }
Пример #7
0
  /**
   * Determines if this Collision Tree intersects the given CollisionTree. If a collision occurs,
   * true is returned, otherwise false is returned. If the provided collisionTree is invalid, false
   * is returned. All collisions that occur are stored in lists as an integer index into the mesh's
   * triangle buffer. where aList is the primitives for this mesh and bList is the primitives for
   * the test tree.
   *
   * @param collisionTree The Tree to test.
   * @param aList a list to contain the colliding primitives of this mesh.
   * @param bList a list to contain the colliding primitives of the testing mesh.
   * @return True if they intersect, false otherwise.
   */
  public boolean intersect(
      final CollisionTree collisionTree,
      final List<PrimitiveKey> aList,
      final List<PrimitiveKey> bList) {

    if (collisionTree == null) {
      return false;
    }

    collisionTree._worldBounds =
        collisionTree._bounds.transform(
            collisionTree.getMesh().getWorldTransform(), collisionTree._worldBounds);

    // our two collision bounds do not intersect, therefore, our primitives
    // must not intersect. Return false.
    if (!intersectsBounding(collisionTree._worldBounds)) {
      return false;
    }

    // if our node is not a leaf send the children (both left and right) to
    // the test tree.
    if (_left != null) { // This is not a leaf
      boolean test = collisionTree.intersect(_left, bList, aList);
      test = collisionTree.intersect(_right, bList, aList) || test;
      return test;
    }

    // This node is a leaf, but the testing tree node is not. Therefore,
    // continue processing the testing tree until we find its leaves.
    if (collisionTree._left != null) {
      boolean test = intersect(collisionTree._left, aList, bList);
      test = intersect(collisionTree._right, aList, bList) || test;
      return test;
    }

    // both this node and the testing node are leaves. Therefore, we can
    // switch to checking the contained primitives with each other. Any
    // that are found to intersect are placed in the appropriate list.
    final ReadOnlyTransform transformA = getMesh().getWorldTransform();
    final ReadOnlyTransform transformB = collisionTree.getMesh().getWorldTransform();

    final MeshData dataA = getMesh().getMeshData();
    final MeshData dataB = collisionTree.getMesh().getMeshData();

    Vector3[] storeA = null;
    Vector3[] storeB = null;

    boolean test = false;

    for (int i = _start; i < _end; i++) {
      storeA = dataA.getPrimitiveVertices(_primitiveIndices[i], _section, storeA);
      // to world space
      for (int t = 0; t < storeA.length; t++) {
        transformA.applyForward(storeA[t]);
      }
      for (int j = collisionTree._start; j < collisionTree._end; j++) {
        storeB =
            dataB.getPrimitiveVertices(
                collisionTree._primitiveIndices[j], collisionTree._section, storeB);
        // to world space
        for (int t = 0; t < storeB.length; t++) {
          transformB.applyForward(storeB[t]);
        }
        if (Intersection.intersection(storeA, storeB)) {
          test = true;
          aList.add(new PrimitiveKey(_primitiveIndices[i], _section));
          bList.add(new PrimitiveKey(collisionTree._primitiveIndices[j], collisionTree._section));
        }
      }
    }

    return test;
  }
Пример #8
0
  /**
   * Determines if this Collision Tree intersects the given CollisionTree. If a collision occurs,
   * true is returned, otherwise false is returned. If the provided collisionTree is invalid, false
   * is returned.
   *
   * @param collisionTree The Tree to test.
   * @return True if they intersect, false otherwise.
   */
  public boolean intersect(final CollisionTree collisionTree) {
    if (collisionTree == null) {
      return false;
    }

    collisionTree._worldBounds =
        collisionTree._bounds.transform(
            collisionTree.getMesh().getWorldTransform(), collisionTree._worldBounds);

    // our two collision bounds do not intersect, therefore, our primitives
    // must not intersect. Return false.
    if (!intersectsBounding(collisionTree._worldBounds)) {
      return false;
    }

    // check children
    if (_left != null) { // This is not a leaf
      if (collisionTree.intersect(_left)) {
        return true;
      }
      if (collisionTree.intersect(_right)) {
        return true;
      }
      return false;
    }

    // This is a leaf
    if (collisionTree._left != null) {
      // but collision isn't
      if (intersect(collisionTree._left)) {
        return true;
      }
      if (intersect(collisionTree._right)) {
        return true;
      }
      return false;
    }

    // both are leaves
    final ReadOnlyTransform transformA = getMesh().getWorldTransform();
    final ReadOnlyTransform transformB = collisionTree.getMesh().getWorldTransform();

    final MeshData dataA = getMesh().getMeshData();
    final MeshData dataB = collisionTree.getMesh().getMeshData();

    Vector3[] storeA = null;
    Vector3[] storeB = null;

    // for every primitive to compare, put them into world space and check for intersections
    for (int i = _start; i < _end; i++) {
      storeA = dataA.getPrimitiveVertices(_primitiveIndices[i], _section, storeA);
      // to world space
      for (int t = 0; t < storeA.length; t++) {
        transformA.applyForward(storeA[t]);
      }
      for (int j = collisionTree._start; j < collisionTree._end; j++) {
        storeB =
            dataB.getPrimitiveVertices(
                collisionTree._primitiveIndices[j], collisionTree._section, storeB);
        // to world space
        for (int t = 0; t < storeB.length; t++) {
          transformB.applyForward(storeB[t]);
        }
        if (Intersection.intersection(storeA, storeB)) {
          return true;
        }
      }
    }

    return false;
  }