예제 #1
0
  /**
   * Visit each scene graph element ordered by BFS
   *
   * @param visitor
   */
  public void breadthFirstTraversal(SceneGraphVisitor visitor) {
    Queue<Spatial> queue = new LinkedList<Spatial>();
    queue.add(this);

    while (!queue.isEmpty()) {
      Spatial s = queue.poll();
      visitor.visit(s);
      s.breadthFirstTraversal(visitor, queue);
    }
  }
예제 #2
0
  /** Indicate that the bounding of this spatial has changed and that a refresh is required. */
  protected void setBoundRefresh() {
    refreshFlags |= RF_BOUND;

    Spatial p = parent;
    while (p != null) {
      if ((p.refreshFlags & RF_BOUND) != 0) {
        return;
      }

      p.refreshFlags |= RF_BOUND;
      p = p.parent;
    }
  }
예제 #3
0
  /** Computes the world transform of this Spatial in the most efficient manner possible. */
  void checkDoTransformUpdate() {
    if ((refreshFlags & RF_TRANSFORM) == 0) {
      return;
    }

    if (parent == null) {
      worldTransform.set(localTransform);
      refreshFlags &= ~RF_TRANSFORM;
    } else {
      TempVars vars = TempVars.get();

      Spatial[] stack = vars.spatialStack;
      Spatial rootNode = this;
      int i = 0;
      while (true) {
        Spatial hisParent = rootNode.parent;
        if (hisParent == null) {
          rootNode.worldTransform.set(rootNode.localTransform);
          rootNode.refreshFlags &= ~RF_TRANSFORM;
          i--;
          break;
        }

        stack[i] = rootNode;

        if ((hisParent.refreshFlags & RF_TRANSFORM) == 0) {
          break;
        }

        rootNode = hisParent;
        i++;
      }

      vars.release();

      for (int j = i; j >= 0; j--) {
        rootNode = stack[j];
        // rootNode.worldTransform.set(rootNode.localTransform);
        // rootNode.worldTransform.combineWithParent(rootNode.parent.worldTransform);
        // rootNode.refreshFlags &= ~RF_TRANSFORM;
        rootNode.updateWorldTransforms();
      }
    }
  }
예제 #4
0
  /** Computes this Spatial's world bounding volume in the most efficient manner possible. */
  void checkDoBoundUpdate() {
    if ((refreshFlags & RF_BOUND) == 0) {
      return;
    }

    checkDoTransformUpdate();

    // Go to children recursively and update their bound
    if (this instanceof Node) {
      Node node = (Node) this;
      int len = node.getQuantity();
      for (int i = 0; i < len; i++) {
        Spatial child = node.getChild(i);
        child.checkDoBoundUpdate();
      }
    }

    // All children's bounds have been updated. Update my own now.
    updateWorldBound();
  }
예제 #5
0
  /**
   * @return A clone of this Spatial, the scene graph in its entirety is cloned and can be altered
   *     independently of the original scene graph.
   *     <p>Note that meshes of geometries are not cloned explicitly, they are shared if static, or
   *     specially cloned if animated.
   *     <p>All controls will be cloned using the Control.cloneForSpatial method on the clone.
   * @see Mesh#cloneForAnim()
   */
  public Spatial clone(boolean cloneMaterial) {
    try {
      Spatial clone = (Spatial) super.clone();
      if (worldBound != null) {
        clone.worldBound = worldBound.clone();
      }
      clone.worldLights = worldLights.clone();
      clone.localLights = localLights.clone();

      // Set the new owner of the light lists
      clone.localLights.setOwner(clone);
      clone.worldLights.setOwner(clone);

      // No need to force cloned to update.
      // This node already has the refresh flags
      // set below so it will have to update anyway.
      clone.worldTransform = worldTransform.clone();
      clone.localTransform = localTransform.clone();

      if (clone instanceof Node) {
        Node node = (Node) this;
        Node nodeClone = (Node) clone;
        nodeClone.children = new SafeArrayList<Spatial>(Spatial.class);
        for (Spatial child : node.children) {
          Spatial childClone = child.clone(cloneMaterial);
          childClone.parent = nodeClone;
          nodeClone.children.add(childClone);
        }
      }

      clone.parent = null;
      clone.setBoundRefresh();
      clone.setTransformRefresh();
      clone.setLightListRefresh();

      clone.controls = new SafeArrayList<Control>(Control.class);
      for (int i = 0; i < controls.size(); i++) {
        Control newControl = controls.get(i).cloneForSpatial(clone);
        newControl.setSpatial(clone);
        clone.controls.add(newControl);
      }

      if (userData != null) {
        clone.userData = (HashMap<String, Savable>) userData.clone();
      }

      return clone;
    } catch (CloneNotSupportedException ex) {
      throw new AssertionError();
    }
  }