Java tutorial
/* * %Z%%M% %I% %E% %U% * * ************************************************************** "Copyright (c) * 2001 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * -Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * -Redistribution in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Sun Microsystems, Inc. or the names of contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY * OF SUCH DAMAGES. * * You acknowledge that Software is not designed,licensed or intended for use in * the design, construction, operation or maintenance of any nuclear facility." * * *************************************************************************** */ import java.applet.Applet; import java.awt.BorderLayout; import java.awt.GraphicsConfiguration; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.text.NumberFormat; import javax.media.j3d.Appearance; import javax.media.j3d.BoundingSphere; import javax.media.j3d.BranchGroup; import javax.media.j3d.Canvas3D; import javax.media.j3d.Group; import javax.media.j3d.Texture; import javax.media.j3d.Texture2D; import javax.media.j3d.Transform3D; import javax.media.j3d.View; import javax.swing.ButtonGroup; import javax.swing.JCheckBox; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JRadioButton; import javax.vecmath.AxisAngle4f; import javax.vecmath.Color3f; import javax.vecmath.Color4f; import javax.vecmath.Point3d; import javax.vecmath.Point3f; import javax.vecmath.Vector3f; import com.sun.j3d.utils.applet.MainFrame; import com.sun.j3d.utils.behaviors.vp.OrbitBehavior; import com.sun.j3d.utils.geometry.Sphere; import com.sun.j3d.utils.image.TextureLoader; import com.sun.j3d.utils.universe.SimpleUniverse; import com.sun.j3d.utils.universe.ViewingPlatform; public class TexBug extends Applet implements ActionListener, Java3DExplorerConstants { // Scene graph items SimpleUniverse u; Group scene; Appearance appearance; // temp image grabber boolean isApplication; Canvas3D canvas; View view; // Texture2D Texture2D texture; TextureLoader texLoader; int texWidth; int texHeight; int texFormat; boolean texEnable; String texEnableString = "Enable Texture"; String texMipEnableString = "Enable MipMap"; JCheckBox texEnableCheckBox; int texBoundaryModeS; int texBoundaryModeT; String wrapString = "WRAP"; String clampString = "CLAMP"; String texBoundarySWrapString = "S WRAP"; String texBoundarySClampString = "S CLAMP"; String texBoundaryTWrapString = "T WRAP"; String texBoundaryTClampString = "T CLAMP"; Color4f texBoundaryColor; int texMinFilter; int texMagFilter; String texFilterBasePointString = "BASE_LEVEL_POINT"; String texFilterBaseLinearString = "BASE_LEVEL_LINEAR"; String texFilterMultiPointString = "MULTI_LEVEL_POINT"; String texFilterMultiLinearString = "MULTI_LEVEL_LINEAR"; String texMinFilterBasePointString = "min base point"; String texMinFilterBaseLinearString = "min base linear"; String texMinFilterMultiPointString = "mag multi point"; String texMinFilterMultiLinearString = "mag multi linear"; String texMinFilterFastestString = "min fastest"; String texMinFilterNicestString = "min nicest"; String texMagFilterBasePointString = "mag base point"; String texMagFilterBaseLinearString = "mag base linear"; String texMagFilterNicestString = "mag nicest"; String texMagFilterFastestString = "mag fastest"; int texMipMapMode; String texMipMapBaseString = "BASE_LEVEL"; String texMipMapMultiString = "MULTI_LEVEL_MIPMAP"; // Temporaries that are reused Transform3D tmpTrans = new Transform3D(); Vector3f tmpVector = new Vector3f(); AxisAngle4f tmpAxisAngle = new AxisAngle4f(); // colors Color3f black = new Color3f(0.0f, 0.0f, 0.0f); Color3f red = new Color3f(1.0f, 0.0f, 0.0f); Color3f green = new Color3f(0.0f, 1.0f, 0.0f); Color3f blue = new Color3f(0.0f, 0.0f, 1.0f); Color3f cyan = new Color3f(0.0f, 1.0f, 1.0f); Color3f magenta = new Color3f(1.0f, 0.0f, 1.0f); Color3f yellow = new Color3f(1.0f, 1.0f, 0.0f); Color3f white = new Color3f(1.0f, 1.0f, 1.0f); Color3f darkGrey = new Color3f(0.2f, 0.2f, 0.2f); Color3f grey = new Color3f(0.5f, 0.5f, 0.5f); // geometric constant Point3f origin = new Point3f(); Vector3f yAxis = new Vector3f(0.0f, 1.0f, 0.0f); // NumberFormat to print out floats with only two digits NumberFormat nf; // Base for URLs, used to handle application/applet split String codeBaseString = null; // create the appearance and it's components void setupAppearance() { appearance = new Appearance(); // Texture2D // set the values to the defaults texEnable = false; texMipMapMode = Texture.BASE_LEVEL; texBoundaryModeS = Texture.WRAP; texBoundaryModeT = Texture.WRAP; texMinFilter = Texture.BASE_LEVEL_POINT; texMagFilter = Texture.BASE_LEVEL_POINT; texBoundaryColor = new Color4f(1.0f, 1.0f, 1.0f, 1.0f); // set up the appearance to allow the texture to be changed appearance.setCapability(Appearance.ALLOW_TEXTURE_WRITE); // set the texture setTexture(); } int powerOfTwo(int value) { int retval = 2; while (retval < value) { retval *= 2; } return retval; } // create a Texture2D using the current values from the GUI // and attach it to the appearance void setTexture() { // set up the image using the TextureLoader java.net.URL imageURL = null; try { imageURL = new java.net.URL(codeBaseString + "earth.jpg"); //imageURL = new java.net.URL(codeBaseString + // "decal_textures/fish1.gif"); } catch (Exception e) { System.err.println("Exception: " + e); System.exit(1); } int flags; if (texMipMapMode == Texture.BASE_LEVEL) { flags = 0; } else { flags = TextureLoader.GENERATE_MIPMAP; } texLoader = new TextureLoader(imageURL, new String("RGBA"), //new String("LUMINANCE"), flags, this); // We could create texture from image // // Get the image from the loader. We need an image which // has power of two dimensions, so we'll get the unscaled image, // figure out what the scaled size should be and then get a scale // image //ImageComponent2D unscaledImage = texLoader.getImage(); //int width = unscaledImage.getWidth(); //int height = unscaledImage.getWidth(); // // scaled values are next power of two greater than or equal to // value //texWidth = powerOfTwo(width); //texHeight = powerOfTwo(height); // // rescale the image if necessary //ImageComponent2D texImage; //if ((texWidth == width) && (texHeight == height)) { // texImage = unscaledImage; //} else { // texImage = texLoader.getScaledImage(texWidth, texHeight); //} //texFormat = Texture.RGB; //texture = new Texture2D(texMipMapMode, texFormat, texWidth, // texHeight); //texture.setImage(0, texImage); // instead we'll just get get the texture from loader texture = (Texture2D) texLoader.getTexture(); //texture.setBoundaryColor(texBoundaryColor); texture.setBoundaryColor(1.0f, 1.0f, 1.0f, 1.0f); texture.setBoundaryModeS(texBoundaryModeS); texture.setBoundaryModeT(texBoundaryModeT); texture.setEnable(texEnable); texture.setMinFilter(texMinFilter); texture.setMagFilter(texMagFilter); // Set the capabilities to enable the changable attrs texture.setCapability(Texture.ALLOW_ENABLE_WRITE); texture.setCapability(Texture.ALLOW_IMAGE_WRITE); // connect the new texture to the appearance System.out.println("Appearance.setTexture(" + texture + ")"); appearance.setTexture(texture); } // sets up the scene switch void setupScene() { scene = new Group(); // create a sphere with the shared appearance Sphere sphere = new Sphere(1.0f, Sphere.GENERATE_NORMALS | Sphere.GENERATE_TEXTURE_COORDS, appearance); scene.addChild(sphere); } public void actionPerformed(ActionEvent e) { String action = e.getActionCommand(); Object source = e.getSource(); if (action == texEnableString) { texEnable = texEnableCheckBox.isSelected(); System.out.println("texture.setEnable(" + texEnable + ")"); texture.setEnable(texEnable); } else if (action == texBoundarySWrapString) { texBoundaryModeS = Texture.WRAP; setTexture(); } else if (action == texBoundarySClampString) { texBoundaryModeS = Texture.CLAMP; setTexture(); } else if (action == texBoundaryTWrapString) { texBoundaryModeT = Texture.WRAP; setTexture(); } else if (action == texBoundaryTClampString) { texBoundaryModeT = Texture.CLAMP; setTexture(); } else if (action == texMinFilterBasePointString) { texMinFilter = Texture.BASE_LEVEL_POINT; setTexture(); } else if (action == texMinFilterBaseLinearString) { texMinFilter = Texture.BASE_LEVEL_LINEAR; setTexture(); } else if (action == texMinFilterMultiPointString) { texMinFilter = Texture.MULTI_LEVEL_POINT; setTexture(); } else if (action == texMinFilterMultiLinearString) { texMinFilter = Texture.MULTI_LEVEL_LINEAR; setTexture(); } else if (action == texMinFilterFastestString) { texMinFilter = Texture.FASTEST; setTexture(); } else if (action == texMinFilterNicestString) { texMinFilter = Texture.NICEST; setTexture(); } else if (action == texMagFilterBasePointString) { texMagFilter = Texture.BASE_LEVEL_POINT; setTexture(); } else if (action == texMagFilterBaseLinearString) { texMagFilter = Texture.BASE_LEVEL_LINEAR; setTexture(); } else if (action == texMagFilterNicestString) { texMagFilter = Texture.NICEST; setTexture(); } else if (action == texMagFilterFastestString) { texMagFilter = Texture.FASTEST; setTexture(); } else if (action == texMipMapBaseString) { texMipMapMode = Texture.BASE_LEVEL; setTexture(); } else if (action == texMipMapMultiString) { texMipMapMode = Texture.MULTI_LEVEL_MIPMAP; setTexture(); } } BranchGroup createSceneGraph() { // Create the root of the branch graph BranchGroup objRoot = new BranchGroup(); // Add the primitives to the scene setupAppearance(); setupScene(); objRoot.addChild(scene); return objRoot; } public TexBug() { this(false); } public TexBug(boolean isApplication) { this.isApplication = isApplication; } public void init() { // initialize the code base try { java.net.URL codeBase = getCodeBase(); codeBaseString = codeBase.toString(); } catch (Exception e) { // probably running as an application, try the application // code base codeBaseString = "file:./"; } // set up a NumFormat object to print out float with only 3 fraction // digits nf = NumberFormat.getInstance(); nf.setMaximumFractionDigits(3); setLayout(new BorderLayout()); GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration(); canvas = new Canvas3D(config); add("Center", canvas); // Create a simple scene and attach it to the virtual universe BranchGroup scene = createSceneGraph(); u = new SimpleUniverse(canvas); // set up sound u.getViewer().createAudioDevice(); // get the view view = u.getViewer().getView(); // Get the viewing platform ViewingPlatform viewingPlatform = u.getViewingPlatform(); // Move the viewing platform back to enclose the -2 -> 2 range double viewRadius = 2.0; // want to be able to see circle // of viewRadius size around origin // get the field of view double fov = u.getViewer().getView().getFieldOfView(); // calc view distance to make circle view in fov float viewDistance = (float) (viewRadius / Math.tan(fov / 2.0)); tmpVector.set(0.0f, 0.0f, viewDistance);// setup offset tmpTrans.set(tmpVector); // set trans to translate // move the view platform viewingPlatform.getViewPlatformTransform().setTransform(tmpTrans); // add an orbit behavior to move the viewing platform OrbitBehavior orbit = new OrbitBehavior(canvas); BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0), 100.0); orbit.setSchedulingBounds(bounds); viewingPlatform.setViewPlatformBehavior(orbit); u.addBranchGraph(scene); add("South", guiPanel()); } public void destroy() { u.removeAllLocales(); } // create a panel with a tabbed pane holding each of the edit panels JPanel guiPanel() { JPanel panel = new JPanel(); panel.setLayout(new BorderLayout()); panel.add("Center", texture2DPanel()); return panel; } JPanel texture2DPanel() { JPanel panel = new JPanel(); panel.setLayout(new GridLayout(1, 0)); // horizontal JPanel leftPanel = new JPanel(); leftPanel.setLayout(new GridLayout(0, 1)); // vertical panel.add(leftPanel); JPanel rightPanel = new JPanel(); rightPanel.setLayout(new GridLayout(0, 1)); // vertical panel.add(rightPanel); texEnableCheckBox = new JCheckBox(texEnableString); // set up the action commands texEnableCheckBox.setActionCommand(texEnableString); // register the applet as the listener for the buttons texEnableCheckBox.addActionListener(this); // set the initial value texEnableCheckBox.setSelected(texEnable); // add the checkbox to the panel leftPanel.add(texEnableCheckBox); // texture boundary S leftPanel.add(new JLabel("Boundary S Mode:")); // create the buttons JRadioButton texBoundarySWrapButton = new JRadioButton(wrapString); JRadioButton texBoundarySClampButton = new JRadioButton(clampString); // set up the action commands texBoundarySWrapButton.setActionCommand(texBoundarySWrapString); texBoundarySClampButton.setActionCommand(texBoundarySClampString); // add the buttons to a group so that only one can be selected ButtonGroup boundSButtonGroup = new ButtonGroup(); boundSButtonGroup.add(texBoundarySWrapButton); boundSButtonGroup.add(texBoundarySClampButton); // register the applet as the listener for the buttons texBoundarySWrapButton.addActionListener(this); texBoundarySClampButton.addActionListener(this); // add the buttons to the panel leftPanel.add(texBoundarySWrapButton); leftPanel.add(texBoundarySClampButton); // set the default texBoundarySWrapButton.setSelected(true); // texture boundary T leftPanel.add(new JLabel("Boundary T Mode:")); // create the buttons JRadioButton texBoundaryTWrapButton = new JRadioButton(wrapString); JRadioButton texBoundaryTClampButton = new JRadioButton(clampString); // set up the action commands texBoundaryTWrapButton.setActionCommand(texBoundaryTWrapString); texBoundaryTClampButton.setActionCommand(texBoundaryTClampString); // add the buttons to a group so that only one can be selected ButtonGroup boundTButtonGroup = new ButtonGroup(); boundTButtonGroup.add(texBoundaryTWrapButton); boundTButtonGroup.add(texBoundaryTClampButton); // register the applet as the listener for the buttons texBoundaryTWrapButton.addActionListener(this); texBoundaryTClampButton.addActionListener(this); // add the buttons to the panel leftPanel.add(texBoundaryTWrapButton); leftPanel.add(texBoundaryTClampButton); // set the default texBoundaryTWrapButton.setSelected(true); // texture min filter rightPanel.add(new JLabel("Min Filter:")); // create the buttons JRadioButton texMinFilterBasePointButton = new JRadioButton(texFilterBasePointString); JRadioButton texMinFilterBaseLinearButton = new JRadioButton(texFilterBaseLinearString); JRadioButton texMinFilterMultiPointButton = new JRadioButton(texFilterMultiPointString); JRadioButton texMinFilterMultiLinearButton = new JRadioButton(texFilterMultiLinearString); JRadioButton texMinFilterNicestButton = new JRadioButton(nicestString); JRadioButton texMinFilterFastestButton = new JRadioButton(fastestString); // set up the action commands texMinFilterBasePointButton.setActionCommand(texMinFilterBasePointString); texMinFilterBaseLinearButton.setActionCommand(texMinFilterBaseLinearString); texMinFilterMultiPointButton.setActionCommand(texMinFilterMultiPointString); texMinFilterMultiLinearButton.setActionCommand(texMinFilterMultiLinearString); texMinFilterNicestButton.setActionCommand(texMinFilterNicestString); texMinFilterFastestButton.setActionCommand(texMinFilterFastestString); // add the buttons to a group so that only one can be selected ButtonGroup minFilterButtonGroup = new ButtonGroup(); minFilterButtonGroup.add(texMinFilterBasePointButton); minFilterButtonGroup.add(texMinFilterBaseLinearButton); minFilterButtonGroup.add(texMinFilterMultiPointButton); minFilterButtonGroup.add(texMinFilterMultiLinearButton); minFilterButtonGroup.add(texMinFilterNicestButton); minFilterButtonGroup.add(texMinFilterFastestButton); // register the applet as the listener for the buttons texMinFilterBasePointButton.addActionListener(this); texMinFilterBaseLinearButton.addActionListener(this); texMinFilterMultiPointButton.addActionListener(this); texMinFilterMultiLinearButton.addActionListener(this); texMinFilterNicestButton.addActionListener(this); texMinFilterFastestButton.addActionListener(this); // add the buttons to the panel rightPanel.add(texMinFilterBasePointButton); rightPanel.add(texMinFilterBaseLinearButton); rightPanel.add(texMinFilterMultiPointButton); rightPanel.add(texMinFilterMultiLinearButton); rightPanel.add(texMinFilterNicestButton); rightPanel.add(texMinFilterFastestButton); // set the default texMinFilterBasePointButton.setSelected(true); // texture max filter rightPanel.add(new JLabel("Mag Filter:")); // create the buttons JRadioButton texMagFilterBasePointButton = new JRadioButton(texFilterBasePointString); JRadioButton texMagFilterBaseLinearButton = new JRadioButton(texFilterBaseLinearString); JRadioButton texMagFilterNicestButton = new JRadioButton(nicestString); JRadioButton texMagFilterFastestButton = new JRadioButton(fastestString); // set up the action commands texMagFilterBasePointButton.setActionCommand(texMagFilterBasePointString); texMagFilterBaseLinearButton.setActionCommand(texMagFilterBaseLinearString); texMagFilterNicestButton.setActionCommand(texMagFilterNicestString); texMagFilterFastestButton.setActionCommand(texMagFilterFastestString); // add the buttons to a group so that only one can be selected ButtonGroup magFilterButtonGroup = new ButtonGroup(); magFilterButtonGroup.add(texMagFilterBasePointButton); magFilterButtonGroup.add(texMagFilterBaseLinearButton); magFilterButtonGroup.add(texMagFilterNicestButton); magFilterButtonGroup.add(texMagFilterFastestButton); // register the applet as the listener for the buttons texMagFilterBasePointButton.addActionListener(this); texMagFilterBaseLinearButton.addActionListener(this); texMagFilterNicestButton.addActionListener(this); texMagFilterFastestButton.addActionListener(this); // add the buttons to the panel rightPanel.add(texMagFilterBasePointButton); rightPanel.add(texMagFilterBaseLinearButton); rightPanel.add(texMagFilterNicestButton); rightPanel.add(texMagFilterFastestButton); // set the default texMagFilterBasePointButton.setSelected(true); // MipMap Mode leftPanel.add(new JLabel("MipMap Mode:")); // create the buttons JRadioButton texMipMapBaseButton = new JRadioButton(texMipMapBaseString); JRadioButton texMipMapMultiButton = new JRadioButton(texMipMapMultiString); // set up the action commands texMipMapBaseButton.setActionCommand(texMipMapBaseString); texMipMapMultiButton.setActionCommand(texMipMapMultiString); // add the buttons to a group so that only one can be selected ButtonGroup texMipMapButtonGroup = new ButtonGroup(); texMipMapButtonGroup.add(texMipMapBaseButton); texMipMapButtonGroup.add(texMipMapMultiButton); // register the applet as the listener for the buttons texMipMapBaseButton.addActionListener(this); texMipMapMultiButton.addActionListener(this); // add the buttons to the panel leftPanel.add(texMipMapBaseButton); leftPanel.add(texMipMapMultiButton); // set the default texMipMapBaseButton.setSelected(true); return panel; } // The following allows TexBug to be run as an application // as well as an applet // public static void main(String[] args) { new MainFrame(new TexBug(true), 650, 800); } } interface Java3DExplorerConstants { // colors static Color3f black = new Color3f(0.0f, 0.0f, 0.0f); static Color3f red = new Color3f(1.0f, 0.0f, 0.0f); static Color3f green = new Color3f(0.0f, 1.0f, 0.0f); static Color3f blue = new Color3f(0.0f, 0.0f, 1.0f); static Color3f skyBlue = new Color3f(0.6f, 0.7f, 0.9f); static Color3f cyan = new Color3f(0.0f, 1.0f, 1.0f); static Color3f magenta = new Color3f(1.0f, 0.0f, 1.0f); static Color3f yellow = new Color3f(1.0f, 1.0f, 0.0f); static Color3f brightWhite = new Color3f(1.0f, 1.5f, 1.5f); static Color3f white = new Color3f(1.0f, 1.0f, 1.0f); static Color3f darkGrey = new Color3f(0.15f, 0.15f, 0.15f); static Color3f medGrey = new Color3f(0.3f, 0.3f, 0.3f); static Color3f grey = new Color3f(0.5f, 0.5f, 0.5f); static Color3f lightGrey = new Color3f(0.75f, 0.75f, 0.75f); // infinite bounding region, used to make env nodes active everywhere BoundingSphere infiniteBounds = new BoundingSphere(new Point3d(), Double.MAX_VALUE); // common values static final String nicestString = "NICEST"; static final String fastestString = "FASTEST"; static final String antiAliasString = "Anti-Aliasing"; static final String noneString = "NONE"; // light type constants static int LIGHT_AMBIENT = 1; static int LIGHT_DIRECTIONAL = 2; static int LIGHT_POSITIONAL = 3; static int LIGHT_SPOT = 4; // screen capture constants static final int USE_COLOR = 1; static final int USE_BLACK_AND_WHITE = 2; // number formatter NumberFormat nf = NumberFormat.getInstance(); }