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