TexBug.java Source code

Java tutorial

Introduction

Here is the source code for TexBug.java

Source

/*
 * %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();

}