aboutsummaryrefslogtreecommitdiffstats
path: root/src/javax/media/j3d/View.java
diff options
context:
space:
mode:
authorHarvey Harrison <[email protected]>2015-04-19 21:02:06 -0700
committerHarvey Harrison <[email protected]>2015-04-19 21:02:06 -0700
commit7a2e20caac9db6f789a7b3fab344b9758af45335 (patch)
treeb5236ff2570178de356eab569225108948eb4d30 /src/javax/media/j3d/View.java
parentf76ce302c4bb2a9f03bbee571ec5d05c29633023 (diff)
j3dcore: flatten the directory structure a bit
Signed-off-by: Harvey Harrison <[email protected]>
Diffstat (limited to 'src/javax/media/j3d/View.java')
-rw-r--r--src/javax/media/j3d/View.java3336
1 files changed, 3336 insertions, 0 deletions
diff --git a/src/javax/media/j3d/View.java b/src/javax/media/j3d/View.java
new file mode 100644
index 0000000..d162ecd
--- /dev/null
+++ b/src/javax/media/j3d/View.java
@@ -0,0 +1,3336 @@
+/*
+ * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ */
+
+package javax.media.j3d;
+
+import java.awt.AWTEvent;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Vector;
+
+import javax.vecmath.Point3d;
+import javax.vecmath.Point3f;
+
+/**
+ * The View object contains all parameters needed in rendering a
+ * three dimensional scene from one viewpoint. A view contains a list
+ * of Canvas3D objects that the view is rendered into. It exists outside
+ * of the scene graph, but attaches to a ViewPlatform leaf node object
+ * in the scene graph. It also contains a reference to a PhysicalBody
+ * and a PhysicalEnvironment object.
+ * <P>
+ * The View object is the main Java 3D object for controlling the
+ * Java 3D viewing model. All of the components that specify the
+ * view transform used to render to the 3D canvases are either contained
+ * in the View object or in objects that are referenced by the View
+ * object.
+ * <P>
+ * Java 3D allows applications to specify multiple simultaneously active
+ * View objects, each controlling its own set of canvases.
+ * <P>
+ * The Java 3D View object has several instance variables and methods,
+ * but most are calibration variables or user-helping functions. The
+ * viewing policies defined by the View object are described below.
+ * <P>
+ * <b>Policies</b><P>
+ *
+ * The View object defines the following policies:<P>
+ * <UL>
+ * <LI>View policy - informs Java 3D whether it should generate
+ * the view using the head-tracked system of transformations or the
+ * head-mounted system of transformations. These policies are attached
+ * to the Java 3D View object. There are two view policies:</LI><P>
+ * <UL>
+ * <LI>SCREEN_VIEW - specifies that Java 3D should compute a new
+ * viewpoint using the sequence of transforms appropriate to screen-based
+ * head-tracked display environments (fish-tank VR/portals/VR-desks).
+ * This is the default setting.</LI><P>
+ * <LI>HMD_VIEW - specifies that Java 3D should compute a new viewpoint
+ * using the sequence of transforms appropriate to head mounted display
+ * environments. This policy is not available in compatibility mode
+ * (see the setCompatibilityModeEnable method description).</LI><P>
+ * </UL>
+ * <LI>Projection policy - specifies whether Java 3D should generate
+ * a parallel projection or a perspective projection. This policy
+ * is attached to the Java 3D View object. There are two projection
+ * policies:</LI><P>
+ * <UL>
+ * <LI>PARALLEL_PROJECTION - specifies that a parallel projection
+ * transform is computed.</LI><P>
+ * <LI>PERSPECTIVE_PROJECTION - specifies that a perspective projection
+ * transform is computed. This is the default policy.</LI><P>
+ * </UL>
+ * <LI>Screen scale policy - specifies where the screen scale comes from.
+ * There are two screen scale policies:</LI><P>
+ * <UL>
+ * <LI>SCALE_SCREEN_SIZE - specifies that the scale is derived from the
+ * physical screen according to the following formula (this is the
+ * default mode):</LI>
+ * <UL>
+ * <code>screenScale = physicalScreenWidth / 2.0</code><P>
+ * </UL>
+ * <LI>SCALE_EXPLICIT - pecifies that the scale is taken directly from
+ * the user-provided <code>screenScale</code> attribute (see the
+ * setScreenScale method description).</LI><P>
+ * </UL>
+ * <LI>Window resize policy - specifies how Java 3D modifies the view
+ * when users resize windows. When users resize or move windows,
+ * Java 3D can choose to think of the window as attached either to
+ * the physical world or to the virtual world. The window resize
+ * policy allows an application to specify how the
+ * view model will handle resizing requests.
+ * There are two window resize policies:</LI><P>
+ * <UL>
+ * <LI>VIRTUAL_WORLD - implies that the original image remains the
+ * same size on the screen but the user sees more or less of the
+ * virtual world depending on whether the window grew or shrank
+ * in size.</LI><P>
+ * <LI>PHYSICAL_WORLD - implies that the original image continues
+ * to fill the window in the same way using more or less pixels
+ * depending on whether the window grew or shrank in size.</LI><P>
+ * </UL>
+ * <LI>Window movement policy - specifies what part of the virtual
+ * world Java 3D draws as a function of window placement on the screen.
+ * There are two window movement policies:</LI><P>
+ * <UL>
+ * <LI>VIRTUAL_WORLD - implies that the image seen in the window
+ * changes as the position of the window shifts on the screen.
+ * (This mode acts as if the window were a window into the virtual
+ * world.)</LI><P>
+ * <LI>PHYSICAL_WORLD - implies that the image seen in the window
+ * remains the same no matter where the user positions the window
+ * on the screen.</LI><P>
+ * </UL>
+ * <LI>Window eyepoint policy - comes into effect in a non-head-tracked
+ * environment. The policy tells Java 3D how to construct a new view
+ * frustum based on changes in the field of view and in the Canvas3D's
+ * location on the screen. The policy only comes into effect when the
+ * application changes a parameter that can change the placement of the
+ * eyepoint relative to the view frustum.
+ * There are three window eyepoint policies:</LI><P>
+ * <UL>
+ * <LI>RELATIVE_TO_SCREEN - tells Java 3D to interpret the eye's position
+ * relative to the entire screen. No matter where an end user moves a
+ * window (a Canvas3D), Java 3D continues to interpret the eye's position
+ * relative to the screen. This implies that the view frustum changes shape
+ * whenever an end user moves the location of a window on the screen.
+ * In this mode, the field of view is read-only.</LI><P>
+ * <LI>RELATIVE_TO_WINDOW - specifies that Java 3D should interpret the
+ * eye's position information relative to the window (Canvas3D). No matter
+ * where an end user moves a window (a Canvas3D), Java 3D continues to
+ * interpret the eye's position relative to that window. This implies
+ * that the frustum remains the same no matter where the end user
+ * moves the window on the screen. In this mode, the field of view
+ * is read-only.</LI><P>
+ * <LI>RELATIVE_TO_FIELD_OF_VIEW - tells Java 3D that it should
+ * modify the eyepoint position so it is located at the appropriate
+ * place relative to the window to match the specified field of view.
+ * This implies that the view frustum will change whenever the
+ * application changes the field of view. In this mode, the eye
+ * position is read-only. This is the default setting.</LI><P>
+ * <LI>RELATIVE_TO_COEXISTENCE - tells Java 3D to interpret the eye's
+ * position in coexistence coordinates. In this mode, the eye position
+ * is taken from the view (rather than the Canvas3D) and transformed from
+ * coexistence coordinates to image plate coordinates for each
+ * Canvas3D. The resulting eye position is relative to the screen. As
+ * in RELATIVE_TO_SCREEN mode, this implies that the view frustum
+ * changes shape whenever an end user moves the location of a window
+ * on the screen. In this mode, the field of view is
+ * read-only.</LI><P>
+ * </UL>
+ * <LI>Front and back clip policies - specifies how Java 3D
+ * interprets clipping distances to both the near and far clip
+ * planes. The policies can contain one of four values specifying
+ * whether a distance measurement should be interpreted in
+ * the physical or the virtual world and whether that distance
+ * measurement should be interpreted relative to the physical
+ * eyepoint or the physical screen.
+ * The front and back clip policies
+ * are specified separately. The front clip policy determines
+ * where Java 3D places the front clipping plane. The back clip
+ * policy determines where Java 3D places the back clipping plane.
+ * The values for both front and back clipping planes are:</LI><P>
+ * <UL>
+ * <LI>VIRTUAL_EYE - specifies that the associated distance is from
+ * the eye and in units of virtual distance.</LI><P>
+ * <LI>PHYSICAL_EYE - specifies that the associated distance is from
+ * the eye and in units of physical distance (in meters).
+ * This is the default policy for both front and back clipping.</LI><P>
+ * <LI>VIRTUAL_SCREEN - specifies that the associated distance is
+ * from the screen and in units of virtual distance. </LI><P>
+ * <LI>PHYSICAL_SCREEN - specifies that the associated distance is
+ * from the screen and in units of physical distance (in meters).
+ * </LI><P>
+ * </UL>
+ * <LI>Visibility policy - specifies how visible and invisible objects
+ * are drawn. There are three visibility policies:</LI><P>
+ * <UL>
+ * <LI>VISIBILITY_DRAW_VISIBLE - only visible objects are drawn
+ * (this is the default).</LI><P>
+ * <LI>VISIBILITY_DRAW_INVISIBLE - only invisible objects are drawn.</LI><P>
+ * <LI>VISIBILITY_DRAW_ALL - both visible and invisible
+ * objects are drawn. </LI><P>
+ * </UL>
+ * <LI>Transparency sorting policy - specifies whether and how
+ * transparent objects are sorted. Sorting multiple transparent
+ * objects is necessary to avoid artifacts caused by overlapping
+ * transparent objects. There are two transparency sorting
+ * policies:</LI><P>
+ * <UL>
+ * <LI>TRANSPARENCY_SORT_NONE - no depth sorting of transparent
+ * objects is performed (this is the default). Transparent objects
+ * are drawn after opaque objects, but are not sorted from back to
+ * front.</LI><P>
+ * <LI>TRANSPARENCY_SORT_GEOMETRY - transparent objects are
+ * depth-sorted on a per-geometry basis. Each geometry object of each
+ * transparent Shape3D node is drawn from back to front. Note that
+ * this policy will not split geometry into smaller pieces, so
+ * intersecting or intertwined objects may not be sorted
+ * correctly. The method used for determining which geometry is closer
+ * is implementation dependent.</LI><P>
+ * </UL>
+ * </UL>
+ * <b>Projection and Clip Parameters</b><P>
+ * The projection and clip parameters determine the view model's
+ * field of view and the front and back clipping distances.<P>
+ * <UL>
+ * <LI>Field of view - specifies the view model's horizontal
+ * field of view in radians, when in the default non-head-tracked
+ * mode. This value is ignored when the view model is operating
+ * in head-tracked mode, or when the Canvas3D's window eyepoint
+ * policy is set to a value other than the default setting of
+ * RELATIVE_TO_FIELD_OF_VIEW.</LI><P>
+ * <LI>Front clip distance - specifies the distance away from the
+ * clip origin, specified by the front clip policy variable, in
+ * the direction of gaze where objects stop disappearing. Objects
+ * closer than the clip origin (eye or screen)
+ * plus the front clip distance are not drawn. Measurements are
+ * done in the space (physical or virtual) that is specified by
+ * the associated front clip policy parameter.</LI><P>
+ * <LI>Back clip distance - specifies the distance away from the
+ * clip origin (specified by the back clip policy variable) in the
+ * direction of gaze where objects begin disappearing. Objects
+ * farther away from the clip origin (eye or
+ * screen) plus the back clip distance are not drawn.
+ * Measurements are done in the space (physical or virtual) that
+ * is specified by the associated back clip policy
+ * parameter. The View object's back clip distance is ignored
+ * if the scene graph contains an active Clip leaf node.</LI><P>
+ * There are several considerations to take into account when
+ * choosing values for the front and back clip distances.<P>
+ * <UL>
+ * <LI>The front clip distance must be greater than 0.0 in physical
+ * eye coordinates.</LI><P>
+ * <LI>The front clipping plane must be in front of the back clipping
+ * plane, that is, the front clip distance must be less than the
+ * back clip distance in physical eye coordinates.</LI><P>
+ * <LI>The front and back clip distances, in physical eye coordinates,
+ * must be less than the largest positive single-precision floating
+ * point value, Float.MAX_VALUE. In practice, since these physical
+ * eye coordinate distances are in meters, the values
+ * should be much less than that.</LI><P>
+ * <LI>The ratio of the back distance divided by the front distance,
+ * in physical eye coordinates, affects Z-buffer precision. This ratio
+ * should be less than about 3000 to accommodate 16-bit Z-buffers.
+ * Values of 100 to less than 1000 will produce better results.</LI><P>
+ * </UL>
+ * Violating any of the above rules will result in undefined behavior.
+ * In many cases, no picture will be drawn.<P>
+ * </UL>
+ * <b>Frame Start Time, Duration, and Number</b><P>
+ *
+ * There are five methods used to get information about system
+ * execution and performance:<P>
+ * <UL>
+ * <code>getCurrentFrameStartTime</code> returns the time at which
+ * the most recent rendering frame started.<P>
+ * <code>getLastFrameDuration</code> returns the duration, in milliseconds, of
+ * the most recently completed rendering frame.<P>
+ * <code>getFrameNumber</code> returns the frame number for this view.<P>
+ * <code>getMaxFrameStartTimes</code> retrieves the implementation-dependent
+ * maximum number of frames whose start times will be recorded by
+ * the system.<P>
+ * <code>getFrameStartTimes</code> copies the last k frame start time values
+ * into the user-specified array.<P>
+ * </UL>
+ * <b>View Traversal and Behavior Scheduling</b><P>
+ * The following methods control the traversal, the rendering, and
+ * the execution of the behavior scheduler for this view:<P>
+ * <UL>
+ * <code>startBehaviorScheduler</code> starts the behavior scheduler
+ * running after it has been stopped.<P>
+ * <code>stopBehaviorScheduler</code> stops the behavior scheduler after all
+ * currently-scheduled behaviors are executed.<P>
+ * <code>isBehaviorSchedulerRunning</code> retrieves a flag that indicates
+ * whether the behavior scheduler is currently running.<P>
+ * <code>startView</code> starts traversing this view and starts the renderers
+ * associated with all canvases attached to this view.<P>
+ * <code>stopView</code> stops traversing this view after the current state of
+ * the scene graph is reflected on all canvases attached to this
+ * view.<P>
+ * <code>isViewRunning</code> returns a flag indicating whether the traverser
+ * is currently running on this view.<P>
+ * </UL>
+ * Note: The above six methods are heavy-weight methods intended
+ * for verification and image capture (recording). They are not
+ * intended to be used for flow control.<P>
+ *
+ * <b>Scene Antialiasing</b><P>
+ *
+ * The following methods set and retrieve the scene antialiasing
+ * flag. Scene antialiasing is either enabled or disabled for this
+ * view. If enabled, the entire scene will be antialiased on each
+ * canvas in which scene antialiasing is available. Scene
+ * antialiasing is disabled by default.<P>
+ * <UL>
+ * <code>setSceneAntialiasingEnable</code> sets the scene antialiasing flag.<P>
+ * <code>getSceneAntialiasingEnable</code> returns the scene antialiasing
+ * flag.<P>
+ * </UL>
+ * Note that line and point antialiasing are independent of scene
+ * antialiasing. If antialiasing is enabled for lines and points,
+ * the lines and points will be antialiased prior to scene antialiasing.
+ * If scene antialiasing is disabled, antialiased lines and points will
+ * still be antialiased.
+ * <p>
+ * <b>Note:</b> Scene antialiasing is ignored in pure immediate mode,
+ * but is supported in mixed-immediate mode.
+ * <p>
+ * <b>Depth Buffer</b><P>
+ *
+ * The following two methods enable and disable automatic freezing
+ * of the depth buffer for objects rendered during the transparent
+ * rendering pass (that is, objects rendered using alpha blending)
+ * for this view. If enabled, depth buffer writes are disabled
+ * during the transparent rendering pass regardless of the value
+ * of the depth-buffer-write-enable flag in the RenderingAttributes
+ * object for a particular node. This flag is enabled by default.<P>
+ * <UL>
+ * <code>setDepthBufferFreezeTransparent</code> enables depth buffer freezing.<P>
+ * <code>getDepthBufferFreezeTransparent</code> retrieves the depth buffer
+ * flag.<P>
+ * </UL>
+ * Transparent objects include BLENDED transparent primitives
+ * and antialiased lines
+ * and points. Transparent objects do not include opaque objects
+ * or primitives rendered with SCREEN_DOOR transparency.<p>
+ *
+ * <b>Sensors</b><P>
+ *
+ * The following methods retrieve the sensor's location in the
+ * virtual world:<P>
+ * <UL>
+ * <code>getSensorToVworld</code> takes the sensor's last reading and
+ * generates a sensor-to-vworld coordinate system transform. This
+ * Transform3D object takes points in that sensor's local coordinate
+ * system and transforms them into virtual world coordinates.<P>
+ *
+ * <code>getSensorHotSpotInVworld</code> retrieves the specified sensor's
+ * last hotspot location in virtual world coordinates.<P>
+ * </UL>
+ *
+ * <b>Compatibility Mode</b><P>
+ *
+ * A camera-based view model allows application programmers to think
+ * about the images displayed on the computer screen as if a virtual
+ * camera took those images. Such a view model allows application
+ * programmers to position and orient a virtual camera within a
+ * virtual scene, to manipulate some parameters of the virtual
+ * camera's lens (specify its field of view), and to specify the
+ * locations of the near and far clipping planes.<P>
+ * Java 3D allows applications to enable compatibility mode for
+ * room-mounted, non-head-tracked display environments, or to disable
+ * compatibility mode using the following methods. Camera-based
+ * viewing functions are only available in compatibility mode.<P>
+ * <UL>
+ * <code>setCompatibilityModeEnable</code> turns compatibility mode on or off.
+ * Compatibility mode is disabled by default.<P>
+ * <code>getCompatabilityModeEnable</code> returns the compatibility mode
+ * enable flag.<P>
+ * </UL>
+ * Use of these view-compatibility functions will disable some of
+ * Java 3D's view model features and limit the portability of Java
+ * 3D programs. These methods are primarily intended to help
+ * jump-start porting of existing applications.<P>
+ *
+ * Setting the Viewing Transform<P>
+ *
+ * The View object provides the following compatibility-mode
+ * methods that operate on the viewing transform.<P>
+ * <UL>
+ * <code>setVpcToEc</code> a compatibility mode method that
+ * specifies the ViewPlatform
+ * coordinates (VPC) to eye coordinates viewing transform.<P>
+ * <code>getVpcToEc</code> returns the VPC.<P>
+ * </UL>
+ * Setting the Projection Transform
+ * <p>
+ * The View object provides the following compatibility-mode
+ * methods that operate on the projection transform:<P>
+ * <UL>
+ * The <code>setLeftProjection</code> and <code>setRightProjection</code>
+ * methods specify
+ * a viewing frustum for the left and right eye that transforms
+ * points in eye coordinates to clipping coordinates.<P>
+ *
+ * The <code>getLeftProjection</code> and <code>getRightProjection</code>
+ * methods return
+ * the viewing frustum for the left and right eye.<P>
+ * </UL>
+ *
+ * <p>
+ * <b>Additional Information</b>
+ * <p>
+ * For more information, see the
+ * <a href="doc-files/intro.html">Introduction to the Java 3D API</a> and
+ * <a href="doc-files/ViewModel.html">View Model</a>
+ * documents.
+ *
+ * @see Canvas3D
+ * @see PhysicalBody
+ * @see PhysicalEnvironment
+ * @see ViewPlatform
+ * @see TransparencyAttributes
+ */
+
+public class View extends Object {
+ /**
+ * Specifies a policy whereby the origin of physical or virtual
+ * coordinates is relative to the position of the nominal head.
+ * When used as a view attach policy, this sets the origin of view
+ * platform coordinates to be at the eyepoint.
+ * @see ViewPlatform#setViewAttachPolicy
+ * @see PhysicalEnvironment#setCoexistenceCenterInPworldPolicy
+ */
+ public static final int NOMINAL_HEAD = 0;
+
+ /**
+ * Specifies a policy whereby the origin of physical or virtual
+ * coordinates is relative to the position of the nominal feet.
+ * When used as a view attach policy, this sets the origin of view
+ * platform coordinates to be at the ground plane.
+ * @see ViewPlatform#setViewAttachPolicy
+ * @see PhysicalEnvironment#setCoexistenceCenterInPworldPolicy
+ */
+ public static final int NOMINAL_FEET = 1;
+
+ /**
+ * Specifies a policy whereby the origin of physical or virtual
+ * coordinates is relative to the screen.
+ * When used as a view attach policy, this sets the origin of view
+ * platform coordinates to be at the center of the window or screen,
+ * in effect, allowing the user to view objects from an optimal viewpoint.
+ * @see ViewPlatform#setViewAttachPolicy
+ * @see PhysicalEnvironment#setCoexistenceCenterInPworldPolicy
+ */
+ public static final int NOMINAL_SCREEN = 2;
+
+ /**
+ * Specifies that the screen scale for this view is derived from
+ * the physical screen size. This scale factor is computed as follows:
+ * <ul>
+ * physical_screen_width / 2.0
+ * </ul>
+ * This allows an application to define a world in a normalized
+ * [-1,1] space and view it on a screen of any size.
+ * @see #setScreenScalePolicy
+ */
+ public static final int SCALE_SCREEN_SIZE = 0;
+
+ /**
+ * Specifies that the screen scale for this view is taken directly
+ * from the user-provided screenScale parameter.
+ * @see #setScreenScalePolicy
+ * @see #setScreenScale
+ */
+ public static final int SCALE_EXPLICIT = 1;
+
+ /**
+ * Specifies that the associated distance is measured
+ * from the screen in virtual world coordinates.
+ * Policy for interpreting clip plane distances.
+ * Used in specifying the policy in frontClipPolicy and backClipPolicy.
+ * @see #setFrontClipPolicy
+ * @see #setBackClipPolicy
+ */
+ public static final int VIRTUAL_SCREEN = 0;
+
+ /**
+ * Specifies that the associated distance is measured
+ * from the screen in meters.
+ * Policy for interpreting clip plane distances.
+ * Used in specifying the policy in frontClipPolicy and backClipPolicy.
+ * @see #setFrontClipPolicy
+ * @see #setBackClipPolicy
+ */
+ public static final int PHYSICAL_SCREEN = 1;
+
+ /**
+ * Specifies that the associated distance is measured
+ * from the eye in virtual world coordinates.
+ * Policy for interpreting clip plane distances.
+ * Used in specifying the policy in frontClipPolicy and backClipPolicy.
+ * @see #setFrontClipPolicy
+ * @see #setBackClipPolicy
+ */
+ public static final int VIRTUAL_EYE = 2;
+
+ /**
+ * Specifies that the associated distance is measured
+ * from the eye in meters.
+ * Policy for interpreting clip plane distances.
+ * Used in specifying the policy in frontClipPolicy and backClipPolicy.
+ * This is the default policy for both front and back clipping.
+ * @see #setFrontClipPolicy
+ * @see #setBackClipPolicy
+ */
+ public static final int PHYSICAL_EYE = 3;
+
+ /**
+ * Policy for resizing and moving windows.
+ * Used in specifying windowResizePolicy and windowMovementPolicy.
+ * VIRTUAL_WORLD specifies that the associated action takes place
+ * in the virtual world as well as in the physical world.
+ * @see #setWindowResizePolicy
+ * @see #setWindowMovementPolicy
+ */
+ public static final int VIRTUAL_WORLD = 0;
+
+ /**
+ * Policy for resizing and moving windows.
+ * Used in specifying windowResizePolicy and windowMovementPolicy.
+ * PHYSICAL_WORLD specifies that the specified action takes place
+ * only in the physical world.
+ * @see #setWindowResizePolicy
+ * @see #setWindowMovementPolicy
+ */
+ public static final int PHYSICAL_WORLD = 1;
+
+ /**
+ * Policy for placing the eyepoint in non-head-tracked modes.
+ * Specifies that Java 3D should interpret the
+ * given fixed eyepoint position as relative to the entire screen.
+ * This implies
+ * that the view frustum shape will change whenever a
+ * user moves the location of a window on the screen.
+ * @see #setWindowEyepointPolicy
+ */
+ public static final int RELATIVE_TO_SCREEN = 0;
+
+ /**
+ * Policy for placing the eyepoint in non-head-tracked modes.
+ * Specifies that Java 3D should interpret the
+ * given fixed-eyepoint position as relative to the window.
+ * @see #setWindowEyepointPolicy
+ */
+ public static final int RELATIVE_TO_WINDOW = 1;
+
+ /**
+ * Policy for placing the eyepoint in non-head-tracked modes.
+ * Specifies that Java 3D should
+ * modify the position of the eyepoint to match any changes in field
+ * of view; the view frustum will change whenever the application
+ * program changes the field of view.
+ * <p>
+ * NOTE: when this policy is specified, the Z coordinate of
+ * the derived eyepoint is used in place of
+ * nominalEyeOffsetFromNominalScreen.
+ * @see #setWindowEyepointPolicy
+ */
+ public static final int RELATIVE_TO_FIELD_OF_VIEW = 2;
+
+ /**
+ * Policy for placing the eyepoint in non-head-tracked modes.
+ * Specifies that Java 3D should interpret the fixed eyepoint
+ * position in the view as relative to the origin
+ * of coexistence coordinates. This eyepoint is transformed from
+ * coexistence coordinates to image plate coordinates for each
+ * Canvas3D.
+ * As in RELATIVE_TO_SCREEN mode, this implies
+ * that the view frustum shape will change whenever a
+ * user moves the location of a window on the screen.
+ * @see #setWindowEyepointPolicy
+ *
+ * @since Java 3D 1.2
+ */
+ public static final int RELATIVE_TO_COEXISTENCE = 3;
+
+ /**
+ * Specifies that monoscopic view generated should be the view as seen
+ * from the left eye.
+ * @see Canvas3D#setMonoscopicViewPolicy
+ */
+ public static final int LEFT_EYE_VIEW = 0;
+
+ /**
+ * Specifies that monoscopic view generated should be the view as seen
+ * from the right eye.
+ * @see Canvas3D#setMonoscopicViewPolicy
+ */
+ public static final int RIGHT_EYE_VIEW = 1;
+
+ /**
+ * Specifies that monoscopic view generated should be the view as seen
+ * from the 'center eye', the fictional eye half-way between the left and
+ * right eye.
+ * @see Canvas3D#setMonoscopicViewPolicy
+ */
+ public static final int CYCLOPEAN_EYE_VIEW = 2;
+
+ /**
+ * Specifies that the viewing environment for this view is a
+ * standard screen-based display environment.
+ * In this mode, Java 3D will compute new viewpoints
+ * using that sequence of transforms appropriate to screen-based,
+ * display environments, that may or may not include head tracking
+ * (e.g., a monoscopic screen, fish-tank VR, portals, VR-desks).
+ * This is the default mode.
+ * @see #setViewPolicy
+ */
+ public static final int SCREEN_VIEW = 0;
+
+ /**
+ * Specifies that the viewing environment for this view is a
+ * head-mounted display environment.
+ * In this mode, Java 3D will compute new viewpoints
+ * using that sequence of transforms appropriate to head-mounted display
+ * environments. These environments are generally head-tracked.
+ * @see #setViewPolicy
+ */
+ public static final int HMD_VIEW = 1;
+
+ /**
+ * Specifies that Java 3D should generate a parallel projection matrix
+ * for this View.
+ * @see #setProjectionPolicy
+ */
+ public static final int PARALLEL_PROJECTION = 0;
+
+ /**
+ * Specifies that Java 3D should generate a perspective projection matrix
+ * for this View.
+ * This is the default mode.
+ * @see #setProjectionPolicy
+ */
+ public static final int PERSPECTIVE_PROJECTION = 1;
+
+ /**
+ * Policy that specifies that only visible objects should be drawn.
+ * This is the default mode.
+ * @see #setVisibilityPolicy
+ *
+ * @since Java 3D 1.2
+ */
+ public static final int VISIBILITY_DRAW_VISIBLE = 0;
+
+ /**
+ * Policy that specifies that only invisible objects should be drawn.
+ * @see #setVisibilityPolicy
+ *
+ * @since Java 3D 1.2
+ */
+ public static final int VISIBILITY_DRAW_INVISIBLE = 1;
+
+ /**
+ * Policy that specifies that both visible and invisible objects
+ * should be drawn.
+ * @see #setVisibilityPolicy
+ *
+ * @since Java 3D 1.2
+ */
+ public static final int VISIBILITY_DRAW_ALL = 2;
+
+ /**
+ * Policy that specifies that no sorting of transparent objects
+ * is done.
+ * This is the default mode.
+ * @see #setTransparencySortingPolicy
+ *
+ * @since Java 3D 1.3
+ */
+ public static final int TRANSPARENCY_SORT_NONE = 0;
+
+ /**
+ * Policy that specifies that transparent objects
+ * are sorted from back to front on a per-geometry basis.
+ * @see #setTransparencySortingPolicy
+ *
+ * @since Java 3D 1.3
+ */
+ public static final int TRANSPARENCY_SORT_GEOMETRY = 1;
+
+
+ //
+ // The AWT window for display.
+ //
+ // This object can be queried to obtain:
+ // screen width in pixels
+ // screen height in pixels
+ // window width in pixels
+ // window height in pixels
+ // window upper left corner location in pixels relative to screen
+ //
+ // Use getCanvases() to access this
+private Vector<Canvas3D> canvases = new Vector<Canvas3D>(3);
+
+ //
+ // The current universe associated with this view
+ //
+ VirtualUniverse universe = null;
+
+ //
+ // The RenderBin associated with this view.
+ //
+ RenderBin renderBin = null;
+
+ // This is the SoundScheduler associated with this view.
+ SoundScheduler soundScheduler = null;
+
+ // AudioDevice enumerator current position
+ // AudioDeviceEnumerator allAudioEnumerator = null;
+
+ // These are used for tracking the frame times
+ static final int NUMBER_FRAME_START_TIMES = 10;
+
+ long[] frameStartTimes = new long[NUMBER_FRAME_START_TIMES];
+ long[] frameNumbers = new long[NUMBER_FRAME_START_TIMES];
+ int currentFrameIndex = 0;
+
+ // These are the values that are set at the end of each frame
+ long currentFrameStartTime = 0;
+ long currentFrameDuration = 0;
+ long currentFrameNumber = 0;
+
+ // These are the ones that get updated directly by MC
+ long frameNumber = 0;
+ long startTime = 0;
+ long stopTime = 0;
+
+ // User adjustable minimum frame cycle time
+ long minFrameCycleTime;
+
+ // True when stopBehaviorScheduler invoke
+ boolean stopBehavior;
+
+ //
+ // View cache for this view.
+ //
+ ViewCache viewCache = null;
+
+ // Compatibility mode related field has changed.
+ // { compatibilityModeEnable, compatVpcToEc, compatLeftProjection,
+ // compatRightProjection }
+ static final int COMPATIBILITY_MODE_DIRTY = 0x01;
+ // ScreenScalePolicy field has changed.
+ static final int SCREEN_SCALE_POLICY_DIRTY = 0x02;
+ // Screen scale field has changed.
+ static final int SCREEN_SCALE_DIRTY = 0x04;
+ // Window Resize Policy field has changed.
+ static final int WINDOW_RESIZE_POLICY_DIRTY = 0x08;
+ // View Policy eye in image plate field has changed.
+ static final int VIEW_POLICY_DIRTY = 0x10;
+ // Clip related field has changed.
+ // { frontClipDistance, backClipDistance, frontClipPolicy, backClipPolicy }
+ static final int CLIP_DIRTY = 0x20;
+ // Projection Policy field has changed.
+ static final int PROJECTION_POLICY_DIRTY = 0x40;
+ // Window Movement Policy field has changed.
+ static final int WINDOW_MOVEMENT_POLICY_DIRTY = 0x80;
+ // Window Eye Point Policy field has changed.
+ static final int WINDOW_EYE_POINT_POLICY_DIRTY = 0x100;
+ // Monoscopic View Policy field has changed.
+ static final int MONOSCOPIC_VIEW_POLICY_DIRTY = 0x200;
+ // Field Of View field has changed.
+ static final int FIELD_OF_VIEW_DIRTY = 0x400;
+ // Tracking Enable field has changed.
+ static final int TRACKING_ENABLE_DIRTY = 0x800;
+ // User Head To Vworld Enable field has changed.
+ static final int USER_HEAD_TO_VWORLD_ENABLE_DIRTY = 0x1000;
+ // coexistenceCenteringEnable flag has changed.
+ static final int COEXISTENCE_CENTERING_ENABLE_DIRTY = 0x2000;
+ // leftManualEyeInCoexistence has changed.
+ static final int LEFT_MANUAL_EYE_IN_COEXISTENCE_DIRTY = 0x4000;
+ // rightManualEyeInCoexistence has changed.
+ static final int RIGHT_MANUAL_EYE_IN_COEXISTENCE_DIRTY = 0x8000;
+ // visibilityPolicy has changed.
+ static final int VISIBILITY_POLICY_DIRTY = 0x10000;
+
+ // This is not from View object. It is here for the purpose
+ // keeping all ViewCache's dirty mask bit declaration in one place.
+ // ViewPlatformRetained viewAttach Policy field has changed.
+ static final int VPR_VIEW_ATTACH_POLICY_DIRTY = 0x10000;
+ static final int VPR_VIEWPLATFORM_DIRTY = 0x20000;
+
+ // PhysicalEnvironment fields has changed.
+ static final int PE_COE_TO_TRACKER_BASE_DIRTY = 0x100000;
+ static final int PE_TRACKING_AVAILABLE_DIRTY = 0x200000;
+ static final int PE_COE_CENTER_IN_PWORLD_POLICY_DIRTY = 0x400000;
+
+ // PhysicalBody fields has changed.
+ static final int PB_EYE_POSITION_DIRTY = 0x1000000;
+ static final int PB_EAR_POSITION_DIRTY = 0x2000000;
+ static final int PB_NOMINAL_EYE_HEIGHT_FROM_GROUND_DIRTY = 0x4000000;
+ static final int PB_NOMINAL_EYE_OFFSET_FROM_NOMINAL_SCREEN_DIRTY = 0x8000000;
+
+
+ // Mask that indicates this View's view dependence info. has changed,
+ // and CanvasViewCache may need to recompute the final view matries.
+ int vDirtyMask = (COMPATIBILITY_MODE_DIRTY | SCREEN_SCALE_POLICY_DIRTY
+ | SCREEN_SCALE_DIRTY | WINDOW_RESIZE_POLICY_DIRTY
+ | VIEW_POLICY_DIRTY | CLIP_DIRTY
+ | PROJECTION_POLICY_DIRTY | WINDOW_MOVEMENT_POLICY_DIRTY
+ | WINDOW_EYE_POINT_POLICY_DIRTY | MONOSCOPIC_VIEW_POLICY_DIRTY
+ | FIELD_OF_VIEW_DIRTY | TRACKING_ENABLE_DIRTY
+ | USER_HEAD_TO_VWORLD_ENABLE_DIRTY
+ | COEXISTENCE_CENTERING_ENABLE_DIRTY
+ | LEFT_MANUAL_EYE_IN_COEXISTENCE_DIRTY
+ | RIGHT_MANUAL_EYE_IN_COEXISTENCE_DIRTY
+ | VISIBILITY_POLICY_DIRTY);
+
+
+ //
+ // This object contains a specification of the user's physical body.
+ //
+ // Attributes of this object are defined in head coordinates and
+ // include information such as the location of the user's eyes and
+ // ears.
+ // The origin is defined to be halfway between the left and right eye
+ // in the plane of the face.
+ // The x-axis extends to the right (of the head looking out from the head).
+ // The y-axis extends up. The z-axis extends to the rear of the head.
+ //
+ PhysicalBody physicalBody;
+
+ // This object contains a specification of the physical environment.
+ PhysicalEnvironment physicalEnvironment;
+
+ // View model compatibility mode flag
+ boolean compatibilityModeEnable = false;
+
+ // View model coexistenceCenteringEnable flag
+ boolean coexistenceCenteringEnable = true;
+
+ Point3d leftManualEyeInCoexistence = new Point3d();
+ Point3d rightManualEyeInCoexistence = new Point3d();
+
+ //
+ // Indicates which major mode of view computation to use:
+ // HMD mode or screen/fish-tank-VR mode.
+ //
+ int viewPolicy = SCREEN_VIEW;
+
+ // The current projection policy (parallel versus perspective)
+ int projectionPolicy = PERSPECTIVE_PROJECTION;
+
+ //
+ // The view model's field of view.
+ //
+ double fieldOfView = 45.0 * Math.PI / 180.0;
+
+ //
+ // The distance away from the clip origin
+ // in the direction of gaze for the front and back clip planes.
+ // The default values are in meters.
+ //
+ double frontClipDistance = 0.1;
+ double backClipDistance = 10.0;
+
+ // This variable specifies where the screen scale comes from
+ int screenScalePolicy = SCALE_SCREEN_SIZE;
+
+ // The screen scale value used when the screen scale policy is
+ // SCALE_EXPLICIT
+ double screenScale = 1.0;
+
+ //
+ // This variable specifies how Java 3D modifies the view when
+ // the window is resized (VIRTUAL_WORLD or PHYSICAL_WORLD).
+ //
+ int windowResizePolicy = PHYSICAL_WORLD;
+
+ //
+ // This variable specifies how Java 3D modifies the view when
+ // the window is moved (VIRTUAL_WORLD or PHYSICAL_WORLD).
+ //
+ int windowMovementPolicy = PHYSICAL_WORLD;
+
+ //
+ // Specifies how Java 3D handles the predefined eyepoint in
+ // non-head-tracked environment (RELATIVE_TO_SCREEN,
+ // RELATIVE_TO_WINDOW, RELATIVE_TO_FIELD_OF_VIEW, or
+ // RELATIVE_TO_COEXISTENCE)
+ //
+ int windowEyepointPolicy = RELATIVE_TO_FIELD_OF_VIEW;
+
+ //
+ // Specifies how Java 3D generates monoscopic view
+ // (LEFT_EYE_VIEW, RIGHT_EYE_VIEW, or CYCLOPEAN_EYE_VIEW).
+ //
+ int monoscopicViewPolicy = CYCLOPEAN_EYE_VIEW;
+
+ /**
+ * Defines the policy for placing the front clipping plane.
+ * Legal values include PHYSICAL_EYE, PHYSICAL_SCREEN,
+ * VIRTUAL_EYE, and VIRTUAL_SCREEN.
+ */
+ int frontClipPolicy = PHYSICAL_EYE;
+
+ /**
+ * Defines the policy for placing the back clipping plane.
+ */
+ int backClipPolicy = PHYSICAL_EYE;
+
+ /**
+ * Defines the visibility policy.
+ */
+ int visibilityPolicy = VISIBILITY_DRAW_VISIBLE;
+
+ /**
+ * Defines the transparency sorting policy.
+ */
+ int transparencySortingPolicy = TRANSPARENCY_SORT_NONE;
+
+ /**
+ * Flag to enable tracking, if so allowed by the trackingAvailable flag.
+ */
+ boolean trackingEnable = false;
+
+ /**
+ * This setting enables the continuous updating by Java 3D of the
+ * userHeadToVworld transform.
+ */
+ boolean userHeadToVworldEnable = false;
+
+ /**
+ * The view platform currently associated with this view.
+ */
+ private ViewPlatform viewPlatform = null;
+
+ // The current compatibility mode view transform
+ Transform3D compatVpcToEc = new Transform3D();
+
+ // The current compatibility mode projection transforms
+ Transform3D compatLeftProjection = new Transform3D();
+ Transform3D compatRightProjection = new Transform3D();
+
+ // The long id of this view - used for dirty bit evaluation in the scene graph
+ Integer viewId = null;
+ int viewIndex = -1;
+
+ // A boolean that indicates whether or not this is the primary view
+ boolean primaryView = false;
+
+ // A boolean that indicates whether or not this view is active as
+ // seen by MasterControl
+ boolean active = false;
+
+ // A boolean that indicates whether or not this view is active as
+ // seen by this view. There is a delay before MasterControl set
+ // active flag, so a local activeStatus is used. Otherwise
+ // activate event may lost if it proceed by deactivate event
+ // but MC not yet set active to false. This happens in
+ // viewplatform detach and attach.
+ boolean activeStatus = false;
+
+ // This boolean indicates whether or not the view is running. It
+ // is used for startView/stopView
+ volatile boolean isRunning = true;
+
+ // A flag to indicate that we are in a canvas callback routine
+ boolean inCanvasCallback = false;
+
+ //
+ // Flag to enable depth buffer freeze during trasparent rendering pass
+ //
+ boolean depthBufferFreezeTransparent = true;
+
+ //
+ // Flag to enable scene antialiasing
+ //
+ boolean sceneAntialiasingEnable = false;
+
+ //
+ // Flag to enable local eye lighting
+ //
+ boolean localEyeLightingEnable = false;
+
+// Array Lists to track the screens and canvases associated with this View.
+// use getScreens() to access this
+private ArrayList<Screen3D> screenList = new ArrayList<Screen3D>();
+
+// use getCanvasList() to access this
+private ArrayList<ArrayList<Canvas3D>> canvasList = new ArrayList<ArrayList<Canvas3D>>();
+
+ private Canvas3D[][] cachedCanvasList;
+ private Canvas3D[] cachedCanvases;
+ private Screen3D[] cachedScreens;
+ private int longestScreenList = 0;
+ private boolean canvasesDirty = true;
+
+ // Flag to notify user thread when renderOnce is finished
+ volatile boolean renderOnceFinish = true;
+
+ // Lock to synchronize start/stop/renderOnce call
+ private Object startStopViewLock = new Object();
+
+ // Lock for evaluateActive() only. This is used to prevent
+ // using lock this which will cause deadlock when MC call
+ // snapshot which waitForMC() in user thread.
+ private Object evaluateLock = new Object();
+
+ /**
+ * use for stop view, when stopview, set to count -1,
+ * when reach 1, call stopView() in MC and reset to -1.
+ */
+ int stopViewCount = -1;
+
+ /**
+ * False if current frame cycle time less than minimum frame cycle time
+ */
+ boolean isMinCycleTimeAchieve = true;
+
+ // Time to sleep if minimum frame cycle time not achieve
+ long sleepTime = 0;
+
+ // use in pure immediate mode to tell whether this view rendering
+ // thread is added in MC renderThreadData
+ volatile boolean inRenderThreadData = false;
+
+ // use to notify MC that render bin has run once, and is ready for
+ // renderer to render
+ boolean renderBinReady = false;
+
+ // No of time setUniverse() is invoke
+ long universeCount = 0;
+
+ // The universe count when UNREGISTER_VIEW request is post,
+ // this is used to distingish whether new setUniverse() is
+ // invoked after UNREGISTER_VIEW request post to avoid
+ // resetting the newly set universe.
+ long resetUnivCount = 0;
+
+ // This notify user thread waitForMC() to continue when
+ // MC finish unregisterView
+ volatile boolean doneUnregister = false;
+
+ static final int TRANSP_SORT_POLICY_CHANGED = 0x0001;
+ static final int OTHER_ATTRS_CHANGED = 0x0002;
+
+ /**
+ * Constructs a View object with default parameters. The default
+ * values are as follows:
+ * <ul>
+ * view policy : SCREEN_VIEW<br>
+ * projection policy : PERSPECTIVE_PROJECTION<br>
+ * screen scale policy : SCALE_SCREEN_SIZE<br>
+ * window resize policy : PHYSICAL_WORLD<br>
+ * window movement policy : PHYSICAL_WORLD<br>
+ * window eyepoint policy : RELATIVE_TO_FIELD_OF_VIEW<br>
+ * monoscopic view policy : CYCLOPEAN_EYE_VIEW<br>
+ * front clip policy : PHYSICAL_EYE<br>
+ * back clip policy : PHYSICAL_EYE<br>
+ * visibility policy : VISIBILITY_DRAW_VISIBLE<br>
+ * transparency sorting policy : TRANSPARENCY_SORT_NONE<br>
+ * coexistenceCentering flag : true<br>
+ * compatibility mode : false<br>
+ * left projection : identity<br>
+ * right projection : identity<br>
+ * vpc to ec transform : identity<br>
+ * physical body : null<br>
+ * physical environment : null<br>
+ * screen scale : 1.0<br>
+ * field of view : PI/4<br>
+ * left manual eye in coexistence : (-0.033, 0.0, 0.4572)<br>
+ * right manual eye in coexistence : (0.033, 0.0, 0.4572)<br>
+ * front clip distance : 0.1<br>
+ * back clip distance : 10.0<br>
+ * tracking enable : false<br>
+ * user head to vworld enable : false<br>
+ * list of Canvas3D objects : empty<br>
+ * depth buffer freeze transparent : true<br>
+ * scene antialiasing : false<br>
+ * local eye lighting : false<br>
+ * view platform : null<br>
+ * behavior scheduler running : true<br>
+ * view running : true<br>
+ * minimum frame cycle time : 0<br>
+ * </ul>
+ */
+ public View() {
+ viewCache = new ViewCache(this);
+ }
+
+ /**
+ * Sets the policy for view computation.
+ * This variable specifies how Java 3D uses its transforms in
+ * computing new viewpoints.
+ * <UL>
+ * <LI>SCREEN_VIEW specifies that Java 3D should compute a new viewpoint
+ * using the sequence of transforms appropriate to screen-based
+ * head-tracked display environments (fish-tank VR/portals/VR-desks).
+ * </LI>
+ * <LI>HMD_VIEW specifies that Java 3D should compute a new viewpoint
+ * using the sequence of transforms appropriate to head mounted
+ * display environments.
+ * </LI>
+ * </UL>
+ * The default view policy is SCREEN_VIEW.
+ * @param policy the new policy, one of SCREEN_VIEW or HMD_VIEW
+ * @exception IllegalArgumentException if policy is a value other than
+ * SCREEN_VIEW or HMD_VIEW
+ * @exception IllegalStateException if the specified policy
+ * is HMD_VIEW and if any canvas associated with this view is
+ * a stereo canvas with a monoscopicEyePolicy of CYCLOPEAN_EYE_VIEW
+ */
+ public void setViewPolicy(int policy) {
+ if (policy != HMD_VIEW &&
+ policy != SCREEN_VIEW) {
+
+ throw new IllegalArgumentException(J3dI18N.getString("View0"));
+ }
+ if(policy == HMD_VIEW) {
+ // Check the following :
+ // 1) If the view is in HMD mode and there exists a canvas in
+ // CYCLOPEAN_EYE_VIEW mode then throw exception.
+ synchronized (canvasList) {
+ for (int i=canvases.size()-1; i>=0; i--) {
+ Canvas3D c3d = canvases.elementAt(i);
+
+ if ((c3d.monoscopicViewPolicy == View.CYCLOPEAN_EYE_VIEW) &&
+ (!c3d.useStereo)){
+ throw new
+ IllegalStateException(J3dI18N.getString("View31"));
+ }
+ }
+ }
+ }
+ synchronized(this) {
+ this.viewPolicy = policy;
+ vDirtyMask |= View.VIEW_POLICY_DIRTY;
+ }
+ repaint();
+ }
+
+ /**
+ * Retrieves the current view computation policy for this View.
+ * @return one of: SCREEN_VIEW or HMD_VIEW.
+ */
+ public int getViewPolicy() {
+ return this.viewPolicy;
+ }
+
+ /**
+ * Sets the projection policy for this View.
+ * This variable specifies the type of projection transform that
+ * will be generated. A value of PARALLEL_PROJECTION specifies that
+ * a parallel projection transform is generated. A value of
+ * PERSPECTIVE_PROJECTION specifies that
+ * a perspective projection transform is generated.
+ * The default projection policy is PERSPECTIVE.
+ * @param policy the new policy, one of PARALLEL_PROJECTION or
+ * PERSPECTIVE_PROJECTION
+ * @exception IllegalArgumentException if policy is a value other than
+ * PARALLEL_PROJECTION or PERSPECTIVE_PROJECTION
+ */
+ public void setProjectionPolicy(int policy) {
+ if (policy != PERSPECTIVE_PROJECTION &&
+ policy != PARALLEL_PROJECTION) {
+
+ throw new IllegalArgumentException(J3dI18N.getString("View1"));
+ }
+ synchronized(this) {
+ this.projectionPolicy = policy;
+ vDirtyMask |= View.PROJECTION_POLICY_DIRTY;
+ }
+
+ repaint();
+ }
+
+ /**
+ * Retrieves the current projection policy for this View.
+ * @return one of: PARALLEL_PROJECTION or PERSPECTIVE_PROJECTION.
+ */
+ public int getProjectionPolicy() {
+ return this.projectionPolicy;
+ }
+
+ /**
+ * Sets the screen scale policy for this view.
+ * This policy specifies how the screen scale is derived.
+ * The value is either SCALE_SCREEN_SIZE or SCALE_EXPLICIT.
+ * A value of SCALE_SCREEN_SIZE specifies that the scale is derived
+ * from the size of the physical screen. A value of SCALE_EXPLICIT
+ * specifies that the scale is taken directly from the screenScale
+ * parameter.
+ * The default screen scale policy is SCALE_SCREEN_SIZE.
+ * @param policy the new policy, one of SCALE_SCREEN_SIZE or
+ * SCALE_EXPLICIT.
+ */
+ public void setScreenScalePolicy(int policy) {
+
+ synchronized(this) {
+ this.screenScalePolicy = policy;
+ vDirtyMask |= View.SCREEN_SCALE_POLICY_DIRTY;
+ }
+
+ repaint();
+ }
+
+ /**
+ * Returns the current screen scale policy, one of:
+ * SCALE_SCREEN_SIZE or SCALE_EXPLICIT.
+ * @return the current screen scale policy
+ */
+ public int getScreenScalePolicy() {
+ return this.screenScalePolicy;
+ }
+
+ /**
+ * Sets the window resize policy.
+ * This variable specifies how Java 3D modifies the view when
+ * users resize windows. The variable can contain one of
+ * VIRTUAL_WORLD or PHYSICAL_WORLD.
+ * A value of VIRTUAL_WORLD implies that the original image
+ * remains the same size on the screen but the user sees more
+ * or less of the virtual world depending on whether the window
+ * grew or shrank in size.
+ * A value of PHYSICAL_WORLD implies that the original image
+ * continues to fill the window in the same way using more or
+ * less pixels depending on whether the window grew or shrank
+ * in size.
+ * The default window resize policy is PHYSICAL_WORLD.
+ * @param policy the new policy, one of VIRTUAL_WORLD or PHYSICAL_WORLD
+ */
+ public void setWindowResizePolicy(int policy) {
+
+ synchronized(this) {
+ this.windowResizePolicy = policy;
+ vDirtyMask |= View.WINDOW_RESIZE_POLICY_DIRTY;
+ }
+ repaint();
+ }
+
+ /**
+ * Returns the current window resize policy, one of:
+ * VIRTUAL_WORLD or PHYSICAL_WORLD.
+ * @return the current window resize policy
+ */
+ public int getWindowResizePolicy() {
+ return this.windowResizePolicy;
+ }
+
+ /**
+ * Sets the window movement policy.
+ * This variable specifies what part of the virtual world Java 3D
+ * draws as a function of window placement on the screen. The
+ * variable can contain one of VIRTUAL_WORLD or PHYSICAL_WORLD.
+ * A value of VIRTUAL_WORLD implies that the image seen in the
+ * window changes as the position of the window shifts on the
+ * screen. (This mode acts as if the window were a window into
+ * the virtual world.)
+ * A value of PHYSICAL_WORLD implies that the image seen in the
+ * window remains the same no matter where the user positions
+ * the window on the screen.
+ * The default window movement policy is PHYSICAL_WORLD.
+ * @param policy the new policy, one of VIRTUAL_WORLD or PHYSICAL_WORLD
+ */
+ public void setWindowMovementPolicy(int policy) {
+
+ synchronized(this) {
+ this.windowMovementPolicy = policy;
+ vDirtyMask |= View.WINDOW_MOVEMENT_POLICY_DIRTY;
+ }
+ repaint();
+ }
+
+ /**
+ * Returns the current window movement policy,
+ * one of: VIRTUAL_WORLD or PHYSICAL_WORLD.
+ * @return the current window movement policy
+ */
+ public int getWindowMovementPolicy() {
+ return this.windowMovementPolicy;
+ }
+
+ /**
+ * Sets the view model's window eyepoint policy.
+ * This variable specifies how Java 3D handles the predefined eye
+ * point in a non-head-tracked environment. The variable can contain
+ * one of:
+ * <UL>
+ * <LI>RELATIVE_TO_SCREEN, Java 3D should interpret the
+ * given fixed-eyepoint position as relative to the screen (this
+ * implies that the view frustum shape will change whenever a
+ * user moves the location of a window on the screen).
+ * </LI>
+ * <LI>RELATIVE_TO_WINDOW, Java 3D should interpret the
+ * given fixed-eyepoint position as relative to the window. In this
+ * mode, the X and Y values are taken as the center of the window and
+ * the Z value is taken from the canvas eyepoint position.
+ * </LI>
+ * <LI>RELATIVE_TO_FIELD_OF_VIEW, Java 3D should
+ * modify the position of the eyepoint to match any changes in field
+ * of view (the view frustum will change whenever the application
+ * program changes the field of view).
+ * </LI>
+ * <LI>RELATIVE_TO_COEXISTENCE, Java 3D should interpret the eye's
+ * position in coexistence coordinates. In this mode, the eye position
+ * is taken from the view (rather than the Canvas3D) and transformed from
+ * coexistence coordinates to image plate coordinates for each
+ * Canvas3D. The resulting eye position is relative to the screen (this
+ * implies that the view frustum shape will change whenever a
+ * user moves the location of a window on the screen).
+ * </LI>
+ * </UL>
+ * The default window eyepoint policy is RELATIVE_TO_FIELD_OF_VIEW.
+ * @param policy the new policy, one of RELATIVE_TO_SCREEN,
+ * RELATIVE_TO_WINDOW, RELATIVE_TO_FIELD_OF_VIEW, or
+ * RELATIVE_TO_COEXISTENCE
+ */
+ public void setWindowEyepointPolicy(int policy) {
+ synchronized(this) {
+ this.windowEyepointPolicy = policy;
+ vDirtyMask |= View.WINDOW_EYE_POINT_POLICY_DIRTY;
+ }
+
+ repaint();
+ }
+
+ /**
+ * Returns the current window eyepoint policy, one of:
+ * RELATIVE_TO_SCREEN, RELATIVE_TO_WINDOW, RELATIVE_TO_FIELD_OF_VIEW or
+ * RELATIVE_TO_COEXISTENCE.
+ * @return the current window eyepoint policy
+ */
+ public int getWindowEyepointPolicy() {
+ return this.windowEyepointPolicy;
+ }
+
+ /**
+ * @deprecated As of Java 3D version 1.2, replaced by
+ * <code>Canvas3D.setMonoscopicViewPolicy</code>
+ */
+ public void setMonoscopicViewPolicy(int policy) {
+ synchronized(this) {
+ this.monoscopicViewPolicy = policy;
+ vDirtyMask |= View.MONOSCOPIC_VIEW_POLICY_DIRTY;
+ }
+ repaint();
+ }
+
+ /**
+ * @deprecated As of Java 3D version 1.2, replaced by
+ * <code>Canvas3D.getMonoscopicViewPolicy</code>
+ */
+ public int getMonoscopicViewPolicy() {
+ return this.monoscopicViewPolicy;
+ }
+
+ /**
+ * Sets the coexistenceCentering enable flag to true or false.
+ * If the coexistenceCentering flag is true, the center of
+ * coexistence in image plate coordinates, as specified by the
+ * trackerBaseToImagePlate transform, is translated to the center
+ * of either the window or the screen in image plate coordinates,
+ * according to the value of windowMovementPolicy.
+ *
+ * <p>
+ * By default, coexistenceCentering is enabled. It should be
+ * disabled if the trackerBaseToImagePlate calibration transform
+ * is set to a value other than the identity (for example, when
+ * rendering to multiple screens or when head tracking is
+ * enabled). This flag is ignored for HMD mode, or when the
+ * coexistenceCenterInPworldPolicy is <i>not</i>
+ * NOMINAL_SCREEN.
+ *
+ * @param flag the new coexistenceCentering enable flag
+ *
+ * @since Java 3D 1.2
+ */
+ public void setCoexistenceCenteringEnable(boolean flag) {
+ synchronized(this) {
+ this.coexistenceCenteringEnable = flag;
+ vDirtyMask |= View.COEXISTENCE_CENTERING_ENABLE_DIRTY;
+ }
+ repaint();
+ }
+
+ /**
+ * Retrieves the coexistenceCentering enable flag.
+ *
+ * @return the current coexistenceCentering enable flag
+ *
+ * @since Java 3D 1.2
+ */
+ public boolean getCoexistenceCenteringEnable() {
+ return this.coexistenceCenteringEnable;
+ }
+
+ /**
+ * Sets the compatibility mode enable flag to true or false.
+ * Compatibility mode is disabled by default.
+ * @param flag the new compatibility mode enable flag
+ */
+ public void setCompatibilityModeEnable(boolean flag) {
+ synchronized(this) {
+ this.compatibilityModeEnable = flag;
+ vDirtyMask |= View.COMPATIBILITY_MODE_DIRTY;
+ }
+ repaint();
+ }
+
+ /**
+ * Retrieves the compatibility mode enable flag.
+ * @return the current compatibility mode enable flag
+ */
+ public boolean getCompatibilityModeEnable() {
+ return this.compatibilityModeEnable;
+ }
+
+ /**
+ * Compatibility mode method that specifies a viewing frustum for
+ * the left eye that transforms points in Eye Coordinates (EC) to
+ * Clipping Coordinates (CC).
+ * If compatibility mode is disabled, then this transform is not used;
+ * the actual projection is derived from other values.
+ * In monoscopic mode, only the left eye projection matrix is used.
+ * @param projection the new left eye projection transform
+ * @exception RestrictedAccessException if compatibility mode is disabled.
+ */
+ public void setLeftProjection(Transform3D projection) {
+ if (!compatibilityModeEnable) {
+ throw new RestrictedAccessException(J3dI18N.getString("View2"));
+ }
+
+ synchronized(this) {
+ compatLeftProjection.setWithLock(projection);
+ vDirtyMask |= View.COMPATIBILITY_MODE_DIRTY;
+ }
+ repaint();
+ }
+
+ /**
+ * Compatibility mode method that specifies a viewing frustum for
+ * the right eye that transforms points in Eye Coordinates (EC) to
+ * Clipping Coordinates (CC).
+ * If compatibility mode is disabled, then this transform is not used;
+ * the actual projection is derived from other values.
+ * In monoscopic mode, the right eye projection matrix is ignored.
+ * @param projection the new right eye projection transform
+ * @exception RestrictedAccessException if compatibility mode is disabled.
+ */
+ public void setRightProjection(Transform3D projection) {
+ if (!compatibilityModeEnable) {
+ throw new RestrictedAccessException(J3dI18N.getString("View2"));
+ }
+
+ synchronized(this) {
+ compatRightProjection.setWithLock(projection);
+ vDirtyMask |= View.COMPATIBILITY_MODE_DIRTY;
+ }
+
+ repaint();
+ }
+
+ /**
+ * Compatibility mode method that retrieves the current
+ * compatibility mode projection transform for the left eye and
+ * places it into the specified object.
+ * @param projection the Transform3D object that will receive the
+ * projection
+ * @exception RestrictedAccessException if compatibility mode is disabled.
+ */
+ public void getLeftProjection(Transform3D projection) {
+ if (!compatibilityModeEnable) {
+ throw new RestrictedAccessException(J3dI18N.getString("View4"));
+ }
+
+ projection.set(compatLeftProjection);
+ }
+
+ /**
+ * Compatibility mode method that retrieves the current
+ * compatibility mode projection transform for the right eye and
+ * places it into the specified object.
+ * @param projection the Transform3D object that will receive the
+ * projection
+ * @exception RestrictedAccessException if compatibility mode is disabled.
+ */
+ public void getRightProjection(Transform3D projection) {
+ if (!compatibilityModeEnable) {
+ throw new RestrictedAccessException(J3dI18N.getString("View4"));
+ }
+
+ projection.set(compatRightProjection);
+ }
+
+ /**
+ * Compatibility mode method that specifies the ViewPlatform
+ * Coordinates (VPC) to Eye Coordinates (EC) transform.
+ * If compatibility mode is disabled, then this transform
+ * is derived from other values and is read-only.
+ * @param vpcToEc the new VPC to EC transform
+ * @exception RestrictedAccessException if compatibility mode is disabled.
+ * @exception BadTransformException if the transform is not affine.
+ */
+ public void setVpcToEc(Transform3D vpcToEc) {
+ if (!compatibilityModeEnable) {
+ throw new RestrictedAccessException(J3dI18N.getString("View6"));
+ }
+
+ if (!vpcToEc.isAffine()) {
+ throw new BadTransformException(J3dI18N.getString("View7"));
+ }
+
+ synchronized(this) {
+ compatVpcToEc.setWithLock(vpcToEc);
+ vDirtyMask |= View.COMPATIBILITY_MODE_DIRTY;
+ }
+
+ repaint();
+ }
+
+ /**
+ * Compatibility mode method that retrieves the current
+ * ViewPlatform Coordinates (VPC) system to
+ * Eye Coordinates (EC) transform and copies it into the specified
+ * object.
+ * @param vpcToEc the object that will receive the vpcToEc transform.
+ * @exception RestrictedAccessException if compatibility mode is disabled.
+ */
+ public void getVpcToEc(Transform3D vpcToEc) {
+ if (!compatibilityModeEnable) {
+ throw new RestrictedAccessException(J3dI18N.getString("View8"));
+ }
+
+ vpcToEc.set(compatVpcToEc);
+ }
+
+ /**
+ * Sets the view model's physical body to the PhysicalBody object provided.
+ * Java 3D uses the parameters in the PhysicalBody to ensure accurate
+ * image and sound generation when in head-tracked mode.
+ * @param physicalBody the new PhysicalBody object
+ */
+ public void setPhysicalBody(PhysicalBody physicalBody) {
+ // need to synchronize variable activateStatus
+ synchronized (canvasList) {
+ if (activeStatus) {
+ if (this.physicalBody != null) {
+ this.physicalBody.removeUser(this);
+ }
+ physicalBody.addUser(this);
+ }
+ }
+ this.physicalBody = physicalBody;
+ repaint();
+ }
+
+ /**
+ * Returns a reference to the view model's PhysicalBody object.
+ * @return the view object's PhysicalBody object
+ */
+ public PhysicalBody getPhysicalBody() {
+ return this.physicalBody;
+ }
+
+ /**
+ * Sets the view model's physical environment to the PhysicalEnvironment
+ * object provided.
+ * @param physicalEnvironment the new PhysicalEnvironment object
+ */
+ public void setPhysicalEnvironment(PhysicalEnvironment physicalEnvironment) {
+ synchronized (canvasList) {
+ if (activeStatus) {
+ if (this.physicalEnvironment != null) {
+ this.physicalEnvironment.removeUser(this);
+ }
+ physicalEnvironment.addUser(this);
+ }
+ }
+ this.physicalEnvironment = physicalEnvironment;
+
+
+ if ((viewPlatform != null) && viewPlatform.isLive()) {
+ VirtualUniverse.mc.postRequest(MasterControl.PHYSICAL_ENV_CHANGE, this);
+ }
+ repaint();
+ }
+
+ /**
+ * Returns a reference to the view model's PhysicalEnvironment object.
+ * @return the view object's PhysicalEnvironment object
+ */
+ public PhysicalEnvironment getPhysicalEnvironment() {
+ return this.physicalEnvironment;
+ }
+
+ /**
+ * Sets the screen scale value for this view.
+ * This is used when the screen scale policy is SCALE_EXPLICIT.
+ * The default value is 1.0 (i.e., unscaled).
+ * @param scale the new screen scale
+ */
+ public void setScreenScale(double scale) {
+ synchronized(this) {
+ this.screenScale = scale;
+ vDirtyMask |= View.SCREEN_SCALE_DIRTY;
+ }
+ repaint();
+ }
+
+ /**
+ * Returns the current screen scale value
+ * @return the current screen scale value
+ */
+ public double getScreenScale() {
+ return this.screenScale;
+ }
+
+ /**
+ * Sets the field of view used to compute the projection transform.
+ * This is used when head tracking is disabled and when the Canvas3D's
+ * windowEyepointPolicy is RELATIVE_TO_FIELD_OF_VIEW.
+ * @param fieldOfView the new field of view in radians
+ */
+ public void setFieldOfView(double fieldOfView) {
+ synchronized(this) {
+ this.fieldOfView = fieldOfView;
+ vDirtyMask |= View.FIELD_OF_VIEW_DIRTY;
+ }
+ repaint();
+
+ }
+
+ /**
+ * Returns the current field of view.
+ * @return the current field of view in radians
+ */
+ public double getFieldOfView() {
+ return this.fieldOfView;
+ }
+
+
+ /**
+ * Sets the position of the manual left eye in coexistence
+ * coordinates. This value determines eye placement when a head
+ * tracker is not in use and the application is directly controlling
+ * the eye position in coexistence coordinates. This value is
+ * ignored when in head-tracked mode or when the
+ * windowEyePointPolicy is <i>not</i> RELATIVE_TO_COEXISTENCE.
+ *
+ * @param position the new manual left eye position
+ *
+ * @since Java 3D 1.2
+ */
+ public void setLeftManualEyeInCoexistence(Point3d position) {
+ synchronized(this) {
+ leftManualEyeInCoexistence.set(position);
+ vDirtyMask |= View.LEFT_MANUAL_EYE_IN_COEXISTENCE_DIRTY;
+ }
+ repaint();
+ }
+
+ /**
+ * Sets the position of the manual right eye in coexistence
+ * coordinates. This value determines eye placement when a head
+ * tracker is not in use and the application is directly controlling
+ * the eye position in coexistence coordinates. This value is
+ * ignored when in head-tracked mode or when the
+ * windowEyePointPolicy is <i>not</i> RELATIVE_TO_COEXISTENCE.
+ *
+ * @param position the new manual right eye position
+ *
+ * @since Java 3D 1.2
+ */
+ public void setRightManualEyeInCoexistence(Point3d position) {
+ synchronized(this) {
+ rightManualEyeInCoexistence.set(position);
+ vDirtyMask |= View.RIGHT_MANUAL_EYE_IN_COEXISTENCE_DIRTY;
+ }
+ repaint();
+ }
+
+ /**
+ * Retrieves the position of the user-specified, manual left eye
+ * in coexistence
+ * coordinates and copies that value into the object provided.
+ * @param position the object that will receive the position
+ *
+ * @since Java 3D 1.2
+ */
+ public void getLeftManualEyeInCoexistence(Point3d position) {
+ position.set(leftManualEyeInCoexistence);
+ }
+
+ /**
+ * Retrieves the position of the user-specified, manual right eye
+ * in coexistence
+ * coordinates and copies that value into the object provided.
+ * @param position the object that will receive the position
+ *
+ * @since Java 3D 1.2
+ */
+ public void getRightManualEyeInCoexistence(Point3d position) {
+ position.set(rightManualEyeInCoexistence);
+ }
+
+
+ /**
+ * Sets the view model's front clip distance.
+ * This value specifies the distance away from the eyepoint
+ * in the direction of gaze where objects stop disappearing.
+ * Objects closer to the eye than the front clip
+ * distance are not drawn. The default value is 0.1 meters.
+ * <p>
+ * There are several considerations that need to be taken into
+ * account when choosing values for the front and back clip
+ * distances.
+ * <ul>
+ * <li>The front clip distance must be greater than
+ * 0.0 in physical eye coordinates.</li>
+ * <li>The front clipping plane must be in front of the
+ * back clipping plane, that is, the front clip distance
+ * must be less than the back clip distance in physical eye
+ * coordinates.</li>
+ * <li>The front and back clip distances, in physical
+ * eye coordinates, must be less than the largest positive
+ * single-precision floating point value, <code>Float.MAX_VALUE</code>.
+ * In practice, since these physical eye coordinate distances are in
+ * meters, the values should be <i>much</i> less than that.
+ * <li>The ratio of the back distance divided by the front distance,
+ * in physical eye coordinates, affects Z-buffer precision. This
+ * ratio should be less than about 3000 in order to accommodate 16-bit
+ * Z-buffers. Values of 100 to less than 1000 will produce better
+ * results.</li>
+ * </ul>
+ * Violating any of the above rules will result in undefined
+ * behavior. In many cases, no picture will be drawn.
+ *
+ * @param distance the new front clip distance
+ * @see #setBackClipDistance
+ */
+ public void setFrontClipDistance(double distance) {
+ synchronized(this) {
+ this.frontClipDistance = distance;
+ vDirtyMask |= View.CLIP_DIRTY;
+ }
+ repaint();
+ }
+
+ /**
+ * Returns the view model's front clip distance.
+ * @return the current front clip distance
+ */
+ public double getFrontClipDistance() {
+ return this.frontClipDistance;
+ }
+
+ /**
+ * Sets the view model's back clip distance.
+ * The parameter specifies the distance from the eyepoint
+ * in the direction of gaze to where objects begin disappearing.
+ * Objects farther away from the eye than the
+ * back clip distance are not drawn.
+ * The default value is 10.0 meters.
+ * <p>
+ * There are several considerations that need to be taken into
+ * account when choosing values for the front and back clip
+ * distances. These are enumerated in the description of
+ * <a href=#setFrontClipDistance(double)>setFrontClipDistance</a>.
+ * <p>
+ * Note that this attribute is only used if there is no Clip node
+ * that is in scope of the view platform associated with this view.
+ * @param distance the new back clip distance
+ * @see #setFrontClipDistance
+ * @see Clip#setBackDistance
+ */
+ public void setBackClipDistance(double distance) {
+ synchronized(this) {
+ this.backClipDistance = distance;
+ vDirtyMask |= View.CLIP_DIRTY;
+ }
+ repaint();
+ }
+
+ /**
+ * Returns the view model's back clip distance.
+ * @return the current back clip distance
+ */
+ public double getBackClipDistance() {
+ return this.backClipDistance;
+ }
+
+ /**
+ * Retrieves the user-head to virtual-world transform
+ * and copies that value into the transform provided.
+ * @param t the Transform3D object that will receive the transform
+ */
+ public void getUserHeadToVworld(Transform3D t) {
+
+ if( userHeadToVworldEnable ) {
+
+ // get the calculated userHeadToVworld transform
+ // from the view cache.
+ // grab the first canvas -- not sure for multiple canvases
+ Canvas3D canvas = this.canvases.firstElement();
+ synchronized(canvas.canvasViewCache) {
+ t.set(canvas.canvasViewCache.getHeadToVworld());
+ }
+ }else {
+ throw new RestrictedAccessException(J3dI18N.getString("View9"));
+ }
+ }
+
+ /**
+ * Sets the view model's front clip policy, the policy Java 3D uses
+ * in computing where to place the front clip plane. The variable
+ * can contain one of:
+ * <UL>
+ * <LI>VIRTUAL_EYE, to specify that the associated distance is
+ * from the eye and in units of virtual distance
+ * </LI>
+ * <LI>PHYSICAL_EYE, to specify that the associated distance is
+ * from the eye and in units of physical distance (meters)
+ * </LI>
+ * <LI>VIRTUAL_SCREEN, to specify that the associated distance is
+ * from the screen and in units of virtual distance
+ * </LI>
+ * <LI>PHYSICAL_SCREEN, to specify that the associated distance is
+ * from the screen and in units of physical distance (meters)
+ * </LI>
+ * </UL>
+ * The default front clip policy is PHYSICAL_EYE.
+ * @param policy the new policy, one of PHYSICAL_EYE, PHYSICAL_SCREEN,
+ * VIRTUAL_EYE, or VIRTUAL_SCREEN
+ */
+ public void setFrontClipPolicy(int policy) {
+ synchronized(this) {
+ this.frontClipPolicy = policy;
+ vDirtyMask |= View.CLIP_DIRTY;
+ }
+ repaint();
+ }
+
+ /**
+ * Returns the view model's current front clip policy.
+ * @return one of:
+ * VIRTUAL_EYE, PHYSICAL_EYE, VIRTUAL_SCREEN, or PHYSICAL_SCREEN
+ */
+ public int getFrontClipPolicy() {
+ return this.frontClipPolicy;
+ }
+
+ /**
+ * Sets the view model's back clip policy, the policy Java 3D uses
+ * in computing where to place the back clip plane. The variable
+ * can contain one of:
+ * <UL>
+ * <LI>VIRTUAL_EYE, to specify that the associated distance is
+ * from the eye and in units of virtual distance
+ * </LI>
+ * <LI>PHYSICAL_EYE, to specify that the associated distance is
+ * from the eye and in units of physical distance (meters)
+ * </LI>
+ * <LI>VIRTUAL_SCREEN, to specify that the associated distance is
+ * from the screen and in units of virtual distance
+ * </LI>
+ * <LI>PHYSICAL_SCREEN, to specify that the associated distance is
+ * from the screen and in units of physical distance (meters)
+ * </LI>
+ * </UL>
+ * The default back clip policy is PHYSICAL_EYE.
+ * @param policy the new policy, one of PHYSICAL_EYE, PHYSICAL_SCREEN,
+ * VIRTUAL_EYE, or VIRTUAL_SCREEN
+ */
+ public void setBackClipPolicy(int policy) {
+ synchronized(this) {
+ this.backClipPolicy = policy;
+ vDirtyMask |= View.CLIP_DIRTY;
+ }
+ repaint();
+ }
+
+ /**
+ * Returns the view model's current back clip policy.
+ * @return one of:
+ * VIRTUAL_EYE, PHYSICAL_EYE, VIRTUAL_SCREEN, or PHYSICAL_SCREEN
+ */
+ public int getBackClipPolicy() {
+ return this.backClipPolicy;
+ }
+
+ /**
+ * Sets the visibility policy for this view. This attribute
+ * is one of:
+ * <UL>
+ * <LI>VISIBILITY_DRAW_VISIBLE, to specify that only visible objects
+ * are drawn.
+ * </LI>
+ * <LI>VISIBILITY_DRAW_INVISIBLE, to specify that only invisible objects
+ * are drawn.
+ * </LI>
+ * <LI>VISIBILITY_DRAW_ALL, to specify that both visible and
+ * invisible objects are drawn.
+ * </LI>
+ * </UL>
+ * The default visibility policy is VISIBILITY_DRAW_VISIBLE.
+ *
+ * @param policy the new policy, one of VISIBILITY_DRAW_VISIBLE,
+ * VISIBILITY_DRAW_INVISIBLE, or VISIBILITY_DRAW_ALL.
+ *
+ * @see RenderingAttributes#setVisible
+ *
+ * @since Java 3D 1.2
+ */
+ public void setVisibilityPolicy(int policy) {
+
+ synchronized(this) {
+ this.visibilityPolicy = policy;
+ vDirtyMask |= View.VISIBILITY_POLICY_DIRTY;
+ }
+
+ if (activeStatus && isRunning) {
+
+ J3dMessage vpMessage = new J3dMessage();
+ vpMessage.universe = universe;
+ vpMessage.view = this;
+ vpMessage.type = J3dMessage.UPDATE_VIEW;
+ vpMessage.threads = J3dThread.UPDATE_RENDER;
+ vpMessage.args[0] = this;
+ synchronized(((ViewPlatformRetained)viewPlatform.retained).sphere) {
+ vpMessage.args[1] = new Float(((ViewPlatformRetained)viewPlatform.
+ retained).sphere.radius);
+ }
+ vpMessage.args[2] = new Integer(OTHER_ATTRS_CHANGED);
+ vpMessage.args[3] = new Integer(transparencySortingPolicy);
+ VirtualUniverse.mc.processMessage(vpMessage);
+ }
+ }
+
+ /**
+ * Retrieves the current visibility policy.
+ * @return one of:
+ * VISIBILITY_DRAW_VISIBLE,
+ * VISIBILITY_DRAW_INVISIBLE, or VISIBILITY_DRAW_ALL.
+ *
+ * @since Java 3D 1.2
+ */
+ public int getVisibilityPolicy() {
+ return this.visibilityPolicy;
+ }
+
+ /**
+ * Sets the transparency sorting policy for this view. This attribute
+ * is one of:
+ *
+ * <UL>
+ * <LI>TRANSPARENCY_SORT_NONE, to specify that no depth sorting of
+ * transparent objects is performed. Transparent objects are
+ * drawn after opaque objects, but are not sorted from back to
+ * front.</LI>
+ *
+ * <LI>TRANSPARENCY_SORT_GEOMETRY, to specify that transparent
+ * objects are depth-sorted on a per-geometry basis. Each
+ * geometry object of each transparent Shape3D node is drawn from
+ * back to front. Note that this policy will not split geometry
+ * into smaller pieces, so intersecting or intertwined objects may
+ * not be sorted correctly.</LI>
+ * </UL>
+ *
+ * The default policy is TRANSPARENCY_SORT_NONE.
+ *
+ * @param policy the new policy, one of TRANSPARENCY_SORT_NONE
+ * or TRANSPARENCY_SORT_GEOMETRY.
+ *
+ * @since Java 3D 1.3
+ */
+ public void setTransparencySortingPolicy(int policy) {
+ if (policy == transparencySortingPolicy) {
+ return;
+ }
+
+ transparencySortingPolicy = policy;
+ if (activeStatus && isRunning) {
+
+ J3dMessage vpMessage = new J3dMessage();
+ vpMessage.universe = universe;
+ vpMessage.view = this;
+ vpMessage.type = J3dMessage.UPDATE_VIEW;
+ vpMessage.threads = J3dThread.UPDATE_RENDER;
+ vpMessage.args[0] = this;
+ vpMessage.args[1] = null;
+ vpMessage.args[2] = new Integer(TRANSP_SORT_POLICY_CHANGED);
+ vpMessage.args[3] = new Integer(policy);
+ VirtualUniverse.mc.processMessage(vpMessage);
+ }
+ }
+
+ /**
+ * Retrieves the current transparency sorting policy.
+ * @return one of:
+ * TRANSPARENCY_SORT_NONE or TRANSPARENCY_SORT_GEOMETRY.
+ *
+ * @since Java 3D 1.3
+ */
+ public int getTransparencySortingPolicy() {
+ return this.transparencySortingPolicy;
+ }
+
+ /**
+ * Turns head tracking on or off for this view.
+ * @param flag specifies whether head tracking is enabled or
+ * disabled for this view
+ */
+ public void setTrackingEnable(boolean flag) {
+
+ synchronized(this) {
+ this.trackingEnable = flag;
+ vDirtyMask |= View.TRACKING_ENABLE_DIRTY;
+ }
+
+ repaint();
+ }
+
+ /**
+ * Returns a status flag indicating whether or not head tracking
+ * is enabled.
+ * @return a flag telling whether head tracking is enabled
+ */
+ public boolean getTrackingEnable() {
+ return this.trackingEnable;
+ }
+
+ /**
+ * Turns on or off the continuous
+ * updating of the userHeadToVworld transform.
+ * @param flag enables or disables continuous updating
+ */
+ public void setUserHeadToVworldEnable(boolean flag) {
+
+ synchronized(this) {
+ userHeadToVworldEnable = flag;
+ vDirtyMask |= View.USER_HEAD_TO_VWORLD_ENABLE_DIRTY;
+ }
+ repaint();
+ }
+
+ /**
+ * Returns a status flag indicating whether or not
+ * Java 3D is continuously updating the userHeadToVworldEnable transform.
+ * @return a flag indicating if continuously updating userHeadToVworld
+ */
+ public boolean getUserHeadToVworldEnable() {
+ return userHeadToVworldEnable;
+ }
+
+ /**
+ * Computes the sensor to virtual-world transform
+ * and copies that value into the transform provided.
+ * The computed transforms takes points in the sensor's coordinate
+ * system and produces the point's corresponding value in
+ * virtual-world coordinates.
+ * @param sensor the sensor in question
+ * @param t the object that will receive the transform
+ */
+ public void getSensorToVworld(Sensor sensor, Transform3D t) {
+ // grab the first canvas -- not sure for multiple canvases
+ Canvas3D canvas = this.canvases.firstElement();
+ Transform3D localTrans = new Transform3D();
+ synchronized(canvas.canvasViewCache) {
+ t.set(canvas.canvasViewCache.getVworldToTrackerBase());
+ }
+ t.invert();
+ sensor.getRead(localTrans);
+ t.mul(localTrans);
+ }
+
+ /**
+ * Retrieves the position of the specified Sensor's
+ * hotspot in virtual-world coordinates
+ * and copies that value into the position provided.
+ * This value is derived from other values and is read-only.
+ * @param sensor the sensor in question
+ * @param position the variable that will receive the position
+ */
+ public void getSensorHotspotInVworld(Sensor sensor,
+ Point3f position) {
+
+ Transform3D sensorToVworld = new Transform3D();
+ Point3d hotspot3d = new Point3d();
+
+ getSensorToVworld(sensor, sensorToVworld);
+ sensor.getHotspot(hotspot3d);
+ position.set(hotspot3d);
+ sensorToVworld.transform(position);
+ }
+
+ /**
+ * Retrieves the position of the specified Sensor's
+ * hotspot in virtual-world coordinates
+ * and copies that value into the position provided.
+ * This value is derived from other values and is read-only.
+ * @param sensor the sensor in question
+ * @param position the variable that will receive the position
+ */
+ public void getSensorHotspotInVworld(Sensor sensor,
+ Point3d position) {
+
+ Transform3D sensorToVworld = new Transform3D();
+
+ getSensorToVworld(sensor, sensorToVworld);
+ sensor.getHotspot(position);
+ sensorToVworld.transform(position);
+ }
+
+ /**
+ * Sets given Canvas3D at the given index position.
+ * @param canvas3D the given Canvas3D to be set
+ * @param index the position to be set
+ * @exception IllegalStateException if the specified canvas is
+ * a stereo canvas with a monoscopicEyePolicy of CYCLOPEAN_EYE_VIEW,
+ * and the viewPolicy for this view is HMD_VIEW
+ * @exception IllegalSharingException if the specified canvas is
+ * associated with another view
+ */
+ public void setCanvas3D(Canvas3D canvas3D, int index) {
+
+ if((viewPolicy == HMD_VIEW) &&
+ (canvas3D.monoscopicViewPolicy == View.CYCLOPEAN_EYE_VIEW) &&
+ (!canvas3D.useStereo)){
+
+ throw new
+ IllegalStateException(J3dI18N.getString("View31"));
+ }
+
+ Canvas3D cv;
+
+ synchronized(canvasList) {
+ if (canvas3D.getView() != null)
+ throw new IllegalSharingException(J3dI18N.getString("View10"));
+ cv = canvases.elementAt(index);
+ canvases.setElementAt(canvas3D, index);
+ removeFromCanvasList(cv);
+ addToCanvasList(canvas3D);
+ canvasesDirty = true;
+ }
+
+ canvas3D.setView(this);
+ cv.setView(null);
+
+ if (canvas3D.added) {
+ evaluateActive();
+ }
+ if (cv.added) {
+ evaluateActive();
+ }
+
+ }
+
+ /**
+ * Gets the Canvas3D at the specified index position.
+ * @param index the position from which to get Canvas3D object
+ * @return the Canvas3D at the sprcified index position
+ */
+ public Canvas3D getCanvas3D(int index){
+ return this.canvases.elementAt(index);
+ }
+
+ /**
+ * Gets the enumeration object of all the Canvas3Ds.
+ * @return the enumeration object of all the Canvas3Ds.
+ */
+ public Enumeration<Canvas3D> getAllCanvas3Ds(){
+ return canvases.elements();
+ }
+
+ /**
+ * Returns the number of Canvas3Ds in this View.
+ * @return the number of Canvas3Ds in this View
+ *
+ * @since Java 3D 1.2
+ */
+ public int numCanvas3Ds() {
+ return canvases.size();
+ }
+
+ /**
+ * Adds the given Canvas3D at the end of the list.
+ * @param canvas3D the Canvas3D to be added
+ * @exception IllegalStateException if the specified canvas is
+ * a stereo canvas with a monoscopicEyePolicy of CYCLOPEAN_EYE_VIEW,
+ * and the viewPolicy for this view is HMD_VIEW
+ * @exception IllegalSharingException if the specified canvas is
+ * associated with another view
+ */
+ public void addCanvas3D(Canvas3D canvas3D){
+
+ if((viewPolicy == HMD_VIEW) &&
+ (canvas3D.monoscopicViewPolicy == View.CYCLOPEAN_EYE_VIEW) &&
+ (!canvas3D.useStereo)) {
+ throw new
+ IllegalStateException(J3dI18N.getString("View31"));
+ }
+
+ synchronized(canvasList) {
+ if (canvas3D.getView() != null)
+ throw new IllegalSharingException(J3dI18N.getString("View10"));
+ canvases.addElement(canvas3D);
+ addToCanvasList(canvas3D);
+ canvasesDirty = true;
+ }
+
+ canvas3D.setView(this);
+
+ if (canvas3D.added) {
+ if ((canvas3D.visible || canvas3D.offScreen) &&
+ canvas3D.firstPaintCalled) {
+ canvas3D.active = true;
+ }
+ evaluateActive();
+ }
+ }
+
+ /**
+ * Inserts the Canvas3D at the given index position.
+ * @param canvas3D the Canvas3D to be inserted
+ * @param index the position to be inserted at
+ * @exception IllegalStateException if the specified canvas is
+ * a stereo canvas with a monoscopicEyePolicy of CYCLOPEAN_EYE_VIEW,
+ * and the viewPolicy for this view is HMD_VIEW
+ * @exception IllegalSharingException if the specified canvas is
+ * associated with another view
+ */
+ public void insertCanvas3D(Canvas3D canvas3D, int index){
+
+ if((viewPolicy == HMD_VIEW) &&
+ (canvas3D.monoscopicViewPolicy == View.CYCLOPEAN_EYE_VIEW) &&
+ (!canvas3D.useStereo)) {
+ throw new
+ IllegalStateException(J3dI18N.getString("View31"));
+ }
+
+ synchronized(canvasList) {
+ if (canvas3D.getView() != null)
+ throw new IllegalSharingException(J3dI18N.getString("View10"));
+ this.canvases.insertElementAt(canvas3D, index);
+ addToCanvasList(canvas3D);
+ canvasesDirty = true;
+ }
+
+ canvas3D.setView(this);
+
+ if (canvas3D.added) {
+ if ((canvas3D.visible || canvas3D.offScreen) &&
+ canvas3D.firstPaintCalled) {
+ canvas3D.active = true;
+ }
+ evaluateActive();
+ }
+ }
+
+ /**
+ * Removes the Canvas3D from the given index position.
+ * @param index the position of Canvas3D object to be removed
+ */
+ public void removeCanvas3D(int index) {
+ // index -1 is possible if the view is unregistered first
+ // because viewPlatform is clearLived,
+ // and then removeCanvas from the view
+ if (index == -1)
+ return;
+
+ Canvas3D cv;
+
+ synchronized(canvasList) {
+ cv = canvases.elementAt(index);
+
+ canvases.removeElementAt(index);
+ removeFromCanvasList(cv);
+ canvasesDirty = true;
+ }
+
+ // reset canvas will set view to null also
+ VirtualUniverse.mc.postRequest(MasterControl.RESET_CANVAS,
+ cv);
+ cv.pendingView = null;
+
+ computeCanvasesCached();
+
+ if (cv.added) {
+ cv.active = false;
+ evaluateActive();
+ }
+ if (universe != null) {
+ universe.waitForMC();
+ }
+ }
+
+
+ /**
+ * Retrieves the index of the specified Canvas3D in
+ * this View's list of Canvas3Ds
+ *
+ * @param canvas3D the Canvas3D to be looked up.
+ * @return the index of the specified Canvas3D;
+ * returns -1 if the object is not in the list.
+ *
+ * @since Java 3D 1.3
+ */
+ public int indexOfCanvas3D(Canvas3D canvas3D) {
+ return canvases.indexOf(canvas3D);
+ }
+
+
+ /**
+ * Removes the specified Canvas3D from this View's
+ * list of Canvas3Ds.
+ * If the specified object is not in the list, the list is not modified.
+ *
+ * @param canvas3D the Canvas3D to be removed.
+ */
+ public void removeCanvas3D(Canvas3D canvas3D) {
+ removeCanvas3D(canvases.indexOf(canvas3D));
+ }
+
+
+ /**
+ * Removes all Canvas3Ds from this View.
+ *
+ * @since Java 3D 1.3
+ */
+ public void removeAllCanvas3Ds() {
+ LinkedList<Canvas3D> tmpCanvases = new LinkedList<Canvas3D>();
+
+ synchronized(canvasList) {
+ int numCanvases = canvases.size();
+
+ // Remove in reverse order to ensure valid indices
+ for (int index = numCanvases - 1; index >= 0; index--) {
+ Canvas3D cv = canvases.elementAt(index);
+
+ // Record list of canvases to be deleted;
+ tmpCanvases.add(cv);
+
+ canvases.removeElementAt(index);
+ removeFromCanvasList(cv);
+ canvasesDirty = true;
+ }
+ }
+
+ // ISSUE 83: postRequest must *not* be called while holding
+ // canvasList lock. Holding the lock can cause a deadlock.
+
+ Iterator<Canvas3D> iterator = tmpCanvases.iterator();
+ while (iterator.hasNext()) {
+ Canvas3D cv = iterator.next();
+
+ // reset canvas will set view to null also
+ VirtualUniverse.mc.postRequest(MasterControl.RESET_CANVAS,
+ cv);
+ cv.pendingView = null;
+
+ if (cv.added) {
+ cv.active = false;
+ }
+ }
+
+ computeCanvasesCached();
+
+ evaluateActive();
+
+ if (universe != null) {
+ universe.waitForMC();
+ }
+ }
+
+
+ // This adds this canvas and its screen to the screen list.
+ // Locks are already acquired before this is called.
+ private void addToCanvasList(Canvas3D c) {
+
+ for (int i=screenList.size()-1; i>=0; i--) {
+ if (screenList.get(i) == c.screen) {
+ // This is the right screen slot
+ canvasList.get(i).add(c);
+ canvasesDirty = true;
+ return;
+ }
+ }
+
+ // Add a screen slot
+ screenList.add(c.screen);
+ ArrayList<Canvas3D> clist = new ArrayList<Canvas3D>();
+ canvasList.add(clist);
+ clist.add(c);
+ canvasesDirty = true;
+ }
+
+ // This removes this canvas and its screen from the screen list
+ // Locks are already acquired before this is called.
+ private void removeFromCanvasList(Canvas3D c) {
+
+ for (int i=screenList.size()-1; i>=0; i--) {
+ if (screenList.get(i) == c.screen) {
+ // This is the right screen slot
+ ArrayList<Canvas3D> clist = canvasList.get(i);
+ clist.remove(clist.indexOf(c));
+
+ if (clist.size() == 0) {
+ canvasList.remove(i);
+ screenList.remove(i);
+ canvasesDirty = true;
+ }
+ return;
+ }
+ }
+ }
+
+ // Locks are not acquired before this is called.
+ void computeCanvasesCached() {
+
+ synchronized (canvasList) {
+ ArrayList<Canvas3D> cv;
+ int len = canvases.size();
+
+ Canvas3D newCachedCanvases[] = new Canvas3D[len];
+ for (int i=0; i < len; i++) {
+ newCachedCanvases[i] = canvases.get(i);
+ }
+ // Do this in one instruction so there is no need to
+ // synchronized getCanvases()
+
+ cachedCanvases = newCachedCanvases;
+ len = 0;
+ longestScreenList = 0;
+ cachedCanvasList = new Canvas3D[canvasList.size()][0];
+ for (int i=0; i < cachedCanvasList.length; i++) {
+ cv = canvasList.get(i);
+ len = cv.size();
+ cachedCanvasList[i] = new Canvas3D[len];
+ for (int j=0; j < len; j++) {
+ cachedCanvasList[i][j] = cv.get(j);
+ }
+
+ if (len > longestScreenList) {
+ longestScreenList = len;
+ }
+ }
+ len = screenList.size();
+ Screen3D newCachedScreens[] = new Screen3D[len];
+
+ for (int i=0; i < len; i++) {
+ newCachedScreens[i] = screenList.get(i);
+ }
+ // Do this in one instruction so there is no need to
+ // synchronized getScreens()
+ cachedScreens = newCachedScreens;
+ canvasesDirty = false;
+ }
+ }
+
+ // This creates a 2 dimentional list of canvases
+ // ONLY MC can call this procedure with canCompute=true,
+ // since MC want the result return by
+ // evaluateCanvases and updateWorkThreads agree to each other,
+ // so only evaluateCanvases can compute a new list.
+ // Other threads should use getCanvasList(false).
+ Canvas3D[][] getCanvasList(boolean canCompute) {
+ if (canvasesDirty && canCompute) {
+ computeCanvasesCached();
+ }
+ return cachedCanvasList;
+ }
+
+ // assume getCanvasList is called before
+ int getLongestScreenList() {
+ return longestScreenList;
+ }
+
+ // assume getCanvasList is called before
+ Canvas3D[] getCanvases() {
+ return cachedCanvases;
+ }
+
+ // assume getCanvasList is called before
+ Screen3D[] getScreens() {
+ return cachedScreens;
+ }
+
+ Canvas3D getFirstCanvas() {
+ synchronized (canvasList) {
+ if (canvases.size() > 0) {
+ return canvases.elementAt(0);
+ }
+ return null;
+ }
+ }
+
+ /**
+ * This method returns the time at which the most recent rendering
+ * frame started. It is defined as the number of milliseconds
+ * since January 1, 1970 00:00:00 GMT.
+ * Since multiple canvases might be attached to this View,
+ * the start of a frame is defined as the point in time just prior
+ * to clearing any canvas attached to this view.
+ * @return the time at which the most recent rendering frame started
+ */
+ public long getCurrentFrameStartTime() {
+ synchronized (frameStartTimes) {
+ return currentFrameStartTime;
+ }
+ }
+
+ /**
+ * This method returns the duration, in milliseconds, of the most
+ * recently completed rendering frame. The time taken to render
+ * all canvases attached to this view is measured. This duration
+ * is computed as the difference between the start of the most recently
+ * completed frame and the end of that frame.
+ * Since multiple canvases might be attached to this View,
+ * the start of a frame is defined as the point in time just prior
+ * to clearing any canvas attached to this view--before preRender
+ * is called for any canvas. Similarly, the end of a frame is
+ * defined as the point in time just after swapping the buffer for
+ * all canvases--after postSwap is called for all canvases.
+ * Note that since the frame duration is measured from start to stop
+ * for this view only, the value returned is not the same as
+ * frame rate; it measures only the rendering time for this view.
+ *
+ * @return the duration, in milliseconds, of the most recently
+ * completed rendering frame
+ */
+ public long getLastFrameDuration() {
+ synchronized (frameStartTimes) {
+ return currentFrameDuration;
+ }
+ }
+
+ /**
+ * This method returns the frame number for this view. The frame
+ * number starts at 0 and is incremented at the start of each
+ * frame--prior to clearing all the canvases attached to this
+ * view.
+ *
+ * @return the current frame number for this view
+ */
+ public long getFrameNumber() {
+ synchronized (frameStartTimes) {
+ return currentFrameNumber;
+ }
+ }
+
+ /**
+ * Retrieves the implementation-dependent maximum number of
+ * frames whose start times will be recorded by the system. This
+ * value is guaranteed to be at least 10 for all implementations
+ * of the Java 3D API.
+ * @return the maximum number of frame start times recorded
+ */
+ public static int getMaxFrameStartTimes() {
+ return (NUMBER_FRAME_START_TIMES);
+ }
+
+ /**
+ * Copies the last <i>k</i> frame start time values into
+ * the user-specified array. The most recent frame start time is
+ * copied to location 0 of the array, the next most recent frame
+ * start time is copied into location 1 of the array, and so forth.
+ * If times.length is smaller than
+ * maxFrameStartTimes, then only the last times.length values are
+ * copied. If times.length is greater than maxFrameStartTimes,
+ * then all array elements after index maxFrameStartTimes-1 are
+ * set to 0.
+ *
+ * @return the frame number of the most recent frame in the array
+ *
+ * @see #setMinimumFrameCycleTime
+ */
+ public long getFrameStartTimes(long[] times) {
+ int index, i, loopCount;
+ long lastFrameNumber;
+
+ synchronized (frameStartTimes) {
+ index = currentFrameIndex - 1;
+ if (index < 0) {
+ index = NUMBER_FRAME_START_TIMES - 1;
+ }
+ lastFrameNumber = frameNumbers[index];
+
+ if (times.length <= NUMBER_FRAME_START_TIMES) {
+ loopCount = times.length;
+ } else {
+ loopCount = NUMBER_FRAME_START_TIMES;
+ }
+
+ for (i=0; i<loopCount; i++) {
+ times[i] = frameStartTimes[index];
+ index--;
+ if (index < 0) {
+ index = NUMBER_FRAME_START_TIMES - 1;
+ }
+ }
+
+ if (times.length > NUMBER_FRAME_START_TIMES) {
+ for (; i<times.length; i++) {
+ times[i] = 0;
+ }
+ }
+ }
+
+ return (lastFrameNumber);
+ }
+
+ /**
+ * Sets the minimum frame cycle time, in milliseconds, for this
+ * view. The Java 3D renderer will ensure that the time between
+ * the start of each successive frame is at least the specified
+ * number of milliseconds. The default value is 0.
+ *
+ * @param minimumTime the minimum number of milliseconds between
+ * successive frames
+ *
+ * @exception IllegalArgumentException if <code>minimumTime < 0</code>
+ *
+ * @see #getFrameStartTimes
+ *
+ * @since Java 3D 1.2
+ */
+ public void setMinimumFrameCycleTime(long minimumTime) {
+ if (minimumTime < 0L)
+ throw new IllegalArgumentException(J3dI18N.getString("View27"));
+
+ minFrameCycleTime = minimumTime;
+ VirtualUniverse.mc.setWork();
+ }
+
+ /**
+ * Retrieves the minimum frame cycle time, in milliseconds, for this view.
+ * @return the minimum frame cycle time for this view.
+ *
+ * @see #getFrameStartTimes
+ *
+ * @since Java 3D 1.2
+ */
+ public long getMinimumFrameCycleTime() {
+ return minFrameCycleTime;
+ }
+
+
+ /**
+ * This adds a frame time to the this of frame times
+ */
+ void setFrameTimingValues() {
+
+ synchronized (frameStartTimes) {
+ if (currentFrameIndex == NUMBER_FRAME_START_TIMES) {
+ currentFrameIndex = 0;
+ }
+
+ frameNumbers[currentFrameIndex] = frameNumber;
+
+ frameStartTimes[currentFrameIndex++] = startTime;
+ currentFrameStartTime = startTime;
+ currentFrameDuration = stopTime - startTime;
+ currentFrameNumber = frameNumber;
+ }
+ }
+
+ /**
+ * Return true if maximum fps impose by user reach
+ */
+ void computeCycleTime() {
+ if (minFrameCycleTime == 0) {
+ isMinCycleTimeAchieve = true;
+ sleepTime = 0;
+ } else {
+ sleepTime = minFrameCycleTime -
+ (J3dClock.currentTimeMillis() - startTime);
+ isMinCycleTimeAchieve = (sleepTime <= 0);
+ }
+ }
+
+
+ /**
+ * Enables or disables automatic freezing of the depth buffer for
+ * objects rendered
+ * during the transparent rendering pass (i.e., objects rendered
+ * using alpha blending) for this view.
+ * If enabled, depth buffer writes will be disabled during the
+ * transparent rendering pass regardless of the value of
+ * the depth buffer write enable flag in the RenderingAttributes
+ * object for a particular node.
+ * This flag is enabled by default.
+ * @param flag indicates whether automatic freezing of the depth buffer
+ * for transparent/antialiased objects is enabled.
+ * @see RenderingAttributes#setDepthBufferWriteEnable
+ */
+ public void setDepthBufferFreezeTransparent(boolean flag) {
+ depthBufferFreezeTransparent = flag;
+ repaint();
+ }
+
+ /**
+ * Retrieves the current value of the depth buffer freeze transparent
+ * flag for this view.
+ * @return a flag that indicates whether or not the depth
+ * buffer is automatically frozen during the transparent rendering pass.
+ */
+ public boolean getDepthBufferFreezeTransparent() {
+ return depthBufferFreezeTransparent;
+ }
+
+ /**
+ * Enables or disables scene antialiasing for this view.
+ * If enabled, the entire scene will be antialiased on
+ * each canvas in which scene antialiasing is available.
+ * Scene antialiasing is disabled by default.
+ * <p>
+ * NOTE: Scene antialiasing is ignored in pure immediate mode,
+ * but is supported in mixed-immediate mode.
+ * @param flag indicates whether scene antialiasing is enabled
+ *
+ * @see Canvas3D#queryProperties
+ */
+ public void setSceneAntialiasingEnable(boolean flag) {
+ sceneAntialiasingEnable = flag;
+ repaint();
+ }
+
+ /**
+ * Returns a flag that indicates whether or not scene antialiasing
+ * is enabled for this view.
+ * @return a flag that indicates whether scene antialiasing is enabled
+ */
+ public boolean getSceneAntialiasingEnable() {
+ return sceneAntialiasingEnable;
+ }
+
+ /**
+ * Sets a flag that indicates whether the local eyepoint is used in
+ * lighting calculations for perspective projections.
+ * If this flag is set to true, the view vector is calculated per-vertex
+ * based on the direction from the actual eyepoint to the vertex.
+ * If this flag is set to false, a single view vector is computed from
+ * the eyepoint to the center of the view frustum. This is
+ * called infinite eye lighting.
+ * Local eye lighting is disabled by default, and is ignored for
+ * parallel projections.
+ * @param flag indicates whether local eye lighting is enabled
+ */
+ public void setLocalEyeLightingEnable(boolean flag) {
+ localEyeLightingEnable = flag;
+ repaint();
+ }
+
+ /**
+ * Retrieves a flag that indicates whether or not local eye lighting
+ * is enabled for this view.
+ * @return a flag that indicates whether local eye lighting is enabled
+ */
+ public boolean getLocalEyeLightingEnable() {
+ return localEyeLightingEnable;
+ }
+
+ /**
+ * Attach viewPlatform structure to this view.
+ * @param vp the viewPlatform to be attached
+ */
+ public void attachViewPlatform(ViewPlatform vp) {
+
+ if ((vp != null) && (vp == viewPlatform)) {
+ return;
+ }
+
+ if (viewPlatform != null) {
+ ((ViewPlatformRetained)viewPlatform.retained).removeView(this);
+ if (viewPlatform.isLive()) {
+ synchronized (evaluateLock) {
+ viewPlatform = null;
+ // cleanup View stuff for the old platform
+ evaluateActive();
+ viewPlatform = vp;
+ }
+ if (universe != null) {
+ universe.waitForMC();
+ }
+ } else {
+ viewPlatform = vp;
+ }
+ } else {
+ viewPlatform = vp;
+ }
+ if (vp != null) {
+ if (vp.isLive()) {
+ checkView();
+ setUniverse(((ViewPlatformRetained)vp.retained).universe);
+ }
+ ((ViewPlatformRetained)vp.retained).setView(this);
+ }
+
+ evaluateActive();
+ if ((vp == null) && (universe != null)) {
+ universe.waitForMC();
+ }
+ }
+
+ /**
+ * Retrieves the currently attached ViewPlatform object
+ * @return the currently attached ViewPlatform
+ */
+ public ViewPlatform getViewPlatform() {
+ return viewPlatform;
+ }
+
+ /**
+ * Checks view parameters for consistency
+ */
+ void checkView() {
+ if (physicalBody == null)
+ throw new IllegalStateException(J3dI18N.getString("View13"));
+
+ if (physicalEnvironment == null)
+ throw new IllegalStateException(J3dI18N.getString("View14"));
+ }
+
+
+ /**
+ * Stops the behavior scheduler after all
+ * currently scheduled behaviors are executed. Any frame-based
+ * behaviors scheduled to wake up on the next frame will be
+ * executed at least once before the behavior scheduler is
+ * stopped.
+ * <p>
+ * NOTE: This is a heavy-weight method
+ * intended for verification and image capture (recording); it
+ * is <i>not</i> intended to be used for flow control.
+ * @return a pair of integers that specify the beginning and ending
+ * time (in milliseconds since January 1, 1970 00:00:00 GMT)
+ * of the behavior scheduler's last pass
+ * @exception IllegalStateException if this method is called
+ * from a Behavior method or from any Canvas3D render callback
+ * method
+ */
+ public final long[] stopBehaviorScheduler() {
+ long[] intervalTime = new long[2];
+
+ if (checkBehaviorSchedulerState("View15", "View16")) {
+ if (activeStatus && isRunning &&
+ (universe.behaviorScheduler != null)) {
+ // view is active
+ universe.behaviorScheduler.stopBehaviorScheduler(intervalTime);
+ } else {
+ if ((universe != null) &&
+ (universe.behaviorScheduler != null)) {
+ universe.behaviorScheduler.userStop = true;
+ }
+ }
+ }
+ stopBehavior = true;
+ return intervalTime;
+ }
+
+ /**
+ * Starts the behavior scheduler running after it has been stopped.
+ * @exception IllegalStateException if this method is called
+ * from a Behavior method or from any Canvas3D render callback
+ * method
+ */
+ public final void startBehaviorScheduler() {
+ if (checkBehaviorSchedulerState("View17", "View18")) {
+ if (activeStatus && isRunning &&
+ (universe.behaviorScheduler != null)) {
+ universe.behaviorScheduler.startBehaviorScheduler();
+
+ } else {
+ if ((universe != null) &&
+ (universe.behaviorScheduler != null)) {
+ universe.behaviorScheduler.userStop = false;
+ }
+ }
+ }
+
+ stopBehavior = false;
+ }
+
+ /**
+ * Check if BehaviorScheduler is in valid state to start/stop
+ * itself.
+ * @param s1 Exception String if method is called from a Canvas3D
+ * @param s2 Exception String if method is called from a Behavior method
+ * @return true if viewPlatform is live
+ * @exception IllegalStateException if this method is called
+ * from a Behavior method or from any Canvas3D render callback
+ * method
+ *
+ */
+ boolean checkBehaviorSchedulerState(String s1, String s2) {
+ Thread me = Thread.currentThread();
+
+ if (inCanvasCallback) {
+ synchronized (canvasList) {
+ for (int i=canvases.size()-1; i>=0; i--) {
+ if (canvases.elementAt(i).screen.renderer == me) {
+ throw new IllegalStateException(J3dI18N.getString(s1));
+ }
+ }
+ }
+ }
+
+ if ((viewPlatform != null) && viewPlatform.isLive()) {
+ if (universe.inBehavior && (universe.behaviorScheduler == me)) {
+ throw new IllegalStateException(J3dI18N.getString(s2));
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Retrieves a flag that indicates whether the behavior scheduler is
+ * currently running.
+ * @return true if the behavior scheduler is running, false otherwise
+ * @exception IllegalStateException if this method is called
+ * from a Behavior method or from any Canvas3D render callback
+ * method
+ */
+ public final boolean isBehaviorSchedulerRunning() {
+ return (((universe != null) && !stopBehavior &&
+ (universe.behaviorScheduler != null)) ?
+ !universe.behaviorScheduler.userStop : false);
+ }
+
+ /**
+ * Stops traversing the scene graph for this
+ * view after the current state of the scene graph is reflected on
+ * all canvases attached to this view. The renderers associated
+ * with these canvases are also stopped.
+ * <p>
+ * NOTE: This is a heavy-weight method
+ * intended for verification and image capture (recording); it
+ * is <i>not</i> intended to be used for flow control.
+ * @exception IllegalStateException if this method is called
+ * from a Behavior method or from any Canvas3D render callback
+ * method
+ */
+ public final void stopView() {
+ checkViewState("View19", "View20");
+ synchronized (startStopViewLock) {
+ if (activeStatus && isRunning) {
+ VirtualUniverse.mc.postRequest(MasterControl.STOP_VIEW, this);
+ while (isRunning) {
+ MasterControl.threadYield();
+ }
+ } else {
+ isRunning = false;
+ }
+ }
+ }
+
+ /**
+ * Starts
+ * traversing this view, and starts the renderers associated
+ * with all canvases attached to this view.
+ * @exception IllegalStateException if this method is called
+ * from a Behavior method or from any Canvas3D render callback
+ * method
+ */
+ public final void startView() {
+
+ checkViewState("View21", "View22");
+ synchronized (startStopViewLock) {
+ if (activeStatus && !isRunning) {
+ VirtualUniverse.mc.postRequest(MasterControl.START_VIEW, this);
+ while (!isRunning) {
+ MasterControl.threadYield();
+ }
+ VirtualUniverse.mc.sendRunMessage(this,
+ J3dThread.RENDER_THREAD);
+ } else {
+ isRunning = true;
+ }
+ }
+
+ }
+
+ /**
+ * This will throw IllegalStateException if not in valid state
+ * for start/stop request.
+ */
+ void checkViewState(String s1, String s2) throws IllegalStateException {
+ if (inCanvasCallback) {
+ Thread me = Thread.currentThread();
+ synchronized (canvasList) {
+ for (int i= canvases.size()-1; i>=0; i--) {
+ Canvas3D cv = canvases.elementAt(i);
+ if (cv.screen.renderer == me) {
+ throw new
+ IllegalStateException(J3dI18N.getString(s1));
+ }
+ }
+ }
+ }
+
+ if ((viewPlatform != null) && viewPlatform.isLive()) {
+ if (universe.inBehavior &&
+ (Thread.currentThread() == universe.behaviorScheduler)) {
+ throw new IllegalStateException(J3dI18N.getString(s2));
+ }
+ }
+ }
+
+ /**
+ * Retrieves a flag that indicates whether the traverser is
+ * currently running on this view.
+ * @return true if the traverser is running, false otherwise
+ * @exception IllegalStateException if this method is called
+ * from a Behavior method or from any Canvas3D render callback
+ * method
+ */
+ public final boolean isViewRunning() {
+ return isRunning;
+ }
+
+ /**
+ * Renders one frame for a stopped View. Functionally, this
+ * method is equivalent to <code>startView()</code> followed by
+ * <code>stopview()</code>, except that it is atomic, which
+ * guarantees that only one frame is rendered.
+ *
+ * @exception IllegalStateException if this method is called from
+ * a Behavior method or from any Canvas3D render callback, or if
+ * the view is currently running.
+ *
+ * @since Java 3D 1.2
+ */
+ public void renderOnce() {
+ checkViewState("View28", "View29");
+ synchronized (startStopViewLock) {
+ if (isRunning) {
+ throw new IllegalStateException(J3dI18N.getString("View30"));
+ }
+ renderOnceFinish = false;
+ VirtualUniverse.mc.postRequest(MasterControl.RENDER_ONCE, this);
+ while (!renderOnceFinish) {
+ MasterControl.threadYield();
+ }
+ renderOnceFinish = true;
+ }
+ }
+
+ /**
+ * Requests that this View be scheduled for rendering as soon as
+ * possible. The repaint method may return before the frame has
+ * been rendered. If the view is stopped, or if the view is
+ * continuously running (for example, due to a free-running
+ * interpolator), this method will have no effect. Most
+ * applications will not need to call this method, since any
+ * update to the scene graph or to viewing parameters will
+ * automatically cause all affected views to be rendered.
+ *
+ * @since Java 3D 1.2
+ */
+ public void repaint() {
+ if (activeStatus && isRunning) {
+ VirtualUniverse.mc.sendRunMessage(this,
+ J3dThread.RENDER_THREAD);
+ }
+ }
+
+
+ /**
+ * Update the view cache associated with this view. Also, shapshot
+ * the per-screen parameters associated with all screens attached
+ * to this view.
+ */
+ final void updateViewCache() {
+
+ synchronized(this) {
+ viewCache.snapshot();
+ viewCache.computeDerivedData();
+ }
+
+ // Just take the brute force approach and snapshot the
+ // parameters for each screen attached to each canvas. We won't
+ // worry about whether a screen is cached more than once.
+ // Eventually, dirty bits will take care of this.
+
+ synchronized (canvasList) {
+ int i = canvases.size()-1;
+ while (i>=0) {
+ Screen3D scr = canvases.elementAt(i--).getScreen3D();
+ if (scr != null)
+ scr.updateViewCache();
+ }
+ }
+ }
+
+
+ /**
+ * This routine activates or deactivates a view based on various information
+ */
+ void evaluateActive() {
+
+ synchronized (evaluateLock) {
+ if (universe == null) {
+ return;
+ }
+
+ if ((viewPlatform == null) ||
+ !viewPlatform.isLive() ||
+ !((ViewPlatformRetained)viewPlatform.retained).switchState.currentSwitchOn) {
+ if (activeStatus) {
+ deactivate();
+ activeStatus = false;
+ }
+ // Destroy threads from MC
+ if (VirtualUniverse.mc.isRegistered(this) &&
+ (universe.isEmpty() ||
+ (canvases.isEmpty() &&
+ ((viewPlatform == null) ||
+ !viewPlatform.isLive())))) {
+ // We can't wait until MC finish unregister view
+ // here because user thread may
+ // holds the universe.sceneGraphLock if branch
+ // or locale remove in clearLive(). In this way
+ // There is deadlock since MC also need need
+ // sceneGraphLock in some threads
+ // (e.g. TransformStructure update thread)
+ universe.unRegViewWaiting = this;
+ resetUnivCount = universeCount;
+ VirtualUniverse.mc.postRequest(
+ MasterControl.UNREGISTER_VIEW, this);
+ }
+ } else {
+
+ // We're on a live view platform. See what the canvases say
+ // If view not register, MC will register it automatically
+
+ int i;
+ VirtualUniverse u = null;
+ synchronized (canvasList) {
+
+ for (i=canvases.size()-1; i>=0; i--) {
+ Canvas3D cv = canvases.elementAt(i);
+ if (cv.active) {
+
+ if (!activeStatus && (universeCount > resetUnivCount)) {
+ u = universe;
+ }
+ break;
+ }
+ }
+ }
+
+ // We should do this outside canvasList lock,
+ // otherwise it may cause deadlock with MC
+ if (u != null) {
+ activate(u);
+ activeStatus = true;
+ return;
+ }
+
+
+ if ((i < 0) && activeStatus) {
+ deactivate();
+ activeStatus = false;
+ return;
+ }
+
+ if (VirtualUniverse.mc.isRegistered(this)) {
+ // notify MC that canvases state for this view changed
+ VirtualUniverse.mc.postRequest(
+ MasterControl.REEVALUATE_CANVAS, this);
+ }
+ }
+ }
+ }
+
+ void setUniverse(VirtualUniverse universe) {
+
+ synchronized (VirtualUniverse.mc.requestObjList) {
+ if ((renderBin == null) ||
+ (renderBin.universe != universe)) {
+ if (renderBin != null) {
+ renderBin.cleanup();
+ }
+ renderBin = new RenderBin(universe, this);
+ renderBin.universe = universe;
+ }
+
+
+ if ((soundScheduler == null) ||
+ (soundScheduler.universe != universe)) {
+ // create a sound scheduler for this view, with this universe
+ if (soundScheduler != null) {
+ soundScheduler.cleanup();
+ }
+ soundScheduler = new SoundScheduler(universe, this);
+ }
+
+
+ // This has to be the last call before
+ // RenderBin and SoundScheduler construct. Since it is
+ // possible that canvas receive paint call and invoked
+ // evaluateActive in another thread - which check for
+ // universe == null and may let it pass before soundScheduler
+ // and renderBin initialize.
+ universeCount++;
+ this.universe = universe;
+ }
+ evaluateActive();
+ }
+
+ /**
+ * This activates all traversers and renderers associated with this view.
+ */
+ void activate(VirtualUniverse universe) {
+
+ universe.checkForEnableEvents();
+
+ if (physicalBody != null) {
+ physicalBody.addUser(this);
+ }
+
+ if (!VirtualUniverse.mc.isRegistered(this)) {
+ universe.regViewWaiting = this;
+ }
+
+ VirtualUniverse.mc.postRequest(MasterControl.ACTIVATE_VIEW,
+ this);
+
+ if (!universe.isSceneGraphLock) {
+ universe.waitForMC();
+ }
+ if (soundScheduler != null) {
+ soundScheduler.reset();
+ }
+
+ J3dMessage vpMessage = new J3dMessage();
+ vpMessage.universe = universe;
+ vpMessage.view = this;
+ vpMessage.type = J3dMessage.UPDATE_VIEW;
+ vpMessage.threads =
+ J3dThread.SOUND_SCHEDULER |
+ J3dThread.UPDATE_RENDER |
+ J3dThread.UPDATE_BEHAVIOR;
+ vpMessage.args[0] = this;
+ synchronized(((ViewPlatformRetained)viewPlatform.retained).sphere) {
+ vpMessage.args[1] = new Float(((ViewPlatformRetained)viewPlatform.retained).sphere.radius);
+ }
+ vpMessage.args[2] = new Integer(OTHER_ATTRS_CHANGED);
+ vpMessage.args[3] = new Integer(transparencySortingPolicy);
+ VirtualUniverse.mc.processMessage(vpMessage);
+ }
+
+ /**
+ * This deactivates all traversers and renderers associated with this view.
+ */
+ void deactivate() {
+ VirtualUniverse.mc.postRequest(MasterControl.DEACTIVATE_VIEW, this);
+ if (physicalBody != null) {
+ physicalBody.removeUser(this);
+ }
+
+ // This is a temporary fix for bug 4267395
+ // XXXX:cleanup in RenderBin after View detach
+ // universe.addViewIdToFreeList(viewId);
+
+ // using new property -Dj3d.forceReleaseView to disable bug fix 4267395
+ // this bug fix can produce memory leaks in *some* applications which creates
+ // and destroy Canvas3D from time to time. This just add the view in the
+ // FreeList earlier.
+ if (VirtualUniverse.mc.forceReleaseView) {
+ universe.addViewIdToFreeList(viewId);
+ }
+
+
+ J3dMessage vpMessage = new J3dMessage();
+ vpMessage.universe = universe;
+ vpMessage.view = this;
+ vpMessage.type = J3dMessage.UPDATE_VIEW;
+ vpMessage.threads =
+ J3dThread.SOUND_SCHEDULER |
+ J3dThread.UPDATE_RENDER |
+ J3dThread.UPDATE_BEHAVIOR;
+ vpMessage.args[0] = this;
+ if (viewPlatform != null) {
+ synchronized(((ViewPlatformRetained)viewPlatform.retained).sphere) {
+ vpMessage.args[1] = new Float(((ViewPlatformRetained)viewPlatform.retained).sphere.radius);
+ }
+ } else {
+ vpMessage.args[1] = new Float(0);
+ }
+ vpMessage.args[2] = new Integer(OTHER_ATTRS_CHANGED);
+ vpMessage.args[3] = new Integer(transparencySortingPolicy);
+ VirtualUniverse.mc.processMessage(vpMessage);
+
+ }
+
+ void cleanupViewId() {
+ universe.addViewIdToFreeList(viewId);
+ viewId = null;
+ }
+
+
+ void assignViewId () {
+ if (viewId == null) {
+ viewId = universe.getViewId();
+ viewIndex = viewId.intValue();
+ }
+ }
+
+ /**
+ * This method passes window event to SoundScheduler
+ */
+ void sendEventToSoundScheduler(AWTEvent evt) {
+ if (soundScheduler != null) {
+ soundScheduler.receiveAWTEvent(evt);
+ }
+ }
+
+ void reset() {
+
+ for (int i=0; i < canvases.size(); i++) {
+ canvases.get(i).reset();
+ }
+
+ // reset the renderBinReady flag
+ renderBinReady = false;
+
+ soundScheduler.cleanup();
+ soundScheduler = null;
+
+ viewCache = new ViewCache(this);
+ getCanvasList(true);
+ cleanupViewId();
+ renderBin.cleanup();
+ renderBin = null;
+ universe = null;
+ }
+}