spatial.java

来自「java 3d game jme 工程开发源代码」· Java 代码 · 共 1,773 行 · 第 1/4 页

JAVA
1,773
字号
/*
 * Copyright (c) 2003-2009 jMonkeyEngine
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
 *   may be used to endorse or promote products derived from this software
 *   without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package com.jme.scene;

import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Stack;

import com.jme.bounding.BoundingVolume;
import com.jme.intersection.CollisionResults;
import com.jme.intersection.PickResults;
import com.jme.math.Matrix3f;
import com.jme.math.Matrix4f;
import com.jme.math.Quaternion;
import com.jme.math.Ray;
import com.jme.math.Vector3f;
import com.jme.renderer.Camera;
import com.jme.renderer.Renderer;
import com.jme.scene.state.RenderState;
import com.jme.system.DisplaySystem;
import com.jme.util.export.InputCapsule;
import com.jme.util.export.JMEExporter;
import com.jme.util.export.JMEImporter;
import com.jme.util.export.OutputCapsule;
import com.jme.util.export.Savable;

/**
 * <code>Spatial</code> defines the base class for scene graph nodes. It
 * maintains a link to a parent, it's local transforms and the world's
 * transforms. All other nodes, such as <code>Node</code> and
 * <code>Geometry</code> are subclasses of <code>Spatial</code>.
 * 
 * @author Mark Powell
 * @author Joshua Slack
 * @version $Revision: 4091 $, $Data$
 */
public abstract class Spatial implements Serializable, Savable {

    /**
     * Describes how to combine textures from ancestor texturestates when an
     * updateRenderState is called on a Spatial.
     * 
     * @author Joshua Slack
     */
    public enum TextureCombineMode {
        /** When updating render states, turn off texturing for this spatial. */
        Off,

        /**
         * Combine textures starting from the root node and working towards the
         * given Spatial. Ignore disabled states.
         */
        CombineFirst,

        /**
         * Combine textures starting from the given Spatial and working towards
         * the root. Ignore disabled states. (Default)
         */
        CombineClosest,

        /**
         * Similar to CombineClosest, but if a disabled state is encountered, it
         * will stop combining at that point.
         */
        CombineClosestEnabled,

        /** Inherit mode from parent. */
        Inherit,

        /** Do not combine textures, just use the most recent texture state. */
        Replace;
    }

    /**
     * Describes how to combine lights from ancestor lightstates when an
     * updateRenderState is called on a Spatial.
     * 
     * @author Joshua Slack
     */
    public enum LightCombineMode {
        /** When updating render states, turn off lighting for this spatial. */
        Off,

        /**
         * Combine lights starting from the root node and working towards the
         * given Spatial. Ignore disabled states. Stop combining when lights ==
         * MAX_LIGHTS_ALLOWED
         */
        CombineFirst,

        /**
         * Combine lights starting from the given Spatial and working up towards
         * the root. Ignore disabled states. Stop combining when lights ==
         * MAX_LIGHTS_ALLOWED
         */
        CombineClosest,

        /**
         * Similar to CombineClosest, but if a disabled state is encountered, it
         * will stop combining at that point. Stop combining when lights ==
         * MAX_LIGHTS_ALLOWED
         */
        CombineClosestEnabled,

        /** Inherit mode from parent. */
        Inherit,

        /** Do not combine lights, just use the most recent light state. */
        Replace;
    }

    public enum CullHint {
        /** Do whatever our parent does. If no parent, we'll default to dynamic. */
        Inherit,
        /**
         * Do not draw if we are not at least partially within the view frustum
         * of the renderer's camera.
         */
        Dynamic,
        /** Always cull this from view. */
        Always,
        /**
         * Never cull this from view. Note that we will still get culled if our
         * parent is culled.
         */
        Never;
    }

