0001: /*
0002: * $RCSfile: Viewer.java,v $
0003: *
0004: * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved.
0005: *
0006: * Redistribution and use in source and binary forms, with or without
0007: * modification, are permitted provided that the following conditions
0008: * are met:
0009: *
0010: * - Redistribution of source code must retain the above copyright
0011: * notice, this list of conditions and the following disclaimer.
0012: *
0013: * - Redistribution in binary form must reproduce the above copyright
0014: * notice, this list of conditions and the following disclaimer in
0015: * the documentation and/or other materials provided with the
0016: * distribution.
0017: *
0018: * Neither the name of Sun Microsystems, Inc. or the names of
0019: * contributors may be used to endorse or promote products derived
0020: * from this software without specific prior written permission.
0021: *
0022: * This software is provided "AS IS," without a warranty of any
0023: * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
0024: * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
0025: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
0026: * EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL
0027: * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF
0028: * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
0029: * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR
0030: * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
0031: * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
0032: * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
0033: * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
0034: * POSSIBILITY OF SUCH DAMAGES.
0035: *
0036: * You acknowledge that this software is not designed, licensed or
0037: * intended for use in the design, construction, operation or
0038: * maintenance of any nuclear facility.
0039: *
0040: * $Revision: 1.9 $
0041: * $Date: 2007/02/09 17:20:45 $
0042: * $State: Exp $
0043: */
0044:
0045: package com.sun.j3d.utils.universe;
0046:
0047: import java.awt.event.*;
0048: import java.awt.*;
0049: import java.net.URL;
0050: import java.util.*;
0051: import javax.media.j3d.*;
0052: import javax.swing.*;
0053: import com.sun.j3d.audioengines.AudioEngine3DL2;
0054: import java.lang.reflect.Constructor;
0055:
0056: /**
0057: * The Viewer class holds all the information that describes the physical
0058: * and virtual "presence" in the Java 3D universe. The Viewer object
0059: * consists of:
0060: * <UL>
0061: * <LI>Physical Objects</LI>
0062: * <UL>
0063: * <LI>Canvas3D's - used to render with.</LI>
0064: * <LI>PhysicalEnvironment - holds characteristics of the hardware platform
0065: * being used to render on.</LI>
0066: * <LI>PhysicalBody - holds the physical characteristics and personal
0067: * preferences of the person who will be viewing the Java 3D universe.</LI>
0068: * </UL>
0069: * <LI>Virtual Objects</LI>
0070: * <UL>
0071: * <LI>View - the Java 3D View object.</LI>
0072: * <LI>ViewerAvatar - the geometry that is used by Java 3D to represent the
0073: * person viewing the Java 3D universe.</LI>
0074: * </UL>
0075: * </UL>
0076: * If the Viewer object is created without any Canvas3D's, or indirectly
0077: * through a configuration file, it will create the Canvas3D's as needed.
0078: * The default Viewer creates one Canvas3D. If the Viewer object creates
0079: * the Canvas3D's, it will also create a JPanel and JFrame for each Canvas3D.
0080: *
0081: * Dynamic video resize is a new feature in Java 3D 1.3.1.
0082: * This feature provides a means for doing swap synchronous resizing
0083: * of the area that is to be magnified (or passed through) to the
0084: * output video resolution. This functionality allows an application
0085: * to draw into a smaller viewport in the framebuffer in order to reduce
0086: * the time spent doing pixel fill. The reduced size viewport is then
0087: * magnified up to the video output resolution using the SUN_video_resize
0088: * extension. This extension is only implemented in XVR-4000 and later
0089: * hardware with back end video out resizing capability.
0090: *
0091: * If video size compensation is enable, the line widths, point sizes and pixel
0092: * operations will be scaled internally with the resize factor to approximately
0093: * compensate for video resizing. The location of the pixel ( x, y ) in the
0094: * resized framebuffer = ( floor( x * factor + 0.5 ), floor( y * factor + 0.5 ) )
0095: *
0096: * <p>
0097: * @see Canvas3D
0098: * @see PhysicalEnvironment
0099: * @see PhysicalBody
0100: * @see View
0101: * @see ViewerAvatar
0102: */
0103: public class Viewer {
0104: private static final boolean debug = false;
0105: private static PhysicalBody physicalBody = null;
0106: private static PhysicalEnvironment physicalEnvironment = null;
0107: private View view = null;
0108: private ViewerAvatar avatar = null;
0109: private Canvas3D[] canvases = null;
0110: private JFrame[] j3dJFrames = null;
0111: private JPanel[] j3dJPanels = null;
0112: private Window[] j3dWindows = null;
0113: private ViewingPlatform viewingPlatform = null;
0114:
0115: static HashMap viewerMap = new HashMap(5);
0116: private float dvrFactor = 1.0f;
0117: private boolean doDvr = false;
0118: private boolean doDvrResizeCompensation = true;
0119:
0120: /**
0121: * Get the Viewer associated with the view object.
0122: *
0123: * @param view The View object for inquiry.
0124: * @return The Viewer object associated with this View object.
0125: *
0126: * Note: This method is targeted for SUN framebuffer XVR-4000 and later
0127: * hardware that support video size extension.
0128: *
0129: * @since Java 3D 1.3.1
0130: */
0131: // To support a back door for DVR support.
0132: public static Viewer getViewer(View view) {
0133: Viewer viewer = null;
0134: synchronized (viewerMap) {
0135: //System.out.println("Viewer.getViewer viewerMap's size is " + viewerMap.size());
0136: viewer = (Viewer) (viewerMap.get(view));
0137: }
0138: return viewer;
0139: }
0140:
0141: /**
0142: * Removes the entry associated with the view object.
0143: *
0144: * @param view The View object to be removed.
0145: * @return The Viewer object associated with this View object.
0146: *
0147: * Note: This method is targeted for SUN framebuffer XVR-4000 and later
0148: * hardware that support video size extension.
0149: *
0150: * @since Java 3D 1.3.1
0151: */
0152: // To support a back door for DVR support.
0153: public static Viewer removeViewerMapEntry(View view) {
0154: Viewer viewer = null;
0155: synchronized (viewerMap) {
0156:
0157: viewer = (Viewer) (viewerMap.remove(view));
0158: }
0159: // System.out.println("viewerMap.size() " + viewerMap.size());
0160:
0161: return viewer;
0162: }
0163:
0164: /**
0165: * Removes all Viewer mappings from the Viewer map.
0166: *
0167: * Note: This method is targeted for SUN framebuffer XVR-4000 and later
0168: * hardware that support video size extension.
0169: *
0170: * @since Java 3D 1.3.1
0171: */
0172: // To support a back door for DVR support.
0173: public static void clearViewerMap() {
0174: synchronized (viewerMap) {
0175: viewerMap.clear();
0176: }
0177: // System.out.println("clearViewerMap - viewerMap.size() " + viewerMap.size());
0178:
0179: }
0180:
0181: /**
0182: * Returns a status flag indicating whether or not dynamic video size
0183: * is enabled.
0184: *
0185: * Note: This method is targeted for SUN framebuffer XVR-4000 and later
0186: * hardware that support video size extension.
0187: *
0188: * @since Java 3D 1.3.1
0189: */
0190: // To support a back door for DVR support.
0191: public boolean isDvrEnabled() {
0192: return doDvr;
0193: }
0194:
0195: /**
0196: * Turns on or off dynamic video size.
0197: *
0198: * Note: This method is targeted for SUN framebuffer XVR-4000 and later
0199: * hardware that support video size extension.
0200: *
0201: * @param dvr enables or disables dynamic video size.
0202: *
0203: * @since Java 3D 1.3.1
0204: */
0205: // To support a back door for DVR support.
0206: public void setDvrEnable(boolean dvr) {
0207: doDvr = dvr;
0208: view.repaint();
0209:
0210: }
0211:
0212: /**
0213: * Retrieves the dynamic video resize factor of this
0214: * viewer.
0215: *
0216: * Note: This method is targeted for SUN framebuffer XVR-4000 and later
0217: * hardware that support video size extension.
0218: *
0219: * @since Java 3D 1.3.1
0220: */
0221: // To support a back door for DVR support.
0222: public float getDvrFactor() {
0223: return dvrFactor;
0224: }
0225:
0226: /**
0227: * Set the dynamic video resize factor for this viewer.
0228: *
0229: * Note: This method is targeted for SUN framebuffer XVR-4000 and later
0230: * hardware that support video size extension.
0231: *
0232: * @param dvr set the dynamic video resize factor for this viewer.
0233: *
0234: * @since Java 3D 1.3.1
0235: */
0236: // To support a back door for DVR support.
0237: public void setDvrFactor(float dvr) {
0238: dvrFactor = dvr;
0239: view.repaint();
0240:
0241: }
0242:
0243: /**
0244: * Turns on or off dynamic video resize compensation.
0245: *
0246: * Note: This method is targeted for SUN framebuffer XVR-4000 and later
0247: * hardware that support video size extension.
0248: *
0249: * @param dvrRCE enables or disables dynamic video resize compensation.
0250: *
0251: * @since Java 3D 1.3.1
0252: */
0253: // To support a back door for DVR support.
0254: public void setDvrResizeCompensationEnable(boolean dvrRCE) {
0255: doDvrResizeCompensation = dvrRCE;
0256: view.repaint();
0257: }
0258:
0259: /**
0260: * Returns a status flag indicating whether or not dynamic video resize
0261: * compensation is enabled.
0262: *
0263: * Note: This method is targeted for SUN framebuffer XVR-4000 and later
0264: * hardware that support video size extension.
0265: *
0266: * @since Java 3D 1.3.1
0267: */
0268: // To support a back door for DVR support.
0269: public boolean getDvrResizeCompensationEnable() {
0270: return doDvrResizeCompensation;
0271: }
0272:
0273: /**
0274: * Creates a default viewer object. The default values are used to create
0275: * the PhysicalBody and PhysicalEnvironment. A single RGB, double buffered
0276: * and depth buffered Canvas3D object is created. The View is created
0277: * with a front clip distance of 0.1f and a back clip distance of 10.0f.
0278: */
0279: public Viewer() {
0280: // Call main constructor with default values.
0281: this (null, null, null, true);
0282: }
0283:
0284: /**
0285: * Creates a default viewer object. The default values are used to create
0286: * the PhysicalBody and PhysicalEnvironment. The View is created
0287: * with a front clip distance of 0.1f and a back clip distance of 10.0f.
0288: *
0289: * @param userCanvas the Canvas3D object to be used for rendering;
0290: * if this is null then a single RGB, double buffered and depth buffered
0291: * Canvas3D object is created
0292: * @since Java3D 1.1
0293: */
0294: public Viewer(Canvas3D userCanvas) {
0295: // Call main constructor.
0296: this (userCanvas == null ? null : new Canvas3D[] { userCanvas },
0297: null, null, true);
0298: }
0299:
0300: /**
0301: * Creates a default viewer object. The default values are used to create
0302: * the PhysicalBody and PhysicalEnvironment. The View is created
0303: * with a front clip distance of 0.1f and a back clip distance of 10.0f.
0304: *
0305: * @param userCanvases the Canvas3D objects to be used for rendering;
0306: * if this is null then a single RGB, double buffered and depth buffered
0307: * Canvas3D object is created
0308: * @since Java3D 1.3
0309: */
0310: public Viewer(Canvas3D[] userCanvases) {
0311: this (userCanvases, null, null, true);
0312: }
0313:
0314: /**
0315: * Creates a viewer object. The Canvas3D objects, PhysicalEnvironment, and
0316: * PhysicalBody are taken from the arguments.
0317: *
0318: * @param userCanvases the Canvas3D objects to be used for rendering;
0319: * if this is null then a single RGB, double buffered and depth buffered
0320: * Canvas3D object is created
0321: * @param userBody the PhysicalBody to use for this Viewer; if it is
0322: * null, a default PhysicalBody object is created
0323: * @param userEnvironment the PhysicalEnvironment to use for this Viewer;
0324: * if it is null, a default PhysicalEnvironment object is created
0325: * @param setVisible determines if the Frames should be set to visible once created
0326: * @since Java3D 1.3
0327: */
0328: public Viewer(Canvas3D[] userCanvases, PhysicalBody userBody,
0329: PhysicalEnvironment userEnvironment, boolean setVisible) {
0330:
0331: if (userBody == null) {
0332: physicalBody = new PhysicalBody();
0333: } else {
0334: physicalBody = userBody;
0335: }
0336:
0337: if (userEnvironment == null) {
0338: physicalEnvironment = new PhysicalEnvironment();
0339: } else {
0340: physicalEnvironment = userEnvironment;
0341: }
0342:
0343: // Create Canvas3D object if none was passed in.
0344: if (userCanvases == null) {
0345: GraphicsConfiguration config = ConfiguredUniverse
0346: .getPreferredConfiguration();
0347:
0348: canvases = new Canvas3D[1];
0349: canvases[0] = new Canvas3D(config);
0350: try {
0351: canvases[0].setFocusable(true);
0352: } catch (NoSuchMethodError e) {
0353: }
0354: createFramesAndPanels(setVisible);
0355: } else {
0356: canvases = new Canvas3D[userCanvases.length];
0357: for (int i = 0; i < userCanvases.length; i++) {
0358: canvases[i] = userCanvases[i];
0359: try {
0360: canvases[i].setFocusable(true);
0361: } catch (NoSuchMethodError e) {
0362: }
0363: }
0364: }
0365:
0366: // Create a View and attach the Canvas3D and the physical
0367: // body and environment to the view.
0368: view = new View();
0369:
0370: // Fix to issue 424
0371: view.setUserHeadToVworldEnable(true);
0372:
0373: // Add it to the Viewer's HashMap.
0374: synchronized (viewerMap) {
0375: Viewer.viewerMap.put(view, this );
0376: }
0377: for (int i = 0; i < canvases.length; i++) {
0378: view.addCanvas3D(canvases[i]);
0379: }
0380: view.setPhysicalBody(physicalBody);
0381: view.setPhysicalEnvironment(physicalEnvironment);
0382: }
0383:
0384: /**
0385: * Creates a default Viewer object. The default values are used to create
0386: * the PhysicalEnvironment and PhysicalBody. A single RGB, double buffered
0387: * and depth buffered Canvas3D object is created. The View is created
0388: * with a front clip distance of 0.1f and a back clip distance of 10.0f.
0389: *
0390: * @param userConfig the URL of the user configuration file used to
0391: * initialize the PhysicalBody object; this is always ignored
0392: * @since Java3D 1.1
0393: * @deprecated create a ConfiguredUniverse to use a configuration file
0394: */
0395: public Viewer(URL userConfig) {
0396: // Call main constructor.
0397: this (null, userConfig);
0398: }
0399:
0400: /**
0401: * Creates a default viewer object. The default values are used to create
0402: * the PhysicalEnvironment and PhysicalBody. The View is created
0403: * with a front clip distance of 0.1f and a back clip distance of 10.0f.
0404: *
0405: * @param userCanvas the Canvas3D object to be used for rendering;
0406: * if this is null then a single RGB, double buffered and depth buffered
0407: * Canvas3D object is created
0408: * @param userConfig the URL of the user configuration file used to
0409: * initialize the PhysicalBody object; this is always ignored
0410: * @since Java3D 1.1
0411: * @deprecated create a ConfiguredUniverse to use a configuration file
0412: */
0413: public Viewer(Canvas3D userCanvas, URL userConfig) {
0414: // Only one PhysicalBody per Universe.
0415: if (physicalBody == null) {
0416: physicalBody = new PhysicalBody();
0417: }
0418:
0419: // Only one PhysicalEnvironment per Universe.
0420: if (physicalEnvironment == null) {
0421: physicalEnvironment = new PhysicalEnvironment();
0422: }
0423:
0424: // Create Canvas3D object if none was passed in.
0425: if (userCanvas == null) {
0426: GraphicsConfiguration config = SimpleUniverse
0427: .getPreferredConfiguration();
0428:
0429: canvases = new Canvas3D[1];
0430: canvases[0] = new Canvas3D(config);
0431: createFramesAndPanels(true);
0432: } else {
0433: canvases = new Canvas3D[1];
0434: canvases[0] = userCanvas;
0435: }
0436:
0437: try {
0438: canvases[0].setFocusable(true);
0439: } catch (NoSuchMethodError e) {
0440: }
0441:
0442: // Create a View and attach the Canvas3D and the physical
0443: // body and environment to the view.
0444: view = new View();
0445:
0446: // Fix to issue 424
0447: view.setUserHeadToVworldEnable(true);
0448:
0449: // Add it to the Viewer's HashMap.
0450: synchronized (viewerMap) {
0451: Viewer.viewerMap.put(view, this );
0452: }
0453: view.addCanvas3D(canvases[0]);
0454: view.setPhysicalBody(physicalBody);
0455: view.setPhysicalEnvironment(physicalEnvironment);
0456: }
0457:
0458: /**
0459: * Package-scoped constructor to create a Viewer from the configuration
0460: * objects provided by ConfiguredUniverse.
0461: *
0462: * @param cs array of ConfigScreen objects containing configuration
0463: * information for the physical screens in the environment
0464: * @param cv ConfigView object containing configuration information about
0465: * the view to be created using the given screens
0466: * @param setVisible if true, call setVisible(true) on all created Window
0467: * components; otherwise, they remain invisible
0468: */
0469: Viewer(ConfigScreen[] cs, ConfigView cv, boolean setVisible) {
0470:
0471: // Retrieve the J3D View object from the ConfigView object.
0472: // The physical body and environment have already been set there.
0473: view = cv.j3dView;
0474: // Add it to the Viewer's HashMap.
0475: synchronized (viewerMap) {
0476: Viewer.viewerMap.put(view, this );
0477: }
0478:
0479: // Set this Viewer's references to the physical body and environment.
0480: physicalBody = cv.physicalBody;
0481: physicalEnvironment = cv.physicalEnvironment;
0482:
0483: // Get available screen devices.
0484: //
0485: // When running with JDK 1.3.1 or older under the X Window System with
0486: // Xinerama enabled, a single screen device is returned which is
0487: // actually a virtual screen spanning all the physical screens in the
0488: // X display. These can only be configured as a single planar screen
0489: // in the configuration file.
0490: //
0491: // JDK 1.4 and newer returns a screen device for each physical screen,
0492: // allowing them to configured as distinct screens with arbitrary
0493: // orientations relative to each other.
0494: //
0495: GraphicsDevice[] devices;
0496: GraphicsEnvironment graphicsEnv;
0497:
0498: graphicsEnv = GraphicsEnvironment.getLocalGraphicsEnvironment();
0499: devices = graphicsEnv.getScreenDevices();
0500:
0501: if (devices == null)
0502: throw new RuntimeException(
0503: "No screen devices available in local environment");
0504:
0505: if (debug) {
0506: System.out.println("Viewer: GraphicsEnvironment returned "
0507: + devices.length + " GraphicsDevice object"
0508: + (devices.length == 1 ? "" : "s"));
0509:
0510: for (int i = 0; i < devices.length; i++) {
0511: System.out.println(devices[i]
0512: + "\n"
0513: + devices[i].getDefaultConfiguration()
0514: .getBounds() + "\n");
0515: }
0516: }
0517:
0518: // Allocate the arrays of components to be used. AWT Windows are used
0519: // to hold either a JFrame or a JWindow.
0520: canvases = new Canvas3D[cs.length];
0521: j3dJFrames = new JFrame[cs.length];
0522: j3dJPanels = new JPanel[cs.length];
0523: j3dWindows = new Window[cs.length];
0524:
0525: // Create a graphics template requesting the desired capabilities.
0526: GraphicsConfigTemplate3D tpl3D = new GraphicsConfigTemplate3D();
0527: if (cv.stereoEnable) {
0528: tpl3D.setStereo(tpl3D.PREFERRED);
0529: }
0530: if (cv.antialiasingEnable) {
0531: tpl3D.setSceneAntialiasing(tpl3D.PREFERRED);
0532: }
0533:
0534: // Loop through all screens. Set up the Swing component structure and
0535: // the configured attributes for the Canvas3D and Screen3D associated
0536: // with each screen.
0537: for (int i = 0; i < cs.length; i++) {
0538: if (cs[i].frameBufferNumber >= devices.length)
0539: throw new ArrayIndexOutOfBoundsException(cs[i]
0540: .errorMessage(cs[i].creatingCommand, "Screen "
0541: + cs[i].frameBufferNumber
0542: + " is invalid; "
0543: + (devices.length - 1)
0544: + " is the maximum local index."));
0545:
0546: Rectangle bounds;
0547: Container contentPane;
0548: GraphicsConfiguration cfg = devices[cs[i].frameBufferNumber]
0549: .getBestConfiguration(tpl3D);
0550:
0551: if (cfg == null)
0552: throw new RuntimeException(
0553: "No GraphicsConfiguration on screen "
0554: + cs[i].frameBufferNumber
0555: + " conforms to template");
0556:
0557: // Workaround for Issue 316 - use the default config for the screen
0558: GraphicsConfiguration defCfg = cfg.getDevice()
0559: .getDefaultConfiguration();
0560: bounds = defCfg.getBounds();
0561: cs[i].j3dJFrame = j3dJFrames[i] = new JFrame(
0562: cs[i].instanceName, defCfg);
0563:
0564: if (cs[i].noBorderFullScreen) {
0565: try {
0566: // Required by JDK 1.4 AWT for borderless full screen.
0567: j3dJFrames[i].setUndecorated(true);
0568:
0569: cs[i].j3dWindow = j3dWindows[i] = j3dJFrames[i];
0570: contentPane = j3dJFrames[i].getContentPane();
0571: } catch (NoSuchMethodError e) {
0572: // Handle borderless full screen running under JDK 1.3.1.
0573: JWindow jwin = new JWindow(j3dJFrames[i], cfg);
0574:
0575: cs[i].j3dWindow = j3dWindows[i] = jwin;
0576: contentPane = jwin.getContentPane();
0577: }
0578:
0579: contentPane.setLayout(new BorderLayout());
0580: j3dWindows[i].setSize(bounds.width, bounds.height);
0581: j3dWindows[i].setLocation(bounds.x, bounds.y);
0582: } else {
0583: cs[i].j3dWindow = j3dWindows[i] = j3dJFrames[i];
0584:
0585: contentPane = j3dJFrames[i].getContentPane();
0586: contentPane.setLayout(new BorderLayout());
0587:
0588: if (cs[i].fullScreen) {
0589: j3dWindows[i].setSize(bounds.width, bounds.height);
0590: j3dWindows[i].setLocation(bounds.x, bounds.y);
0591: } else {
0592: j3dWindows[i].setSize(cs[i].windowWidthInPixels,
0593: cs[i].windowHeightInPixels);
0594: j3dWindows[i].setLocation(bounds.x + cs[i].windowX,
0595: bounds.y + cs[i].windowY);
0596: }
0597: }
0598:
0599: // Create a Canvas3D and set its attributes.
0600: cs[i].j3dCanvas = canvases[i] = new Canvas3D(cfg);
0601: canvases[i].setStereoEnable(cv.stereoEnable);
0602: canvases[i]
0603: .setMonoscopicViewPolicy(cs[i].monoscopicViewPolicy);
0604:
0605: // Get the Screen3D and set its attributes.
0606: Screen3D screen = canvases[i].getScreen3D();
0607:
0608: if (cs[i].physicalScreenWidth != 0.0)
0609: screen
0610: .setPhysicalScreenWidth(cs[i].physicalScreenWidth);
0611:
0612: if (cs[i].physicalScreenHeight != 0.0)
0613: screen
0614: .setPhysicalScreenHeight(cs[i].physicalScreenHeight);
0615:
0616: if (cs[i].trackerBaseToImagePlate != null)
0617: screen.setTrackerBaseToImagePlate(new Transform3D(
0618: cs[i].trackerBaseToImagePlate));
0619:
0620: if (cs[i].headTrackerToLeftImagePlate != null)
0621: screen.setHeadTrackerToLeftImagePlate(new Transform3D(
0622: cs[i].headTrackerToLeftImagePlate));
0623:
0624: if (cs[i].headTrackerToRightImagePlate != null)
0625: screen.setHeadTrackerToRightImagePlate(new Transform3D(
0626: cs[i].headTrackerToRightImagePlate));
0627:
0628: // Put the Canvas3D into a JPanel.
0629: cs[i].j3dJPanel = j3dJPanels[i] = new JPanel();
0630: j3dJPanels[i].setLayout(new BorderLayout());
0631: j3dJPanels[i].add("Center", canvases[i]);
0632:
0633: // Put the JPanel into the content pane used by JWindow or JFrame.
0634: contentPane.add("Center", j3dJPanels[i]);
0635:
0636: // Attach the Canvas3D to the View.
0637: view.addCanvas3D(canvases[i]);
0638:
0639: // Add a windowListener to detect the window close event.
0640: addWindowCloseListener(j3dWindows[i]);
0641:
0642: // Set Canvas3D focus as required by the JDK 1.4 focus model for
0643: // full screen frames. JDK 1.3.1 sets the focus automatically for
0644: // full screen components.
0645: try {
0646: canvases[i].setFocusable(true);
0647: } catch (NoSuchMethodError e) {
0648: }
0649:
0650: if (debug) {
0651: System.out
0652: .println("Viewer: created Canvas3D for screen "
0653: + cs[i].frameBufferNumber
0654: + " with size\n "
0655: + j3dWindows[i].getSize());
0656: System.out.println("Screen3D[" + i
0657: + "]: size in pixels ("
0658: + screen.getSize().width + " x "
0659: + screen.getSize().height + ")");
0660: System.out.println(" physical size in meters: ("
0661: + screen.getPhysicalScreenWidth() + " x "
0662: + screen.getPhysicalScreenHeight() + ")");
0663: System.out.println(" hashCode = " + screen.hashCode()
0664: + "\n");
0665: }
0666: }
0667:
0668: if (setVisible)
0669: // Call setVisible() on all created Window components.
0670: setVisible(true);
0671: }
0672:
0673: // Create the JFrames and JPanels for application-supplied Canvas3D
0674: // objects.
0675: private void createFramesAndPanels(boolean setVisible) {
0676: j3dJFrames = new JFrame[canvases.length];
0677: j3dJPanels = new JPanel[canvases.length];
0678: j3dWindows = new Window[canvases.length];
0679:
0680: for (int i = 0; i < canvases.length; i++) {
0681: j3dWindows[i] = j3dJFrames[i] = new JFrame();
0682: j3dJFrames[i].getContentPane()
0683: .setLayout(new BorderLayout());
0684: j3dJFrames[i].setSize(256, 256);
0685:
0686: // Put the Canvas3D into a JPanel.
0687: j3dJPanels[i] = new JPanel();
0688: j3dJPanels[i].setLayout(new BorderLayout());
0689: j3dJPanels[i].add("Center", canvases[i]);
0690: j3dJFrames[i].getContentPane().add("Center", j3dJPanels[i]);
0691: if (setVisible) {
0692: j3dJFrames[i].setVisible(true);
0693: }
0694: addWindowCloseListener(j3dJFrames[i]);
0695: }
0696: }
0697:
0698: /**
0699: * Call setVisible() on all Window components created by this Viewer.
0700: *
0701: * @param visible boolean to be passed to the setVisible() calls on the
0702: * Window components created by this Viewer
0703: * @since Java3D 1.3
0704: */
0705: public void setVisible(boolean visible) {
0706: for (int i = 0; i < j3dWindows.length; i++) {
0707: j3dWindows[i].setVisible(visible);
0708: }
0709: }
0710:
0711: /**
0712: * Returns the View object associated with the Viewer object.
0713: *
0714: * @return The View object of this Viewer.
0715: */
0716: public View getView() {
0717: return view;
0718: }
0719:
0720: /**
0721: * Set the ViewingPlatform object used by this Viewer.
0722: *
0723: * @param platform The ViewingPlatform object to set for this
0724: * Viewer object. Use null to unset the current value and
0725: * not assign assign a new ViewingPlatform object.
0726: */
0727: public void setViewingPlatform(ViewingPlatform platform) {
0728: if (viewingPlatform != null) {
0729: viewingPlatform.removeViewer(this );
0730: }
0731:
0732: viewingPlatform = platform;
0733:
0734: if (platform != null) {
0735: view.attachViewPlatform(platform.getViewPlatform());
0736: platform.addViewer(this );
0737:
0738: if (avatar != null)
0739: viewingPlatform.setAvatar(this , avatar);
0740: } else
0741: view.attachViewPlatform(null);
0742: }
0743:
0744: /**
0745: * Get the ViewingPlatform object used by this Viewer.
0746: *
0747: * @return The ViewingPlatform object used by this
0748: * Viewer object.
0749: */
0750: public ViewingPlatform getViewingPlatform() {
0751: return viewingPlatform;
0752: }
0753:
0754: /**
0755: * Sets the geometry to be associated with the viewer's avatar. The
0756: * avatar is the geometry used to represent the viewer in the virtual
0757: * world.
0758: *
0759: * @param avatar The geometry to associate with this Viewer object.
0760: * Passing in null will cause any geometry associated with the Viewer
0761: * to be removed from the scen graph.
0762: */
0763: public void setAvatar(ViewerAvatar avatar) {
0764: // Just return if trying to set the same ViewerAvatar object.
0765: if (this .avatar == avatar)
0766: return;
0767:
0768: this .avatar = avatar;
0769: if (viewingPlatform != null)
0770: viewingPlatform.setAvatar(this , this .avatar);
0771: }
0772:
0773: /**
0774: * Gets the geometry associated with the viewer's avatar. The
0775: * avatar is the geometry used to represent the viewer in the virtual
0776: * world.
0777: *
0778: * @return The root of the scene graph that is used to represent the
0779: * viewer's avatar.
0780: */
0781: public ViewerAvatar getAvatar() {
0782: return avatar;
0783: }
0784:
0785: /**
0786: * Returns the PhysicalBody object associated with the Viewer object.
0787: *
0788: * @return A reference to the PhysicalBody object.
0789: */
0790: public PhysicalBody getPhysicalBody() {
0791: return physicalBody;
0792: }
0793:
0794: /**
0795: * Returns the PhysicalEnvironment object associated with the Viewer
0796: * object.
0797: *
0798: * @return A reference to the PhysicalEnvironment object.
0799: */
0800: public PhysicalEnvironment getPhysicalEnvironment() {
0801: return physicalEnvironment;
0802: }
0803:
0804: /**
0805: * Returns the 0th Canvas3D object associated with this Viewer object
0806: *
0807: * @return a reference to the 0th Canvas3D object associated with this
0808: * Viewer object
0809: * @since Java3D 1.3
0810: */
0811: public Canvas3D getCanvas3D() {
0812: return canvases[0];
0813: }
0814:
0815: /**
0816: * Returns the Canvas3D object at the specified index associated with
0817: * this Viewer object.
0818: *
0819: * @param canvasNum the index of the Canvas3D object to retrieve;
0820: * if there is no Canvas3D object for the given index, null is returned
0821: * @return a reference to a Canvas3D object associated with this
0822: * Viewer object
0823: * @since Java3D 1.3
0824: */
0825: public Canvas3D getCanvas3D(int canvasNum) {
0826: if (canvasNum > canvases.length) {
0827: return null;
0828: }
0829: return canvases[canvasNum];
0830: }
0831:
0832: /**
0833: * Returns all the Canvas3D objects associated with this Viewer object.
0834: *
0835: * @return an array of references to the Canvas3D objects associated with
0836: * this Viewer object
0837: * @since Java3D 1.3
0838: */
0839: public Canvas3D[] getCanvas3Ds() {
0840: Canvas3D[] ret = new Canvas3D[canvases.length];
0841: for (int i = 0; i < canvases.length; i++) {
0842: ret[i] = canvases[i];
0843: }
0844: return ret;
0845: }
0846:
0847: /**
0848: * Returns the canvas associated with this Viewer object.
0849: * @deprecated superceded by getCanvas3D()
0850: */
0851: public Canvas3D getCanvases() {
0852: return getCanvas3D();
0853: }
0854:
0855: /**
0856: * This method is no longer supported since Java 3D 1.3.
0857: * @exception UnsupportedOperationException if called.
0858: * @deprecated AWT Frame components are no longer created by the
0859: * Viewer class.
0860: */
0861: public Frame getFrame() {
0862: throw new UnsupportedOperationException(
0863: "AWT Frame components are not created by the Viewer class");
0864: }
0865:
0866: /**
0867: * Returns the JFrame object created by this Viewer object at the
0868: * specified index. If a Viewer is constructed without any Canvas3D
0869: * objects then the Viewer object will create a Canva3D object, a JPanel
0870: * containing the Canvas3D object, and a JFrame to place the JPanel in.
0871: * <p>
0872: * NOTE: When running under JDK 1.4 or newer, the JFrame always directly
0873: * contains the JPanel which contains the Canvas3D. When running under
0874: * JDK 1.3.1 and creating a borderless full screen through a configuration
0875: * file, the JFrame will instead contain a JWindow which will contain the
0876: * JPanel and Canvas3D.
0877: * <p>
0878: * @param frameNum the index of the JFrame object to retrieve;
0879: * if there is no JFrame object for the given index, null is returned
0880: * @return a reference to JFrame object created by this Viewer object
0881: * @since Java3D 1.3
0882: */
0883: public JFrame getJFrame(int frameNum) {
0884: if (j3dJFrames == null || frameNum > j3dJFrames.length) {
0885: return (null);
0886: }
0887: return j3dJFrames[frameNum];
0888: }
0889:
0890: /**
0891: * Returns all the JFrames created by this Viewer object. If a Viewer is
0892: * constructed without any Canvas3D objects then the Viewer object will
0893: * create a Canva3D object, a JPanel containing the Canvas3D object, and a
0894: * JFrame to place the JPanel in.<p>
0895: *
0896: * NOTE: When running under JDK 1.4 or newer, the JFrame always directly
0897: * contains the JPanel which contains the Canvas3D. When running under
0898: * JDK 1.3.1 and creating a borderless full screen through a configuration
0899: * file, the JFrame will instead contain a JWindow which will contain the
0900: * JPanel and Canvas3D.<p>
0901: *
0902: * @return an array of references to the JFrame objects created by
0903: * this Viewer object, or null if no JFrame objects were created
0904: * @since Java3D 1.3
0905: */
0906: public JFrame[] getJFrames() {
0907: if (j3dJFrames == null)
0908: return null;
0909:
0910: JFrame[] ret = new JFrame[j3dJFrames.length];
0911: for (int i = 0; i < j3dJFrames.length; i++) {
0912: ret[i] = j3dJFrames[i];
0913: }
0914: return ret;
0915: }
0916:
0917: /**
0918: * This method is no longer supported since Java 3D 1.3.
0919: * @exception UnsupportedOperationException if called.
0920: * @deprecated AWT Panel components are no longer created by the
0921: * Viewer class.
0922: */
0923: public Panel getPanel() {
0924: throw new UnsupportedOperationException(
0925: "AWT Panel components are not created by the Viewer class");
0926: }
0927:
0928: /**
0929: * Returns the JPanel object created by this Viewer object at the
0930: * specified index. If a Viewer is constructed without any Canvas3D
0931: * objects then the Viewer object will create a Canva3D object and a
0932: * JPanel into which to place the Canvas3D object.
0933: *
0934: * @param panelNum the index of the JPanel object to retrieve;
0935: * if there is no JPanel object for the given index, null is returned
0936: * @return a reference to a JPanel object created by this Viewer object
0937: * @since Java3D 1.3
0938: */
0939: public JPanel getJPanel(int panelNum) {
0940: if (j3dJPanels == null || panelNum > j3dJPanels.length) {
0941: return (null);
0942: }
0943: return j3dJPanels[panelNum];
0944: }
0945:
0946: /**
0947: * Returns all the JPanel objects created by this Viewer object. If a
0948: * Viewer is constructed without any Canvas3D objects then the Viewer
0949: * object will create a Canva3D object and a JPanel into which to place
0950: * the Canvas3D object.
0951: *
0952: * @return an array of references to the JPanel objects created by
0953: * this Viewer object, or null or no JPanel objects were created
0954: * @since Java3D 1.3
0955: */
0956: public JPanel[] getJPanels() {
0957: if (j3dJPanels == null)
0958: return null;
0959:
0960: JPanel[] ret = new JPanel[j3dJPanels.length];
0961: for (int i = 0; i < j3dJPanels.length; i++) {
0962: ret[i] = j3dJPanels[i];
0963: }
0964: return ret;
0965: }
0966:
0967: /**
0968: * Used to create and initialize a default AudioDevice3D used for sound
0969: * rendering.
0970: *
0971: * @return reference to created AudioDevice, or null if error occurs.
0972: */
0973: public AudioDevice createAudioDevice() {
0974: if (physicalEnvironment == null) {
0975: System.err
0976: .println("Java 3D: createAudioDevice: physicalEnvironment is null");
0977: return null;
0978: }
0979:
0980: try {
0981: String audioDeviceClassName = (String) java.security.AccessController
0982: .doPrivileged(new java.security.PrivilegedAction() {
0983: public Object run() {
0984: return System
0985: .getProperty("j3d.audiodevice");
0986: }
0987: });
0988:
0989: if (audioDeviceClassName == null) {
0990: throw new UnsupportedOperationException(
0991: "No AudioDevice specified");
0992: }
0993:
0994: // Issue 341: try the current class loader first before trying the
0995: // system class loader
0996: Class audioDeviceClass = null;
0997: try {
0998: audioDeviceClass = Class.forName(audioDeviceClassName);
0999: } catch (ClassNotFoundException ex) {
1000: // Ignore excpetion and try system class loader
1001: }
1002:
1003: if (audioDeviceClass == null) {
1004: ClassLoader audioDeviceClassLoader = (ClassLoader) java.security.AccessController
1005: .doPrivileged(new java.security.PrivilegedAction() {
1006: public Object run() {
1007: return ClassLoader
1008: .getSystemClassLoader();
1009: }
1010: });
1011:
1012: if (audioDeviceClassLoader == null) {
1013: throw new IllegalStateException(
1014: "System ClassLoader is null");
1015: }
1016:
1017: audioDeviceClass = Class.forName(audioDeviceClassName,
1018: true, audioDeviceClassLoader);
1019: }
1020:
1021: Class physEnvClass = PhysicalEnvironment.class;
1022: Constructor audioDeviceConstructor = audioDeviceClass
1023: .getConstructor(new Class[] { physEnvClass });
1024: PhysicalEnvironment[] args = new PhysicalEnvironment[] { physicalEnvironment };
1025: AudioEngine3DL2 mixer = (AudioEngine3DL2) audioDeviceConstructor
1026: .newInstance((Object[]) args);
1027: mixer.initialize();
1028: return mixer;
1029: } catch (Throwable e) {
1030: e.printStackTrace();
1031: physicalEnvironment.setAudioDevice(null);
1032: System.err.println("Java 3D: audio is disabled");
1033: return null;
1034: }
1035: }
1036:
1037: /**
1038: * Returns the Universe to which this Viewer is attached
1039: *
1040: * @return the Universe to which this Viewer is attached
1041: * @since Java 3D 1.3
1042: */
1043: public SimpleUniverse getUniverse() {
1044: return getViewingPlatform().getUniverse();
1045: }
1046:
1047: /*
1048: * Exit if run as an application
1049: */
1050: void addWindowCloseListener(Window win) {
1051: SecurityManager sm = System.getSecurityManager();
1052: boolean doExit = true;
1053:
1054: if (sm != null) {
1055: try {
1056: sm.checkExit(0);
1057: } catch (SecurityException e) {
1058: doExit = false;
1059: }
1060: }
1061: final boolean _doExit = doExit;
1062:
1063: win.addWindowListener(new WindowAdapter() {
1064: public void windowClosing(WindowEvent winEvent) {
1065: Window w = winEvent.getWindow();
1066: w.setVisible(false);
1067: try {
1068: w.dispose();
1069: } catch (IllegalStateException e) {
1070: }
1071: if (_doExit) {
1072: System.exit(0);
1073: }
1074: }
1075: });
1076: }
1077: }
|