0001: /*
0002: * $RCSfile: View.java,v $
0003: *
0004: * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved.
0005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0006: *
0007: * This code is free software; you can redistribute it and/or modify it
0008: * under the terms of the GNU General Public License version 2 only, as
0009: * published by the Free Software Foundation. Sun designates this
0010: * particular file as subject to the "Classpath" exception as provided
0011: * by Sun in the LICENSE file that accompanied this code.
0012: *
0013: * This code is distributed in the hope that it will be useful, but WITHOUT
0014: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0015: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0016: * version 2 for more details (a copy is included in the LICENSE file that
0017: * accompanied this code).
0018: *
0019: * You should have received a copy of the GNU General Public License version
0020: * 2 along with this work; if not, write to the Free Software Foundation,
0021: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0022: *
0023: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0024: * CA 95054 USA or visit www.sun.com if you need additional information or
0025: * have any questions.
0026: *
0027: * $Revision: 1.13 $
0028: * $Date: 2008/02/28 20:17:32 $
0029: * $State: Exp $
0030: */
0031:
0032: package javax.media.j3d;
0033:
0034: import javax.vecmath.*;
0035: import java.util.Vector;
0036: import java.util.ArrayList;
0037: import java.util.LinkedList;
0038: import java.util.Iterator;
0039: import java.util.Enumeration;
0040: import java.awt.*;
0041: import com.sun.j3d.utils.universe.Viewer; // Needed for Support of DVR.
0042:
0043: /**
0044: * The View object contains all parameters needed in rendering a
0045: * three dimensional scene from one viewpoint. A view contains a list
0046: * of Canvas3D objects that the view is rendered into. It exists outside
0047: * of the scene graph, but attaches to a ViewPlatform leaf node object
0048: * in the scene graph. It also contains a reference to a PhysicalBody
0049: * and a PhysicalEnvironment object.
0050: * <P>
0051: * The View object is the main Java 3D object for controlling the
0052: * Java 3D viewing model. All of the components that specify the
0053: * view transform used to render to the 3D canvases are either contained
0054: * in the View object or in objects that are referenced by the View
0055: * object.
0056: * <P>
0057: * Java 3D allows applications to specify multiple simultaneously active
0058: * View objects, each controlling its own set of canvases.
0059: * <P>
0060: * The Java 3D View object has several instance variables and methods,
0061: * but most are calibration variables or user-helping functions. The
0062: * viewing policies defined by the View object are described below.
0063: * <P>
0064: * <b>Policies</b><P>
0065: *
0066: * The View object defines the following policies:<P>
0067: * <UL>
0068: * <LI>View policy - informs Java 3D whether it should generate
0069: * the view using the head-tracked system of transformations or the
0070: * head-mounted system of transformations. These policies are attached
0071: * to the Java 3D View object. There are two view policies:</LI><P>
0072: * <UL>
0073: * <LI>SCREEN_VIEW - specifies that Java 3D should compute a new
0074: * viewpoint using the sequence of transforms appropriate to screen-based
0075: * head-tracked display environments (fish-tank VR/portals/VR-desks).
0076: * This is the default setting.</LI><P>
0077: * <LI>HMD_VIEW - specifies that Java 3D should compute a new viewpoint
0078: * using the sequence of transforms appropriate to head mounted display
0079: * environments. This policy is not available in compatibility mode
0080: * (see the setCompatibilityModeEnable method description).</LI><P>
0081: * </UL>
0082: * <LI>Projection policy - specifies whether Java 3D should generate
0083: * a parallel projection or a perspective projection. This policy
0084: * is attached to the Java 3D View object. There are two projection
0085: * policies:</LI><P>
0086: * <UL>
0087: * <LI>PARALLEL_PROJECTION - specifies that a parallel projection
0088: * transform is computed.</LI><P>
0089: * <LI>PERSPECTIVE_PROJECTION - specifies that a perspective projection
0090: * transform is computed. This is the default policy.</LI><P>
0091: * </UL>
0092: * <LI>Screen scale policy - specifies where the screen scale comes from.
0093: * There are two screen scale policies:</LI><P>
0094: * <UL>
0095: * <LI>SCALE_SCREEN_SIZE - specifies that the scale is derived from the
0096: * physical screen according to the following formula (this is the
0097: * default mode):</LI>
0098: * <UL>
0099: * <code>screenScale = physicalScreenWidth / 2.0</code><P>
0100: * </UL>
0101: * <LI>SCALE_EXPLICIT - pecifies that the scale is taken directly from
0102: * the user-provided <code>screenScale</code> attribute (see the
0103: * setScreenScale method description).</LI><P>
0104: * </UL>
0105: * <LI>Window resize policy - specifies how Java 3D modifies the view
0106: * when users resize windows. When users resize or move windows,
0107: * Java 3D can choose to think of the window as attached either to
0108: * the physical world or to the virtual world. The window resize
0109: * policy allows an application to specify how the
0110: * view model will handle resizing requests.
0111: * There are two window resize policies:</LI><P>
0112: * <UL>
0113: * <LI>VIRTUAL_WORLD - implies that the original image remains the
0114: * same size on the screen but the user sees more or less of the
0115: * virtual world depending on whether the window grew or shrank
0116: * in size.</LI><P>
0117: * <LI>PHYSICAL_WORLD - implies that the original image continues
0118: * to fill the window in the same way using more or less pixels
0119: * depending on whether the window grew or shrank in size.</LI><P>
0120: * </UL>
0121: * <LI>Window movement policy - specifies what part of the virtual
0122: * world Java 3D draws as a function of window placement on the screen.
0123: * There are two window movement policies:</LI><P>
0124: * <UL>
0125: * <LI>VIRTUAL_WORLD - implies that the image seen in the window
0126: * changes as the position of the window shifts on the screen.
0127: * (This mode acts as if the window were a window into the virtual
0128: * world.)</LI><P>
0129: * <LI>PHYSICAL_WORLD - implies that the image seen in the window
0130: * remains the same no matter where the user positions the window
0131: * on the screen.</LI><P>
0132: * </UL>
0133: * <LI>Window eyepoint policy - comes into effect in a non-head-tracked
0134: * environment. The policy tells Java 3D how to construct a new view
0135: * frustum based on changes in the field of view and in the Canvas3D's
0136: * location on the screen. The policy only comes into effect when the
0137: * application changes a parameter that can change the placement of the
0138: * eyepoint relative to the view frustum.
0139: * There are three window eyepoint policies:</LI><P>
0140: * <UL>
0141: * <LI>RELATIVE_TO_SCREEN - tells Java 3D to interpret the eye's position
0142: * relative to the entire screen. No matter where an end user moves a
0143: * window (a Canvas3D), Java 3D continues to interpret the eye's position
0144: * relative to the screen. This implies that the view frustum changes shape
0145: * whenever an end user moves the location of a window on the screen.
0146: * In this mode, the field of view is read-only.</LI><P>
0147: * <LI>RELATIVE_TO_WINDOW - specifies that Java 3D should interpret the
0148: * eye's position information relative to the window (Canvas3D). No matter
0149: * where an end user moves a window (a Canvas3D), Java 3D continues to
0150: * interpret the eye's position relative to that window. This implies
0151: * that the frustum remains the same no matter where the end user
0152: * moves the window on the screen. In this mode, the field of view
0153: * is read-only.</LI><P>
0154: * <LI>RELATIVE_TO_FIELD_OF_VIEW - tells Java 3D that it should
0155: * modify the eyepoint position so it is located at the appropriate
0156: * place relative to the window to match the specified field of view.
0157: * This implies that the view frustum will change whenever the
0158: * application changes the field of view. In this mode, the eye
0159: * position is read-only. This is the default setting.</LI><P>
0160: * <LI>RELATIVE_TO_COEXISTENCE - tells Java 3D to interpret the eye's
0161: * position in coexistence coordinates. In this mode, the eye position
0162: * is taken from the view (rather than the Canvas3D) and transformed from
0163: * coexistence coordinates to image plate coordinates for each
0164: * Canvas3D. The resulting eye position is relative to the screen. As
0165: * in RELATIVE_TO_SCREEN mode, this implies that the view frustum
0166: * changes shape whenever an end user moves the location of a window
0167: * on the screen. In this mode, the field of view is
0168: * read-only.</LI><P>
0169: * </UL>
0170: * <LI>Front and back clip policies - specifies how Java 3D
0171: * interprets clipping distances to both the near and far clip
0172: * planes. The policies can contain one of four values specifying
0173: * whether a distance measurement should be interpreted in
0174: * the physical or the virtual world and whether that distance
0175: * measurement should be interpreted relative to the physical
0176: * eyepoint or the physical screen.
0177: * The front and back clip policies
0178: * are specified separately. The front clip policy determines
0179: * where Java 3D places the front clipping plane. The back clip
0180: * policy determines where Java 3D places the back clipping plane.
0181: * The values for both front and back clipping planes are:</LI><P>
0182: * <UL>
0183: * <LI>VIRTUAL_EYE - specifies that the associated distance is from
0184: * the eye and in units of virtual distance.</LI><P>
0185: * <LI>PHYSICAL_EYE - specifies that the associated distance is from
0186: * the eye and in units of physical distance (in meters).
0187: * This is the default policy for both front and back clipping.</LI><P>
0188: * <LI>VIRTUAL_SCREEN - specifies that the associated distance is
0189: * from the screen and in units of virtual distance. </LI><P>
0190: * <LI>PHYSICAL_SCREEN - specifies that the associated distance is
0191: * from the screen and in units of physical distance (in meters).
0192: * </LI><P>
0193: * </UL>
0194: * <LI>Visibility policy - specifies how visible and invisible objects
0195: * are drawn. There are three visibility policies:</LI><P>
0196: * <UL>
0197: * <LI>VISIBILITY_DRAW_VISIBLE - only visible objects are drawn
0198: * (this is the default).</LI><P>
0199: * <LI>VISIBILITY_DRAW_INVISIBLE - only invisible objects are drawn.</LI><P>
0200: * <LI>VISIBILITY_DRAW_ALL - both visible and invisible
0201: * objects are drawn. </LI><P>
0202: * </UL>
0203: * <LI>Transparency sorting policy - specifies whether and how
0204: * transparent objects are sorted. Sorting multiple transparent
0205: * objects is necessary to avoid artifacts caused by overlapping
0206: * transparent objects. There are two transparency sorting
0207: * policies:</LI><P>
0208: * <UL>
0209: * <LI>TRANSPARENCY_SORT_NONE - no depth sorting of transparent
0210: * objects is performed (this is the default). Transparent objects
0211: * are drawn after opaque objects, but are not sorted from back to
0212: * front.</LI><P>
0213: * <LI>TRANSPARENCY_SORT_GEOMETRY - transparent objects are
0214: * depth-sorted on a per-geometry basis. Each geometry object of each
0215: * transparent Shape3D node is drawn from back to front. Note that
0216: * this policy will not split geometry into smaller pieces, so
0217: * intersecting or intertwined objects may not be sorted
0218: * correctly. The method used for determining which geometry is closer
0219: * is implementation dependent.</LI><P>
0220: * </UL>
0221: * </UL>
0222: * <b>Projection and Clip Parameters</b><P>
0223: * The projection and clip parameters determine the view model's
0224: * field of view and the front and back clipping distances.<P>
0225: * <UL>
0226: * <LI>Field of view - specifies the view model's horizontal
0227: * field of view in radians, when in the default non-head-tracked
0228: * mode. This value is ignored when the view model is operating
0229: * in head-tracked mode, or when the Canvas3D's window eyepoint
0230: * policy is set to a value other than the default setting of
0231: * RELATIVE_TO_FIELD_OF_VIEW.</LI><P>
0232: * <LI>Front clip distance - specifies the distance away from the
0233: * clip origin, specified by the front clip policy variable, in
0234: * the direction of gaze where objects stop disappearing. Objects
0235: * closer than the clip origin (eye or screen)
0236: * plus the front clip distance are not drawn. Measurements are
0237: * done in the space (physical or virtual) that is specified by
0238: * the associated front clip policy parameter.</LI><P>
0239: * <LI>Back clip distance - specifies the distance away from the
0240: * clip origin (specified by the back clip policy variable) in the
0241: * direction of gaze where objects begin disappearing. Objects
0242: * farther away from the clip origin (eye or
0243: * screen) plus the back clip distance are not drawn.
0244: * Measurements are done in the space (physical or virtual) that
0245: * is specified by the associated back clip policy
0246: * parameter. The View object's back clip distance is ignored
0247: * if the scene graph contains an active Clip leaf node.</LI><P>
0248: * There are several considerations to take into account when
0249: * choosing values for the front and back clip distances.<P>
0250: * <UL>
0251: * <LI>The front clip distance must be greater than 0.0 in physical
0252: * eye coordinates.</LI><P>
0253: * <LI>The front clipping plane must be in front of the back clipping
0254: * plane, that is, the front clip distance must be less than the
0255: * back clip distance in physical eye coordinates.</LI><P>
0256: * <LI>The front and back clip distances, in physical eye coordinates,
0257: * must be less than the largest positive single-precision floating
0258: * point value, Float.MAX_VALUE. In practice, since these physical
0259: * eye coordinate distances are in meters, the values
0260: * should be much less than that.</LI><P>
0261: * <LI>The ratio of the back distance divided by the front distance,
0262: * in physical eye coordinates, affects Z-buffer precision. This ratio
0263: * should be less than about 3000 to accommodate 16-bit Z-buffers.
0264: * Values of 100 to less than 1000 will produce better results.</LI><P>
0265: * </UL>
0266: * Violating any of the above rules will result in undefined behavior.
0267: * In many cases, no picture will be drawn.<P>
0268: * </UL>
0269: * <b>Frame Start Time, Duration, and Number</b><P>
0270: *
0271: * There are five methods used to get information about system
0272: * execution and performance:<P>
0273: * <UL>
0274: * <code>getCurrentFrameStartTime</code> returns the time at which
0275: * the most recent rendering frame started.<P>
0276: * <code>getLastFrameDuration</code> returns the duration, in milliseconds, of
0277: * the most recently completed rendering frame.<P>
0278: * <code>getFrameNumber</code> returns the frame number for this view.<P>
0279: * <code>getMaxFrameStartTimes</code> retrieves the implementation-dependent
0280: * maximum number of frames whose start times will be recorded by
0281: * the system.<P>
0282: * <code>getFrameStartTimes</code> copies the last k frame start time values
0283: * into the user-specified array.<P>
0284: * </UL>
0285: * <b>View Traversal and Behavior Scheduling</b><P>
0286: * The following methods control the traversal, the rendering, and
0287: * the execution of the behavior scheduler for this view:<P>
0288: * <UL>
0289: * <code>startBehaviorScheduler</code> starts the behavior scheduler
0290: * running after it has been stopped.<P>
0291: * <code>stopBehaviorScheduler</code> stops the behavior scheduler after all
0292: * currently-scheduled behaviors are executed.<P>
0293: * <code>isBehaviorSchedulerRunning</code> retrieves a flag that indicates
0294: * whether the behavior scheduler is currently running.<P>
0295: * <code>startView</code> starts traversing this view and starts the renderers
0296: * associated with all canvases attached to this view.<P>
0297: * <code>stopView</code> stops traversing this view after the current state of
0298: * the scene graph is reflected on all canvases attached to this
0299: * view.<P>
0300: * <code>isViewRunning</code> returns a flag indicating whether the traverser
0301: * is currently running on this view.<P>
0302: * </UL>
0303: * Note: The above six methods are heavy-weight methods intended
0304: * for verification and image capture (recording). They are not
0305: * intended to be used for flow control.<P>
0306: *
0307: * <b>Scene Antialiasing</b><P>
0308: *
0309: * The following methods set and retrieve the scene antialiasing
0310: * flag. Scene antialiasing is either enabled or disabled for this
0311: * view. If enabled, the entire scene will be antialiased on each
0312: * canvas in which scene antialiasing is available. Scene
0313: * antialiasing is disabled by default.<P>
0314: * <UL>
0315: * <code>setSceneAntialiasingEnable</code> sets the scene antialiasing flag.<P>
0316: * <code>getSceneAntialiasingEnable</code> returns the scene antialiasing
0317: * flag.<P>
0318: * </UL>
0319: * Note that line and point antialiasing are independent of scene
0320: * antialiasing. If antialiasing is enabled for lines and points,
0321: * the lines and points will be antialiased prior to scene antialiasing.
0322: * If scene antialiasing is disabled, antialiased lines and points will
0323: * still be antialiased.
0324: * <p>
0325: * <b>Note:</b> Scene antialiasing is ignored in pure immediate mode,
0326: * but is supported in mixed-immediate mode.
0327: * <p>
0328: * <b>Depth Buffer</b><P>
0329: *
0330: * The following two methods enable and disable automatic freezing
0331: * of the depth buffer for objects rendered during the transparent
0332: * rendering pass (that is, objects rendered using alpha blending)
0333: * for this view. If enabled, depth buffer writes are disabled
0334: * during the transparent rendering pass regardless of the value
0335: * of the depth-buffer-write-enable flag in the RenderingAttributes
0336: * object for a particular node. This flag is enabled by default.<P>
0337: * <UL>
0338: * <code>setDepthBufferFreezeTransparent</code> enables depth buffer freezing.<P>
0339: * <code>getDepthBufferFreezeTransparent</code> retrieves the depth buffer
0340: * flag.<P>
0341: * </UL>
0342: * Transparent objects include BLENDED transparent primitives
0343: * and antialiased lines
0344: * and points. Transparent objects do not include opaque objects
0345: * or primitives rendered with SCREEN_DOOR transparency.<p>
0346: *
0347: * <b>Sensors</b><P>
0348: *
0349: * The following methods retrieve the sensor's location in the
0350: * virtual world:<P>
0351: * <UL>
0352: * <code>getSensorToVworld</code> takes the sensor's last reading and
0353: * generates a sensor-to-vworld coordinate system transform. This
0354: * Transform3D object takes points in that sensor's local coordinate
0355: * system and transforms them into virtual world coordinates.<P>
0356: *
0357: * <code>getSensorHotSpotInVworld</code> retrieves the specified sensor's
0358: * last hotspot location in virtual world coordinates.<P>
0359: * </UL>
0360: *
0361: * <b>Compatibility Mode</b><P>
0362: *
0363: * A camera-based view model allows application programmers to think
0364: * about the images displayed on the computer screen as if a virtual
0365: * camera took those images. Such a view model allows application
0366: * programmers to position and orient a virtual camera within a
0367: * virtual scene, to manipulate some parameters of the virtual
0368: * camera's lens (specify its field of view), and to specify the
0369: * locations of the near and far clipping planes.<P>
0370: * Java 3D allows applications to enable compatibility mode for
0371: * room-mounted, non-head-tracked display environments, or to disable
0372: * compatibility mode using the following methods. Camera-based
0373: * viewing functions are only available in compatibility mode.<P>
0374: * <UL>
0375: * <code>setCompatibilityModeEnable</code> turns compatibility mode on or off.
0376: * Compatibility mode is disabled by default.<P>
0377: * <code>getCompatabilityModeEnable</code> returns the compatibility mode
0378: * enable flag.<P>
0379: * </UL>
0380: * Use of these view-compatibility functions will disable some of
0381: * Java 3D's view model features and limit the portability of Java
0382: * 3D programs. These methods are primarily intended to help
0383: * jump-start porting of existing applications.<P>
0384: *
0385: * Setting the Viewing Transform<P>
0386: *
0387: * The View object provides the following compatibility-mode
0388: * methods that operate on the viewing transform.<P>
0389: * <UL>
0390: * <code>setVpcToEc</code> a compatibility mode method that
0391: * specifies the ViewPlatform
0392: * coordinates (VPC) to eye coordinates viewing transform.<P>
0393: * <code>getVpcToEc</code> returns the VPC.<P>
0394: * </UL>
0395: * Setting the Projection Transform
0396: * <p>
0397: * The View object provides the following compatibility-mode
0398: * methods that operate on the projection transform:<P>
0399: * <UL>
0400: * The <code>setLeftProjection</code> and <code>setRightProjection</code>
0401: * methods specify
0402: * a viewing frustum for the left and right eye that transforms
0403: * points in eye coordinates to clipping coordinates.<P>
0404: *
0405: * The <code>getLeftProjection</code> and <code>getRightProjection</code>
0406: * methods return
0407: * the viewing frustum for the left and right eye.<P>
0408: * </UL>
0409: *
0410: * <p>
0411: * <b>Additional Information</b>
0412: * <p>
0413: * For more information, see the
0414: * <a href="doc-files/intro.html">Introduction to the Java 3D API</a> and
0415: * <a href="doc-files/ViewModel.html">View Model</a>
0416: * documents.
0417: *
0418: * @see Canvas3D
0419: * @see PhysicalBody
0420: * @see PhysicalEnvironment
0421: * @see ViewPlatform
0422: * @see TransparencyAttributes
0423: */
0424:
0425: public class View extends Object {
0426: /**
0427: * Specifies a policy whereby the origin of physical or virtual
0428: * coordinates is relative to the position of the nominal head.
0429: * When used as a view attach policy, this sets the origin of view
0430: * platform coordinates to be at the eyepoint.
0431: * @see ViewPlatform#setViewAttachPolicy
0432: * @see PhysicalEnvironment#setCoexistenceCenterInPworldPolicy
0433: */
0434: public static final int NOMINAL_HEAD = 0;
0435:
0436: /**
0437: * Specifies a policy whereby the origin of physical or virtual
0438: * coordinates is relative to the position of the nominal feet.
0439: * When used as a view attach policy, this sets the origin of view
0440: * platform coordinates to be at the ground plane.
0441: * @see ViewPlatform#setViewAttachPolicy
0442: * @see PhysicalEnvironment#setCoexistenceCenterInPworldPolicy
0443: */
0444: public static final int NOMINAL_FEET = 1;
0445:
0446: /**
0447: * Specifies a policy whereby the origin of physical or virtual
0448: * coordinates is relative to the screen.
0449: * When used as a view attach policy, this sets the origin of view
0450: * platform coordinates to be at the center of the window or screen,
0451: * in effect, allowing the user to view objects from an optimal viewpoint.
0452: * @see ViewPlatform#setViewAttachPolicy
0453: * @see PhysicalEnvironment#setCoexistenceCenterInPworldPolicy
0454: */
0455: public static final int NOMINAL_SCREEN = 2;
0456:
0457: /**
0458: * Specifies that the screen scale for this view is derived from
0459: * the physical screen size. This scale factor is computed as follows:
0460: * <ul>
0461: * physical_screen_width / 2.0
0462: * </ul>
0463: * This allows an application to define a world in a normalized
0464: * [-1,1] space and view it on a screen of any size.
0465: * @see #setScreenScalePolicy
0466: */
0467: public static final int SCALE_SCREEN_SIZE = 0;
0468:
0469: /**
0470: * Specifies that the screen scale for this view is taken directly
0471: * from the user-provided screenScale parameter.
0472: * @see #setScreenScalePolicy
0473: * @see #setScreenScale
0474: */
0475: public static final int SCALE_EXPLICIT = 1;
0476:
0477: /**
0478: * Specifies that the associated distance is measured
0479: * from the screen in virtual world coordinates.
0480: * Policy for interpreting clip plane distances.
0481: * Used in specifying the policy in frontClipPolicy and backClipPolicy.
0482: * @see #setFrontClipPolicy
0483: * @see #setBackClipPolicy
0484: */
0485: public static final int VIRTUAL_SCREEN = 0;
0486:
0487: /**
0488: * Specifies that the associated distance is measured
0489: * from the screen in meters.
0490: * Policy for interpreting clip plane distances.
0491: * Used in specifying the policy in frontClipPolicy and backClipPolicy.
0492: * @see #setFrontClipPolicy
0493: * @see #setBackClipPolicy
0494: */
0495: public static final int PHYSICAL_SCREEN = 1;
0496:
0497: /**
0498: * Specifies that the associated distance is measured
0499: * from the eye in virtual world coordinates.
0500: * Policy for interpreting clip plane distances.
0501: * Used in specifying the policy in frontClipPolicy and backClipPolicy.
0502: * @see #setFrontClipPolicy
0503: * @see #setBackClipPolicy
0504: */
0505: public static final int VIRTUAL_EYE = 2;
0506:
0507: /**
0508: * Specifies that the associated distance is measured
0509: * from the eye in meters.
0510: * Policy for interpreting clip plane distances.
0511: * Used in specifying the policy in frontClipPolicy and backClipPolicy.
0512: * This is the default policy for both front and back clipping.
0513: * @see #setFrontClipPolicy
0514: * @see #setBackClipPolicy
0515: */
0516: public static final int PHYSICAL_EYE = 3;
0517:
0518: /**
0519: * Policy for resizing and moving windows.
0520: * Used in specifying windowResizePolicy and windowMovementPolicy.
0521: * VIRTUAL_WORLD specifies that the associated action takes place
0522: * in the virtual world as well as in the physical world.
0523: * @see #setWindowResizePolicy
0524: * @see #setWindowMovementPolicy
0525: */
0526: public static final int VIRTUAL_WORLD = 0;
0527:
0528: /**
0529: * Policy for resizing and moving windows.
0530: * Used in specifying windowResizePolicy and windowMovementPolicy.
0531: * PHYSICAL_WORLD specifies that the specified action takes place
0532: * only in the physical world.
0533: * @see #setWindowResizePolicy
0534: * @see #setWindowMovementPolicy
0535: */
0536: public static final int PHYSICAL_WORLD = 1;
0537:
0538: /**
0539: * Policy for placing the eyepoint in non-head-tracked modes.
0540: * Specifies that Java 3D should interpret the
0541: * given fixed eyepoint position as relative to the entire screen.
0542: * This implies
0543: * that the view frustum shape will change whenever a
0544: * user moves the location of a window on the screen.
0545: * @see #setWindowEyepointPolicy
0546: */
0547: public static final int RELATIVE_TO_SCREEN = 0;
0548:
0549: /**
0550: * Policy for placing the eyepoint in non-head-tracked modes.
0551: * Specifies that Java 3D should interpret the
0552: * given fixed-eyepoint position as relative to the window.
0553: * @see #setWindowEyepointPolicy
0554: */
0555: public static final int RELATIVE_TO_WINDOW = 1;
0556:
0557: /**
0558: * Policy for placing the eyepoint in non-head-tracked modes.
0559: * Specifies that Java 3D should
0560: * modify the position of the eyepoint to match any changes in field
0561: * of view; the view frustum will change whenever the application
0562: * program changes the field of view.
0563: * <p>
0564: * NOTE: when this policy is specified, the Z coordinate of
0565: * the derived eyepoint is used in place of
0566: * nominalEyeOffsetFromNominalScreen.
0567: * @see #setWindowEyepointPolicy
0568: */
0569: public static final int RELATIVE_TO_FIELD_OF_VIEW = 2;
0570:
0571: /**
0572: * Policy for placing the eyepoint in non-head-tracked modes.
0573: * Specifies that Java 3D should interpret the fixed eyepoint
0574: * position in the view as relative to the origin
0575: * of coexistence coordinates. This eyepoint is transformed from
0576: * coexistence coordinates to image plate coordinates for each
0577: * Canvas3D.
0578: * As in RELATIVE_TO_SCREEN mode, this implies
0579: * that the view frustum shape will change whenever a
0580: * user moves the location of a window on the screen.
0581: * @see #setWindowEyepointPolicy
0582: *
0583: * @since Java 3D 1.2
0584: */
0585: public static final int RELATIVE_TO_COEXISTENCE = 3;
0586:
0587: /**
0588: * Specifies that monoscopic view generated should be the view as seen
0589: * from the left eye.
0590: * @see Canvas3D#setMonoscopicViewPolicy
0591: */
0592: public static final int LEFT_EYE_VIEW = 0;
0593:
0594: /**
0595: * Specifies that monoscopic view generated should be the view as seen
0596: * from the right eye.
0597: * @see Canvas3D#setMonoscopicViewPolicy
0598: */
0599: public static final int RIGHT_EYE_VIEW = 1;
0600:
0601: /**
0602: * Specifies that monoscopic view generated should be the view as seen
0603: * from the 'center eye', the fictional eye half-way between the left and
0604: * right eye.
0605: * @see Canvas3D#setMonoscopicViewPolicy
0606: */
0607: public static final int CYCLOPEAN_EYE_VIEW = 2;
0608:
0609: /**
0610: * Specifies that the viewing environment for this view is a
0611: * standard screen-based display environment.
0612: * In this mode, Java 3D will compute new viewpoints
0613: * using that sequence of transforms appropriate to screen-based,
0614: * display environments, that may or may not include head tracking
0615: * (e.g., a monoscopic screen, fish-tank VR, portals, VR-desks).
0616: * This is the default mode.
0617: * @see #setViewPolicy
0618: */
0619: public static final int SCREEN_VIEW = 0;
0620:
0621: /**
0622: * Specifies that the viewing environment for this view is a
0623: * head-mounted display environment.
0624: * In this mode, Java 3D will compute new viewpoints
0625: * using that sequence of transforms appropriate to head-mounted display
0626: * environments. These environments are generally head-tracked.
0627: * @see #setViewPolicy
0628: */
0629: public static final int HMD_VIEW = 1;
0630:
0631: /**
0632: * Specifies that Java 3D should generate a parallel projection matrix
0633: * for this View.
0634: * @see #setProjectionPolicy
0635: */
0636: public static final int PARALLEL_PROJECTION = 0;
0637:
0638: /**
0639: * Specifies that Java 3D should generate a perspective projection matrix
0640: * for this View.
0641: * This is the default mode.
0642: * @see #setProjectionPolicy
0643: */
0644: public static final int PERSPECTIVE_PROJECTION = 1;
0645:
0646: /**
0647: * Policy that specifies that only visible objects should be drawn.
0648: * This is the default mode.
0649: * @see #setVisibilityPolicy
0650: *
0651: * @since Java 3D 1.2
0652: */
0653: public static final int VISIBILITY_DRAW_VISIBLE = 0;
0654:
0655: /**
0656: * Policy that specifies that only invisible objects should be drawn.
0657: * @see #setVisibilityPolicy
0658: *
0659: * @since Java 3D 1.2
0660: */
0661: public static final int VISIBILITY_DRAW_INVISIBLE = 1;
0662:
0663: /**
0664: * Policy that specifies that both visible and invisible objects
0665: * should be drawn.
0666: * @see #setVisibilityPolicy
0667: *
0668: * @since Java 3D 1.2
0669: */
0670: public static final int VISIBILITY_DRAW_ALL = 2;
0671:
0672: /**
0673: * Policy that specifies that no sorting of transparent objects
0674: * is done.
0675: * This is the default mode.
0676: * @see #setTransparencySortingPolicy
0677: *
0678: * @since Java 3D 1.3
0679: */
0680: public static final int TRANSPARENCY_SORT_NONE = 0;
0681:
0682: /**
0683: * Policy that specifies that transparent objects
0684: * are sorted from back to front on a per-geometry basis.
0685: * @see #setTransparencySortingPolicy
0686: *
0687: * @since Java 3D 1.3
0688: */
0689: public static final int TRANSPARENCY_SORT_GEOMETRY = 1;
0690:
0691: //
0692: // The AWT window for display.
0693: //
0694: // This object can be queried to obtain:
0695: // screen width in pixels
0696: // screen height in pixels
0697: // window width in pixels
0698: // window height in pixels
0699: // window upper left corner location in pixels relative to screen
0700: //
0701: // Use getCanvases() to access this
0702: private Vector canvases = new Vector(3);
0703:
0704: //
0705: // The current universe associated with this view
0706: //
0707: VirtualUniverse universe = null;
0708:
0709: //
0710: // The RenderBin associated with this view.
0711: //
0712: RenderBin renderBin = null;
0713:
0714: // This is the SoundScheduler associated with this view.
0715: SoundScheduler soundScheduler = null;
0716:
0717: // This is the thread associated with this view.
0718: SoundRenderer soundRenderer = new SoundRenderer();
0719:
0720: // AudioDevice enumerator current position
0721: // AudioDeviceEnumerator allAudioEnumerator = null;
0722:
0723: // These are used for tracking the frame times
0724: static final int NUMBER_FRAME_START_TIMES = 10;
0725:
0726: long[] frameStartTimes = new long[NUMBER_FRAME_START_TIMES];
0727: long[] frameNumbers = new long[NUMBER_FRAME_START_TIMES];
0728: int currentFrameIndex = 0;
0729:
0730: // These are the values that are set at the end of each frame
0731: long currentFrameStartTime = 0;
0732: long currentFrameDuration = 0;
0733: long currentFrameNumber = 0;
0734:
0735: // These are the ones that get updated directly by MC
0736: long frameNumber = 0;
0737: long startTime = 0;
0738: long stopTime = 0;
0739:
0740: // Support dynamic video resize -- DVR.
0741: Viewer viewer = null; // Cached the associate viewer of this view.
0742: boolean firstTime = true;
0743: // float dvrFactor = 1.0f;
0744: // boolean dvrResizeCompensation = true;
0745:
0746: // User adjustable minimum frame cycle time
0747: long minFrameCycleTime;
0748:
0749: // True when stopBehaviorScheduler invoke
0750: boolean stopBehavior;
0751:
0752: //
0753: // View cache for this view.
0754: //
0755: ViewCache viewCache = null;
0756:
0757: // Compatibility mode related field has changed.
0758: // { compatibilityModeEnable, compatVpcToEc, compatLeftProjection,
0759: // compatRightProjection }
0760: static final int COMPATIBILITY_MODE_DIRTY = 0x01;
0761: // ScreenScalePolicy field has changed.
0762: static final int SCREEN_SCALE_POLICY_DIRTY = 0x02;
0763: // Screen scale field has changed.
0764: static final int SCREEN_SCALE_DIRTY = 0x04;
0765: // Window Resize Policy field has changed.
0766: static final int WINDOW_RESIZE_POLICY_DIRTY = 0x08;
0767: // View Policy eye in image plate field has changed.
0768: static final int VIEW_POLICY_DIRTY = 0x10;
0769: // Clip related field has changed.
0770: // { frontClipDistance, backClipDistance, frontClipPolicy, backClipPolicy }
0771: static final int CLIP_DIRTY = 0x20;
0772: // Projection Policy field has changed.
0773: static final int PROJECTION_POLICY_DIRTY = 0x40;
0774: // Window Movement Policy field has changed.
0775: static final int WINDOW_MOVEMENT_POLICY_DIRTY = 0x80;
0776: // Window Eye Point Policy field has changed.
0777: static final int WINDOW_EYE_POINT_POLICY_DIRTY = 0x100;
0778: // Monoscopic View Policy field has changed.
0779: static final int MONOSCOPIC_VIEW_POLICY_DIRTY = 0x200;
0780: // Field Of View field has changed.
0781: static final int FIELD_OF_VIEW_DIRTY = 0x400;
0782: // Tracking Enable field has changed.
0783: static final int TRACKING_ENABLE_DIRTY = 0x800;
0784: // User Head To Vworld Enable field has changed.
0785: static final int USER_HEAD_TO_VWORLD_ENABLE_DIRTY = 0x1000;
0786: // coexistenceCenteringEnable flag has changed.
0787: static final int COEXISTENCE_CENTERING_ENABLE_DIRTY = 0x2000;
0788: // leftManualEyeInCoexistence has changed.
0789: static final int LEFT_MANUAL_EYE_IN_COEXISTENCE_DIRTY = 0x4000;
0790: // rightManualEyeInCoexistence has changed.
0791: static final int RIGHT_MANUAL_EYE_IN_COEXISTENCE_DIRTY = 0x8000;
0792: // visibilityPolicy has changed.
0793: static final int VISIBILITY_POLICY_DIRTY = 0x10000;
0794:
0795: // This is not from View object. It is here for the purpose
0796: // keeping all ViewCache's dirty mask bit declaration in one place.
0797: // ViewPlatformRetained viewAttach Policy field has changed.
0798: static final int VPR_VIEW_ATTACH_POLICY_DIRTY = 0x10000;
0799: static final int VPR_VIEWPLATFORM_DIRTY = 0x20000;
0800:
0801: // PhysicalEnvironment fields has changed.
0802: static final int PE_COE_TO_TRACKER_BASE_DIRTY = 0x100000;
0803: static final int PE_TRACKING_AVAILABLE_DIRTY = 0x200000;
0804: static final int PE_COE_CENTER_IN_PWORLD_POLICY_DIRTY = 0x400000;
0805:
0806: // PhysicalBody fields has changed.
0807: static final int PB_EYE_POSITION_DIRTY = 0x1000000;
0808: static final int PB_EAR_POSITION_DIRTY = 0x2000000;
0809: static final int PB_NOMINAL_EYE_HEIGHT_FROM_GROUND_DIRTY = 0x4000000;
0810: static final int PB_NOMINAL_EYE_OFFSET_FROM_NOMINAL_SCREEN_DIRTY = 0x8000000;
0811:
0812: // Mask that indicates this View's view dependence info. has changed,
0813: // and CanvasViewCache may need to recompute the final view matries.
0814: int vDirtyMask = (COMPATIBILITY_MODE_DIRTY
0815: | SCREEN_SCALE_POLICY_DIRTY | SCREEN_SCALE_DIRTY
0816: | WINDOW_RESIZE_POLICY_DIRTY | VIEW_POLICY_DIRTY
0817: | CLIP_DIRTY | PROJECTION_POLICY_DIRTY
0818: | WINDOW_MOVEMENT_POLICY_DIRTY
0819: | WINDOW_EYE_POINT_POLICY_DIRTY
0820: | MONOSCOPIC_VIEW_POLICY_DIRTY | FIELD_OF_VIEW_DIRTY
0821: | TRACKING_ENABLE_DIRTY | USER_HEAD_TO_VWORLD_ENABLE_DIRTY
0822: | COEXISTENCE_CENTERING_ENABLE_DIRTY
0823: | LEFT_MANUAL_EYE_IN_COEXISTENCE_DIRTY
0824: | RIGHT_MANUAL_EYE_IN_COEXISTENCE_DIRTY | VISIBILITY_POLICY_DIRTY);
0825:
0826: //
0827: // This object contains a specification of the user's physical body.
0828: //
0829: // Attributes of this object are defined in head coordinates and
0830: // include information such as the location of the user's eyes and
0831: // ears.
0832: // The origin is defined to be halfway between the left and right eye
0833: // in the plane of the face.
0834: // The x-axis extends to the right (of the head looking out from the head).
0835: // The y-axis extends up. The z-axis extends to the rear of the head.
0836: //
0837: PhysicalBody physicalBody;
0838:
0839: // This object contains a specification of the physical environment.
0840: PhysicalEnvironment physicalEnvironment;
0841:
0842: // View model compatibility mode flag
0843: boolean compatibilityModeEnable = false;
0844:
0845: // View model coexistenceCenteringEnable flag
0846: boolean coexistenceCenteringEnable = true;
0847:
0848: Point3d leftManualEyeInCoexistence = new Point3d();
0849: Point3d rightManualEyeInCoexistence = new Point3d();
0850:
0851: //
0852: // Indicates which major mode of view computation to use:
0853: // HMD mode or screen/fish-tank-VR mode.
0854: //
0855: int viewPolicy = SCREEN_VIEW;
0856:
0857: // The current projection policy (parallel versus perspective)
0858: int projectionPolicy = PERSPECTIVE_PROJECTION;
0859:
0860: //
0861: // The view model's field of view.
0862: //
0863: double fieldOfView = 45.0 * Math.PI / 180.0;
0864:
0865: //
0866: // The distance away from the clip origin
0867: // in the direction of gaze for the front and back clip planes.
0868: // The default values are in meters.
0869: //
0870: double frontClipDistance = 0.1;
0871: double backClipDistance = 10.0;
0872:
0873: // This variable specifies where the screen scale comes from
0874: int screenScalePolicy = SCALE_SCREEN_SIZE;
0875:
0876: // The screen scale value used when the screen scale policy is
0877: // SCALE_EXPLICIT
0878: double screenScale = 1.0;
0879:
0880: //
0881: // This variable specifies how Java 3D modifies the view when
0882: // the window is resized (VIRTUAL_WORLD or PHYSICAL_WORLD).
0883: //
0884: int windowResizePolicy = PHYSICAL_WORLD;
0885:
0886: //
0887: // This variable specifies how Java 3D modifies the view when
0888: // the window is moved (VIRTUAL_WORLD or PHYSICAL_WORLD).
0889: //
0890: int windowMovementPolicy = PHYSICAL_WORLD;
0891:
0892: //
0893: // Specifies how Java 3D handles the predefined eyepoint in
0894: // non-head-tracked environment (RELATIVE_TO_SCREEN,
0895: // RELATIVE_TO_WINDOW, RELATIVE_TO_FIELD_OF_VIEW, or
0896: // RELATIVE_TO_COEXISTENCE)
0897: //
0898: int windowEyepointPolicy = RELATIVE_TO_FIELD_OF_VIEW;
0899:
0900: //
0901: // Specifies how Java 3D generates monoscopic view
0902: // (LEFT_EYE_VIEW, RIGHT_EYE_VIEW, or CYCLOPEAN_EYE_VIEW).
0903: //
0904: int monoscopicViewPolicy = CYCLOPEAN_EYE_VIEW;
0905:
0906: /**
0907: * Defines the policy for placing the front clipping plane.
0908: * Legal values include PHYSICAL_EYE, PHYSICAL_SCREEN,
0909: * VIRTUAL_EYE, and VIRTUAL_SCREEN.
0910: */
0911: int frontClipPolicy = PHYSICAL_EYE;
0912:
0913: /**
0914: * Defines the policy for placing the back clipping plane.
0915: */
0916: int backClipPolicy = PHYSICAL_EYE;
0917:
0918: /**
0919: * Defines the visibility policy.
0920: */
0921: int visibilityPolicy = VISIBILITY_DRAW_VISIBLE;
0922:
0923: /**
0924: * Defines the transparency sorting policy.
0925: */
0926: int transparencySortingPolicy = TRANSPARENCY_SORT_NONE;
0927:
0928: /**
0929: * Flag to enable tracking, if so allowed by the trackingAvailable flag.
0930: */
0931: boolean trackingEnable = false;
0932:
0933: /**
0934: * This setting enables the continuous updating by Java 3D of the
0935: * userHeadToVworld transform.
0936: */
0937: boolean userHeadToVworldEnable = false;
0938:
0939: /**
0940: * The view platform currently associated with this view.
0941: */
0942: private ViewPlatform viewPlatform = null;
0943:
0944: // The current compatibility mode view transform
0945: Transform3D compatVpcToEc = new Transform3D();
0946:
0947: // The current compatibility mode projection transforms
0948: Transform3D compatLeftProjection = new Transform3D();
0949: Transform3D compatRightProjection = new Transform3D();
0950:
0951: // The long id of this view - used for dirty bit evaluation in the scene graph
0952: Integer viewId = null;
0953: int viewIndex = -1;
0954:
0955: // A boolean that indicates whether or not this is the primary view
0956: boolean primaryView = false;
0957:
0958: // A boolean that indicates whether or not this view is active as
0959: // seen by MasterControl
0960: boolean active = false;
0961:
0962: // A boolean that indicates whether or not this view is active as
0963: // seen by this view. There is a delay before MasterControl set
0964: // active flag, so a local activeStatus is used. Otherwise
0965: // activate event may lost if it proceed by deactivate event
0966: // but MC not yet set active to false. This happens in
0967: // viewplatform detach and attach.
0968: boolean activeStatus = false;
0969:
0970: // This boolean indicates whether or not the view is running. It
0971: // is used for startView/stopView
0972: volatile boolean isRunning = true;
0973:
0974: // A flag to indicate that we are in a canvas callback routine
0975: boolean inCanvasCallback = false;
0976:
0977: //
0978: // Flag to enable depth buffer freeze during trasparent rendering pass
0979: //
0980: boolean depthBufferFreezeTransparent = true;
0981:
0982: //
0983: // Flag to enable scene antialiasing
0984: //
0985: boolean sceneAntialiasingEnable = false;
0986:
0987: //
0988: // Flag to enable local eye lighting
0989: //
0990: boolean localEyeLightingEnable = false;
0991:
0992: // Array Lists to track the screens and canvases associated with this View.
0993: // use getScreens() to access this
0994: private ArrayList screenList = new ArrayList();
0995:
0996: // use getCanvasList() to access this
0997: private ArrayList canvasList = new ArrayList();
0998:
0999: private Canvas3D[][] cachedCanvasList;
1000: private Canvas3D[] cachedCanvases;
1001: private Screen3D[] cachedScreens;
1002: private int longestScreenList = 0;
1003: private boolean canvasesDirty = true;
1004:
1005: // Flag to notify user thread when renderOnce is finished
1006: volatile boolean renderOnceFinish = true;
1007:
1008: // Lock to synchronize start/stop/renderOnce call
1009: private Object startStopViewLock = new Object();
1010:
1011: // Lock for evaluateActive() only. This is used to prevent
1012: // using lock this which will cause deadlock when MC call
1013: // snapshot which waitForMC() in user thread.
1014: private Object evaluateLock = new Object();
1015:
1016: /**
1017: * use for stop view, when stopview, set to count -1,
1018: * when reach 1, call stopView() in MC and reset to -1.
1019: */
1020: int stopViewCount = -1;
1021:
1022: /**
1023: * False if current frame cycle time less than minimum frame cycle time
1024: */
1025: boolean isMinCycleTimeAchieve = true;
1026:
1027: // Time to sleep if minimum frame cycle time not achieve
1028: long sleepTime = 0;
1029:
1030: // use in pure immediate mode to tell whether this view rendering
1031: // thread is added in MC renderThreadData
1032: volatile boolean inRenderThreadData = false;
1033:
1034: // use to notify MC that render bin has run once, and is ready for
1035: // renderer to render
1036: boolean renderBinReady = false;
1037:
1038: // No of time setUniverse() is invoke
1039: long universeCount = 0;
1040:
1041: // The universe count when UNREGISTER_VIEW request is post,
1042: // this is used to distingish whether new setUniverse() is
1043: // invoked after UNREGISTER_VIEW request post to avoid
1044: // resetting the newly set universe.
1045: long resetUnivCount = 0;
1046:
1047: // This notify user thread waitForMC() to continue when
1048: // MC finish unregisterView
1049: volatile boolean doneUnregister = false;
1050:
1051: static final int TRANSP_SORT_POLICY_CHANGED = 0x0001;
1052: static final int OTHER_ATTRS_CHANGED = 0x0002;
1053:
1054: /**
1055: * Constructs a View object with default parameters. The default
1056: * values are as follows:
1057: * <ul>
1058: * view policy : SCREEN_VIEW<br>
1059: * projection policy : PERSPECTIVE_PROJECTION<br>
1060: * screen scale policy : SCALE_SCREEN_SIZE<br>
1061: * window resize policy : PHYSICAL_WORLD<br>
1062: * window movement policy : PHYSICAL_WORLD<br>
1063: * window eyepoint policy : RELATIVE_TO_FIELD_OF_VIEW<br>
1064: * monoscopic view policy : CYCLOPEAN_EYE_VIEW<br>
1065: * front clip policy : PHYSICAL_EYE<br>
1066: * back clip policy : PHYSICAL_EYE<br>
1067: * visibility policy : VISIBILITY_DRAW_VISIBLE<br>
1068: * transparency sorting policy : TRANSPARENCY_SORT_NONE<br>
1069: * coexistenceCentering flag : true<br>
1070: * compatibility mode : false<br>
1071: * left projection : identity<br>
1072: * right projection : identity<br>
1073: * vpc to ec transform : identity<br>
1074: * physical body : null<br>
1075: * physical environment : null<br>
1076: * screen scale : 1.0<br>
1077: * field of view : PI/4<br>
1078: * left manual eye in coexistence : (-0.033, 0.0, 0.4572)<br>
1079: * right manual eye in coexistence : (0.033, 0.0, 0.4572)<br>
1080: * front clip distance : 0.1<br>
1081: * back clip distance : 10.0<br>
1082: * tracking enable : false<br>
1083: * user head to vworld enable : false<br>
1084: * list of Canvas3D objects : empty<br>
1085: * depth buffer freeze transparent : true<br>
1086: * scene antialiasing : false<br>
1087: * local eye lighting : false<br>
1088: * view platform : null<br>
1089: * behavior scheduler running : true<br>
1090: * view running : true<br>
1091: * minimum frame cycle time : 0<br>
1092: * </ul>
1093: */
1094: public View() {
1095: viewCache = new ViewCache(this );
1096: }
1097:
1098: /**
1099: * Sets the policy for view computation.
1100: * This variable specifies how Java 3D uses its transforms in
1101: * computing new viewpoints.
1102: * <UL>
1103: * <LI>SCREEN_VIEW specifies that Java 3D should compute a new viewpoint
1104: * using the sequence of transforms appropriate to screen-based
1105: * head-tracked display environments (fish-tank VR/portals/VR-desks).
1106: * </LI>
1107: * <LI>HMD_VIEW specifies that Java 3D should compute a new viewpoint
1108: * using the sequence of transforms appropriate to head mounted
1109: * display environments.
1110: * </LI>
1111: * </UL>
1112: * The default view policy is SCREEN_VIEW.
1113: * @param policy the new policy, one of SCREEN_VIEW or HMD_VIEW
1114: * @exception IllegalArgumentException if policy is a value other than
1115: * SCREEN_VIEW or HMD_VIEW
1116: * @exception IllegalStateException if the specified policy
1117: * is HMD_VIEW and if any canvas associated with this view is
1118: * a stereo canvas with a monoscopicEyePolicy of CYCLOPEAN_EYE_VIEW
1119: */
1120: public void setViewPolicy(int policy) {
1121: if (policy != HMD_VIEW && policy != SCREEN_VIEW) {
1122:
1123: throw new IllegalArgumentException(J3dI18N
1124: .getString("View0"));
1125: }
1126: if (policy == HMD_VIEW) {
1127: // Check the following :
1128: // 1) If the view is in HMD mode and there exists a canvas in
1129: // CYCLOPEAN_EYE_VIEW mode then throw exception.
1130: synchronized (canvasList) {
1131: for (int i = canvases.size() - 1; i >= 0; i--) {
1132: Canvas3D c3d = (Canvas3D) canvases.elementAt(i);
1133:
1134: if ((c3d.monoscopicViewPolicy == View.CYCLOPEAN_EYE_VIEW)
1135: && (!c3d.useStereo)) {
1136: throw new IllegalStateException(J3dI18N
1137: .getString("View31"));
1138: }
1139: }
1140: }
1141: }
1142: synchronized (this ) {
1143: this .viewPolicy = policy;
1144: vDirtyMask |= View.VIEW_POLICY_DIRTY;
1145: }
1146: repaint();
1147: }
1148:
1149: /**
1150: * Retrieves the current view computation policy for this View.
1151: * @return one of: SCREEN_VIEW or HMD_VIEW.
1152: */
1153: public int getViewPolicy() {
1154: return this .viewPolicy;
1155: }
1156:
1157: /**
1158: * Sets the projection policy for this View.
1159: * This variable specifies the type of projection transform that
1160: * will be generated. A value of PARALLEL_PROJECTION specifies that
1161: * a parallel projection transform is generated. A value of
1162: * PERSPECTIVE_PROJECTION specifies that
1163: * a perspective projection transform is generated.
1164: * The default projection policy is PERSPECTIVE.
1165: * @param policy the new policy, one of PARALLEL_PROJECTION or
1166: * PERSPECTIVE_PROJECTION
1167: * @exception IllegalArgumentException if policy is a value other than
1168: * PARALLEL_PROJECTION or PERSPECTIVE_PROJECTION
1169: */
1170: public void setProjectionPolicy(int policy) {
1171: if (policy != PERSPECTIVE_PROJECTION
1172: && policy != PARALLEL_PROJECTION) {
1173:
1174: throw new IllegalArgumentException(J3dI18N
1175: .getString("View1"));
1176: }
1177: synchronized (this ) {
1178: this .projectionPolicy = policy;
1179: vDirtyMask |= View.PROJECTION_POLICY_DIRTY;
1180: }
1181:
1182: repaint();
1183: }
1184:
1185: /**
1186: * Retrieves the current projection policy for this View.
1187: * @return one of: PARALLEL_PROJECTION or PERSPECTIVE_PROJECTION.
1188: */
1189: public int getProjectionPolicy() {
1190: return this .projectionPolicy;
1191: }
1192:
1193: /**
1194: * Sets the screen scale policy for this view.
1195: * This policy specifies how the screen scale is derived.
1196: * The value is either SCALE_SCREEN_SIZE or SCALE_EXPLICIT.
1197: * A value of SCALE_SCREEN_SIZE specifies that the scale is derived
1198: * from the size of the physical screen. A value of SCALE_EXPLICIT
1199: * specifies that the scale is taken directly from the screenScale
1200: * parameter.
1201: * The default screen scale policy is SCALE_SCREEN_SIZE.
1202: * @param policy the new policy, one of SCALE_SCREEN_SIZE or
1203: * SCALE_EXPLICIT.
1204: */
1205: public void setScreenScalePolicy(int policy) {
1206:
1207: synchronized (this ) {
1208: this .screenScalePolicy = policy;
1209: vDirtyMask |= View.SCREEN_SCALE_POLICY_DIRTY;
1210: }
1211:
1212: repaint();
1213: }
1214:
1215: /**
1216: * Returns the current screen scale policy, one of:
1217: * SCALE_SCREEN_SIZE or SCALE_EXPLICIT.
1218: * @return the current screen scale policy
1219: */
1220: public int getScreenScalePolicy() {
1221: return this .screenScalePolicy;
1222: }
1223:
1224: /**
1225: * Sets the window resize policy.
1226: * This variable specifies how Java 3D modifies the view when
1227: * users resize windows. The variable can contain one of
1228: * VIRTUAL_WORLD or PHYSICAL_WORLD.
1229: * A value of VIRTUAL_WORLD implies that the original image
1230: * remains the same size on the screen but the user sees more
1231: * or less of the virtual world depending on whether the window
1232: * grew or shrank in size.
1233: * A value of PHYSICAL_WORLD implies that the original image
1234: * continues to fill the window in the same way using more or
1235: * less pixels depending on whether the window grew or shrank
1236: * in size.
1237: * The default window resize policy is PHYSICAL_WORLD.
1238: * @param policy the new policy, one of VIRTUAL_WORLD or PHYSICAL_WORLD
1239: */
1240: public void setWindowResizePolicy(int policy) {
1241:
1242: synchronized (this ) {
1243: this .windowResizePolicy = policy;
1244: vDirtyMask |= View.WINDOW_RESIZE_POLICY_DIRTY;
1245: }
1246: repaint();
1247: }
1248:
1249: /**
1250: * Returns the current window resize policy, one of:
1251: * VIRTUAL_WORLD or PHYSICAL_WORLD.
1252: * @return the current window resize policy
1253: */
1254: public int getWindowResizePolicy() {
1255: return this .windowResizePolicy;
1256: }
1257:
1258: /**
1259: * Sets the window movement policy.
1260: * This variable specifies what part of the virtual world Java 3D
1261: * draws as a function of window placement on the screen. The
1262: * variable can contain one of VIRTUAL_WORLD or PHYSICAL_WORLD.
1263: * A value of VIRTUAL_WORLD implies that the image seen in the
1264: * window changes as the position of the window shifts on the
1265: * screen. (This mode acts as if the window were a window into
1266: * the virtual world.)
1267: * A value of PHYSICAL_WORLD implies that the image seen in the
1268: * window remains the same no matter where the user positions
1269: * the window on the screen.
1270: * The default window movement policy is PHYSICAL_WORLD.
1271: * @param policy the new policy, one of VIRTUAL_WORLD or PHYSICAL_WORLD
1272: */
1273: public void setWindowMovementPolicy(int policy) {
1274:
1275: synchronized (this ) {
1276: this .windowMovementPolicy = policy;
1277: vDirtyMask |= View.WINDOW_MOVEMENT_POLICY_DIRTY;
1278: }
1279: repaint();
1280: }
1281:
1282: /**
1283: * Returns the current window movement policy,
1284: * one of: VIRTUAL_WORLD or PHYSICAL_WORLD.
1285: * @return the current window movement policy
1286: */
1287: public int getWindowMovementPolicy() {
1288: return this .windowMovementPolicy;
1289: }
1290:
1291: /**
1292: * Sets the view model's window eyepoint policy.
1293: * This variable specifies how Java 3D handles the predefined eye
1294: * point in a non-head-tracked environment. The variable can contain
1295: * one of:
1296: * <UL>
1297: * <LI>RELATIVE_TO_SCREEN, Java 3D should interpret the
1298: * given fixed-eyepoint position as relative to the screen (this
1299: * implies that the view frustum shape will change whenever a
1300: * user moves the location of a window on the screen).
1301: * </LI>
1302: * <LI>RELATIVE_TO_WINDOW, Java 3D should interpret the
1303: * given fixed-eyepoint position as relative to the window. In this
1304: * mode, the X and Y values are taken as the center of the window and
1305: * the Z value is taken from the canvas eyepoint position.
1306: * </LI>
1307: * <LI>RELATIVE_TO_FIELD_OF_VIEW, Java 3D should
1308: * modify the position of the eyepoint to match any changes in field
1309: * of view (the view frustum will change whenever the application
1310: * program changes the field of view).
1311: * </LI>
1312: * <LI>RELATIVE_TO_COEXISTENCE, Java 3D should interpret the eye's
1313: * position in coexistence coordinates. In this mode, the eye position
1314: * is taken from the view (rather than the Canvas3D) and transformed from
1315: * coexistence coordinates to image plate coordinates for each
1316: * Canvas3D. The resulting eye position is relative to the screen (this
1317: * implies that the view frustum shape will change whenever a
1318: * user moves the location of a window on the screen).
1319: * </LI>
1320: * </UL>
1321: * The default window eyepoint policy is RELATIVE_TO_FIELD_OF_VIEW.
1322: * @param policy the new policy, one of RELATIVE_TO_SCREEN,
1323: * RELATIVE_TO_WINDOW, RELATIVE_TO_FIELD_OF_VIEW, or
1324: * RELATIVE_TO_COEXISTENCE
1325: */
1326: public void setWindowEyepointPolicy(int policy) {
1327: synchronized (this ) {
1328: this .windowEyepointPolicy = policy;
1329: vDirtyMask |= View.WINDOW_EYE_POINT_POLICY_DIRTY;
1330: }
1331:
1332: repaint();
1333: }
1334:
1335: /**
1336: * Returns the current window eyepoint policy, one of:
1337: * RELATIVE_TO_SCREEN, RELATIVE_TO_WINDOW, RELATIVE_TO_FIELD_OF_VIEW or
1338: * RELATIVE_TO_COEXISTENCE.
1339: * @return the current window eyepoint policy
1340: */
1341: public int getWindowEyepointPolicy() {
1342: return this .windowEyepointPolicy;
1343: }
1344:
1345: /**
1346: * @deprecated As of Java 3D version 1.2, replaced by
1347: * <code>Canvas3D.setMonoscopicViewPolicy</code>
1348: */
1349: public void setMonoscopicViewPolicy(int policy) {
1350: synchronized (this ) {
1351: this .monoscopicViewPolicy = policy;
1352: vDirtyMask |= View.MONOSCOPIC_VIEW_POLICY_DIRTY;
1353: }
1354: repaint();
1355: }
1356:
1357: /**
1358: * @deprecated As of Java 3D version 1.2, replaced by
1359: * <code>Canvas3D.getMonoscopicViewPolicy</code>
1360: */
1361: public int getMonoscopicViewPolicy() {
1362: return this .monoscopicViewPolicy;
1363: }
1364:
1365: /**
1366: * Sets the coexistenceCentering enable flag to true or false.
1367: * If the coexistenceCentering flag is true, the center of
1368: * coexistence in image plate coordinates, as specified by the
1369: * trackerBaseToImagePlate transform, is translated to the center
1370: * of either the window or the screen in image plate coordinates,
1371: * according to the value of windowMovementPolicy.
1372: *
1373: * <p>
1374: * By default, coexistenceCentering is enabled. It should be
1375: * disabled if the trackerBaseToImagePlate calibration transform
1376: * is set to a value other than the identity (for example, when
1377: * rendering to multiple screens or when head tracking is
1378: * enabled). This flag is ignored for HMD mode, or when the
1379: * coexistenceCenterInPworldPolicy is <i>not</i>
1380: * NOMINAL_SCREEN.
1381: *
1382: * @param flag the new coexistenceCentering enable flag
1383: *
1384: * @since Java 3D 1.2
1385: */
1386: public void setCoexistenceCenteringEnable(boolean flag) {
1387: synchronized (this ) {
1388: this .coexistenceCenteringEnable = flag;
1389: vDirtyMask |= View.COEXISTENCE_CENTERING_ENABLE_DIRTY;
1390: }
1391: repaint();
1392: }
1393:
1394: /**
1395: * Retrieves the coexistenceCentering enable flag.
1396: *
1397: * @return the current coexistenceCentering enable flag
1398: *
1399: * @since Java 3D 1.2
1400: */
1401: public boolean getCoexistenceCenteringEnable() {
1402: return this .coexistenceCenteringEnable;
1403: }
1404:
1405: /**
1406: * Sets the compatibility mode enable flag to true or false.
1407: * Compatibility mode is disabled by default.
1408: * @param flag the new compatibility mode enable flag
1409: */
1410: public void setCompatibilityModeEnable(boolean flag) {
1411: synchronized (this ) {
1412: this .compatibilityModeEnable = flag;
1413: vDirtyMask |= View.COMPATIBILITY_MODE_DIRTY;
1414: }
1415: repaint();
1416: }
1417:
1418: /**
1419: * Retrieves the compatibility mode enable flag.
1420: * @return the current compatibility mode enable flag
1421: */
1422: public boolean getCompatibilityModeEnable() {
1423: return this .compatibilityModeEnable;
1424: }
1425:
1426: /**
1427: * Compatibility mode method that specifies a viewing frustum for
1428: * the left eye that transforms points in Eye Coordinates (EC) to
1429: * Clipping Coordinates (CC).
1430: * If compatibility mode is disabled, then this transform is not used;
1431: * the actual projection is derived from other values.
1432: * In monoscopic mode, only the left eye projection matrix is used.
1433: * @param projection the new left eye projection transform
1434: * @exception RestrictedAccessException if compatibility mode is disabled.
1435: */
1436: public void setLeftProjection(Transform3D projection) {
1437: if (!compatibilityModeEnable) {
1438: throw new RestrictedAccessException(J3dI18N
1439: .getString("View2"));
1440: }
1441:
1442: synchronized (this ) {
1443: compatLeftProjection.setWithLock(projection);
1444: vDirtyMask |= View.COMPATIBILITY_MODE_DIRTY;
1445: }
1446: repaint();
1447: }
1448:
1449: /**
1450: * Compatibility mode method that specifies a viewing frustum for
1451: * the right eye that transforms points in Eye Coordinates (EC) to
1452: * Clipping Coordinates (CC).
1453: * If compatibility mode is disabled, then this transform is not used;
1454: * the actual projection is derived from other values.
1455: * In monoscopic mode, the right eye projection matrix is ignored.
1456: * @param projection the new right eye projection transform
1457: * @exception RestrictedAccessException if compatibility mode is disabled.
1458: */
1459: public void setRightProjection(Transform3D projection) {
1460: if (!compatibilityModeEnable) {
1461: throw new RestrictedAccessException(J3dI18N
1462: .getString("View2"));
1463: }
1464:
1465: synchronized (this ) {
1466: compatRightProjection.setWithLock(projection);
1467: vDirtyMask |= View.COMPATIBILITY_MODE_DIRTY;
1468: }
1469:
1470: repaint();
1471: }
1472:
1473: /**
1474: * Compatibility mode method that retrieves the current
1475: * compatibility mode projection transform for the left eye and
1476: * places it into the specified object.
1477: * @param projection the Transform3D object that will receive the
1478: * projection
1479: * @exception RestrictedAccessException if compatibility mode is disabled.
1480: */
1481: public void getLeftProjection(Transform3D projection) {
1482: if (!compatibilityModeEnable) {
1483: throw new RestrictedAccessException(J3dI18N
1484: .getString("View4"));
1485: }
1486:
1487: projection.set(compatLeftProjection);
1488: }
1489:
1490: /**
1491: * Compatibility mode method that retrieves the current
1492: * compatibility mode projection transform for the right eye and
1493: * places it into the specified object.
1494: * @param projection the Transform3D object that will receive the
1495: * projection
1496: * @exception RestrictedAccessException if compatibility mode is disabled.
1497: */
1498: public void getRightProjection(Transform3D projection) {
1499: if (!compatibilityModeEnable) {
1500: throw new RestrictedAccessException(J3dI18N
1501: .getString("View4"));
1502: }
1503:
1504: projection.set(compatRightProjection);
1505: }
1506:
1507: /**
1508: * Compatibility mode method that specifies the ViewPlatform
1509: * Coordinates (VPC) to Eye Coordinates (EC) transform.
1510: * If compatibility mode is disabled, then this transform
1511: * is derived from other values and is read-only.
1512: * @param vpcToEc the new VPC to EC transform
1513: * @exception RestrictedAccessException if compatibility mode is disabled.
1514: * @exception BadTransformException if the transform is not affine.
1515: */
1516: public void setVpcToEc(Transform3D vpcToEc) {
1517: if (!compatibilityModeEnable) {
1518: throw new RestrictedAccessException(J3dI18N
1519: .getString("View6"));
1520: }
1521:
1522: if (!vpcToEc.isAffine()) {
1523: throw new BadTransformException(J3dI18N.getString("View7"));
1524: }
1525:
1526: synchronized (this ) {
1527: compatVpcToEc.setWithLock(vpcToEc);
1528: vDirtyMask |= View.COMPATIBILITY_MODE_DIRTY;
1529: }
1530:
1531: repaint();
1532: }
1533:
1534: /**
1535: * Compatibility mode method that retrieves the current
1536: * ViewPlatform Coordinates (VPC) system to
1537: * Eye Coordinates (EC) transform and copies it into the specified
1538: * object.
1539: * @param vpcToEc the object that will receive the vpcToEc transform.
1540: * @exception RestrictedAccessException if compatibility mode is disabled.
1541: */
1542: public void getVpcToEc(Transform3D vpcToEc) {
1543: if (!compatibilityModeEnable) {
1544: throw new RestrictedAccessException(J3dI18N
1545: .getString("View8"));
1546: }
1547:
1548: vpcToEc.set(compatVpcToEc);
1549: }
1550:
1551: /**
1552: * Sets the view model's physical body to the PhysicalBody object provided.
1553: * Java 3D uses the parameters in the PhysicalBody to ensure accurate
1554: * image and sound generation when in head-tracked mode.
1555: * @param physicalBody the new PhysicalBody object
1556: */
1557: public void setPhysicalBody(PhysicalBody physicalBody) {
1558: // need to synchronize variable activateStatus
1559: synchronized (canvasList) {
1560: if (activeStatus) {
1561: if (this .physicalBody != null) {
1562: this .physicalBody.removeUser(this );
1563: }
1564: physicalBody.addUser(this );
1565: }
1566: }
1567: this .physicalBody = physicalBody;
1568: repaint();
1569: }
1570:
1571: /**
1572: * Returns a reference to the view model's PhysicalBody object.
1573: * @return the view object's PhysicalBody object
1574: */
1575: public PhysicalBody getPhysicalBody() {
1576: return this .physicalBody;
1577: }
1578:
1579: /**
1580: * Sets the view model's physical environment to the PhysicalEnvironment
1581: * object provided.
1582: * @param physicalEnvironment the new PhysicalEnvironment object
1583: */
1584: public void setPhysicalEnvironment(
1585: PhysicalEnvironment physicalEnvironment) {
1586: synchronized (canvasList) {
1587: if (activeStatus) {
1588: if (this .physicalEnvironment != null) {
1589: this .physicalEnvironment.removeUser(this );
1590: }
1591: physicalEnvironment.addUser(this );
1592: }
1593: }
1594: this .physicalEnvironment = physicalEnvironment;
1595:
1596: if ((viewPlatform != null) && viewPlatform.isLive()) {
1597: VirtualUniverse.mc.postRequest(
1598: MasterControl.PHYSICAL_ENV_CHANGE, this );
1599: }
1600: repaint();
1601: }
1602:
1603: /**
1604: * Returns a reference to the view model's PhysicalEnvironment object.
1605: * @return the view object's PhysicalEnvironment object
1606: */
1607: public PhysicalEnvironment getPhysicalEnvironment() {
1608: return this .physicalEnvironment;
1609: }
1610:
1611: /**
1612: * Sets the screen scale value for this view.
1613: * This is used when the screen scale policy is SCALE_EXPLICIT.
1614: * The default value is 1.0 (i.e., unscaled).
1615: * @param scale the new screen scale
1616: */
1617: public void setScreenScale(double scale) {
1618: synchronized (this ) {
1619: this .screenScale = scale;
1620: vDirtyMask |= View.SCREEN_SCALE_DIRTY;
1621: }
1622: repaint();
1623: }
1624:
1625: /**
1626: * Returns the current screen scale value
1627: * @return the current screen scale value
1628: */
1629: public double getScreenScale() {
1630: return this .screenScale;
1631: }
1632:
1633: /**
1634: * Sets the field of view used to compute the projection transform.
1635: * This is used when head tracking is disabled and when the Canvas3D's
1636: * windowEyepointPolicy is RELATIVE_TO_FIELD_OF_VIEW.
1637: * @param fieldOfView the new field of view in radians
1638: */
1639: public void setFieldOfView(double fieldOfView) {
1640: synchronized (this ) {
1641: this .fieldOfView = fieldOfView;
1642: vDirtyMask |= View.FIELD_OF_VIEW_DIRTY;
1643: }
1644: repaint();
1645:
1646: }
1647:
1648: /**
1649: * Returns the current field of view.
1650: * @return the current field of view in radians
1651: */
1652: public double getFieldOfView() {
1653: return this .fieldOfView;
1654: }
1655:
1656: /**
1657: * Sets the position of the manual left eye in coexistence
1658: * coordinates. This value determines eye placement when a head
1659: * tracker is not in use and the application is directly controlling
1660: * the eye position in coexistence coordinates. This value is
1661: * ignored when in head-tracked mode or when the
1662: * windowEyePointPolicy is <i>not</i> RELATIVE_TO_COEXISTENCE.
1663: *
1664: * @param position the new manual left eye position
1665: *
1666: * @since Java 3D 1.2
1667: */
1668: public void setLeftManualEyeInCoexistence(Point3d position) {
1669: synchronized (this ) {
1670: leftManualEyeInCoexistence.set(position);
1671: vDirtyMask |= View.LEFT_MANUAL_EYE_IN_COEXISTENCE_DIRTY;
1672: }
1673: repaint();
1674: }
1675:
1676: /**
1677: * Sets the position of the manual right eye in coexistence
1678: * coordinates. This value determines eye placement when a head
1679: * tracker is not in use and the application is directly controlling
1680: * the eye position in coexistence coordinates. This value is
1681: * ignored when in head-tracked mode or when the
1682: * windowEyePointPolicy is <i>not</i> RELATIVE_TO_COEXISTENCE.
1683: *
1684: * @param position the new manual right eye position
1685: *
1686: * @since Java 3D 1.2
1687: */
1688: public void setRightManualEyeInCoexistence(Point3d position) {
1689: synchronized (this ) {
1690: rightManualEyeInCoexistence.set(position);
1691: vDirtyMask |= View.RIGHT_MANUAL_EYE_IN_COEXISTENCE_DIRTY;
1692: }
1693: repaint();
1694: }
1695:
1696: /**
1697: * Retrieves the position of the user-specified, manual left eye
1698: * in coexistence
1699: * coordinates and copies that value into the object provided.
1700: * @param position the object that will receive the position
1701: *
1702: * @since Java 3D 1.2
1703: */
1704: public void getLeftManualEyeInCoexistence(Point3d position) {
1705: position.set(leftManualEyeInCoexistence);
1706: }
1707:
1708: /**
1709: * Retrieves the position of the user-specified, manual right eye
1710: * in coexistence
1711: * coordinates and copies that value into the object provided.
1712: * @param position the object that will receive the position
1713: *
1714: * @since Java 3D 1.2
1715: */
1716: public void getRightManualEyeInCoexistence(Point3d position) {
1717: position.set(rightManualEyeInCoexistence);
1718: }
1719:
1720: /**
1721: * Sets the view model's front clip distance.
1722: * This value specifies the distance away from the eyepoint
1723: * in the direction of gaze where objects stop disappearing.
1724: * Objects closer to the eye than the front clip
1725: * distance are not drawn. The default value is 0.1 meters.
1726: * <p>
1727: * There are several considerations that need to be taken into
1728: * account when choosing values for the front and back clip
1729: * distances.
1730: * <ul>
1731: * <li>The front clip distance must be greater than
1732: * 0.0 in physical eye coordinates.</li>
1733: * <li>The front clipping plane must be in front of the
1734: * back clipping plane, that is, the front clip distance
1735: * must be less than the back clip distance in physical eye
1736: * coordinates.</li>
1737: * <li>The front and back clip distances, in physical
1738: * eye coordinates, must be less than the largest positive
1739: * single-precision floating point value, <code>Float.MAX_VALUE</code>.
1740: * In practice, since these physical eye coordinate distances are in
1741: * meters, the values should be <i>much</i> less than that.
1742: * <li>The ratio of the back distance divided by the front distance,
1743: * in physical eye coordinates, affects Z-buffer precision. This
1744: * ratio should be less than about 3000 in order to accommodate 16-bit
1745: * Z-buffers. Values of 100 to less than 1000 will produce better
1746: * results.</li>
1747: * </ul>
1748: * Violating any of the above rules will result in undefined
1749: * behavior. In many cases, no picture will be drawn.
1750: *
1751: * @param distance the new front clip distance
1752: * @see #setBackClipDistance
1753: */
1754: public void setFrontClipDistance(double distance) {
1755: synchronized (this ) {
1756: this .frontClipDistance = distance;
1757: vDirtyMask |= View.CLIP_DIRTY;
1758: }
1759: repaint();
1760: }
1761:
1762: /**
1763: * Returns the view model's front clip distance.
1764: * @return the current front clip distance
1765: */
1766: public double getFrontClipDistance() {
1767: return this .frontClipDistance;
1768: }
1769:
1770: /**
1771: * Sets the view model's back clip distance.
1772: * The parameter specifies the distance from the eyepoint
1773: * in the direction of gaze to where objects begin disappearing.
1774: * Objects farther away from the eye than the
1775: * back clip distance are not drawn.
1776: * The default value is 10.0 meters.
1777: * <p>
1778: * There are several considerations that need to be taken into
1779: * account when choosing values for the front and back clip
1780: * distances. These are enumerated in the description of
1781: * <a href=#setFrontClipDistance(double)>setFrontClipDistance</a>.
1782: * <p>
1783: * Note that this attribute is only used if there is no Clip node
1784: * that is in scope of the view platform associated with this view.
1785: * @param distance the new back clip distance
1786: * @see #setFrontClipDistance
1787: * @see Clip#setBackDistance
1788: */
1789: public void setBackClipDistance(double distance) {
1790: synchronized (this ) {
1791: this .backClipDistance = distance;
1792: vDirtyMask |= View.CLIP_DIRTY;
1793: }
1794: repaint();
1795: }
1796:
1797: /**
1798: * Returns the view model's back clip distance.
1799: * @return the current back clip distance
1800: */
1801: public double getBackClipDistance() {
1802: return this .backClipDistance;
1803: }
1804:
1805: /**
1806: * Retrieves the user-head to virtual-world transform
1807: * and copies that value into the transform provided.
1808: * @param t the Transform3D object that will receive the transform
1809: */
1810: public void getUserHeadToVworld(Transform3D t) {
1811:
1812: if (userHeadToVworldEnable) {
1813:
1814: // get the calculated userHeadToVworld transform
1815: // from the view cache.
1816: // grab the first canvas -- not sure for multiple canvases
1817: Canvas3D canvas = (Canvas3D) this .canvases.firstElement();
1818: synchronized (canvas.canvasViewCache) {
1819: t.set(canvas.canvasViewCache.getHeadToVworld());
1820: }
1821: } else {
1822: throw new RestrictedAccessException(J3dI18N
1823: .getString("View9"));
1824: }
1825: }
1826:
1827: /**
1828: * Sets the view model's front clip policy, the policy Java 3D uses
1829: * in computing where to place the front clip plane. The variable
1830: * can contain one of:
1831: * <UL>
1832: * <LI>VIRTUAL_EYE, to specify that the associated distance is
1833: * from the eye and in units of virtual distance
1834: * </LI>
1835: * <LI>PHYSICAL_EYE, to specify that the associated distance is
1836: * from the eye and in units of physical distance (meters)
1837: * </LI>
1838: * <LI>VIRTUAL_SCREEN, to specify that the associated distance is
1839: * from the screen and in units of virtual distance
1840: * </LI>
1841: * <LI>PHYSICAL_SCREEN, to specify that the associated distance is
1842: * from the screen and in units of physical distance (meters)
1843: * </LI>
1844: * </UL>
1845: * The default front clip policy is PHYSICAL_EYE.
1846: * @param policy the new policy, one of PHYSICAL_EYE, PHYSICAL_SCREEN,
1847: * VIRTUAL_EYE, or VIRTUAL_SCREEN
1848: */
1849: public void setFrontClipPolicy(int policy) {
1850: synchronized (this ) {
1851: this .frontClipPolicy = policy;
1852: vDirtyMask |= View.CLIP_DIRTY;
1853: }
1854: repaint();
1855: }
1856:
1857: /**
1858: * Returns the view model's current front clip policy.
1859: * @return one of:
1860: * VIRTUAL_EYE, PHYSICAL_EYE, VIRTUAL_SCREEN, or PHYSICAL_SCREEN
1861: */
1862: public int getFrontClipPolicy() {
1863: return this .frontClipPolicy;
1864: }
1865:
1866: /**
1867: * Sets the view model's back clip policy, the policy Java 3D uses
1868: * in computing where to place the back clip plane. The variable
1869: * can contain one of:
1870: * <UL>
1871: * <LI>VIRTUAL_EYE, to specify that the associated distance is
1872: * from the eye and in units of virtual distance
1873: * </LI>
1874: * <LI>PHYSICAL_EYE, to specify that the associated distance is
1875: * from the eye and in units of physical distance (meters)
1876: * </LI>
1877: * <LI>VIRTUAL_SCREEN, to specify that the associated distance is
1878: * from the screen and in units of virtual distance
1879: * </LI>
1880: * <LI>PHYSICAL_SCREEN, to specify that the associated distance is
1881: * from the screen and in units of physical distance (meters)
1882: * </LI>
1883: * </UL>
1884: * The default back clip policy is PHYSICAL_EYE.
1885: * @param policy the new policy, one of PHYSICAL_EYE, PHYSICAL_SCREEN,
1886: * VIRTUAL_EYE, or VIRTUAL_SCREEN
1887: */
1888: public void setBackClipPolicy(int policy) {
1889: synchronized (this ) {
1890: this .backClipPolicy = policy;
1891: vDirtyMask |= View.CLIP_DIRTY;
1892: }
1893: repaint();
1894: }
1895:
1896: /**
1897: * Returns the view model's current back clip policy.
1898: * @return one of:
1899: * VIRTUAL_EYE, PHYSICAL_EYE, VIRTUAL_SCREEN, or PHYSICAL_SCREEN
1900: */
1901: public int getBackClipPolicy() {
1902: return this .backClipPolicy;
1903: }
1904:
1905: /**
1906: * Sets the visibility policy for this view. This attribute
1907: * is one of:
1908: * <UL>
1909: * <LI>VISIBILITY_DRAW_VISIBLE, to specify that only visible objects
1910: * are drawn.
1911: * </LI>
1912: * <LI>VISIBILITY_DRAW_INVISIBLE, to specify that only invisible objects
1913: * are drawn.
1914: * </LI>
1915: * <LI>VISIBILITY_DRAW_ALL, to specify that both visible and
1916: * invisible objects are drawn.
1917: * </LI>
1918: * </UL>
1919: * The default visibility policy is VISIBILITY_DRAW_VISIBLE.
1920: *
1921: * @param policy the new policy, one of VISIBILITY_DRAW_VISIBLE,
1922: * VISIBILITY_DRAW_INVISIBLE, or VISIBILITY_DRAW_ALL.
1923: *
1924: * @see RenderingAttributes#setVisible
1925: *
1926: * @since Java 3D 1.2
1927: */
1928: public void setVisibilityPolicy(int policy) {
1929:
1930: synchronized (this ) {
1931: this .visibilityPolicy = policy;
1932: vDirtyMask |= View.VISIBILITY_POLICY_DIRTY;
1933: }
1934:
1935: if (activeStatus && isRunning) {
1936:
1937: J3dMessage vpMessage = new J3dMessage();
1938: vpMessage.universe = universe;
1939: vpMessage.view = this ;
1940: vpMessage.type = J3dMessage.UPDATE_VIEW;
1941: vpMessage.threads = J3dThread.UPDATE_RENDER;
1942: vpMessage.args[0] = this ;
1943: synchronized (((ViewPlatformRetained) viewPlatform.retained).sphere) {
1944: vpMessage.args[1] = new Float(
1945: ((ViewPlatformRetained) viewPlatform.retained).sphere.radius);
1946: }
1947: vpMessage.args[2] = new Integer(OTHER_ATTRS_CHANGED);
1948: vpMessage.args[3] = new Integer(transparencySortingPolicy);
1949: VirtualUniverse.mc.processMessage(vpMessage);
1950: }
1951: }
1952:
1953: /**
1954: * Retrieves the current visibility policy.
1955: * @return one of:
1956: * VISIBILITY_DRAW_VISIBLE,
1957: * VISIBILITY_DRAW_INVISIBLE, or VISIBILITY_DRAW_ALL.
1958: *
1959: * @since Java 3D 1.2
1960: */
1961: public int getVisibilityPolicy() {
1962: return this .visibilityPolicy;
1963: }
1964:
1965: /**
1966: * Sets the transparency sorting policy for this view. This attribute
1967: * is one of:
1968: *
1969: * <UL>
1970: * <LI>TRANSPARENCY_SORT_NONE, to specify that no depth sorting of
1971: * transparent objects is performed. Transparent objects are
1972: * drawn after opaque objects, but are not sorted from back to
1973: * front.</LI>
1974: *
1975: * <LI>TRANSPARENCY_SORT_GEOMETRY, to specify that transparent
1976: * objects are depth-sorted on a per-geometry basis. Each
1977: * geometry object of each transparent Shape3D node is drawn from
1978: * back to front. Note that this policy will not split geometry
1979: * into smaller pieces, so intersecting or intertwined objects may
1980: * not be sorted correctly.</LI>
1981: * </UL>
1982: *
1983: * The default policy is TRANSPARENCY_SORT_NONE.
1984: *
1985: * @param policy the new policy, one of TRANSPARENCY_SORT_NONE
1986: * or TRANSPARENCY_SORT_GEOMETRY.
1987: *
1988: * @since Java 3D 1.3
1989: */
1990: public void setTransparencySortingPolicy(int policy) {
1991: if (policy == transparencySortingPolicy) {
1992: return;
1993: }
1994:
1995: transparencySortingPolicy = policy;
1996: if (activeStatus && isRunning) {
1997:
1998: J3dMessage vpMessage = new J3dMessage();
1999: vpMessage.universe = universe;
2000: vpMessage.view = this ;
2001: vpMessage.type = J3dMessage.UPDATE_VIEW;
2002: vpMessage.threads = J3dThread.UPDATE_RENDER;
2003: vpMessage.args[0] = this ;
2004: vpMessage.args[1] = null;
2005: vpMessage.args[2] = new Integer(TRANSP_SORT_POLICY_CHANGED);
2006: vpMessage.args[3] = new Integer(policy);
2007: VirtualUniverse.mc.processMessage(vpMessage);
2008: }
2009: }
2010:
2011: /**
2012: * Retrieves the current transparency sorting policy.
2013: * @return one of:
2014: * TRANSPARENCY_SORT_NONE or TRANSPARENCY_SORT_GEOMETRY.
2015: *
2016: * @since Java 3D 1.3
2017: */
2018: public int getTransparencySortingPolicy() {
2019: return this .transparencySortingPolicy;
2020: }
2021:
2022: /**
2023: * Turns head tracking on or off for this view.
2024: * @param flag specifies whether head tracking is enabled or
2025: * disabled for this view
2026: */
2027: public void setTrackingEnable(boolean flag) {
2028:
2029: synchronized (this ) {
2030: this .trackingEnable = flag;
2031: vDirtyMask |= View.TRACKING_ENABLE_DIRTY;
2032: }
2033:
2034: repaint();
2035: }
2036:
2037: /**
2038: * Returns a status flag indicating whether or not head tracking
2039: * is enabled.
2040: * @return a flag telling whether head tracking is enabled
2041: */
2042: public boolean getTrackingEnable() {
2043: return this .trackingEnable;
2044: }
2045:
2046: /**
2047: * Turns on or off the continuous
2048: * updating of the userHeadToVworld transform.
2049: * @param flag enables or disables continuous updating
2050: */
2051: public void setUserHeadToVworldEnable(boolean flag) {
2052:
2053: synchronized (this ) {
2054: userHeadToVworldEnable = flag;
2055: vDirtyMask |= View.USER_HEAD_TO_VWORLD_ENABLE_DIRTY;
2056: }
2057: repaint();
2058: }
2059:
2060: /**
2061: * Returns a status flag indicating whether or not
2062: * Java 3D is continuously updating the userHeadToVworldEnable transform.
2063: * @return a flag indicating if continuously updating userHeadToVworld
2064: */
2065: public boolean getUserHeadToVworldEnable() {
2066: return userHeadToVworldEnable;
2067: }
2068:
2069: /**
2070: * Computes the sensor to virtual-world transform
2071: * and copies that value into the transform provided.
2072: * The computed transforms takes points in the sensor's coordinate
2073: * system and produces the point's corresponding value in
2074: * virtual-world coordinates.
2075: * @param sensor the sensor in question
2076: * @param t the object that will receive the transform
2077: */
2078: public void getSensorToVworld(Sensor sensor, Transform3D t) {
2079: // grab the first canvas -- not sure for multiple canvases
2080: Canvas3D canvas = (Canvas3D) this .canvases.firstElement();
2081: Transform3D localTrans = new Transform3D();
2082: synchronized (canvas.canvasViewCache) {
2083: t.set(canvas.canvasViewCache.getVworldToTrackerBase());
2084: }
2085: t.invert();
2086: sensor.getRead(localTrans);
2087: t.mul(localTrans);
2088: }
2089:
2090: /**
2091: * Retrieves the position of the specified Sensor's
2092: * hotspot in virtual-world coordinates
2093: * and copies that value into the position provided.
2094: * This value is derived from other values and is read-only.
2095: * @param sensor the sensor in question
2096: * @param position the variable that will receive the position
2097: */
2098: public void getSensorHotspotInVworld(Sensor sensor, Point3f position) {
2099:
2100: Canvas3D canvas = (Canvas3D) this .canvases.firstElement();
2101: Transform3D sensorToVworld = new Transform3D();
2102: Point3d hotspot3d = new Point3d();
2103:
2104: getSensorToVworld(sensor, sensorToVworld);
2105: sensor.getHotspot(hotspot3d);
2106: position.set(hotspot3d);
2107: sensorToVworld.transform(position);
2108: }
2109:
2110: /**
2111: * Retrieves the position of the specified Sensor's
2112: * hotspot in virtual-world coordinates
2113: * and copies that value into the position provided.
2114: * This value is derived from other values and is read-only.
2115: * @param sensor the sensor in question
2116: * @param position the variable that will receive the position
2117: */
2118: public void getSensorHotspotInVworld(Sensor sensor, Point3d position) {
2119:
2120: Canvas3D canvas = (Canvas3D) this .canvases.firstElement();
2121: Transform3D sensorToVworld = new Transform3D();
2122:
2123: getSensorToVworld(sensor, sensorToVworld);
2124: sensor.getHotspot(position);
2125: sensorToVworld.transform(position);
2126: }
2127:
2128: /**
2129: * Sets given Canvas3D at the given index position.
2130: * @param canvas3D the given Canvas3D to be set
2131: * @param index the position to be set
2132: * @exception IllegalStateException if the specified canvas is
2133: * a stereo canvas with a monoscopicEyePolicy of CYCLOPEAN_EYE_VIEW,
2134: * and the viewPolicy for this view is HMD_VIEW
2135: * @exception IllegalSharingException if the specified canvas is
2136: * associated with another view
2137: */
2138: public void setCanvas3D(Canvas3D canvas3D, int index) {
2139:
2140: if ((viewPolicy == HMD_VIEW)
2141: && (canvas3D.monoscopicViewPolicy == View.CYCLOPEAN_EYE_VIEW)
2142: && (!canvas3D.useStereo)) {
2143:
2144: throw new IllegalStateException(J3dI18N.getString("View31"));
2145: }
2146:
2147: Canvas3D cv;
2148:
2149: synchronized (canvasList) {
2150: if (canvas3D.getView() != null)
2151: throw new IllegalSharingException(J3dI18N
2152: .getString("View10"));
2153: cv = (Canvas3D) canvases.elementAt(index);
2154: canvases.setElementAt(canvas3D, index);
2155: removeFromCanvasList(cv);
2156: addToCanvasList(canvas3D);
2157: canvasesDirty = true;
2158: }
2159:
2160: canvas3D.setView(this );
2161: cv.setView(null);
2162:
2163: if (canvas3D.added) {
2164: evaluateActive();
2165: }
2166: if (cv.added) {
2167: evaluateActive();
2168: }
2169:
2170: }
2171:
2172: /**
2173: * Gets the Canvas3D at the specified index position.
2174: * @param index the position from which to get Canvas3D object
2175: * @return the Canvas3D at the sprcified index position
2176: */
2177: public Canvas3D getCanvas3D(int index) {
2178: return (Canvas3D) this .canvases.elementAt(index);
2179: }
2180:
2181: /**
2182: * Gets the enumeration object of all the Canvas3Ds.
2183: * @return the enumeration object of all the Canvas3Ds.
2184: */
2185: public Enumeration getAllCanvas3Ds() {
2186: return canvases.elements();
2187: }
2188:
2189: /**
2190: * Returns the number of Canvas3Ds in this View.
2191: * @return the number of Canvas3Ds in this View
2192: *
2193: * @since Java 3D 1.2
2194: */
2195: public int numCanvas3Ds() {
2196: return canvases.size();
2197: }
2198:
2199: /**
2200: * Adds the given Canvas3D at the end of the list.
2201: * @param canvas3D the Canvas3D to be added
2202: * @exception IllegalStateException if the specified canvas is
2203: * a stereo canvas with a monoscopicEyePolicy of CYCLOPEAN_EYE_VIEW,
2204: * and the viewPolicy for this view is HMD_VIEW
2205: * @exception IllegalSharingException if the specified canvas is
2206: * associated with another view
2207: */
2208: public void addCanvas3D(Canvas3D canvas3D) {
2209:
2210: if ((viewPolicy == HMD_VIEW)
2211: && (canvas3D.monoscopicViewPolicy == View.CYCLOPEAN_EYE_VIEW)
2212: && (!canvas3D.useStereo)) {
2213: throw new IllegalStateException(J3dI18N.getString("View31"));
2214: }
2215:
2216: synchronized (canvasList) {
2217: if (canvas3D.getView() != null)
2218: throw new IllegalSharingException(J3dI18N
2219: .getString("View10"));
2220: canvases.addElement(canvas3D);
2221: addToCanvasList(canvas3D);
2222: canvasesDirty = true;
2223: }
2224:
2225: canvas3D.setView(this );
2226:
2227: if (canvas3D.added) {
2228: if ((canvas3D.visible || canvas3D.offScreen)
2229: && canvas3D.firstPaintCalled) {
2230: canvas3D.active = true;
2231: }
2232: evaluateActive();
2233: }
2234: }
2235:
2236: /**
2237: * Inserts the Canvas3D at the given index position.
2238: * @param canvas3D the Canvas3D to be inserted
2239: * @param index the position to be inserted at
2240: * @exception IllegalStateException if the specified canvas is
2241: * a stereo canvas with a monoscopicEyePolicy of CYCLOPEAN_EYE_VIEW,
2242: * and the viewPolicy for this view is HMD_VIEW
2243: * @exception IllegalSharingException if the specified canvas is
2244: * associated with another view
2245: */
2246: public void insertCanvas3D(Canvas3D canvas3D, int index) {
2247:
2248: if ((viewPolicy == HMD_VIEW)
2249: && (canvas3D.monoscopicViewPolicy == View.CYCLOPEAN_EYE_VIEW)
2250: && (!canvas3D.useStereo)) {
2251: throw new IllegalStateException(J3dI18N.getString("View31"));
2252: }
2253:
2254: synchronized (canvasList) {
2255: if (canvas3D.getView() != null)
2256: throw new IllegalSharingException(J3dI18N
2257: .getString("View10"));
2258: this .canvases.insertElementAt(canvas3D, index);
2259: addToCanvasList(canvas3D);
2260: canvasesDirty = true;
2261: }
2262:
2263: canvas3D.setView(this );
2264:
2265: if (canvas3D.added) {
2266: if ((canvas3D.visible || canvas3D.offScreen)
2267: && canvas3D.firstPaintCalled) {
2268: canvas3D.active = true;
2269: }
2270: evaluateActive();
2271: }
2272: }
2273:
2274: /**
2275: * Removes the Canvas3D from the given index position.
2276: * @param index the position of Canvas3D object to be removed
2277: */
2278: public void removeCanvas3D(int index) {
2279: // index -1 is possible if the view is unregistered first
2280: // because viewPlatform is clearLived,
2281: // and then removeCanvas from the view
2282: if (index == -1)
2283: return;
2284:
2285: Canvas3D cv;
2286:
2287: synchronized (canvasList) {
2288: cv = (Canvas3D) canvases.elementAt(index);
2289:
2290: canvases.removeElementAt(index);
2291: removeFromCanvasList(cv);
2292: canvasesDirty = true;
2293: }
2294:
2295: // reset canvas will set view to null also
2296: VirtualUniverse.mc.postRequest(MasterControl.RESET_CANVAS, cv);
2297: cv.pendingView = null;
2298:
2299: computeCanvasesCached();
2300:
2301: if (cv.added) {
2302: cv.active = false;
2303: evaluateActive();
2304: }
2305: if (universe != null) {
2306: universe.waitForMC();
2307: }
2308: }
2309:
2310: /**
2311: * Retrieves the index of the specified Canvas3D in
2312: * this View's list of Canvas3Ds
2313: *
2314: * @param canvas3D the Canvas3D to be looked up.
2315: * @return the index of the specified Canvas3D;
2316: * returns -1 if the object is not in the list.
2317: *
2318: * @since Java 3D 1.3
2319: */
2320: public int indexOfCanvas3D(Canvas3D canvas3D) {
2321: return canvases.indexOf(canvas3D);
2322: }
2323:
2324: /**
2325: * Removes the specified Canvas3D from this View's
2326: * list of Canvas3Ds.
2327: * If the specified object is not in the list, the list is not modified.
2328: *
2329: * @param canvas3D the Canvas3D to be removed.
2330: */
2331: public void removeCanvas3D(Canvas3D canvas3D) {
2332: removeCanvas3D(canvases.indexOf(canvas3D));
2333: }
2334:
2335: /**
2336: * Removes all Canvas3Ds from this View.
2337: *
2338: * @since Java 3D 1.3
2339: */
2340: public void removeAllCanvas3Ds() {
2341: LinkedList tmpCanvases = new LinkedList();
2342:
2343: synchronized (canvasList) {
2344: int numCanvases = canvases.size();
2345:
2346: // Remove in reverse order to ensure valid indices
2347: for (int index = numCanvases - 1; index >= 0; index--) {
2348: Canvas3D cv;
2349:
2350: cv = (Canvas3D) canvases.elementAt(index);
2351:
2352: // Record list of canvases to be deleted;
2353: tmpCanvases.add(cv);
2354:
2355: canvases.removeElementAt(index);
2356: removeFromCanvasList(cv);
2357: canvasesDirty = true;
2358: }
2359: }
2360:
2361: // ISSUE 83: postRequest must *not* be called while holding
2362: // canvasList lock. Holding the lock can cause a deadlock.
2363:
2364: Iterator iterator = tmpCanvases.iterator();
2365: while (iterator.hasNext()) {
2366: Canvas3D cv = (Canvas3D) iterator.next();
2367:
2368: // reset canvas will set view to null also
2369: VirtualUniverse.mc.postRequest(MasterControl.RESET_CANVAS,
2370: cv);
2371: cv.pendingView = null;
2372:
2373: if (cv.added) {
2374: cv.active = false;
2375: }
2376: }
2377:
2378: computeCanvasesCached();
2379:
2380: evaluateActive();
2381:
2382: if (universe != null) {
2383: universe.waitForMC();
2384: }
2385: }
2386:
2387: // This adds this canvas and its screen to the screen list.
2388: // Locks are already acquired before this is called.
2389: private void addToCanvasList(Canvas3D c) {
2390:
2391: for (int i = screenList.size() - 1; i >= 0; i--) {
2392: if ((Screen3D) screenList.get(i) == c.screen) {
2393: // This is the right screen slot
2394: ((ArrayList) canvasList.get(i)).add(c);
2395: canvasesDirty = true;
2396: return;
2397: }
2398: }
2399:
2400: // Add a screen slot
2401: screenList.add(c.screen);
2402: ArrayList clist = new ArrayList();
2403: canvasList.add(clist);
2404: clist.add(c);
2405: canvasesDirty = true;
2406: }
2407:
2408: // This removes this canvas and its screen from the screen list
2409: // Locks are already acquired before this is called.
2410: private void removeFromCanvasList(Canvas3D c) {
2411:
2412: for (int i = screenList.size() - 1; i >= 0; i--) {
2413: if ((Screen3D) screenList.get(i) == c.screen) {
2414: // This is the right screen slot
2415: ArrayList clist = (ArrayList) canvasList.get(i);
2416: clist.remove(clist.indexOf(c));
2417:
2418: if (clist.size() == 0) {
2419: canvasList.remove(i);
2420: screenList.remove(i);
2421: canvasesDirty = true;
2422: }
2423: return;
2424: }
2425: }
2426: }
2427:
2428: // Locks are not acquired before this is called.
2429: void computeCanvasesCached() {
2430:
2431: synchronized (canvasList) {
2432: ArrayList cv;
2433: int len = canvases.size();
2434:
2435: Canvas3D newCachedCanvases[] = new Canvas3D[len];
2436: for (int i = 0; i < len; i++) {
2437: newCachedCanvases[i] = (Canvas3D) canvases.get(i);
2438: }
2439: // Do this in one instruction so there is no need to
2440: // synchronized getCanvases()
2441:
2442: cachedCanvases = newCachedCanvases;
2443: len = 0;
2444: longestScreenList = 0;
2445: cachedCanvasList = new Canvas3D[canvasList.size()][0];
2446: for (int i = 0; i < cachedCanvasList.length; i++) {
2447: cv = (ArrayList) canvasList.get(i);
2448: len = cv.size();
2449: cachedCanvasList[i] = new Canvas3D[len];
2450: for (int j = 0; j < len; j++) {
2451: cachedCanvasList[i][j] = (Canvas3D) cv.get(j);
2452: }
2453:
2454: if (len > longestScreenList) {
2455: longestScreenList = len;
2456: }
2457: }
2458: len = screenList.size();
2459: Screen3D newCachedScreens[] = new Screen3D[len];
2460:
2461: for (int i = 0; i < len; i++) {
2462: newCachedScreens[i] = (Screen3D) screenList.get(i);
2463: }
2464: // Do this in one instruction so there is no need to
2465: // synchronized getScreens()
2466: cachedScreens = newCachedScreens;
2467: canvasesDirty = false;
2468: }
2469: }
2470:
2471: // This creates a 2 dimentional list of canvases
2472: // ONLY MC can call this procedure with canCompute=true,
2473: // since MC want the result return by
2474: // evaluateCanvases and updateWorkThreads agree to each other,
2475: // so only evaluateCanvases can compute a new list.
2476: // Other threads should use getCanvasList(false).
2477: Canvas3D[][] getCanvasList(boolean canCompute) {
2478: if (canvasesDirty && canCompute) {
2479: computeCanvasesCached();
2480: }
2481: return cachedCanvasList;
2482: }
2483:
2484: // assume getCanvasList is called before
2485: int getLongestScreenList() {
2486: return longestScreenList;
2487: }
2488:
2489: // assume getCanvasList is called before
2490: Canvas3D[] getCanvases() {
2491: return cachedCanvases;
2492: }
2493:
2494: // assume getCanvasList is called before
2495: Screen3D[] getScreens() {
2496: return cachedScreens;
2497: }
2498:
2499: Canvas3D getFirstCanvas() {
2500: synchronized (canvasList) {
2501: if (canvases.size() > 0) {
2502: return (Canvas3D) canvases.elementAt(0);
2503: }
2504: return null;
2505: }
2506: }
2507:
2508: /**
2509: * This method returns the time at which the most recent rendering
2510: * frame started. It is defined as the number of milliseconds
2511: * since January 1, 1970 00:00:00 GMT.
2512: * Since multiple canvases might be attached to this View,
2513: * the start of a frame is defined as the point in time just prior
2514: * to clearing any canvas attached to this view.
2515: * @return the time at which the most recent rendering frame started
2516: */
2517: public long getCurrentFrameStartTime() {
2518: synchronized (frameStartTimes) {
2519: return currentFrameStartTime;
2520: }
2521: }
2522:
2523: /**
2524: * This method returns the duration, in milliseconds, of the most
2525: * recently completed rendering frame. The time taken to render
2526: * all canvases attached to this view is measured. This duration
2527: * is computed as the difference between the start of the most recently
2528: * completed frame and the end of that frame.
2529: * Since multiple canvases might be attached to this View,
2530: * the start of a frame is defined as the point in time just prior
2531: * to clearing any canvas attached to this view--before preRender
2532: * is called for any canvas. Similarly, the end of a frame is
2533: * defined as the point in time just after swapping the buffer for
2534: * all canvases--after postSwap is called for all canvases.
2535: * Note that since the frame duration is measured from start to stop
2536: * for this view only, the value returned is not the same as
2537: * frame rate; it measures only the rendering time for this view.
2538: *
2539: * @return the duration, in milliseconds, of the most recently
2540: * completed rendering frame
2541: */
2542: public long getLastFrameDuration() {
2543: synchronized (frameStartTimes) {
2544: return currentFrameDuration;
2545: }
2546: }
2547:
2548: /**
2549: * This method returns the frame number for this view. The frame
2550: * number starts at 0 and is incremented at the start of each
2551: * frame--prior to clearing all the canvases attached to this
2552: * view.
2553: *
2554: * @return the current frame number for this view
2555: */
2556: public long getFrameNumber() {
2557: synchronized (frameStartTimes) {
2558: return currentFrameNumber;
2559: }
2560: }
2561:
2562: /**
2563: * Retrieves the implementation-dependent maximum number of
2564: * frames whose start times will be recorded by the system. This
2565: * value is guaranteed to be at least 10 for all implementations
2566: * of the Java 3D API.
2567: * @return the maximum number of frame start times recorded
2568: */
2569: public static int getMaxFrameStartTimes() {
2570: return (NUMBER_FRAME_START_TIMES);
2571: }
2572:
2573: /**
2574: * Copies the last <i>k</i> frame start time values into
2575: * the user-specified array. The most recent frame start time is
2576: * copied to location 0 of the array, the next most recent frame
2577: * start time is copied into location 1 of the array, and so forth.
2578: * If times.length is smaller than
2579: * maxFrameStartTimes, then only the last times.length values are
2580: * copied. If times.length is greater than maxFrameStartTimes,
2581: * then all array elements after index maxFrameStartTimes-1 are
2582: * set to 0.
2583: *
2584: * @return the frame number of the most recent frame in the array
2585: *
2586: * @see #setMinimumFrameCycleTime
2587: */
2588: public long getFrameStartTimes(long[] times) {
2589: int index, i, loopCount;
2590: long lastFrameNumber;
2591:
2592: synchronized (frameStartTimes) {
2593: index = currentFrameIndex - 1;
2594: if (index < 0) {
2595: index = NUMBER_FRAME_START_TIMES - 1;
2596: }
2597: lastFrameNumber = frameNumbers[index];
2598:
2599: if (times.length <= NUMBER_FRAME_START_TIMES) {
2600: loopCount = times.length;
2601: } else {
2602: loopCount = NUMBER_FRAME_START_TIMES;
2603: }
2604:
2605: for (i = 0; i < loopCount; i++) {
2606: times[i] = frameStartTimes[index];
2607: index--;
2608: if (index < 0) {
2609: index = NUMBER_FRAME_START_TIMES - 1;
2610: }
2611: }
2612:
2613: if (times.length > NUMBER_FRAME_START_TIMES) {
2614: for (; i < times.length; i++) {
2615: times[i] = 0;
2616: }
2617: }
2618: }
2619:
2620: return (lastFrameNumber);
2621: }
2622:
2623: /**
2624: * Sets the minimum frame cycle time, in milliseconds, for this
2625: * view. The Java 3D renderer will ensure that the time between
2626: * the start of each successive frame is at least the specified
2627: * number of milliseconds. The default value is 0.
2628: *
2629: * @param minimumTime the minimum number of milliseconds between
2630: * successive frames
2631: *
2632: * @exception IllegalArgumentException if <code>minimumTime < 0</code>
2633: *
2634: * @see #getFrameStartTimes
2635: *
2636: * @since Java 3D 1.2
2637: */
2638: public void setMinimumFrameCycleTime(long minimumTime) {
2639: if (minimumTime < 0L)
2640: throw new IllegalArgumentException(J3dI18N
2641: .getString("View27"));
2642:
2643: minFrameCycleTime = minimumTime;
2644: VirtualUniverse.mc.setWork();
2645: }
2646:
2647: /**
2648: * Retrieves the minimum frame cycle time, in milliseconds, for this view.
2649: * @return the minimum frame cycle time for this view.
2650: *
2651: * @see #getFrameStartTimes
2652: *
2653: * @since Java 3D 1.2
2654: */
2655: public long getMinimumFrameCycleTime() {
2656: return minFrameCycleTime;
2657: }
2658:
2659: /**
2660: * This adds a frame time to the this of frame times
2661: */
2662: void setFrameTimingValues() {
2663:
2664: synchronized (frameStartTimes) {
2665: if (currentFrameIndex == NUMBER_FRAME_START_TIMES) {
2666: currentFrameIndex = 0;
2667: }
2668:
2669: frameNumbers[currentFrameIndex] = frameNumber;
2670:
2671: frameStartTimes[currentFrameIndex++] = startTime;
2672: currentFrameStartTime = startTime;
2673: currentFrameDuration = stopTime - startTime;
2674: currentFrameNumber = frameNumber;
2675: }
2676: }
2677:
2678: /**
2679: * Return true if maximum fps impose by user reach
2680: */
2681: void computeCycleTime() {
2682: if (minFrameCycleTime == 0) {
2683: isMinCycleTimeAchieve = true;
2684: sleepTime = 0;
2685: } else {
2686: sleepTime = minFrameCycleTime
2687: - (J3dClock.currentTimeMillis() - startTime);
2688: isMinCycleTimeAchieve = (sleepTime <= 0);
2689: }
2690: }
2691:
2692: /**
2693: * Enables or disables automatic freezing of the depth buffer for
2694: * objects rendered
2695: * during the transparent rendering pass (i.e., objects rendered
2696: * using alpha blending) for this view.
2697: * If enabled, depth buffer writes will be disabled during the
2698: * transparent rendering pass regardless of the value of
2699: * the depth buffer write enable flag in the RenderingAttributes
2700: * object for a particular node.
2701: * This flag is enabled by default.
2702: * @param flag indicates whether automatic freezing of the depth buffer
2703: * for transparent/antialiased objects is enabled.
2704: * @see RenderingAttributes#setDepthBufferWriteEnable
2705: */
2706: public void setDepthBufferFreezeTransparent(boolean flag) {
2707: depthBufferFreezeTransparent = flag;
2708: repaint();
2709: }
2710:
2711: /**
2712: * Retrieves the current value of the depth buffer freeze transparent
2713: * flag for this view.
2714: * @return a flag that indicates whether or not the depth
2715: * buffer is automatically frozen during the transparent rendering pass.
2716: */
2717: public boolean getDepthBufferFreezeTransparent() {
2718: return depthBufferFreezeTransparent;
2719: }
2720:
2721: /**
2722: * Enables or disables scene antialiasing for this view.
2723: * If enabled, the entire scene will be antialiased on
2724: * each canvas in which scene antialiasing is available.
2725: * Scene antialiasing is disabled by default.
2726: * <p>
2727: * NOTE: Scene antialiasing is ignored in pure immediate mode,
2728: * but is supported in mixed-immediate mode.
2729: * @param flag indicates whether scene antialiasing is enabled
2730: *
2731: * @see Canvas3D#queryProperties
2732: */
2733: public void setSceneAntialiasingEnable(boolean flag) {
2734: sceneAntialiasingEnable = flag;
2735: repaint();
2736: }
2737:
2738: /**
2739: * Returns a flag that indicates whether or not scene antialiasing
2740: * is enabled for this view.
2741: * @return a flag that indicates whether scene antialiasing is enabled
2742: */
2743: public boolean getSceneAntialiasingEnable() {
2744: return sceneAntialiasingEnable;
2745: }
2746:
2747: /**
2748: * Sets a flag that indicates whether the local eyepoint is used in
2749: * lighting calculations for perspective projections.
2750: * If this flag is set to true, the view vector is calculated per-vertex
2751: * based on the direction from the actual eyepoint to the vertex.
2752: * If this flag is set to false, a single view vector is computed from
2753: * the eyepoint to the center of the view frustum. This is
2754: * called infinite eye lighting.
2755: * Local eye lighting is disabled by default, and is ignored for
2756: * parallel projections.
2757: * @param flag indicates whether local eye lighting is enabled
2758: */
2759: public void setLocalEyeLightingEnable(boolean flag) {
2760: localEyeLightingEnable = flag;
2761: repaint();
2762: }
2763:
2764: /**
2765: * Retrieves a flag that indicates whether or not local eye lighting
2766: * is enabled for this view.
2767: * @return a flag that indicates whether local eye lighting is enabled
2768: */
2769: public boolean getLocalEyeLightingEnable() {
2770: return localEyeLightingEnable;
2771: }
2772:
2773: /**
2774: * Attach viewPlatform structure to this view.
2775: * @param vp the viewPlatform to be attached
2776: */
2777: public void attachViewPlatform(ViewPlatform vp) {
2778:
2779: if ((vp != null) && (vp == viewPlatform)) {
2780: return;
2781: }
2782:
2783: if (viewPlatform != null) {
2784: ((ViewPlatformRetained) viewPlatform.retained)
2785: .removeView(this );
2786: if (viewPlatform.isLive()) {
2787: synchronized (evaluateLock) {
2788: viewPlatform = null;
2789: // cleanup View stuff for the old platform
2790: evaluateActive();
2791: viewPlatform = vp;
2792: }
2793: if (universe != null) {
2794: universe.waitForMC();
2795: }
2796: } else {
2797: viewPlatform = vp;
2798: }
2799: } else {
2800: viewPlatform = vp;
2801: }
2802: if (vp != null) {
2803: if (vp.isLive()) {
2804: checkView();
2805: setUniverse(((ViewPlatformRetained) vp.retained).universe);
2806: }
2807: ((ViewPlatformRetained) vp.retained).setView(this );
2808: }
2809:
2810: evaluateActive();
2811: if ((vp == null) && (universe != null)) {
2812: universe.waitForMC();
2813: }
2814: }
2815:
2816: /**
2817: * Retrieves the currently attached ViewPlatform object
2818: * @return the currently attached ViewPlatform
2819: */
2820: public ViewPlatform getViewPlatform() {
2821: return viewPlatform;
2822: }
2823:
2824: /**
2825: * Checks view parameters for consistency
2826: */
2827: void checkView() {
2828: if (physicalBody == null)
2829: throw new IllegalStateException(J3dI18N.getString("View13"));
2830:
2831: if (physicalEnvironment == null)
2832: throw new IllegalStateException(J3dI18N.getString("View14"));
2833: }
2834:
2835: /**
2836: * Stops the behavior scheduler after all
2837: * currently scheduled behaviors are executed. Any frame-based
2838: * behaviors scheduled to wake up on the next frame will be
2839: * executed at least once before the behavior scheduler is
2840: * stopped.
2841: * <p>
2842: * NOTE: This is a heavy-weight method
2843: * intended for verification and image capture (recording); it
2844: * is <i>not</i> intended to be used for flow control.
2845: * @return a pair of integers that specify the beginning and ending
2846: * time (in milliseconds since January 1, 1970 00:00:00 GMT)
2847: * of the behavior scheduler's last pass
2848: * @exception IllegalStateException if this method is called
2849: * from a Behavior method or from any Canvas3D render callback
2850: * method
2851: */
2852: public final long[] stopBehaviorScheduler() {
2853: long[] intervalTime = new long[2];
2854:
2855: if (checkBehaviorSchedulerState("View15", "View16")) {
2856: if (activeStatus && isRunning
2857: && (universe.behaviorScheduler != null)) {
2858: // view is active
2859: universe.behaviorScheduler
2860: .stopBehaviorScheduler(intervalTime);
2861: } else {
2862: if ((universe != null)
2863: && (universe.behaviorScheduler != null)) {
2864: universe.behaviorScheduler.userStop = true;
2865: }
2866: }
2867: }
2868: stopBehavior = true;
2869: return intervalTime;
2870: }
2871:
2872: /**
2873: * Starts the behavior scheduler running after it has been stopped.
2874: * @exception IllegalStateException if this method is called
2875: * from a Behavior method or from any Canvas3D render callback
2876: * method
2877: */
2878: public final void startBehaviorScheduler() {
2879: if (checkBehaviorSchedulerState("View17", "View18")) {
2880: if (activeStatus && isRunning
2881: && (universe.behaviorScheduler != null)) {
2882: universe.behaviorScheduler.startBehaviorScheduler();
2883:
2884: } else {
2885: if ((universe != null)
2886: && (universe.behaviorScheduler != null)) {
2887: universe.behaviorScheduler.userStop = false;
2888: }
2889: }
2890: }
2891:
2892: stopBehavior = false;
2893: }
2894:
2895: /**
2896: * Check if BehaviorScheduler is in valid state to start/stop
2897: * itself.
2898: * @param s1 Exception String if method is called from a Canvas3D
2899: * @param s2 Exception String if method is called from a Behavior method
2900: * @return true if viewPlatform is live
2901: * @exception IllegalStateException if this method is called
2902: * from a Behavior method or from any Canvas3D render callback
2903: * method
2904: *
2905: */
2906: boolean checkBehaviorSchedulerState(String s1, String s2) {
2907: Thread me = Thread.currentThread();
2908:
2909: if (inCanvasCallback) {
2910: synchronized (canvasList) {
2911: for (int i = canvases.size() - 1; i >= 0; i--) {
2912: if (((Canvas3D) canvases.elementAt(i)).screen.renderer == me) {
2913: throw new IllegalStateException(J3dI18N
2914: .getString(s1));
2915: }
2916: }
2917: }
2918: }
2919:
2920: if ((viewPlatform != null) && viewPlatform.isLive()) {
2921: if (universe.inBehavior
2922: && (universe.behaviorScheduler == me)) {
2923: throw new IllegalStateException(J3dI18N.getString(s2));
2924: }
2925: return true;
2926: }
2927: return false;
2928: }
2929:
2930: /**
2931: * Retrieves a flag that indicates whether the behavior scheduler is
2932: * currently running.
2933: * @return true if the behavior scheduler is running, false otherwise
2934: * @exception IllegalStateException if this method is called
2935: * from a Behavior method or from any Canvas3D render callback
2936: * method
2937: */
2938: public final boolean isBehaviorSchedulerRunning() {
2939: return (((universe != null) && !stopBehavior && (universe.behaviorScheduler != null)) ? !universe.behaviorScheduler.userStop
2940: : false);
2941: }
2942:
2943: /**
2944: * Stops traversing the scene graph for this
2945: * view after the current state of the scene graph is reflected on
2946: * all canvases attached to this view. The renderers associated
2947: * with these canvases are also stopped.
2948: * <p>
2949: * NOTE: This is a heavy-weight method
2950: * intended for verification and image capture (recording); it
2951: * is <i>not</i> intended to be used for flow control.
2952: * @exception IllegalStateException if this method is called
2953: * from a Behavior method or from any Canvas3D render callback
2954: * method
2955: */
2956: public final void stopView() {
2957: checkViewState("View19", "View20");
2958: synchronized (startStopViewLock) {
2959: if (activeStatus && isRunning) {
2960: VirtualUniverse.mc.postRequest(MasterControl.STOP_VIEW,
2961: this );
2962: while (isRunning) {
2963: MasterControl.threadYield();
2964: }
2965: } else {
2966: isRunning = false;
2967: }
2968: }
2969: }
2970:
2971: /**
2972: * Starts
2973: * traversing this view, and starts the renderers associated
2974: * with all canvases attached to this view.
2975: * @exception IllegalStateException if this method is called
2976: * from a Behavior method or from any Canvas3D render callback
2977: * method
2978: */
2979: public final void startView() {
2980:
2981: checkViewState("View21", "View22");
2982: synchronized (startStopViewLock) {
2983: if (activeStatus && !isRunning) {
2984: VirtualUniverse.mc.postRequest(
2985: MasterControl.START_VIEW, this );
2986: while (!isRunning) {
2987: MasterControl.threadYield();
2988: }
2989: VirtualUniverse.mc.sendRunMessage(this ,
2990: J3dThread.RENDER_THREAD);
2991: } else {
2992: isRunning = true;
2993: }
2994: }
2995:
2996: }
2997:
2998: /**
2999: * This will throw IllegalStateException if not in valid state
3000: * for start/stop request.
3001: */
3002: void checkViewState(String s1, String s2)
3003: throws IllegalStateException {
3004: if (inCanvasCallback) {
3005: Thread me = Thread.currentThread();
3006: synchronized (canvasList) {
3007: for (int i = canvases.size() - 1; i >= 0; i--) {
3008: Canvas3D cv = (Canvas3D) canvases.elementAt(i);
3009: if (cv.screen.renderer == me) {
3010: throw new IllegalStateException(J3dI18N
3011: .getString(s1));
3012: }
3013: }
3014: }
3015: }
3016:
3017: if ((viewPlatform != null) && viewPlatform.isLive()) {
3018: if (universe.inBehavior
3019: && (Thread.currentThread() == universe.behaviorScheduler)) {
3020: throw new IllegalStateException(J3dI18N.getString(s2));
3021: }
3022: }
3023: }
3024:
3025: /**
3026: * Retrieves a flag that indicates whether the traverser is
3027: * currently running on this view.
3028: * @return true if the traverser is running, false otherwise
3029: * @exception IllegalStateException if this method is called
3030: * from a Behavior method or from any Canvas3D render callback
3031: * method
3032: */
3033: public final boolean isViewRunning() {
3034: return isRunning;
3035: }
3036:
3037: /**
3038: * Renders one frame for a stopped View. Functionally, this
3039: * method is equivalent to <code>startView()</code> followed by
3040: * <code>stopview()</code>, except that it is atomic, which
3041: * guarantees that only one frame is rendered.
3042: *
3043: * @exception IllegalStateException if this method is called from
3044: * a Behavior method or from any Canvas3D render callback, or if
3045: * the view is currently running.
3046: *
3047: * @since Java 3D 1.2
3048: */
3049: public void renderOnce() {
3050: checkViewState("View28", "View29");
3051: synchronized (startStopViewLock) {
3052: if (isRunning) {
3053: throw new IllegalStateException(J3dI18N
3054: .getString("View30"));
3055: }
3056: renderOnceFinish = false;
3057: VirtualUniverse.mc.postRequest(MasterControl.RENDER_ONCE,
3058: this );
3059: while (!renderOnceFinish) {
3060: MasterControl.threadYield();
3061: }
3062: renderOnceFinish = true;
3063: }
3064: }
3065:
3066: /**
3067: * Requests that this View be scheduled for rendering as soon as
3068: * possible. The repaint method may return before the frame has
3069: * been rendered. If the view is stopped, or if the view is
3070: * continuously running (for example, due to a free-running
3071: * interpolator), this method will have no effect. Most
3072: * applications will not need to call this method, since any
3073: * update to the scene graph or to viewing parameters will
3074: * automatically cause all affected views to be rendered.
3075: *
3076: * @since Java 3D 1.2
3077: */
3078: public void repaint() {
3079: if (activeStatus && isRunning) {
3080: VirtualUniverse.mc.sendRunMessage(this ,
3081: J3dThread.RENDER_THREAD);
3082: }
3083: }
3084:
3085: /**
3086: * Update the view cache associated with this view. Also, shapshot
3087: * the per-screen parameters associated with all screens attached
3088: * to this view.
3089: */
3090: final void updateViewCache() {
3091:
3092: // TODO KCR : remove obsolete DVR code (but make sure we don't end
3093: // up with a leak in the Viewer Map object).
3094:
3095: // DVR support
3096: // This is a back door in j3d to provide DVR support.
3097: // A better place to put this code segment is in
3098: // ViewCache.snapshot(). Since it consists of some
3099: // back door code, I've decided to put it here to isolate
3100: // it from the rest of view snapshot code.
3101: if (firstTime) {
3102: // System.err.println("View : First Time is " + firstTime);
3103: // viewer = Viewer.getViewer(this);
3104: // Since we've the handler to the viewer, we can remove the entry
3105: // now to avoid confusion and prevent memory leak problem.
3106: viewer = Viewer.removeViewerMapEntry(this );
3107: firstTime = false;
3108: }
3109:
3110: // if(viewer != null) {
3111: // if(viewer.isDvrEnabled()) {
3112: // dvrFactor = viewer.getDvrFactor();
3113: // dvrResizeCompensation =
3114: // viewer.getDvrResizeCompensationEnable();
3115: // /*
3116: // System.err.println("View : dvrFactor is " + dvrFactor);
3117: // System.err.println("View : dvrResizeCompensation is " +
3118: // dvrResizeCompensation);
3119: // */
3120: // }
3121: // else {
3122: // // Reset back to default.
3123: // dvrFactor = 1.0f;
3124: // dvrResizeCompensation = true;
3125: //
3126: // }
3127: // }
3128: // End of back door -- DVR.
3129:
3130: synchronized (this ) {
3131: viewCache.snapshot();
3132: viewCache.computeDerivedData();
3133: }
3134:
3135: // Just take the brute force approach and snapshot the
3136: // parameters for each screen attached to each canvas. We won't
3137: // worry about whether a screen is cached more than once.
3138: // Eventually, dirty bits will take care of this.
3139:
3140: synchronized (canvasList) {
3141: int i = canvases.size() - 1;
3142: while (i >= 0) {
3143: Screen3D scr = ((Canvas3D) canvases.elementAt(i--))
3144: .getScreen3D();
3145: if (scr != null)
3146: scr.updateViewCache();
3147: }
3148: }
3149: }
3150:
3151: /**
3152: * This routine activates or deactivates a view based on various information
3153: */
3154: void evaluateActive() {
3155:
3156: synchronized (evaluateLock) {
3157: if (universe == null) {
3158: return;
3159: }
3160:
3161: if ((viewPlatform == null)
3162: || !viewPlatform.isLive()
3163: || !((ViewPlatformRetained) viewPlatform.retained).switchState.currentSwitchOn) {
3164: if (activeStatus) {
3165: deactivate();
3166: activeStatus = false;
3167: }
3168: // Destroy threads from MC
3169: if (VirtualUniverse.mc.isRegistered(this )
3170: && (universe.isEmpty() || (canvases.isEmpty() && ((viewPlatform == null) || !viewPlatform
3171: .isLive())))) {
3172: // We can't wait until MC finish unregister view
3173: // here because user thread may
3174: // holds the universe.sceneGraphLock if branch
3175: // or locale remove in clearLive(). In this way
3176: // There is deadlock since MC also need need
3177: // sceneGraphLock in some threads
3178: // (e.g. TransformStructure update thread)
3179: universe.unRegViewWaiting = this ;
3180: resetUnivCount = universeCount;
3181: VirtualUniverse.mc.postRequest(
3182: MasterControl.UNREGISTER_VIEW, this );
3183: }
3184: } else {
3185:
3186: // We're on a live view platform. See what the canvases say
3187: // If view not register, MC will register it automatically
3188:
3189: int i;
3190: VirtualUniverse u = null;
3191: synchronized (canvasList) {
3192:
3193: for (i = canvases.size() - 1; i >= 0; i--) {
3194: Canvas3D cv = (Canvas3D) canvases.elementAt(i);
3195: if (cv.active) {
3196:
3197: if (!activeStatus
3198: && (universeCount > resetUnivCount)) {
3199: u = universe;
3200: }
3201: break;
3202: }
3203: }
3204: }
3205:
3206: // We should do this outside canvasList lock,
3207: // otherwise it may cause deadlock with MC
3208: if (u != null) {
3209: activate(u);
3210: activeStatus = true;
3211: return;
3212: }
3213:
3214: if ((i < 0) && activeStatus) {
3215: deactivate();
3216: activeStatus = false;
3217: return;
3218: }
3219:
3220: if (VirtualUniverse.mc.isRegistered(this )) {
3221: // notify MC that canvases state for this view changed
3222: VirtualUniverse.mc.postRequest(
3223: MasterControl.REEVALUATE_CANVAS, this );
3224: }
3225: }
3226: }
3227: }
3228:
3229: void setUniverse(VirtualUniverse universe) {
3230:
3231: synchronized (VirtualUniverse.mc.requestObjList) {
3232: if ((renderBin == null) || (renderBin.universe != universe)) {
3233: if (renderBin != null) {
3234: renderBin.cleanup();
3235: }
3236: renderBin = new RenderBin(universe, this );
3237: renderBin.universe = universe;
3238: }
3239:
3240: if ((soundScheduler == null)
3241: || (soundScheduler.universe != universe)) {
3242: // create a sound scheduler for this view, with this universe
3243: if (soundScheduler != null) {
3244: soundScheduler.cleanup();
3245: }
3246: soundScheduler = new SoundScheduler(universe, this );
3247: }
3248:
3249: // This has to be the last call before
3250: // RenderBin and SoundScheduler construct. Since it is
3251: // possible that canvas receive paint call and invoked
3252: // evaluateActive in another thread - which check for
3253: // universe == null and may let it pass before soundScheduler
3254: // and renderBin initialize.
3255: universeCount++;
3256: this .universe = universe;
3257: }
3258: evaluateActive();
3259: }
3260:
3261: /**
3262: * This activates all traversers and renderers associated with this view.
3263: */
3264: void activate(VirtualUniverse universe) {
3265:
3266: universe.checkForEnableEvents();
3267:
3268: if (physicalBody != null) {
3269: physicalBody.addUser(this );
3270: }
3271:
3272: if (!VirtualUniverse.mc.isRegistered(this )) {
3273: universe.regViewWaiting = this ;
3274: }
3275:
3276: VirtualUniverse.mc.postRequest(MasterControl.ACTIVATE_VIEW,
3277: this );
3278:
3279: if (!universe.isSceneGraphLock) {
3280: universe.waitForMC();
3281: }
3282: if (soundScheduler != null) {
3283: soundScheduler.reset();
3284: }
3285:
3286: J3dMessage vpMessage = new J3dMessage();
3287: vpMessage.universe = universe;
3288: vpMessage.view = this ;
3289: vpMessage.type = J3dMessage.UPDATE_VIEW;
3290: vpMessage.threads = J3dThread.SOUND_SCHEDULER
3291: | J3dThread.UPDATE_RENDER | J3dThread.UPDATE_BEHAVIOR;
3292: vpMessage.args[0] = this ;
3293: synchronized (((ViewPlatformRetained) viewPlatform.retained).sphere) {
3294: vpMessage.args[1] = new Float(
3295: ((ViewPlatformRetained) viewPlatform.retained).sphere.radius);
3296: }
3297: vpMessage.args[2] = new Integer(OTHER_ATTRS_CHANGED);
3298: vpMessage.args[3] = new Integer(transparencySortingPolicy);
3299: VirtualUniverse.mc.processMessage(vpMessage);
3300: }
3301:
3302: /**
3303: * This deactivates all traversers and renderers associated with this view.
3304: */
3305: void deactivate() {
3306: VirtualUniverse.mc.postRequest(MasterControl.DEACTIVATE_VIEW,
3307: this );
3308: if (physicalBody != null) {
3309: physicalBody.removeUser(this );
3310: }
3311:
3312: // This is a temporary fix for bug 4267395
3313: // XXXX:cleanup in RenderBin after View detach
3314: // universe.addViewIdToFreeList(viewId);
3315:
3316: // using new property -Dj3d.forceReleaseView to disable bug fix 4267395
3317: // this bug fix can produce memory leaks in *some* applications which creates
3318: // and destroy Canvas3D from time to time. This just add the view in the
3319: // FreeList earlier.
3320: if (VirtualUniverse.mc.forceReleaseView) {
3321: universe.addViewIdToFreeList(viewId);
3322: }
3323:
3324: J3dMessage vpMessage = new J3dMessage();
3325: vpMessage.universe = universe;
3326: vpMessage.view = this ;
3327: vpMessage.type = J3dMessage.UPDATE_VIEW;
3328: vpMessage.threads = J3dThread.SOUND_SCHEDULER
3329: | J3dThread.UPDATE_RENDER | J3dThread.UPDATE_BEHAVIOR;
3330: vpMessage.args[0] = this ;
3331: if (viewPlatform != null) {
3332: synchronized (((ViewPlatformRetained) viewPlatform.retained).sphere) {
3333: vpMessage.args[1] = new Float(
3334: ((ViewPlatformRetained) viewPlatform.retained).sphere.radius);
3335: }
3336: } else {
3337: vpMessage.args[1] = new Float(0);
3338: }
3339: vpMessage.args[2] = new Integer(OTHER_ATTRS_CHANGED);
3340: vpMessage.args[3] = new Integer(transparencySortingPolicy);
3341: VirtualUniverse.mc.processMessage(vpMessage);
3342:
3343: }
3344:
3345: void cleanupViewId() {
3346: universe.addViewIdToFreeList(viewId);
3347: viewId = null;
3348: }
3349:
3350: void assignViewId() {
3351: if (viewId == null) {
3352: viewId = universe.getViewId();
3353: viewIndex = viewId.intValue();
3354: }
3355: }
3356:
3357: /**
3358: * This method passes window event to SoundScheduler
3359: */
3360: void sendEventToSoundScheduler(AWTEvent evt) {
3361: if (soundScheduler != null) {
3362: soundScheduler.receiveAWTEvent(evt);
3363: }
3364: }
3365:
3366: void reset() {
3367:
3368: for (int i = 0; i < canvases.size(); i++) {
3369: ((Canvas3D) canvases.get(i)).reset();
3370: }
3371:
3372: // reset the renderBinReady flag
3373: renderBinReady = false;
3374:
3375: soundScheduler.cleanup();
3376: soundScheduler = null;
3377: soundRenderer = new SoundRenderer();
3378:
3379: viewCache = new ViewCache(this );
3380: getCanvasList(true);
3381: cleanupViewId();
3382: renderBin.cleanup();
3383: renderBin = null;
3384: universe = null;
3385: }
3386: }
|