159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/*
259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Copyright (c) 2009-2010 jMonkeyEngine
359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * All rights reserved.
459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Redistribution and use in source and binary forms, with or without
659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * modification, are permitted provided that the following conditions are
759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * met:
859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Redistributions of source code must retain the above copyright
1059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *   notice, this list of conditions and the following disclaimer.
1159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
1259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Redistributions in binary form must reproduce the above copyright
1359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *   notice, this list of conditions and the following disclaimer in the
1459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *   documentation and/or other materials provided with the distribution.
1559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
1659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
1759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *   may be used to endorse or promote products derived from this software
1859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *   without specific prior written permission.
1959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
2059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
2459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
2559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
2759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
2859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
2959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
3059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */
3259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapackage com.jme3.renderer;
3359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
3459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.bounding.BoundingBox;
3559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.bounding.BoundingVolume;
3659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.export.*;
3759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.math.*;
3859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.util.TempVars;
3959b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.io.IOException;
4059b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.logging.Level;
4159b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.logging.Logger;
4259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
4359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/**
4459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <code>Camera</code> is a standalone, purely mathematical class for doing
4559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * camera-related computations.
4659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
4759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <p>
4859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Given input data such as location, orientation (direction, left, up),
4959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * and viewport settings, it can compute data necessary to render objects
5059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * with the graphics library. Two matrices are generated, the view matrix
5159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * transforms objects from world space into eye space, while the projection
5259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * matrix transforms objects from eye space into clip space.
5359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * </p>
5459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <p>Another purpose of the camera class is to do frustum culling operations,
5559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * defined by six planes which define a 3D frustum shape, it is possible to
5659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * test if an object bounded by a mathematically defined volume is inside
5759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * the camera frustum, and thus to avoid rendering objects that are outside
5859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * the frustum
5959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * </p>
6059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
6159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @author Mark Powell
6259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @author Joshua Slack
6359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */
6459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapublic class Camera implements Savable, Cloneable {
6559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
6659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private static final Logger logger = Logger.getLogger(Camera.class.getName());
6759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
6859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
6959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * The <code>FrustumIntersect</code> enum is returned as a result
7059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * of a culling check operation,
7159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * see {@link #contains(com.jme3.bounding.BoundingVolume) }
7259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
7359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public enum FrustumIntersect {
7459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
7559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        /**
7659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta         * defines a constant assigned to spatials that are completely outside
7759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta         * of this camera's view frustum.
7859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta         */
7959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Outside,
8059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        /**
8159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta         * defines a constant assigned to spatials that are completely inside
8259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta         * the camera's view frustum.
8359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta         */
8459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Inside,
8559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        /**
8659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta         * defines a constant assigned to spatials that are intersecting one of
8759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta         * the six planes that define the view frustum.
8859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta         */
8959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Intersects;
9059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
9159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
9259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * LEFT_PLANE represents the left plane of the camera frustum.
9359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
9459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private static final int LEFT_PLANE = 0;
9559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
9659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * RIGHT_PLANE represents the right plane of the camera frustum.
9759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
9859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private static final int RIGHT_PLANE = 1;
9959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
10059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * BOTTOM_PLANE represents the bottom plane of the camera frustum.
10159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
10259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private static final int BOTTOM_PLANE = 2;
10359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
10459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * TOP_PLANE represents the top plane of the camera frustum.
10559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
10659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private static final int TOP_PLANE = 3;
10759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
10859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * FAR_PLANE represents the far plane of the camera frustum.
10959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
11059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private static final int FAR_PLANE = 4;
11159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
11259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * NEAR_PLANE represents the near plane of the camera frustum.
11359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
11459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private static final int NEAR_PLANE = 5;
11559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
11659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * FRUSTUM_PLANES represents the number of planes of the camera frustum.
11759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
11859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private static final int FRUSTUM_PLANES = 6;
11959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
12059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * MAX_WORLD_PLANES holds the maximum planes allowed by the system.
12159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
12259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private static final int MAX_WORLD_PLANES = 6;
12359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
12459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Camera's location
12559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
12659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    protected Vector3f location;
12759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
12859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * The orientation of the camera.
12959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
13059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    protected Quaternion rotation;
13159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
13259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Distance from camera to near frustum plane.
13359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
13459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    protected float frustumNear;
13559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
13659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Distance from camera to far frustum plane.
13759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
13859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    protected float frustumFar;
13959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
14059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Distance from camera to left frustum plane.
14159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
14259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    protected float frustumLeft;
14359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
14459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Distance from camera to right frustum plane.
14559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
14659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    protected float frustumRight;
14759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
14859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Distance from camera to top frustum plane.
14959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
15059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    protected float frustumTop;
15159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
15259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Distance from camera to bottom frustum plane.
15359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
15459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    protected float frustumBottom;
15559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    //Temporary values computed in onFrustumChange that are needed if a
15659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    //call is made to onFrameChange.
15759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    protected float[] coeffLeft;
15859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    protected float[] coeffRight;
15959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    protected float[] coeffBottom;
16059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    protected float[] coeffTop;
16159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    //view port coordinates
16259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
16359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Percent value on display where horizontal viewing starts for this camera.
16459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Default is 0.
16559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
16659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    protected float viewPortLeft;
16759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
16859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Percent value on display where horizontal viewing ends for this camera.
16959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Default is 1.
17059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
17159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    protected float viewPortRight;
17259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
17359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Percent value on display where vertical viewing ends for this camera.
17459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Default is 1.
17559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
17659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    protected float viewPortTop;
17759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
17859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Percent value on display where vertical viewing begins for this camera.
17959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Default is 0.
18059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
18159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    protected float viewPortBottom;
18259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
18359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Array holding the planes that this camera will check for culling.
18459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
18559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    protected Plane[] worldPlane;
18659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
18759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * A mask value set during contains() that allows fast culling of a Node's
18859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * children.
18959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
19059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private int planeState;
19159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    protected int width;
19259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    protected int height;
19359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    protected boolean viewportChanged = true;
19459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
19559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * store the value for field parallelProjection
19659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
19759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private boolean parallelProjection;
19859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    protected Matrix4f projectionMatrixOverride;
19959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    protected Matrix4f viewMatrix = new Matrix4f();
20059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    protected Matrix4f projectionMatrix = new Matrix4f();
20159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    protected Matrix4f viewProjectionMatrix = new Matrix4f();
20259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private BoundingBox guiBounding = new BoundingBox();
20359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /** The camera's name. */
20459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    protected String name;
20559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
20659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
20759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Serialization only. Do not use.
20859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
20959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Camera() {
21059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        worldPlane = new Plane[MAX_WORLD_PLANES];
21159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        for (int i = 0; i < MAX_WORLD_PLANES; i++) {
21259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            worldPlane[i] = new Plane();
21359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
21459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
21559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
21659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
21759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Constructor instantiates a new <code>Camera</code> object. All
21859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * values of the camera are set to default.
21959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
22059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Camera(int width, int height) {
22159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this();
22259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        location = new Vector3f();
22359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        rotation = new Quaternion();
22459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
22559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        frustumNear = 1.0f;
22659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        frustumFar = 2.0f;
22759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        frustumLeft = -0.5f;
22859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        frustumRight = 0.5f;
22959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        frustumTop = 0.5f;
23059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        frustumBottom = -0.5f;
23159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
23259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        coeffLeft = new float[2];
23359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        coeffRight = new float[2];
23459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        coeffBottom = new float[2];
23559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        coeffTop = new float[2];
23659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
23759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        viewPortLeft = 0.0f;
23859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        viewPortRight = 1.0f;
23959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        viewPortTop = 1.0f;
24059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        viewPortBottom = 0.0f;
24159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
24259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.width = width;
24359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.height = height;
24459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
24559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        onFrustumChange();
24659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        onViewPortChange();
24759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        onFrameChange();
24859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
24959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        logger.log(Level.INFO, "Camera created (W: {0}, H: {1})", new Object[]{width, height});
25059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
25159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
25259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    @Override
25359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Camera clone() {
25459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        try {
25559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            Camera cam = (Camera) super.clone();
25659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            cam.viewportChanged = true;
25759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            cam.planeState = 0;
25859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
25959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            cam.worldPlane = new Plane[MAX_WORLD_PLANES];
26059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            for (int i = 0; i < worldPlane.length; i++) {
26159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                cam.worldPlane[i] = worldPlane[i].clone();
26259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
26359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
26459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            cam.coeffLeft = new float[2];
26559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            cam.coeffRight = new float[2];
26659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            cam.coeffBottom = new float[2];
26759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            cam.coeffTop = new float[2];
26859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
26959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            cam.location = location.clone();
27059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            cam.rotation = rotation.clone();
27159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
27259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (projectionMatrixOverride != null) {
27359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                cam.projectionMatrixOverride = projectionMatrixOverride.clone();
27459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
27559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
27659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            cam.viewMatrix = viewMatrix.clone();
27759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            cam.projectionMatrix = projectionMatrix.clone();
27859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            cam.viewProjectionMatrix = viewProjectionMatrix.clone();
27959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            cam.guiBounding = (BoundingBox) guiBounding.clone();
28059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
28159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            cam.update();
28259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
28359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return cam;
28459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } catch (CloneNotSupportedException ex) {
28559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            throw new AssertionError();
28659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
28759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
28859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
28959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	/**
29059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	 * This method copise the settings of the given camera.
29159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	 *
29259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	 * @param cam
29359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	 *            the camera we copy the settings from
29459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	 */
29559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void copyFrom(Camera cam) {
29659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    	location.set(cam.location);
29759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        rotation.set(cam.rotation);
29859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
29959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        frustumNear = cam.frustumNear;
30059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        frustumFar = cam.frustumFar;
30159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        frustumLeft = cam.frustumLeft;
30259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        frustumRight = cam.frustumRight;
30359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        frustumTop = cam.frustumTop;
30459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        frustumBottom = cam.frustumBottom;
30559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
30659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        coeffLeft[0] = cam.coeffLeft[0];
30759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        coeffLeft[1] = cam.coeffLeft[1];
30859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        coeffRight[0] = cam.coeffRight[0];
30959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        coeffRight[1] = cam.coeffRight[1];
31059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        coeffBottom[0] = cam.coeffBottom[0];
31159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        coeffBottom[1] = cam.coeffBottom[1];
31259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        coeffTop[0] = cam.coeffTop[0];
31359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        coeffTop[1] = cam.coeffTop[1];
31459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
31559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        viewPortLeft = cam.viewPortLeft;
31659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        viewPortRight = cam.viewPortRight;
31759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        viewPortTop = cam.viewPortTop;
31859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        viewPortBottom = cam.viewPortBottom;
31959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
32059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.width = cam.width;
32159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.height = cam.height;
32259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
32359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.planeState = cam.planeState;
32459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.viewportChanged = cam.viewportChanged;
32559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        for (int i = 0; i < MAX_WORLD_PLANES; ++i) {
32659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            worldPlane[i].setNormal(cam.worldPlane[i].getNormal());
32759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            worldPlane[i].setConstant(cam.worldPlane[i].getConstant());
32859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
32959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
33059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.parallelProjection = cam.parallelProjection;
33159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if(cam.projectionMatrixOverride != null) {
33259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        	if(this.projectionMatrixOverride == null) {
33359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        		this.projectionMatrixOverride = cam.projectionMatrixOverride.clone();
33459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        	} else {
33559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        		this.projectionMatrixOverride.set(cam.projectionMatrixOverride);
33659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        	}
33759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else {
33859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        	this.projectionMatrixOverride = null;
33959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
34059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.viewMatrix.set(cam.viewMatrix);
34159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.projectionMatrix.set(cam.projectionMatrix);
34259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.viewProjectionMatrix.set(cam.viewProjectionMatrix);
34359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
34459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.guiBounding.setXExtent(cam.guiBounding.getXExtent());
34559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.guiBounding.setYExtent(cam.guiBounding.getYExtent());
34659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.guiBounding.setZExtent(cam.guiBounding.getZExtent());
34759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.guiBounding.setCenter(cam.guiBounding.getCenter());
34859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.guiBounding.setCheckPlane(cam.guiBounding.getCheckPlane());
34959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
35059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.name = cam.name;
35159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
35259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
35359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
35459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * This method sets the cameras name.
35559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param name the cameras name
35659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
35759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setName(String name) {
35859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.name = name;
35959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
36059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
36159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
36259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * This method returns the cameras name.
36359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return the cameras name
36459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
36559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public String getName() {
36659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return name;
36759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
36859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
36959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
37059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Sets a clipPlane for this camera.
37159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * The cliPlane is used to recompute the projectionMatrix using the plane as the near plane
37259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * This technique is known as the oblique near-plane clipping method introduced by Eric Lengyel
37359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * more info here
37459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <ul>
37559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <li><a href="http://www.terathon.com/code/oblique.html">http://www.terathon.com/code/oblique.html</a>
37659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <li><a href="http://aras-p.info/texts/obliqueortho.html">http://aras-p.info/texts/obliqueortho.html</a>
37759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <li><a href="http://hacksoflife.blogspot.com/2008/12/every-now-and-then-i-come-across.html">http://hacksoflife.blogspot.com/2008/12/every-now-and-then-i-come-across.html</a>
37859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * </ul>
37959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
38059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Note that this will work properly only if it's called on each update, and be aware that it won't work properly with the sky bucket.
38159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * if you want to handle the sky bucket, look at how it's done in SimpleWaterProcessor.java
38259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param clipPlane the plane
38359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param side the side the camera stands from the plane
38459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
38559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setClipPlane(Plane clipPlane, Plane.Side side) {
38659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        float sideFactor = 1;
38759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (side == Plane.Side.Negative) {
38859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            sideFactor = -1;
38959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
39059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        //we are on the other side of the plane no need to clip anymore.
39159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (clipPlane.whichSide(location) == side) {
39259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return;
39359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
39459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Matrix4f p = projectionMatrix.clone();
39559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
39659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Matrix4f ivm = viewMatrix.clone();
39759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
39859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Vector3f point = clipPlane.getNormal().mult(clipPlane.getConstant());
39959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Vector3f pp = ivm.mult(point);
40059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Vector3f pn = ivm.multNormal(clipPlane.getNormal(), null);
40159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Vector4f clipPlaneV = new Vector4f(pn.x * sideFactor, pn.y * sideFactor, pn.z * sideFactor, -(pp.dot(pn)) * sideFactor);
40259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
40359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Vector4f v = new Vector4f(0, 0, 0, 0);
40459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
40559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        v.x = (Math.signum(clipPlaneV.x) + p.m02) / p.m00;
40659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        v.y = (Math.signum(clipPlaneV.y) + p.m12) / p.m11;
40759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        v.z = -1.0f;
40859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        v.w = (1.0f + p.m22) / p.m23;
40959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
41059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        float dot = clipPlaneV.dot(v);//clipPlaneV.x * v.x + clipPlaneV.y * v.y + clipPlaneV.z * v.z + clipPlaneV.w * v.w;
41159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Vector4f c = clipPlaneV.mult(2.0f / dot);
41259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
41359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        p.m20 = c.x - p.m30;
41459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        p.m21 = c.y - p.m31;
41559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        p.m22 = c.z - p.m32;
41659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        p.m23 = c.w - p.m33;
41759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        setProjectionMatrix(p);
41859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
41959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
42059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
42159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Sets a clipPlane for this camera.
42259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * The cliPlane is used to recompute the projectionMatrix using the plane as the near plane
42359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * This technique is known as the oblique near-plane clipping method introduced by Eric Lengyel
42459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * more info here
42559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <ul>
42659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <li><a href="http://www.terathon.com/code/oblique.html">http://www.terathon.com/code/oblique.html</a></li>
42759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <li><a href="http://aras-p.info/texts/obliqueortho.html">http://aras-p.info/texts/obliqueortho.html</a></li>
42859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <li><a href="http://hacksoflife.blogspot.com/2008/12/every-now-and-then-i-come-across.html">
42959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * http://hacksoflife.blogspot.com/2008/12/every-now-and-then-i-come-across.html</a></li>
43059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * </ul>
43159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
43259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Note that this will work properly only if it's called on each update, and be aware that it won't work properly with the sky bucket.
43359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * if you want to handle the sky bucket, look at how it's done in SimpleWaterProcessor.java
43459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param clipPlane the plane
43559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
43659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setClipPlane(Plane clipPlane) {
43759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        setClipPlane(clipPlane, clipPlane.whichSide(location));
43859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
43959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
44059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
44159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Resizes this camera's view with the given width and height. This is
44259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * similar to constructing a new camera, but reusing the same Object. This
44359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * method is called by an associated {@link RenderManager} to notify the camera of
44459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * changes in the display dimensions.
44559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
44659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param width the view width
44759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param height the view height
44859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param fixAspect If true, the camera's aspect ratio will be recomputed.
44959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Recomputing the aspect ratio requires changing the frustum values.
45059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
45159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void resize(int width, int height, boolean fixAspect) {
45259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.width = width;
45359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.height = height;
45459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        onViewPortChange();
45559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
45659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (fixAspect /*&& !parallelProjection*/) {
45759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            frustumRight = frustumTop * ((float) width / height);
45859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            frustumLeft = -frustumRight;
45959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            onFrustumChange();
46059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
46159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
46259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
46359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
46459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>getFrustumBottom</code> returns the value of the bottom frustum
46559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * plane.
46659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
46759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return the value of the bottom frustum plane.
46859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
46959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public float getFrustumBottom() {
47059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return frustumBottom;
47159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
47259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
47359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
47459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>setFrustumBottom</code> sets the value of the bottom frustum
47559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * plane.
47659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
47759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param frustumBottom the value of the bottom frustum plane.
47859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
47959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setFrustumBottom(float frustumBottom) {
48059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.frustumBottom = frustumBottom;
48159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        onFrustumChange();
48259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
48359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
48459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
48559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>getFrustumFar</code> gets the value of the far frustum plane.
48659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
48759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return the value of the far frustum plane.
48859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
48959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public float getFrustumFar() {
49059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return frustumFar;
49159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
49259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
49359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
49459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>setFrustumFar</code> sets the value of the far frustum plane.
49559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
49659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param frustumFar the value of the far frustum plane.
49759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
49859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setFrustumFar(float frustumFar) {
49959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.frustumFar = frustumFar;
50059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        onFrustumChange();
50159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
50259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
50359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
50459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>getFrustumLeft</code> gets the value of the left frustum plane.
50559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
50659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return the value of the left frustum plane.
50759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
50859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public float getFrustumLeft() {
50959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return frustumLeft;
51059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
51159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
51259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
51359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>setFrustumLeft</code> sets the value of the left frustum plane.
51459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
51559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param frustumLeft the value of the left frustum plane.
51659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
51759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setFrustumLeft(float frustumLeft) {
51859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.frustumLeft = frustumLeft;
51959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        onFrustumChange();
52059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
52159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
52259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
52359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>getFrustumNear</code> gets the value of the near frustum plane.
52459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
52559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return the value of the near frustum plane.
52659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
52759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public float getFrustumNear() {
52859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return frustumNear;
52959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
53059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
53159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
53259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>setFrustumNear</code> sets the value of the near frustum plane.
53359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
53459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param frustumNear the value of the near frustum plane.
53559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
53659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setFrustumNear(float frustumNear) {
53759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.frustumNear = frustumNear;
53859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        onFrustumChange();
53959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
54059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
54159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
54259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>getFrustumRight</code> gets the value of the right frustum plane.
54359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
54459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return frustumRight the value of the right frustum plane.
54559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
54659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public float getFrustumRight() {
54759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return frustumRight;
54859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
54959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
55059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
55159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>setFrustumRight</code> sets the value of the right frustum plane.
55259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
55359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param frustumRight the value of the right frustum plane.
55459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
55559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setFrustumRight(float frustumRight) {
55659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.frustumRight = frustumRight;
55759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        onFrustumChange();
55859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
55959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
56059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
56159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>getFrustumTop</code> gets the value of the top frustum plane.
56259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
56359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return the value of the top frustum plane.
56459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
56559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public float getFrustumTop() {
56659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return frustumTop;
56759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
56859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
56959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
57059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>setFrustumTop</code> sets the value of the top frustum plane.
57159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
57259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param frustumTop the value of the top frustum plane.
57359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
57459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setFrustumTop(float frustumTop) {
57559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.frustumTop = frustumTop;
57659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        onFrustumChange();
57759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
57859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
57959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
58059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>getLocation</code> retrieves the location vector of the camera.
58159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
58259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return the position of the camera.
58359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @see Camera#getLocation()
58459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
58559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Vector3f getLocation() {
58659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return location;
58759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
58859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
58959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
59059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>getRotation</code> retrieves the rotation quaternion of the camera.
59159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
59259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return the rotation of the camera.
59359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
59459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Quaternion getRotation() {
59559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return rotation;
59659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
59759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
59859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
59959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>getDirection</code> retrieves the direction vector the camera is
60059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * facing.
60159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
60259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return the direction the camera is facing.
60359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @see Camera#getDirection()
60459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
60559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Vector3f getDirection() {
60659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return rotation.getRotationColumn(2);
60759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
60859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
60959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
61059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>getLeft</code> retrieves the left axis of the camera.
61159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
61259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return the left axis of the camera.
61359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @see Camera#getLeft()
61459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
61559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Vector3f getLeft() {
61659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return rotation.getRotationColumn(0);
61759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
61859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
61959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
62059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>getUp</code> retrieves the up axis of the camera.
62159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
62259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return the up axis of the camera.
62359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @see Camera#getUp()
62459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
62559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Vector3f getUp() {
62659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return rotation.getRotationColumn(1);
62759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
62859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
62959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
63059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>getDirection</code> retrieves the direction vector the camera is
63159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * facing.
63259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
63359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return the direction the camera is facing.
63459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @see Camera#getDirection()
63559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
63659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Vector3f getDirection(Vector3f store) {
63759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return rotation.getRotationColumn(2, store);
63859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
63959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
64059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
64159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>getLeft</code> retrieves the left axis of the camera.
64259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
64359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return the left axis of the camera.
64459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @see Camera#getLeft()
64559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
64659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Vector3f getLeft(Vector3f store) {
64759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return rotation.getRotationColumn(0, store);
64859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
64959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
65059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
65159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>getUp</code> retrieves the up axis of the camera.
65259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
65359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return the up axis of the camera.
65459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @see Camera#getUp()
65559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
65659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Vector3f getUp(Vector3f store) {
65759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return rotation.getRotationColumn(1, store);
65859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
65959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
66059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
66159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>setLocation</code> sets the position of the camera.
66259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
66359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param location the position of the camera.
66459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
66559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setLocation(Vector3f location) {
66659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.location.set(location);
66759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        onFrameChange();
66859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
66959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
67059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
67159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>setRotation</code> sets the orientation of this camera.
67259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * This will be equivelant to setting each of the axes:
67359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code><br>
67459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * cam.setLeft(rotation.getRotationColumn(0));<br>
67559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * cam.setUp(rotation.getRotationColumn(1));<br>
67659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * cam.setDirection(rotation.getRotationColumn(2));<br>
67759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * </code>
67859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
67959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param rotation the rotation of this camera
68059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
68159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setRotation(Quaternion rotation) {
68259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.rotation.set(rotation);
68359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        onFrameChange();
68459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
68559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
68659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
68759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>lookAtDirection</code> sets the direction the camera is facing
68859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * given a direction and an up vector.
68959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
69059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param direction the direction this camera is facing.
69159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
69259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void lookAtDirection(Vector3f direction, Vector3f up) {
69359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.rotation.lookAt(direction, up);
69459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        onFrameChange();
69559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
69659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
69759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
69859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>setAxes</code> sets the axes (left, up and direction) for this
69959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * camera.
70059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
70159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param left      the left axis of the camera.
70259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param up        the up axis of the camera.
70359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param direction the direction the camera is facing.
70459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
70559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @see Camera#setAxes(com.jme3.math.Quaternion)
70659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
70759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setAxes(Vector3f left, Vector3f up, Vector3f direction) {
70859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.rotation.fromAxes(left, up, direction);
70959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        onFrameChange();
71059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
71159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
71259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
71359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>setAxes</code> uses a rotational matrix to set the axes of the
71459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * camera.
71559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
71659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param axes the matrix that defines the orientation of the camera.
71759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
71859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setAxes(Quaternion axes) {
71959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.rotation.set(axes);
72059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        onFrameChange();
72159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
72259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
72359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
72459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * normalize normalizes the camera vectors.
72559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
72659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void normalize() {
72759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.rotation.normalizeLocal();
72859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        onFrameChange();
72959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
73059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
73159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
73259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>setFrustum</code> sets the frustum of this camera object.
73359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
73459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param near   the near plane.
73559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param far    the far plane.
73659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param left   the left plane.
73759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param right  the right plane.
73859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param top    the top plane.
73959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param bottom the bottom plane.
74059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @see Camera#setFrustum(float, float, float, float,
74159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *      float, float)
74259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
74359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setFrustum(float near, float far, float left, float right,
74459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            float top, float bottom) {
74559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
74659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        frustumNear = near;
74759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        frustumFar = far;
74859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        frustumLeft = left;
74959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        frustumRight = right;
75059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        frustumTop = top;
75159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        frustumBottom = bottom;
75259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        onFrustumChange();
75359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
75459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
75559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
75659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>setFrustumPerspective</code> defines the frustum for the camera.  This
75759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * frustum is defined by a viewing angle, aspect ratio, and near/far planes
75859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
75959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param fovY   Frame of view angle along the Y in degrees.
76059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param aspect Width:Height ratio
76159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param near   Near view plane distance
76259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param far    Far view plane distance
76359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
76459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setFrustumPerspective(float fovY, float aspect, float near,
76559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            float far) {
76659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (Float.isNaN(aspect) || Float.isInfinite(aspect)) {
76759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // ignore.
76859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            logger.log(Level.WARNING, "Invalid aspect given to setFrustumPerspective: {0}", aspect);
76959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return;
77059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
77159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
77259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        float h = FastMath.tan(fovY * FastMath.DEG_TO_RAD * .5f) * near;
77359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        float w = h * aspect;
77459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        frustumLeft = -w;
77559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        frustumRight = w;
77659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        frustumBottom = -h;
77759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        frustumTop = h;
77859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        frustumNear = near;
77959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        frustumFar = far;
78059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
78159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        onFrustumChange();
78259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
78359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
78459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
78559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>setFrame</code> sets the orientation and location of the camera.
78659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
78759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param location  the point position of the camera.
78859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param left      the left axis of the camera.
78959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param up        the up axis of the camera.
79059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param direction the facing of the camera.
79159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @see Camera#setFrame(com.jme3.math.Vector3f,
79259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *      com.jme3.math.Vector3f, com.jme3.math.Vector3f, com.jme3.math.Vector3f)
79359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
79459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setFrame(Vector3f location, Vector3f left, Vector3f up,
79559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            Vector3f direction) {
79659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
79759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.location = location;
79859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.rotation.fromAxes(left, up, direction);
79959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        onFrameChange();
80059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
80159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
80259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
80359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>lookAt</code> is a convienence method for auto-setting the frame
80459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * based on a world position the user desires the camera to look at. It
80559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * repoints the camera towards the given position using the difference
80659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * between the position and the current camera location as a direction
80759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * vector and the worldUpVector to compute up and left camera vectors.
80859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
80959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param pos           where to look at in terms of world coordinates
81059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param worldUpVector a normalized vector indicating the up direction of the world.
81159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *                      (typically {0, 1, 0} in jME.)
81259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
81359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void lookAt(Vector3f pos, Vector3f worldUpVector) {
81459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        TempVars vars = TempVars.get();
81559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Vector3f newDirection = vars.vect1;
81659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Vector3f newUp = vars.vect2;
81759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Vector3f newLeft = vars.vect3;
81859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
81959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        newDirection.set(pos).subtractLocal(location).normalizeLocal();
82059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
82159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        newUp.set(worldUpVector).normalizeLocal();
82259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (newUp.equals(Vector3f.ZERO)) {
82359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            newUp.set(Vector3f.UNIT_Y);
82459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
82559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
82659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        newLeft.set(newUp).crossLocal(newDirection).normalizeLocal();
82759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (newLeft.equals(Vector3f.ZERO)) {
82859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (newDirection.x != 0) {
82959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                newLeft.set(newDirection.y, -newDirection.x, 0f);
83059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            } else {
83159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                newLeft.set(0f, newDirection.z, -newDirection.y);
83259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
83359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
83459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
83559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        newUp.set(newDirection).crossLocal(newLeft).normalizeLocal();
83659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
83759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.rotation.fromAxes(newLeft, newUp, newDirection);
83859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.rotation.normalizeLocal();
83959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        vars.release();
84059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
84159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        onFrameChange();
84259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
84359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
84459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
84559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>setFrame</code> sets the orientation and location of the camera.
84659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
84759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param location
84859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *            the point position of the camera.
84959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param axes
85059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *            the orientation of the camera.
85159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
85259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setFrame(Vector3f location, Quaternion axes) {
85359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.location = location;
85459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.rotation.set(axes);
85559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        onFrameChange();
85659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
85759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
85859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
85959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>update</code> updates the camera parameters by calling
86059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>onFrustumChange</code>,<code>onViewPortChange</code> and
86159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>onFrameChange</code>.
86259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
86359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @see Camera#update()
86459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
86559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void update() {
86659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        onFrustumChange();
86759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        onViewPortChange();
86859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        onFrameChange();
86959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
87059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
87159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
87259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>getPlaneState</code> returns the state of the frustum planes. So
87359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * checks can be made as to which frustum plane has been examined for
87459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * culling thus far.
87559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
87659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return the current plane state int.
87759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
87859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public int getPlaneState() {
87959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return planeState;
88059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
88159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
88259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
88359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>setPlaneState</code> sets the state to keep track of tested
88459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * planes for culling.
88559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
88659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param planeState the updated state.
88759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
88859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setPlaneState(int planeState) {
88959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.planeState = planeState;
89059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
89159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
89259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
89359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>getViewPortLeft</code> gets the left boundary of the viewport
89459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
89559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return the left boundary of the viewport
89659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
89759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public float getViewPortLeft() {
89859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return viewPortLeft;
89959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
90059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
90159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
90259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>setViewPortLeft</code> sets the left boundary of the viewport
90359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
90459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param left the left boundary of the viewport
90559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
90659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setViewPortLeft(float left) {
90759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        viewPortLeft = left;
90859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        onViewPortChange();
90959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
91059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
91159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
91259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>getViewPortRight</code> gets the right boundary of the viewport
91359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
91459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return the right boundary of the viewport
91559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
91659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public float getViewPortRight() {
91759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return viewPortRight;
91859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
91959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
92059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
92159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>setViewPortRight</code> sets the right boundary of the viewport
92259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
92359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param right the right boundary of the viewport
92459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
92559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setViewPortRight(float right) {
92659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        viewPortRight = right;
92759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        onViewPortChange();
92859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
92959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
93059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
93159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>getViewPortTop</code> gets the top boundary of the viewport
93259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
93359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return the top boundary of the viewport
93459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
93559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public float getViewPortTop() {
93659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return viewPortTop;
93759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
93859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
93959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
94059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>setViewPortTop</code> sets the top boundary of the viewport
94159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
94259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param top the top boundary of the viewport
94359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
94459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setViewPortTop(float top) {
94559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        viewPortTop = top;
94659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        onViewPortChange();
94759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
94859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
94959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
95059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>getViewPortBottom</code> gets the bottom boundary of the viewport
95159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
95259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return the bottom boundary of the viewport
95359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
95459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public float getViewPortBottom() {
95559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return viewPortBottom;
95659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
95759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
95859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
95959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>setViewPortBottom</code> sets the bottom boundary of the viewport
96059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
96159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param bottom the bottom boundary of the viewport
96259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
96359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setViewPortBottom(float bottom) {
96459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        viewPortBottom = bottom;
96559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        onViewPortChange();
96659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
96759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
96859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
96959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>setViewPort</code> sets the boundaries of the viewport
97059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
97159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param left   the left boundary of the viewport (default: 0)
97259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param right  the right boundary of the viewport (default: 1)
97359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param bottom the bottom boundary of the viewport (default: 0)
97459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param top    the top boundary of the viewport (default: 1)
97559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
97659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setViewPort(float left, float right, float bottom, float top) {
97759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.viewPortLeft = left;
97859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.viewPortRight = right;
97959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.viewPortBottom = bottom;
98059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.viewPortTop = top;
98159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        onViewPortChange();
98259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
98359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
98459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
98559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Returns the pseudo distance from the given position to the near
98659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * plane of the camera. This is used for render queue sorting.
98759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param pos The position to compute a distance to.
98859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return Distance from the far plane to the point.
98959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
99059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public float distanceToNearPlane(Vector3f pos) {
99159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return worldPlane[NEAR_PLANE].pseudoDistance(pos);
99259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
99359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
99459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
99559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>contains</code> tests a bounding volume against the planes of the
99659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * camera's frustum. The frustums planes are set such that the normals all
99759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * face in towards the viewable scene. Therefore, if the bounding volume is
99859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * on the negative side of the plane is can be culled out.
99959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
100059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * NOTE: This method is used internally for culling, for public usage,
100159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * the plane state of the bounding volume must be saved and restored, e.g:
100259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>BoundingVolume bv;<br/>
100359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Camera c;<br/>
100459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * int planeState = bv.getPlaneState();<br/>
100559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * bv.setPlaneState(0);<br/>
100659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * c.contains(bv);<br/>
100759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * bv.setPlaneState(plateState);<br/>
100859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * </code>
100959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
101059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param bound the bound to check for culling
101159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return See enums in <code>FrustumIntersect</code>
101259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
101359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public FrustumIntersect contains(BoundingVolume bound) {
101459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (bound == null) {
101559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return FrustumIntersect.Inside;
101659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
101759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
101859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        int mask;
101959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        FrustumIntersect rVal = FrustumIntersect.Inside;
102059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
102159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        for (int planeCounter = FRUSTUM_PLANES; planeCounter >= 0; planeCounter--) {
102259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (planeCounter == bound.getCheckPlane()) {
102359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                continue; // we have already checked this plane at first iteration
102459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
102559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            int planeId = (planeCounter == FRUSTUM_PLANES) ? bound.getCheckPlane() : planeCounter;
102659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            int planeId = planeCounter;
102759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
102859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            mask = 1 << (planeId);
102959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if ((planeState & mask) == 0) {
103059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                Plane.Side side = bound.whichSide(worldPlane[planeId]);
103159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
103259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                if (side == Plane.Side.Negative) {
103359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    //object is outside of frustum
103459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    bound.setCheckPlane(planeId);
103559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    return FrustumIntersect.Outside;
103659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                } else if (side == Plane.Side.Positive) {
103759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    //object is visible on *this* plane, so mark this plane
103859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    //so that we don't check it for sub nodes.
103959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    planeState |= mask;
104059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                } else {
104159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    rVal = FrustumIntersect.Intersects;
104259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                }
104359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
104459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
104559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
104659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return rVal;
104759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
104859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
104959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
105059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>containsGui</code> tests a bounding volume against the ortho
105159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * bounding box of the camera. A bounding box spanning from
105259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * 0, 0 to Width, Height. Constrained by the viewport settings on the
105359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * camera.
105459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
105559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param bound the bound to check for culling
105659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return True if the camera contains the gui element bounding volume.
105759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
105859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public boolean containsGui(BoundingVolume bound) {
105959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return guiBounding.intersects(bound);
106059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
106159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
106259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
106359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return the view matrix of the camera.
106459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * The view matrix transforms world space into eye space.
106559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * This matrix is usually defined by the position and
106659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * orientation of the camera.
106759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
106859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Matrix4f getViewMatrix() {
106959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return viewMatrix;
107059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
107159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
107259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
107359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Overrides the projection matrix used by the camera. Will
107459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * use the matrix for computing the view projection matrix as well.
107559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Use null argument to return to normal functionality.
107659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
107759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param projMatrix
107859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
107959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setProjectionMatrix(Matrix4f projMatrix) {
108059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        projectionMatrixOverride = projMatrix;
108159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        updateViewProjection();
108259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
108359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
108459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
108559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return the projection matrix of the camera.
108659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * The view projection matrix  transforms eye space into clip space.
108759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * This matrix is usually defined by the viewport and perspective settings
108859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * of the camera.
108959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
109059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Matrix4f getProjectionMatrix() {
109159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (projectionMatrixOverride != null) {
109259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return projectionMatrixOverride;
109359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
109459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
109559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return projectionMatrix;
109659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
109759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
109859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
109959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Updates the view projection matrix.
110059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
110159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void updateViewProjection() {
110259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (projectionMatrixOverride != null) {
110359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            viewProjectionMatrix.set(projectionMatrixOverride).multLocal(viewMatrix);
110459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else {
110559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            //viewProjectionMatrix.set(viewMatrix).multLocal(projectionMatrix);
110659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            viewProjectionMatrix.set(projectionMatrix).multLocal(viewMatrix);
110759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
110859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
110959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
111059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
111159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return The result of multiplying the projection matrix by the view
111259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * matrix. This matrix is required for rendering an object. It is
111359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * precomputed so as to not compute it every time an object is rendered.
111459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
111559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Matrix4f getViewProjectionMatrix() {
111659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return viewProjectionMatrix;
111759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
111859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
111959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
112059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return True if the viewport (width, height, left, right, bottom, up)
112159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * has been changed. This is needed in the renderer so that the proper
112259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * viewport can be set-up.
112359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
112459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public boolean isViewportChanged() {
112559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return viewportChanged;
112659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
112759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
112859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
112959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Clears the viewport changed flag once it has been updated inside
113059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * the renderer.
113159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
113259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void clearViewportChanged() {
113359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        viewportChanged = false;
113459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
113559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
113659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
113759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Called when the viewport has been changed.
113859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
113959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void onViewPortChange() {
114059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        viewportChanged = true;
114159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        setGuiBounding();
114259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
114359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
114459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private void setGuiBounding() {
114559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        float sx = width * viewPortLeft;
114659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        float ex = width * viewPortRight;
114759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        float sy = height * viewPortBottom;
114859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        float ey = height * viewPortTop;
114959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        float xExtent = Math.max(0f, (ex - sx) / 2f);
115059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        float yExtent = Math.max(0f, (ey - sy) / 2f);
115159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        guiBounding.setCenter(new Vector3f(sx + xExtent, sy + yExtent, 0));
115259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        guiBounding.setXExtent(xExtent);
115359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        guiBounding.setYExtent(yExtent);
115459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        guiBounding.setZExtent(Float.MAX_VALUE);
115559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
115659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
115759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
115859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>onFrustumChange</code> updates the frustum to reflect any changes
115959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * made to the planes. The new frustum values are kept in a temporary
116059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * location for use when calculating the new frame. The projection
116159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * matrix is updated to reflect the current values of the frustum.
116259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
116359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void onFrustumChange() {
116459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (!isParallelProjection()) {
116559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            float nearSquared = frustumNear * frustumNear;
116659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            float leftSquared = frustumLeft * frustumLeft;
116759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            float rightSquared = frustumRight * frustumRight;
116859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            float bottomSquared = frustumBottom * frustumBottom;
116959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            float topSquared = frustumTop * frustumTop;
117059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
117159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            float inverseLength = FastMath.invSqrt(nearSquared + leftSquared);
117259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            coeffLeft[0] = frustumNear * inverseLength;
117359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            coeffLeft[1] = -frustumLeft * inverseLength;
117459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
117559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            inverseLength = FastMath.invSqrt(nearSquared + rightSquared);
117659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            coeffRight[0] = -frustumNear * inverseLength;
117759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            coeffRight[1] = frustumRight * inverseLength;
117859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
117959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            inverseLength = FastMath.invSqrt(nearSquared + bottomSquared);
118059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            coeffBottom[0] = frustumNear * inverseLength;
118159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            coeffBottom[1] = -frustumBottom * inverseLength;
118259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
118359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            inverseLength = FastMath.invSqrt(nearSquared + topSquared);
118459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            coeffTop[0] = -frustumNear * inverseLength;
118559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            coeffTop[1] = frustumTop * inverseLength;
118659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else {
118759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            coeffLeft[0] = 1;
118859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            coeffLeft[1] = 0;
118959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
119059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            coeffRight[0] = -1;
119159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            coeffRight[1] = 0;
119259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
119359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            coeffBottom[0] = 1;
119459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            coeffBottom[1] = 0;
119559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
119659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            coeffTop[0] = -1;
119759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            coeffTop[1] = 0;
119859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
119959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
120059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        projectionMatrix.fromFrustum(frustumNear, frustumFar, frustumLeft, frustumRight, frustumTop, frustumBottom, parallelProjection);
120159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        projectionMatrix.transposeLocal();
120259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
120359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // The frame is effected by the frustum values
120459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // update it as well
120559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        onFrameChange();
120659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
120759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
120859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
120959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * <code>onFrameChange</code> updates the view frame of the camera.
121059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
121159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void onFrameChange() {
121259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        TempVars vars = TempVars.get();
121359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
121459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Vector3f left = getLeft(vars.vect1);
121559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Vector3f direction = getDirection(vars.vect2);
121659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Vector3f up = getUp(vars.vect3);
121759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
121859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        float dirDotLocation = direction.dot(location);
121959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
122059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // left plane
122159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Vector3f leftPlaneNormal = worldPlane[LEFT_PLANE].getNormal();
122259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        leftPlaneNormal.x = left.x * coeffLeft[0];
122359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        leftPlaneNormal.y = left.y * coeffLeft[0];
122459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        leftPlaneNormal.z = left.z * coeffLeft[0];
122559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        leftPlaneNormal.addLocal(direction.x * coeffLeft[1], direction.y
122659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                * coeffLeft[1], direction.z * coeffLeft[1]);
122759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        worldPlane[LEFT_PLANE].setConstant(location.dot(leftPlaneNormal));
122859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
122959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // right plane
123059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Vector3f rightPlaneNormal = worldPlane[RIGHT_PLANE].getNormal();
123159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        rightPlaneNormal.x = left.x * coeffRight[0];
123259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        rightPlaneNormal.y = left.y * coeffRight[0];
123359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        rightPlaneNormal.z = left.z * coeffRight[0];
123459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        rightPlaneNormal.addLocal(direction.x * coeffRight[1], direction.y
123559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                * coeffRight[1], direction.z * coeffRight[1]);
123659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        worldPlane[RIGHT_PLANE].setConstant(location.dot(rightPlaneNormal));
123759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
123859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // bottom plane
123959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Vector3f bottomPlaneNormal = worldPlane[BOTTOM_PLANE].getNormal();
124059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        bottomPlaneNormal.x = up.x * coeffBottom[0];
124159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        bottomPlaneNormal.y = up.y * coeffBottom[0];
124259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        bottomPlaneNormal.z = up.z * coeffBottom[0];
124359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        bottomPlaneNormal.addLocal(direction.x * coeffBottom[1], direction.y
124459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                * coeffBottom[1], direction.z * coeffBottom[1]);
124559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        worldPlane[BOTTOM_PLANE].setConstant(location.dot(bottomPlaneNormal));
124659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
124759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // top plane
124859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Vector3f topPlaneNormal = worldPlane[TOP_PLANE].getNormal();
124959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        topPlaneNormal.x = up.x * coeffTop[0];
125059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        topPlaneNormal.y = up.y * coeffTop[0];
125159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        topPlaneNormal.z = up.z * coeffTop[0];
125259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        topPlaneNormal.addLocal(direction.x * coeffTop[1], direction.y
125359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                * coeffTop[1], direction.z * coeffTop[1]);
125459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        worldPlane[TOP_PLANE].setConstant(location.dot(topPlaneNormal));
125559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
125659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (isParallelProjection()) {
125759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            worldPlane[LEFT_PLANE].setConstant(worldPlane[LEFT_PLANE].getConstant() + frustumLeft);
125859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            worldPlane[RIGHT_PLANE].setConstant(worldPlane[RIGHT_PLANE].getConstant() - frustumRight);
125959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            worldPlane[TOP_PLANE].setConstant(worldPlane[TOP_PLANE].getConstant() - frustumTop);
126059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            worldPlane[BOTTOM_PLANE].setConstant(worldPlane[BOTTOM_PLANE].getConstant() + frustumBottom);
126159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
126259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
126359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // far plane
126459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        worldPlane[FAR_PLANE].setNormal(left);
126559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        worldPlane[FAR_PLANE].setNormal(-direction.x, -direction.y, -direction.z);
126659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        worldPlane[FAR_PLANE].setConstant(-(dirDotLocation + frustumFar));
126759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
126859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // near plane
126959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        worldPlane[NEAR_PLANE].setNormal(direction.x, direction.y, direction.z);
127059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        worldPlane[NEAR_PLANE].setConstant(dirDotLocation + frustumNear);
127159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
127259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        viewMatrix.fromFrame(location, direction, up, left);
127359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
127459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        vars.release();
127559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
127659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        viewMatrix.transposeLocal();
127759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        updateViewProjection();
127859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
127959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
128059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
128159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return true if parallel projection is enable, false if in normal perspective mode
128259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @see #setParallelProjection(boolean)
128359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
128459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public boolean isParallelProjection() {
128559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return this.parallelProjection;
128659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
128759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
128859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
128959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Enable/disable parallel projection.
129059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
129159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @param value true to set up this camera for parallel projection is enable, false to enter normal perspective mode
129259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
129359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void setParallelProjection(final boolean value) {
129459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.parallelProjection = value;
129559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        onFrustumChange();
129659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
129759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
129859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
129959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @see Camera#getWorldCoordinates
130059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
130159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Vector3f getWorldCoordinates(Vector2f screenPos, float zPos) {
130259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return getWorldCoordinates(screenPos, zPos, null);
130359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
130459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
130559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
130659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @see Camera#getWorldCoordinates
130759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
130859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Vector3f getWorldCoordinates(Vector2f screenPosition,
130959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            float zPos, Vector3f store) {
131059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (store == null) {
131159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            store = new Vector3f();
131259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
131359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
131459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Matrix4f inverseMat = new Matrix4f(viewProjectionMatrix);
131559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        inverseMat.invertLocal();
131659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
131759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        store.set(
131859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                (screenPosition.x / getWidth() - viewPortLeft) / (viewPortRight - viewPortLeft) * 2 - 1,
131959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                (screenPosition.y / getHeight() - viewPortBottom) / (viewPortTop - viewPortBottom) * 2 - 1,
132059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                zPos * 2 - 1);
132159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
132259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        float w = inverseMat.multProj(store, store);
132359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        store.multLocal(1f / w);
132459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
132559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return store;
132659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
132759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
132859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
132959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Converts the given position from world space to screen space.
133059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
133159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @see Camera#getScreenCoordinates
133259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
133359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Vector3f getScreenCoordinates(Vector3f worldPos) {
133459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return getScreenCoordinates(worldPos, null);
133559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
133659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
133759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
133859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * Converts the given position from world space to screen space.
133959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     *
134059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @see Camera#getScreenCoordinates(Vector3f, Vector3f)
134159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
134259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Vector3f getScreenCoordinates(Vector3f worldPosition, Vector3f store) {
134359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (store == null) {
134459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            store = new Vector3f();
134559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
134659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
134759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        TempVars vars = vars.lock();
134859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        Quaternion tmp_quat = vars.quat1;
134959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        tmp_quat.set( worldPosition.x, worldPosition.y, worldPosition.z, 1 );
135059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        viewProjectionMatrix.mult(tmp_quat, tmp_quat);
135159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        tmp_quat.multLocal( 1.0f / tmp_quat.getW() );
135259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        store.x = ( ( tmp_quat.getX() + 1 ) * ( viewPortRight - viewPortLeft ) / 2 + viewPortLeft ) * getWidth();
135359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        store.y = ( ( tmp_quat.getY() + 1 ) * ( viewPortTop - viewPortBottom ) / 2 + viewPortBottom ) * getHeight();
135459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        store.z = ( tmp_quat.getZ() + 1 ) / 2;
135559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//        vars.release();
135659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
135759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        float w = viewProjectionMatrix.multProj(worldPosition, store);
135859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        store.divideLocal(w);
135959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
136059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        store.x = ((store.x + 1f) * (viewPortRight - viewPortLeft) / 2f + viewPortLeft) * getWidth();
136159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        store.y = ((store.y + 1f) * (viewPortTop - viewPortBottom) / 2f + viewPortBottom) * getHeight();
136259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        store.z = (store.z + 1f) / 2f;
136359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
136459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return store;
136559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
136659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
136759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
136859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return the width/resolution of the display.
136959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
137059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public int getWidth() {
137159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return width;
137259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
137359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
137459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    /**
137559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     * @return the height/resolution of the display.
137659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta     */
137759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public int getHeight() {
137859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return height;
137959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
138059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
138159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    @Override
138259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public String toString() {
138359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return "Camera[location=" + location + "\n, direction=" + getDirection() + "\n"
138459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                + "res=" + width + "x" + height + ", parallel=" + parallelProjection + "\n"
138559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                + "near=" + frustumNear + ", far=" + frustumFar + "]";
138659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
138759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
138859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void write(JmeExporter e) throws IOException {
138959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        OutputCapsule capsule = e.getCapsule(this);
139059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        capsule.write(location, "location", Vector3f.ZERO);
139159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        capsule.write(rotation, "rotation", Quaternion.DIRECTION_Z);
139259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        capsule.write(frustumNear, "frustumNear", 1);
139359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        capsule.write(frustumFar, "frustumFar", 2);
139459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        capsule.write(frustumLeft, "frustumLeft", -0.5f);
139559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        capsule.write(frustumRight, "frustumRight", 0.5f);
139659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        capsule.write(frustumTop, "frustumTop", 0.5f);
139759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        capsule.write(frustumBottom, "frustumBottom", -0.5f);
139859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        capsule.write(coeffLeft, "coeffLeft", new float[2]);
139959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        capsule.write(coeffRight, "coeffRight", new float[2]);
140059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        capsule.write(coeffBottom, "coeffBottom", new float[2]);
140159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        capsule.write(coeffTop, "coeffTop", new float[2]);
140259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        capsule.write(viewPortLeft, "viewPortLeft", 0);
140359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        capsule.write(viewPortRight, "viewPortRight", 1);
140459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        capsule.write(viewPortTop, "viewPortTop", 1);
140559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        capsule.write(viewPortBottom, "viewPortBottom", 0);
140659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        capsule.write(width, "width", 0);
140759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        capsule.write(height, "height", 0);
140859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        capsule.write(name, "name", null);
140959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
141059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
141159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public void read(JmeImporter e) throws IOException {
141259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        InputCapsule capsule = e.getCapsule(this);
141359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        location = (Vector3f) capsule.readSavable("location", Vector3f.ZERO.clone());
141459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        rotation = (Quaternion) capsule.readSavable("rotation", Quaternion.DIRECTION_Z.clone());
141559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        frustumNear = capsule.readFloat("frustumNear", 1);
141659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        frustumFar = capsule.readFloat("frustumFar", 2);
141759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        frustumLeft = capsule.readFloat("frustumLeft", -0.5f);
141859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        frustumRight = capsule.readFloat("frustumRight", 0.5f);
141959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        frustumTop = capsule.readFloat("frustumTop", 0.5f);
142059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        frustumBottom = capsule.readFloat("frustumBottom", -0.5f);
142159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        coeffLeft = capsule.readFloatArray("coeffLeft", new float[2]);
142259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        coeffRight = capsule.readFloatArray("coeffRight", new float[2]);
142359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        coeffBottom = capsule.readFloatArray("coeffBottom", new float[2]);
142459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        coeffTop = capsule.readFloatArray("coeffTop", new float[2]);
142559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        viewPortLeft = capsule.readFloat("viewPortLeft", 0);
142659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        viewPortRight = capsule.readFloat("viewPortRight", 1);
142759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        viewPortTop = capsule.readFloat("viewPortTop", 1);
142859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        viewPortBottom = capsule.readFloat("viewPortBottom", 0);
142959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        width = capsule.readInt("width", 1);
143059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        height = capsule.readInt("height", 1);
143159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        name = capsule.readString("name", null);
143259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        onFrustumChange();
143359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        onViewPortChange();
143459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        onFrameChange();
143559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
143659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta}
1437