    public enum NormalsMode {
        /**
         * Do whatever our parent does. If no parent, we'll default to
         * NormalizeIfScaled.
         */
        Inherit,
        /** Send through the normals currently set as-is. */
        UseProvided,
        /**
         * Tell the card to normalize any normals data we might give it for this
         * Spatial.
         */
        AlwaysNormalize,
        /**
         * If this Spatial is scaled other than 1,1,1 then tell the card to
         * normalize any normals data we might give it.
         */
        NormalizeIfScaled,
        /**
         * Do not send normal data to the card for this Spatial, even if we have
         * some.
         */
        Off;
    }

    public static final int LOCKED_NONE = 0;
    public static final int LOCKED_BOUNDS = 1;
    public static final int LOCKED_MESH_DATA = 2;
    public static final int LOCKED_TRANSFORMS = 4;
    public static final int LOCKED_SHADOWS = 8;
    public static final int LOCKED_BRANCH = 16;

    /**
     * A flag indicating how normals should be treated by the renderer.
     */
    protected NormalsMode normalsMode = NormalsMode.Inherit;

    /**
     * A flag indicating if scene culling should be done on this object by
     * inheritance, dynamically, never, or always.
     */
    protected CullHint cullHint = CullHint.Inherit;

    /** Spatial's bounding volume relative to the world. */
    protected BoundingVolume worldBound;

    /** The render states of this spatial. */
    protected RenderState[] renderStateList;

    protected int renderQueueMode = Renderer.QUEUE_INHERIT;

    /** Used to determine draw order for ortho mode rendering. */
    protected int zOrder = 0;

    /**
     * Used to indicate this spatial (and any below it in the case of Node) is
     * locked against certain changes.
     */
    protected int lockedMode = LOCKED_NONE;

    /**
     * Flag signaling how lights are combined for this node. By default set to
     * INHERIT.
     */
    protected LightCombineMode lightCombineMode = LightCombineMode.Inherit;

    /**
     * Flag signaling how textures are combined for this node. By default set to
     * INHERIT.
     */
    protected TextureCombineMode textureCombineMode = TextureCombineMode.Inherit;

    /** This spatial's name. */
    protected String name;

    // scale values
    protected Camera.FrustumIntersect frustrumIntersects = Camera.FrustumIntersect.Intersects;

    /**
     * Defines if this spatial will be used in intersection operations or not.
     * Default is true
     */
    protected boolean isCollidable = true;

    public transient float queueDistance = Float.NEGATIVE_INFINITY;

    private static final long serialVersionUID = 2L;

    /** Spatial's rotation relative to its parent. */
    protected Quaternion localRotation;

    /** Spatial's world absolute rotation. */
    protected Quaternion worldRotation;

    /** Spatial's translation relative to its parent. */
    protected Vector3f localTranslation;

    /** Spatial's world absolute translation. */
    protected Vector3f worldTranslation;

    /** Spatial's scale relative to its parent. */
    protected Vector3f localScale;

    /** Spatial's world absolute scale. */
    protected Vector3f worldScale;

    /** Spatial's parent, or null if it has none. */
    protected transient Node parent;

    /** ArrayList of controllers for this spatial. */
    protected ArrayList<Controller> geometricalControllers;

    private static final Vector3f compVecA = new Vector3f();
    private static final Quaternion compQuat = new Quaternion();

    /**
     * Default Constructor.
     */
    public Spatial() {
        localRotation = new Quaternion();
        worldRotation = new Quaternion();
        localTranslation = new Vector3f();
        worldTranslation = new Vector3f();
        localScale = new Vector3f(1.0f, 1.0f, 1.0f);
        worldScale = new Vector3f(1.0f, 1.0f, 1.0f);
    }

    /**
     * Constructor instantiates a new <code>Spatial</code> object setting the
     * rotation, translation and scale value to defaults.
     * 
     * @param name
     *            the name of the scene element. This is required for
     *            identification and comparision purposes.
     */
    public Spatial(String name) {
        this();
        this.name = name;
    }

