/** * Copyright (c) 2003-2009, Xith3D Project Group all rights reserved. * * Portions based on the Java3D interface, Copyright by Sun Microsystems. * Many thanks to the developers of Java3D and Sun Microsystems for their * innovation and design. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the 'Xith3D Project Group' nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) A * RISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE */ package org.xith3d.scenegraph; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.openmali.FastMath; import org.openmali.spatial.bodies.Frustum; import org.openmali.types.twodee.Sized2iRO; import org.openmali.vecmath2.Matrix3f; import org.openmali.vecmath2.Matrix4f; import org.openmali.vecmath2.Point3f; import org.openmali.vecmath2.Tuple2f; import org.openmali.vecmath2.Tuple3f; import org.openmali.vecmath2.Vector3f; import org.xith3d.render.Canvas3D; import org.xith3d.render.RenderPassConfig; /** * The View defines a Camera or an Eye to tell OpenGL of the perspective to * render from. * * @author David Yazel * @author Marvin Froehlich (aka Qudus) * @author Amos Wenger (aka BlueSky) */ public class View extends SceneGraphObject implements Transformable { /** * Camera mode for a View. * * @author Marvin Froehlich (aka Qudus) */ public static enum CameraMode { /** * Geometry will be rendered like normal geometry with the camera in its * current location. This field is set in Background and Foreground * NodeS. */ VIEW_NORMAL, /** * Geometry will be rendered with the camera in the same location and * facing the same directrion This field is set in Background and * Foreground NodeS. */ VIEW_FIXED, /** * Geometry will be rendered with the camera in the same location but * with the camera facing its current direction. This field is set in * Background and Foreground NodeS. */ VIEW_FIXED_POSITION; } /** * Projection policy to render from. * * @author Marvin Froehlich (aka Qudus) */ public static enum ProjectionPolicy { /** * render the scene in parallel projection mode */ PARALLEL_PROJECTION, /** * render the scene in perspective projection mode */ PERSPECTIVE_PROJECTION, /** * Uses the custom projection matrix. */ CUSTOM_PROJECTION, ; } /** * Render the scene in parallel projection mode */ public static final ProjectionPolicy PARALLEL_PROJECTION = ProjectionPolicy.PARALLEL_PROJECTION; /** * Render the scene in perspective projection mode */ public static final ProjectionPolicy PERSPECTIVE_PROJECTION = ProjectionPolicy.PERSPECTIVE_PROJECTION; /** * The default field of view (FOV) */ public static final float DEFAULT_FIELD_OF_VIEW = FastMath.toRad( 35.0f ); /** * The default front clip distance (near clip plane) for perspective projection mode. */ public static final float DEFAULT_FRONT_CLIP_DISTANCE_PERSPECTIVE = 1.0f; /** * The default front clip distance (near clip plane) for parallel projection mode. */ public static final float DEFAULT_FRONT_CLIP_DISTANCE_PARALLEL = -1.0f; /** * The default back clip distance (far clip plane) for perspective projection mode. */ public static final float DEFAULT_BACK_CLIP_DISTANCE_PERSPECTIVE = 2000.0f; /** * The default back clip distance (far clip plane) for parallel projection mode. */ public static final float DEFAULT_BACK_CLIP_DISTANCE_PARALLEL = 100.0f; private final ArrayList< Canvas3D > canvasList; private final List< Canvas3D > unmodCanvasList; private ProjectionPolicy projectionPolicy = PERSPECTIVE_PROJECTION; private float fieldOfView = DEFAULT_FIELD_OF_VIEW; private float frontClipDistance; private float backClipDistance; private boolean isFrontClipSet = false; private boolean isBackClipSet = false; private float screenScale = 1.0f; private Tuple2f centerOfView = null; private RenderPassConfig[] rpcStack = new RenderPassConfig[ 16 ]; private int rpcStackSize = 0; private final Transform3D transform = new Transform3D(); private final Transform3D modelViewTransform = new Transform3D(); private final Transform3D modelViewTransform2 = new Transform3D(); private final Point3f position = new Point3f(); private final Transform3D projection = new Transform3D(); private Transform3D customProjection = null; private final Matrix4f projViewMatrix = new Matrix4f(); private final Matrix3f tempMatrix = new Matrix3f(); private final Matrix4f IDENTITY = new Matrix4f(); private final Frustum frustum = new Frustum(); private final Matrix3f rotMat = new Matrix3f(); private static final Vector3f TO_BACK = new Vector3f( 0.0f, 0.0f, -1.0f ); private static final Vector3f TO_RIGHT = new Vector3f( 1.0f, 0.0f, 0.0f ); private static final Vector3f TO_UP = new Vector3f( 0.0f, 1.0f, 0.0f ); private float soundActivationRadius = 40f; private PointLight attachedLight = null; /** * Attaches a {@link PointLight}/{@link SpotLight} to this View (or detaches if for <code>null</code>). * * @param light */ public final void setAttachedLight( PointLight light ) { this.attachedLight = light; } /** * @return the View-attached {@link PointLight}/{@link SpotLight}. */ public final PointLight getAttachedLight() { return ( attachedLight ); } /** * Sets the projection policy. */ public final void setProjectionPolicy( ProjectionPolicy policy ) { this.projectionPolicy = policy; } /** * @return the projection policy. */ public final ProjectionPolicy getProjectionPolicy() { if ( rpcStackSize > 0 ) { for ( int i = rpcStackSize - 1; i >= 0; i-- ) { if ( ( rpcStack[ i ] != null ) && ( rpcStack[ i ].getProjectionPolicy() != null ) ) return ( rpcStack[ i ].getProjectionPolicy() ); } } return ( projectionPolicy ); } /** * Sets the center of the View. * * @param cov values range from 1 (left) to -1 (right) a value of null * sets the center to (0|0) - the default */ public final void setCenterOfView( Tuple2f cov ) { this.centerOfView = cov; } /** * @return the center of this View - values range from 1 (left) to -1 (right) */ public final Tuple2f getCenterOfView() { if ( rpcStackSize > 0 ) { for ( int i = rpcStackSize - 1; i >= 0; i-- ) { if ( ( rpcStack[ i ] != null ) && ( rpcStack[ i ].getCenterOfView() != null ) ) return ( rpcStack[ i ].getCenterOfView() ); } } return ( centerOfView ); } /** * Sets the screen scale. */ public final void setScreenScale( float screenScale ) { this.screenScale = screenScale; } /** * @return the screen scale. */ public final float getScreenScale() { if ( rpcStackSize > 0 ) { for ( int i = rpcStackSize - 1; i >= 0; i-- ) { if ( ( rpcStack[ i ] != null ) && ( rpcStack[ i ].getScreenScale() > -9998.0f ) ) return ( rpcStack[ i ].getScreenScale() ); } } return ( screenScale ); } /** * Sets the front clip distance (near clip plane) for this View. */ public final void setFrontClipDistance( float value ) { this.frontClipDistance = value; this.isFrontClipSet = true; } /** * @return the front clip distance (near clip plane) for this View. */ public final float getFrontClipDistance() { if ( rpcStackSize > 0 ) { for ( int i = rpcStackSize - 1; i >= 0; i-- ) { if ( ( rpcStack[ i ] != null ) && ( rpcStack[ i ].getFrontClipDistance() > -9998.0f ) ) return ( rpcStack[ i ].getFrontClipDistance() ); } } if ( isFrontClipSet ) return ( frontClipDistance ); else if ( getProjectionPolicy() == ProjectionPolicy.PARALLEL_PROJECTION ) return ( DEFAULT_FRONT_CLIP_DISTANCE_PARALLEL ); else// if ( getProjectionPolicy() == ProjectionPolicy.PERSPECTIVE_PROJECTION ) return ( DEFAULT_FRONT_CLIP_DISTANCE_PERSPECTIVE ); //throw new Error( "Mission impossible!" ); } /** * Sets the back clip distance (far clip plane) for this View. */ public final void setBackClipDistance( float value ) { this.backClipDistance = value; this.isBackClipSet = true; } /** * @return the back clip distance (far clip plane) for this View. */ public final float getBackClipDistance() { if ( rpcStackSize > 0 ) { for ( int i = rpcStackSize - 1; i >= 0; i-- ) { if ( ( rpcStack[ i ] != null ) && ( rpcStack[ i ].getBackClipDistance() > -9998.0f ) ) return ( rpcStack[ i ].getBackClipDistance() ); } } if ( isBackClipSet ) return ( backClipDistance ); else if ( getProjectionPolicy() == ProjectionPolicy.PARALLEL_PROJECTION ) return ( DEFAULT_BACK_CLIP_DISTANCE_PARALLEL ); else// if ( getProjectionPolicy() == ProjectionPolicy.PERSPECTIVE_PROJECTION ) return ( DEFAULT_BACK_CLIP_DISTANCE_PERSPECTIVE ); //throw new Error( "Mission impossible!" ); } /** * Sets the field of view (viewing angle). */ public final void setFieldOfView( float value ) { this.fieldOfView = value; } /** * @return the field of view (viewing angle). */ public final float getFieldOfView() { if ( rpcStackSize > 0 ) { for ( int i = rpcStackSize - 1; i >= 0; i-- ) { if ( ( rpcStack[ i ] != null ) && ( rpcStack[ i ].getFieldOfView() > -9998.0f ) ) return ( rpcStack[ i ].getFieldOfView() ); } } return ( fieldOfView ); } /** * <b>Never use this method. It is just for internal use!</b> * * @param b * @param rpc */ final void set( boolean b, RenderPassConfig rpc ) { if ( b ) this.rpcStack[ rpcStackSize++ ] = rpc; else this.rpcStack[ --rpcStackSize ] = null; } /** * Set the sound activation radius.<br> * (Sound Nodes, which are farer from the point of view than this radius * aren't heard.) * * @param radius the new sound activation radius */ public final void setSoundActivationRadius( float radius ) { this.soundActivationRadius = radius; } /** * @return the sound activation radius.<br> * (Sound Nodes, which are farer from the point of view than this radius * aren't heard.) */ public final float getSoundActivationRadius() { return ( soundActivationRadius ); } /** * {@inheritDoc} */ public final void setTransform( Transform3D transform ) { this.transform.set( transform ); } /** * {@inheritDoc} */ public final Transform3D getTransform() { if ( rpcStackSize > 0 ) { for ( int i = rpcStackSize - 1; i >= 0; i-- ) { if ( ( rpcStack[ i ] != null ) && ( rpcStack[ i ].getViewTransform() != null ) ) return ( rpcStack[ i ].getViewTransform() ); } } return ( transform ); } /** * {@inheritDoc} */ public final void getTransform( Transform3D transform ) { getTransform().get( transform ); } /** * {@inheritDoc} */ public void setPosition( float posX, float posY, float posZ ) { getTransform().setTranslation( posX, posY, posZ ); } /** * {@inheritDoc} */ public final void setPosition( Tuple3f position ) { setPosition( position.getX(), position.getY(), position.getZ() ); } /** * {@inheritDoc} */ public final void getPosition( Tuple3f position ) { getTransform().getTranslation( position ); } /** * {@inheritDoc} */ public final Point3f getPosition() { getTransform().getTranslation( position ); return ( position ); } /** * Helper function that specifies the position and orientation of a view * matrix. * * @param eyePositionX the center of the eye * @param eyePositionY the center of the eye * @param eyePositionZ the center of the eye * @param viewFocusX the point the view looks at * @param viewFocusY the point the view looks at * @param viewFocusZ the point the view looks at * @param vecUpX the vector pointing up * @param vecUpY the vector pointing up * @param vecUpZ the vector pointing up */ public final void lookAt( float eyePositionX, float eyePositionY, float eyePositionZ, float viewFocusX, float viewFocusY, float viewFocusZ, float vecUpX, float vecUpY, float vecUpZ ) { transform.lookAt( eyePositionX, eyePositionY, eyePositionZ, viewFocusX, viewFocusY, viewFocusZ, vecUpX, vecUpY, vecUpZ ); } /** * Helper function that specifies the position and orientation of a view * matrix. * * @param eyePosition the center of the eye * @param viewFocus the point the view looks at * @param vecUp the vector pointing up */ public final void lookAt( Tuple3f eyePosition, Tuple3f viewFocus, Tuple3f vecUp ) { transform.lookAt( eyePosition, viewFocus, vecUp ); } /** * Helper function that specifies the position and orientation of a view * matrix. * * @param viewFocus the point the view looks at */ public final void lookAt( Tuple3f viewFocus ) { this.getPosition( position ); Vector3f up = Vector3f.fromPool(); this.getUpDirection( up ); this.lookAt( position, viewFocus, up ); Vector3f.toPool( up ); } /** * Helping function that specifies the position and orientation of a view * matrix. * * @param eyePositionX the center of the eye * @param eyePositionY the center of the eye * @param eyePositionZ the center of the eye * @param viewDirectionX the direction the view looks along * @param viewDirectionY the direction the view looks along * @param viewDirectionZ the direction the view looks along * @param vecUpX the vector pointing up * @param vecUpY the vector pointing up * @param vecUpZ the vector pointing up */ public final void lookAlong( float eyePositionX, float eyePositionY, float eyePositionZ, float viewDirectionX, float viewDirectionY, float viewDirectionZ, float vecUpX, float vecUpY, float vecUpZ ) { transform.lookAlong( eyePositionX, eyePositionY, eyePositionZ, viewDirectionX, viewDirectionY, viewDirectionZ, vecUpX, vecUpY, vecUpZ ); } /** * Helping function that specifies the position and orientation of a view * matrix. * * @param eyePosition the center of the eye * @param viewDirection the direction the view looks along * @param vecUp the vector pointing up */ public final void lookAlong( Tuple3f eyePosition, Tuple3f viewDirection, Tuple3f vecUp ) { transform.lookAlong( eyePosition, viewDirection, vecUp ); } /** * Helping function that specifies the position and orientation of a view * matrix.<br> * <br> * This method assumes Y-up. * * @param eyePositionX the center of the eye * @param eyePositionY the center of the eye * @param eyePositionZ the center of the eye * @param viewDirectionX the direction the view looks along * @param viewDirectionY the direction the view looks along * @param viewDirectionZ the direction the view looks along */ public final void lookAlong( float eyePositionX, float eyePositionY, float eyePositionZ, float viewDirectionX, float viewDirectionY, float viewDirectionZ ) { transform.lookAlong( eyePositionX, eyePositionY, eyePositionZ, viewDirectionX, viewDirectionY, viewDirectionZ ); } /** * Helping function that specifies the position and orientation of a view * matrix.<br> * <br> * This method assumes Y-up. * * @param eyePosition the center of the eye * @param viewDirection the direction the view looks along */ public final void lookAlong( Tuple3f eyePosition, Tuple3f viewDirection ) { transform.lookAlong( eyePosition, viewDirection ); } /** * Sets the direction in which the view looks. * * @param direction */ public final void setFacingDirection( Vector3f direction ) { this.getPosition( position ); Vector3f up = Vector3f.fromPool(); this.getUpDirection( up ); this.lookAlong( position, direction, up ); Vector3f.toPool( up ); } /** * Calculates the direction, the view faces and fills the values into the * given Tuple3f. * * @param direction the Tuple3f to be filled up with the result */ public final <T extends Tuple3f> T getFacingDirection( T direction ) { transform.getRotation( rotMat ); rotMat.mul( TO_BACK, direction ); return ( direction ); } /** * Calculates and returns the direction, the view faces. */ public final Vector3f getFacingDirection() { final Vector3f direction = new Vector3f(); getFacingDirection( direction ); return ( direction ); } /** * Calculates the direction to the right and fills the values into the given * Tuple3f. * * @param direction the Tuple3f to be filled up with the result */ public final <T extends Tuple3f> T getRightDirection( T direction ) { transform.getRotation( rotMat ); rotMat.mul( TO_RIGHT, direction ); return ( direction ); } /** * Calculates and returns the direction to the right. */ public final Vector3f getRightDirection() { final Vector3f direction = new Vector3f(); getRightDirection( direction ); return ( direction ); } /** * Calculates the direction heading up and fills the values into the given * Tuple3f. * * @param direction the Tuple3f to be filled up with the result */ public final <T extends Tuple3f> T getUpDirection( T direction ) { transform.getRotation( rotMat ); rotMat.mul( TO_UP, direction ); return ( direction ); } /** * Calculates and returns the direction heading up. */ public final Vector3f getUpDirection() { final Vector3f direction = new Vector3f(); getUpDirection( direction ); return ( direction ); } /** * Gets model-view transform adjusting it depending on the camera mode. * * @param mode VIEW_NORMAL will return the standard view, * VIEW_FIXED_POSITION will return only the rotational component * of the standard view (the position is left as the identity), * VIEW_FIXED returns the identity matrix. * @param forceRecomputation if true, the model-view-transform is guaranteed to be recalculated */ public final Transform3D getModelViewTransform( CameraMode mode, boolean forceRecomputation ) { if ( !forceRecomputation ) return ( modelViewTransform ); switch ( mode ) { case VIEW_NORMAL: modelViewTransform.set( getTransform() ); modelViewTransform.invert(); return ( modelViewTransform ); case VIEW_FIXED_POSITION: getTransform().getRotation( tempMatrix ); // Applies the rotational component to the model-view-transform. // Note: translation is not applied modelViewTransform.set( tempMatrix ); modelViewTransform.invert(); return ( modelViewTransform ); case VIEW_FIXED: modelViewTransform.setIdentity(); return ( modelViewTransform ); default: throw new AssertionError( "Unknown CameraMode encountered" ); } } /** * Gets model-view transform for the NORMAL camera mode. * * @param forceRecomputation if true, the model-view-transform is guaranteed to be recalculated */ public final Transform3D getModelViewTransform( boolean forceRecomputation ) { return ( getModelViewTransform( CameraMode.VIEW_NORMAL, forceRecomputation ) ); } public Transform3D calculatePerspective( float viewportWidth, float viewportHeight ) { if ( getProjectionPolicy() == ProjectionPolicy.CUSTOM_PROJECTION ) return ( customProjection ); final Tuple2f cov = getCenterOfView(); final float zFar = getBackClipDistance(); final float zNear = getFrontClipDistance(); if ( getProjectionPolicy() == PARALLEL_PROJECTION ) { final float screenScale = getScreenScale(); final float aspect = viewportWidth / viewportHeight; projection.ortho( -screenScale, screenScale, -screenScale / aspect, screenScale / aspect, zNear, zFar ); if ( cov != null ) { projection.getMatrix4f().add( 0, 3, cov.getX() / ( viewportWidth / 2.0f ) ); projection.getMatrix4f().add( 1, 3, cov.getY() / ( viewportHeight / 2.0f ) ); } } else { final float fovy = getFieldOfView(); final float aspect = viewportWidth / viewportHeight; if ( cov == null ) { //projection.perspective( fovy, aspect, zNear, zFar ); projection.perspectiveMesa( fovy, aspect, zNear, zFar ); } else { // same as perspectiveMesa float ymax = zNear * FastMath.tan( fovy ); float ymin = -ymax; float xmin = ymin * aspect; float xmax = ymax * aspect; // now transform with centerOfView ymax = ymax + ymax * cov.getY(); ymin = ymin - ymin * cov.getY(); xmax = xmax + xmax * cov.getX(); xmin = xmin - xmin * cov.getX(); //projection.frustum( xmin, xmax, ymin, ymax, zNear, zFar ); projection.frustumMesa( xmin, xmax, ymin, ymax, zNear, zFar ); } projection.transpose(); } return ( projection ); } public final Transform3D calculatePerspective( Sized2iRO viewport ) { return ( calculatePerspective( viewport.getWidth(), viewport.getHeight() ) ); } /** * Sets the custom projection transform. * This also executes setProjectionPolicy( ( customProjection == null ) ? ProjectionPolicy.PERSPECTIVE_PROJECTION : ProjectionPolicy.PERSPECTIVE_PROJECTION ). * * @param customProjection */ public void setProjection( Transform3D customProjection ) { this.customProjection = customProjection; setProjectionPolicy( ( this.customProjection == null ) ? ProjectionPolicy.PERSPECTIVE_PROJECTION : ProjectionPolicy.PERSPECTIVE_PROJECTION ); } /** * @return the projection Transform3D. calculatePerspective must be called * before the result of this method is valid, if projection policy is not custom. */ public final Transform3D getProjection() { if ( getProjectionPolicy() == ProjectionPolicy.CUSTOM_PROJECTION ) return ( customProjection ); return ( projection ); } /** * Calculates and returns the View's frustum. * * @param viewportWidth the canvas width the take for calculation * @param viewportHeight the canvas height the take for calculation * * @return the View's frustum */ public final Frustum getFrustum( float viewportWidth, float viewportHeight ) { modelViewTransform2.set( getTransform() ); modelViewTransform2.invert(); final Transform3D projection = calculatePerspective( viewportWidth, viewportHeight ); projViewMatrix.mulTransposeBoth( modelViewTransform2.getMatrix4f(), projection.getMatrix4f() ); frustum.compute( projViewMatrix, IDENTITY ); return ( frustum ); } /** * Calculates and returns the View's frustum. * * @param viewport the viewport size the take for calculation * * @return the View's frustum */ public final Frustum getFrustum( Sized2iRO viewport ) { return ( getFrustum( viewport.getWidth(), viewport.getHeight() ) ); } /** * Adds a Canvas3D to this view. * * @param canvas3D the canvas to be added */ public void addCanvas3D( Canvas3D canvas3D ) { canvas3D.setView( this ); canvasList.add( canvas3D ); } /** * Adds a Canvas3D at the specified index. * * @param canvas the Canvas3D to add * @param index the new index of the Canvas3D */ public final void addCanvas3D( Canvas3D canvas, int index ) { canvas.setView( this ); canvasList.add( canvas ); } public final Canvas3D removeCanvas3D( int index ) { final Canvas3D removedCanvas = canvasList.remove( index ); removedCanvas.setView( null ); return ( removedCanvas ); } public void removeCanvas3D( Canvas3D canvas ) { canvasList.remove( canvas ); } public final Canvas3D getCanvas3D( int index ) { return ( canvasList.get( index ) ); } public final int indexOfCanvas3D( Canvas3D canvas ) { return ( canvasList.indexOf( canvas ) ); } public final int numCanvas3Ds() { return ( canvasList.size() ); } /** * @return a read-only List of all Canvas3Ds registered to this View. */ public final List< Canvas3D > getCanvas3Ds() { return ( unmodCanvasList ); } /** * Creates a new View. * * @param eyePositionX the center of the eye * @param eyePositionY the center of the eye * @param eyePositionZ the center of the eye * @param viewFocusX the point the view looks at * @param viewFocusY the point the view looks at * @param viewFocusZ the point the view looks at * @param vecUpX the vector pointing up * @param vecUpY the vector pointing up * @param vecUpZ the vector pointing up */ public View( float eyePositionX, float eyePositionY, float eyePositionZ, float viewFocusX, float viewFocusY, float viewFocusZ, float vecUpX, float vecUpY, float vecUpZ ) { this.IDENTITY.setIdentity(); this.lookAt( eyePositionX, eyePositionY, eyePositionZ, viewFocusX, viewFocusY, viewFocusZ, vecUpX, vecUpY, vecUpZ ); this.canvasList = new ArrayList< Canvas3D >(); this.unmodCanvasList = Collections.unmodifiableList( canvasList ); } /** * Creates a new View. * * @param eyePosition the environment's view's location * @param viewFocus the environment's view's center (where to look at) * @param vecUp the environment's view's normal which is pointing up */ public View( Tuple3f eyePosition, Tuple3f viewFocus, Tuple3f vecUp ) { this( eyePosition.getX(), eyePosition.getY(), eyePosition.getZ(), viewFocus.getX(), viewFocus.getY(), viewFocus.getZ(), vecUp.getX(), vecUp.getY(), vecUp.getZ() ); } /** * Constructs a new View. */ public View() { this( 0.0f, 0.0f, 5.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f ); } }