diff options
author | Harvey Harrison <[email protected]> | 2015-04-19 21:02:06 -0700 |
---|---|---|
committer | Harvey Harrison <[email protected]> | 2015-04-19 21:02:06 -0700 |
commit | 7a2e20caac9db6f789a7b3fab344b9758af45335 (patch) | |
tree | b5236ff2570178de356eab569225108948eb4d30 /src/javax/media/j3d/View.java | |
parent | f76ce302c4bb2a9f03bbee571ec5d05c29633023 (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.java | 3336 |
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; + } +} |