/** Should only be called from updateGeometricState(). In most cases should not be subclassed. */
 protected void updateWorldTransforms() {
   if (parent == null) {
     worldTransform.set(localTransform);
     refreshFlags &= ~RF_TRANSFORM;
   } else {
     // check if transform for parent is updated
     assert ((parent.refreshFlags & RF_TRANSFORM) == 0);
     worldTransform.set(localTransform);
     worldTransform.combineWithParent(parent.worldTransform);
     refreshFlags &= ~RF_TRANSFORM;
   }
 }
Exemple #2
0
 @Override
 public Transform clone() {
   try {
     Transform tq = (Transform) super.clone();
     tq.rot = rot.clone();
     tq.scale = scale.clone();
     tq.translation = translation.clone();
     return tq;
   } catch (CloneNotSupportedException e) {
     throw new AssertionError();
   }
 }
  /**
   * @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();
    }
  }
  /**
   * <code>rotateUpTo</code> is a utility function that alters the local rotation to point the Y
   * axis in the direction given by newUp.
   *
   * @param newUp the up vector to use - assumed to be a unit vector.
   */
  public void rotateUpTo(Vector3f newUp) {
    TempVars vars = TempVars.get();

    Vector3f compVecA = vars.vect1;
    Quaternion q = vars.quat1;

    // First figure out the current up vector.
    Vector3f upY = compVecA.set(Vector3f.UNIT_Y);
    Quaternion rot = localTransform.getRotation();
    rot.multLocal(upY);

    // get angle between vectors
    float angle = upY.angleBetween(newUp);

    // figure out rotation axis by taking cross product
    Vector3f rotAxis = upY.crossLocal(newUp).normalizeLocal();

    // Build a rotation quat and apply current local rotation.
    q.fromAngleNormalAxis(angle, rotAxis);
    q.mult(rot, rot);

    vars.release();

    setTransformRefresh();
  }
  /** 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();
      }
    }
  }
 /**
  * <code>getLocalRotation</code> retrieves the local rotation of this node.
  *
  * @return the local rotation of this node.
  */
 public Quaternion getLocalRotation() {
   return localTransform.getRotation();
 }
 /**
  * <code>getLocalTranslation</code> retrieves the local translation of this node.
  *
  * @return the local translation of this node.
  */
 public Vector3f getLocalTranslation() {
   return localTransform.getTranslation();
 }
 /**
  * <code>setLocalScale</code> sets the local scale of this node.
  *
  * @param localScale the new local scale.
  */
 public void setLocalScale(Vector3f localScale) {
   localTransform.setScale(localScale);
   setTransformRefresh();
 }
 /** <code>setLocalScale</code> sets the local scale of this node. */
 public void setLocalScale(float x, float y, float z) {
   localTransform.setScale(x, y, z);
   setTransformRefresh();
 }
 /**
  * <code>setLocalScale</code> sets the local scale of this node.
  *
  * @param localScale the new local scale, applied to x, y and z
  */
 public void setLocalScale(float localScale) {
   localTransform.setScale(localScale);
   setTransformRefresh();
 }
 /**
  * <code>getLocalScale</code> retrieves the local scale of this node.
  *
  * @return the local scale of this node.
  */
 public Vector3f getLocalScale() {
   return localTransform.getScale();
 }
 /**
  * <code>setLocalRotation</code> sets the local rotation of this node.
  *
  * @param quaternion the new local rotation.
  */
 public void setLocalRotation(Quaternion quaternion) {
   localTransform.setRotation(quaternion);
   setTransformRefresh();
 }
 /**
  * <code>setLocalRotation</code> sets the local rotation of this node by using a {@link Matrix3f}.
  *
  * @param rotation the new local rotation.
  */
 public void setLocalRotation(Matrix3f rotation) {
   localTransform.getRotation().fromRotationMatrix(rotation);
   setTransformRefresh();
 }
 /**
  * <code>getWorldRotation</code> retrieves the absolute rotation of the Spatial.
  *
  * @return the Spatial's world rotation quaternion.
  */
 public Quaternion getWorldRotation() {
   checkDoTransformUpdate();
   return worldTransform.getRotation();
 }
 /**
  * Convert a vector (in) from world coordinate space to this spatials' local coordinate space.
  *
  * @param in vector to read from
  * @param store where to write the result
  * @return the result (store)
  */
 public Vector3f worldToLocal(final Vector3f in, final Vector3f store) {
   checkDoTransformUpdate();
   return worldTransform.transformInverseVector(in, store);
 }
 /**
  * Convert a vector (in) from this spatials' local coordinate space to world coordinate space.
  *
  * @param in vector to read from
  * @param store where to write the result (null to create a new vector, may be same as in)
  * @return the result (store)
  */
 public Vector3f localToWorld(final Vector3f in, Vector3f store) {
   checkDoTransformUpdate();
   return worldTransform.transformVector(in, store);
 }
 /**
  * <code>getWorldTranslation</code> retrieves the absolute translation of the spatial.
  *
  * @return the Spatial's world tranlsation vector.
  */
 public Vector3f getWorldTranslation() {
   checkDoTransformUpdate();
   return worldTransform.getTranslation();
 }
 /**
  * <code>getWorldScale</code> retrieves the absolute scale factor of the spatial.
  *
  * @return the Spatial's world scale factor.
  */
 public Vector3f getWorldScale() {
   checkDoTransformUpdate();
   return worldTransform.getScale();
 }