    /**
     * Adds a Controller to this Spatial's list of controllers.
     * 
     * @param controller
     *            The Controller to add
     * @see com.jme.scene.Controller
     */
    public void addController(Controller controller) {
        if (geometricalControllers == null) {
            geometricalControllers = new ArrayList<Controller>(1);
        }
        geometricalControllers.add(controller);
    }

    /**
     * Removes a Controller from this Spatial's list of controllers, if it
     * exist.
     * 
     * @param controller
     *            The Controller to remove
     * @return True if the Controller was in the list to remove.
     * @see com.jme.scene.Controller
     */
    public boolean removeController(Controller controller) {
        if (geometricalControllers == null) {
            return false;
        }
        return geometricalControllers.remove(controller);
    }

    /**
     * Removes a Controller from this Spatial's list of controllers by index.
     * 
     * @param index
     *            The index of the controller to remove
     * @return The Controller removed or null if nothing was removed.
     * @see com.jme.scene.Controller
     */
    public Controller removeController(int index) {
        if (geometricalControllers == null) {
            return null;
        }
        return geometricalControllers.remove(index);
    }

    /**
     * Removes all Controllers from this Spatial's list of controllers.
     * 
     * @see com.jme.scene.Controller
     */
    public void clearControllers() {
        if (geometricalControllers != null) {
            geometricalControllers.clear();
        }
    }

    /**
     * Returns the controller in this list of controllers at index i.
     * 
     * @param i
     *            The index to get a controller from.
     * @return The controller at index i.
     * @see com.jme.scene.Controller
     */
    public Controller getController(int i) {
        if (geometricalControllers == null) {
            geometricalControllers = new ArrayList<Controller>(1);
        }
        return geometricalControllers.get(i);
    }

    /**
     * Returns the ArrayList that contains this spatial's Controllers.
     * 
     * @return This spatial's geometricalControllers.
     */
    public ArrayList<Controller> getControllers() {
        if (geometricalControllers == null) {
            geometricalControllers = new ArrayList<Controller>(1);
        }
        return geometricalControllers;
    }

    /**
     * @return the number of controllers set on this Spatial.
     */
    public int getControllerCount() {
        if (geometricalControllers == null) {
            return 0;
        }
        return geometricalControllers.size();
    }

    /**
     * <code>onDraw</code> checks the spatial with the camera to see if it
     * should be culled, if not, the node's draw method is called.
     * <p>
     * This method is called by the renderer. Usually it should not be called
     * directly.
     * 
     * @param r
     *            the renderer used for display.
     */
    public void onDraw(Renderer r) {
        CullHint cm = getCullHint();
        if (cm == Spatial.CullHint.Always) {
            setLastFrustumIntersection(Camera.FrustumIntersect.Outside);
            return;
        } else if (cm == Spatial.CullHint.Never) {
            setLastFrustumIntersection(Camera.FrustumIntersect.Intersects);
            draw(r);
            return;
        }

        Camera camera = r.getCamera();
        int state = camera.getPlaneState();

        // check to see if we can cull this node
        frustrumIntersects = (parent != null ? parent.frustrumIntersects
                : Camera.FrustumIntersect.Intersects);

        if (cm == Spatial.CullHint.Dynamic
                && frustrumIntersects == Camera.FrustumIntersect.Intersects) {
            frustrumIntersects = camera.contains(worldBound);
        }

        if (frustrumIntersects != Camera.FrustumIntersect.Outside) {
            draw(r);
        }
        camera.setPlaneState(state);
    }

    /**
     * <code>getWorldRotation</code> retrieves the absolute rotation of the
     * Spatial.
     * 
     * @return the Spatial's world rotation matrix.
     */
    public Quaternion getWorldRotation() {
        return worldRotation;
    }

    /**
     * <code>getWorldTranslation</code> retrieves the absolute translation of

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?