|
This Java tip shows how to create an appearance explorer in Java3D.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GraphicsConfiguration;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.text.NumberFormat;
import java.util.Enumeration;
import java.util.EventListener;
import java.util.EventObject;
import java.util.Hashtable;
import java.util.Vector;
import javax.media.j3d.AmbientLight;
import javax.media.j3d.Appearance;
import javax.media.j3d.Background;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Canvas3D;
import javax.media.j3d.ColoringAttributes;
import javax.media.j3d.DirectionalLight;
import javax.media.j3d.Font3D;
import javax.media.j3d.FontExtrusion;
import javax.media.j3d.GeometryArray;
import javax.media.j3d.Group;
import javax.media.j3d.ImageComponent;
import javax.media.j3d.ImageComponent2D;
import javax.media.j3d.IndexedQuadArray;
import javax.media.j3d.Light;
import javax.media.j3d.LineArray;
import javax.media.j3d.LineAttributes;
import javax.media.j3d.LineStripArray;
import javax.media.j3d.Material;
import javax.media.j3d.PointArray;
import javax.media.j3d.PointAttributes;
import javax.media.j3d.PointLight;
import javax.media.j3d.PolygonAttributes;
import javax.media.j3d.QuadArray;
import javax.media.j3d.RenderingAttributes;
import javax.media.j3d.Screen3D;
import javax.media.j3d.Shape3D;
import javax.media.j3d.Switch;
import javax.media.j3d.TexCoordGeneration;
import javax.media.j3d.Text3D;
import javax.media.j3d.Texture;
import javax.media.j3d.Texture2D;
import javax.media.j3d.TextureAttributes;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransparencyAttributes;
import javax.media.j3d.TriangleArray;
import javax.media.j3d.TriangleFanArray;
import javax.media.j3d.TriangleStripArray;
import javax.media.j3d.View;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JColorChooser;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.JTabbedPane;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.vecmath.AxisAngle4f;
import javax.vecmath.Color3f;
import javax.vecmath.Color4f;
import javax.vecmath.Point3d;
import javax.vecmath.Point3f;
import javax.vecmath.TexCoord2f;
import javax.vecmath.Vector3f;
import javax.vecmath.Vector4f;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGEncodeParam;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
import com.sun.j3d.loaders.Scene;
import com.sun.j3d.loaders.objectfile.ObjectFile;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.behaviors.vp.OrbitBehavior;
import com.sun.j3d.utils.geometry.GeometryInfo;
import com.sun.j3d.utils.geometry.NormalGenerator;
import com.sun.j3d.utils.geometry.Sphere;
import com.sun.j3d.utils.geometry.Triangulator;
import com.sun.j3d.utils.image.TextureLoader;
import com.sun.j3d.utils.universe.SimpleUniverse;
import com.sun.j3d.utils.universe.ViewingPlatform;
public class AppearanceExplorer extends JApplet implements
Java3DExplorerConstants {
// Scene graph items
SimpleUniverse u;
Switch sceneSwitch;
Group beethoven = null;
Group galleon = null;
Switch bgSwitch;
IntChooser bgChooser;
Appearance appearance;
// image grabber
boolean isApplication;
Canvas3D canvas;
OffScreenCanvas3D offScreenCanvas;
View view;
// ColoringAttributes
ColoringAttributes coloringAttr;
ColoringAttributesEditor coloringAttrEditor;
Color3f coloringColor;
int coloringShadeModel = ColoringAttributes.SHADE_GOURAUD;
// PointAttributes
PointAttributes pointAttr;
PointAttributesEditor pointAttrEditor;
float pointSize = 4.0f;
boolean pointAAEnable = false;
// LineAttributes
LineAttributes lineAttr;
float lineWidth = 1.0f;
LineAttributesEditor lineAttrEditor;
boolean lineAAEnable = false;
int linePattern = LineAttributes.PATTERN_SOLID;
// PolygonAttributes
PolygonAttributes polygonAttr;
PolygonAttributesEditor polygonAttrEditor;
int polygonMode = PolygonAttributes.POLYGON_FILL;
int polygonCull = PolygonAttributes.CULL_NONE;
float polygonOffsetBias = 1.0f;
float polygonOffsetFactor = 1.0f;
// RenderingAttributes
RenderingAttributes renderAttr;
RenderingAttributesEditor renderAttrEditor;
boolean renderVisible = true;
boolean renderDepthBuffer = true;
boolean renderDepthBufferWrite = true;
boolean renderIgnoreVertexColor = false;
boolean renderRasterOpEnable = false;
int renderRasterOp = RenderingAttributes.ROP_COPY;
// TransparencyAttributes
TransparencyAttributes transpAttr;
TransparencyAttributesEditor transpAttrEditor;
int transpMode = TransparencyAttributes.NONE;
float transpValue = 0.5f;
// Material
Material material;
MaterialEditor materialEditor;
// Texture2D
Texture2DEditor texture2DEditor;
boolean texEnable;
String texImageFile;
int texBoundaryModeS;
int texBoundaryModeT;
Color4f texBoundaryColor;
int texMinFilter;
int texMagFilter;
int texMipMapMode;
// TextureAttributes
TextureAttributes textureAttr;
TextureAttributesEditor textureAttrEditor;
int texMode;
Color4f texBlendColor;
Transform3D texTransform;
int texPerspCorrect;
// TexCoordGeneration
TexCoordGeneration texGen;
TexCoordGenerationEditor texGenEditor;
boolean texGenEnable;
int texGenMode;
Vector4f texGenPlaneS;
Vector4f texGenPlaneT;
// GUI helpers to allow galleon and beethoven to be loaded as needed
// to reduce the startup time
int galleonIndex;
int beethovenIndex;
String galleonString = "Obj File: Galleon";
String beethovenString = "Obj File: Beethoven";
BranchGroup beethovenPlaceholder;
BranchGroup galleonPlaceholder;
// Config items
Switch lightSwitch;
String snapImageString = "Snap Image";
String outFileBase = "appear";
int outFileSeq = 0;
float offScreenScale = 1.5f;
// Temporaries that are reused
Transform3D tmpTrans = new Transform3D();
Vector3f tmpVector = new Vector3f();
AxisAngle4f tmpAxisAngle = new AxisAngle4f();
// 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();
// ColoringAttributes
coloringColor = new Color3f(red);
coloringAttr = new ColoringAttributes(coloringColor, coloringShadeModel);
coloringAttr.setCapability(ColoringAttributes.ALLOW_COLOR_WRITE);
coloringAttr.setCapability(ColoringAttributes.ALLOW_SHADE_MODEL_WRITE);
appearance.setColoringAttributes(coloringAttr);
// set up the editor
coloringAttrEditor = new ColoringAttributesEditor(coloringAttr);
// PointAttributes
pointAttr = new PointAttributes(pointSize, pointAAEnable);
pointAttr.setCapability(PointAttributes.ALLOW_SIZE_WRITE);
pointAttr.setCapability(PointAttributes.ALLOW_ANTIALIASING_WRITE);
appearance.setPointAttributes(pointAttr);
// set up the editor
pointAttrEditor = new PointAttributesEditor(pointAttr);
// LineAttributes
lineAttr = new LineAttributes(lineWidth, linePattern, lineAAEnable);
lineAttr.setCapability(LineAttributes.ALLOW_WIDTH_WRITE);
lineAttr.setCapability(LineAttributes.ALLOW_PATTERN_WRITE);
lineAttr.setCapability(LineAttributes.ALLOW_ANTIALIASING_WRITE);
appearance.setLineAttributes(lineAttr);
// set up the editor
lineAttrEditor = new LineAttributesEditor(lineAttr);
// PolygonAttributes
polygonAttr = new PolygonAttributes(polygonMode, polygonCull, 0.0f);
polygonAttr.setPolygonOffset(polygonOffsetBias);
polygonAttr.setPolygonOffsetFactor(polygonOffsetFactor);
polygonAttr.setCapability(PolygonAttributes.ALLOW_MODE_WRITE);
polygonAttr.setCapability(PolygonAttributes.ALLOW_CULL_FACE_WRITE);
polygonAttr.setCapability(PolygonAttributes.ALLOW_OFFSET_WRITE);
appearance.setPolygonAttributes(polygonAttr);
// set up the editor
polygonAttrEditor = new PolygonAttributesEditor(polygonAttr);
// Rendering attributes
renderAttr = new RenderingAttributes(renderDepthBuffer,
renderDepthBufferWrite, 0.0f, RenderingAttributes.ALWAYS,
renderVisible, renderIgnoreVertexColor, renderRasterOpEnable,
renderRasterOp);
renderAttr
.setCapability(RenderingAttributes.ALLOW_IGNORE_VERTEX_COLORS_WRITE);
renderAttr.setCapability(RenderingAttributes.ALLOW_VISIBLE_WRITE);
renderAttr.setCapability(RenderingAttributes.ALLOW_RASTER_OP_WRITE);
renderAttr
.setCapability(RenderingAttributes.ALLOW_ALPHA_TEST_FUNCTION_WRITE);
renderAttr
.setCapability(RenderingAttributes.ALLOW_ALPHA_TEST_VALUE_WRITE);
appearance.setRenderingAttributes(renderAttr);
appearance.setCapability(Appearance.ALLOW_RENDERING_ATTRIBUTES_WRITE);
// set up the editor
renderAttrEditor = new RenderingAttributesEditor(renderAttr);
// TransparencyAttributes
transpAttr = new TransparencyAttributes(transpMode, transpValue);
transpAttr.setCapability(TransparencyAttributes.ALLOW_MODE_WRITE);
transpAttr.setCapability(TransparencyAttributes.ALLOW_VALUE_WRITE);
transpAttr
.setCapability(TransparencyAttributes.ALLOW_BLEND_FUNCTION_WRITE);
appearance.setTransparencyAttributes(transpAttr);
// set up the editor
transpAttrEditor = new TransparencyAttributesEditor(transpAttr);
// Material
material = new Material(red, black, red, white, 20.f);
material.setLightingEnable(false);
material.setCapability(Material.ALLOW_COMPONENT_WRITE);
appearance.setMaterial(material);
// material presets
String[] materialNames = { "Red", "White", "Red Ambient",
"Red Diffuse", "Grey Emissive", "White Specular", "Aluminium",
"Blue Plastic", "Copper", "Gold", "Red Alloy", "Black Onyx" };
Material[] materialPresets = new Material[materialNames.length];
materialPresets[0] = new Material(red, black, red, white, 20.0f);
materialPresets[1] = new Material(white, black, white, white, 20.0f);
materialPresets[2] = new Material(red, black, black, black, 20.0f);
materialPresets[3] = new Material(black, black, red, black, 20.0f);
materialPresets[4] = new Material(black, grey, black, black, 20.0f);
materialPresets[5] = new Material(black, black, black, white, 20.0f);
Color3f alum = new Color3f(0.37f, 0.37f, 0.37f);
Color3f alumSpec = new Color3f(0.89f, 0.89f, 0.89f);
materialPresets[6] = new Material(alum, black, alum, alumSpec, 17);
Color3f bluePlastic = new Color3f(0.20f, 0.20f, 0.70f);
Color3f bluePlasticSpec = new Color3f(0.85f, 0.85f, 0.85f);
materialPresets[7] = new Material(bluePlastic, black, bluePlastic,
bluePlasticSpec, 22);
Color3f copper = new Color3f(0.30f, 0.10f, 0.00f);
;
Color3f copperSpec = new Color3f(0.75f, 0.30f, 0.00f);
materialPresets[8] = new Material(copper, black, copper, copperSpec, 10);
Color3f gold = new Color3f(0.49f, 0.34f, 0.00f);
Color3f goldSpec = new Color3f(0.89f, 0.79f, 0.00f);
materialPresets[9] = new Material(gold, black, gold, goldSpec, 15);
Color3f redAlloy = new Color3f(0.34f, 0.00f, 0.34f);
Color3f redAlloySpec = new Color3f(0.84f, 0.00f, 0.00f);
materialPresets[10] = new Material(redAlloy, black, redAlloy,
redAlloySpec, 15);
Color3f blackOnyxSpec = new Color3f(0.72f, 0.72f, 0.72f);
materialPresets[11] = new Material(black, black, black, blackOnyxSpec,
23);
// set up the editor
materialEditor = new MaterialPresetEditor(material, materialNames,
materialPresets);
// 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(0.0f, 0.0f, 0.0f, 0.0f);
// set up the image choices
String[] texImageNames = { "Earth", "Fish", };
String[] texImageFileNames = { "earth.jpg", "fish1.gif", };
int texImageFileIndex = 0;
// set up the appearance to allow the texture to be changed
appearance.setCapability(Appearance.ALLOW_TEXTURE_WRITE);
// set up the editor (this will create the initial Texture2D and
// assign it to the appearance)
texture2DEditor = new Texture2DEditor(appearance, codeBaseString,
texImageNames, texImageFileNames, texImageFileIndex, texEnable,
texBoundaryModeS, texBoundaryModeT, texMinFilter, texMagFilter,
texMipMapMode, texBoundaryColor);
// TextureAttributes
texMode = TextureAttributes.REPLACE;
texBlendColor = new Color4f(1.0f, 1.0f, 1.0f, 1.0f);
texTransform = new Transform3D();
texPerspCorrect = TextureAttributes.NICEST;
textureAttr = new TextureAttributes(texMode, texTransform,
texBlendColor, texPerspCorrect);
// set the capabilities to allow run time changes
textureAttr.setCapability(TextureAttributes.ALLOW_MODE_WRITE);
textureAttr.setCapability(TextureAttributes.ALLOW_BLEND_COLOR_WRITE);
textureAttr.setCapability(TextureAttributes.ALLOW_TRANSFORM_WRITE);
// connect it to the appearance
appearance.setTextureAttributes(textureAttr);
// setup the editor
textureAttrEditor = new TextureAttributesEditor(textureAttr);
// set up the tex coordinate generation
texGenEnable = false;
texGenMode = TexCoordGeneration.OBJECT_LINEAR;
texGenPlaneS = new Vector4f(1.0f, 0.0f, 0.0f, 0.0f);
texGenPlaneT = new Vector4f(0.0f, 1.0f, 0.0f, 0.0f);
// set the appearance so that we can replace the tex gen when live
appearance.setCapability(Appearance.ALLOW_TEXGEN_WRITE);
// setup the editor
texGenEditor = new TexCoordGenerationEditor(appearance, texGenEnable,
texGenMode, texGenPlaneS, texGenPlaneT);
}
int powerOfTwo(int value) {
int retval = 2;
while (retval < value) {
retval *= 2;
}
return retval;
}
// Point Array with three points
Shape3D createPointArray() {
Point3f pnt[] = new Point3f[3];
pnt[0] = new Point3f(-1.0f, -1.0f, 0.0f);
pnt[1] = new Point3f(1.0f, -1.0f, 0.0f);
pnt[2] = new Point3f(1.0f, 1.0f, 0.0f);
PointArray pa = new PointArray(3, GeometryArray.COORDINATES);
pa.setCoordinates(0, pnt);
return new Shape3D(pa, appearance);
}
// Line Array with two lines with vertex colors
Shape3D createLineArray() {
Point3f pnt[] = new Point3f[4];
pnt[0] = new Point3f(-1.0f, -1.0f, 0.0f);
pnt[1] = new Point3f(1.0f, -1.0f, 0.0f);
pnt[2] = new Point3f(1.0f, 1.0f, 0.0f);
pnt[3] = new Point3f(-1.0f, 1.0f, 0.0f);
Color3f colrs[] = new Color3f[4];
colrs[0] = black;
colrs[1] = white;
colrs[2] = red;
colrs[3] = green;
LineArray la = new LineArray(4, GeometryArray.COORDINATES
| GeometryArray.COLOR_3);
la.setCoordinates(0, pnt);
la.setColors(0, colrs);
return new Shape3D(la, appearance);
}
// Triangle Array with one triangle with vertex colors and a facet normal
Shape3D createTriangleArray() {
Point3f pnt[] = new Point3f[3];
pnt[0] = new Point3f(-1.0f, -1.0f, 0.0f);
pnt[1] = new Point3f(1.0f, -1.0f, 0.0f);
pnt[2] = new Point3f(1.0f, 1.0f, 0.0f);
Color3f colrs[] = new Color3f[3];
colrs[0] = red;
colrs[1] = green;
colrs[2] = blue;
Vector3f norms[] = new Vector3f[3];
Vector3f triNormal = new Vector3f(0.0f, 0.0f, 1.0f);
norms[0] = triNormal;
norms[1] = triNormal;
norms[2] = triNormal;
TriangleArray ta = new TriangleArray(3, GeometryArray.COORDINATES
| GeometryArray.COLOR_3 | GeometryArray.NORMALS);
ta.setCoordinates(0, pnt);
ta.setColors(0, colrs);
ta.setNormals(0, norms);
return new Shape3D(ta, appearance);
}
// Line Strip Array with two lines with 3 and 2 vertices each making
// a two segment line and a one segment line
Shape3D createLineStripArray() {
int[] stripLengths = new int[2];
stripLengths[0] = 3;
stripLengths[1] = 2;
Point3f pnt[] = new Point3f[5];
// first line
pnt[0] = new Point3f(-1.0f, -1.0f, 0.0f);
pnt[1] = new Point3f(1.0f, -1.0f, 0.0f);
pnt[2] = new Point3f(1.0f, 1.0f, 0.0f);
// second line
pnt[3] = new Point3f(0.5f, 0.5f, 0.0f);
pnt[4] = new Point3f(-0.5f, -0.5f, 0.0f);
LineStripArray lsa = new LineStripArray(5, GeometryArray.COORDINATES,
stripLengths);
lsa.setCoordinates(0, pnt);
return new Shape3D(lsa, appearance);
}
Shape3D createTriangleStripArray() {
int[] stripLengths = new int[1];
stripLengths[0] = 5;
Point3f pnt[] = new Point3f[5];
pnt[0] = new Point3f(-1.0f, -1.0f, 0.0f);
pnt[1] = new Point3f(1.0f, -1.0f, 0.0f);
pnt[2] = new Point3f(-1.0f, 0.0f, 0.0f);
pnt[3] = new Point3f(1.0f, 0.0f, 0.0f);
pnt[4] = new Point3f(1.0f, 1.0f, 0.0f);
TriangleStripArray tsa = new TriangleStripArray(5,
GeometryArray.COORDINATES, stripLengths);
tsa.setCoordinates(0, pnt);
return new Shape3D(tsa, appearance);
}
Shape3D createTriangleFanArray() {
int[] stripLengths = new int[1];
stripLengths[0] = 5;
Point3f pnt[] = new Point3f[5];
pnt[0] = new Point3f(-1.0f, -1.0f, 0.0f);
pnt[1] = new Point3f(1.0f, -1.0f, 0.0f);
pnt[2] = new Point3f(1.0f, 0.0f, 0.0f);
pnt[3] = new Point3f(0.0f, 1.0f, 0.0f);
pnt[4] = new Point3f(-1.0f, 1.0f, 0.0f);
TriangleFanArray tfa = new TriangleFanArray(5,
GeometryArray.COORDINATES, stripLengths);
tfa.setCoordinates(0, pnt);
return new Shape3D(tfa, appearance);
}
Shape3D createTexTris() {
Point3f pnt[] = new Point3f[9];
pnt[0] = new Point3f(-0.8f, -0.8f, 0.0f);
pnt[1] = new Point3f(-0.5f, -0.7f, 0.0f);
pnt[2] = new Point3f(-0.7f, 0.7f, 0.0f);
pnt[3] = new Point3f(-0.4f, 0.7f, 0.0f);
pnt[4] = new Point3f(0.0f, -0.7f, 0.0f);
pnt[5] = new Point3f(0.4f, 0.7f, 0.0f);
pnt[6] = new Point3f(0.5f, 0.7f, 0.0f);
pnt[7] = new Point3f(0.5f, -0.7f, 0.0f);
pnt[8] = new Point3f(0.9f, 0.0f, 0.0f);
TexCoord2f texCoord[] = new TexCoord2f[9];
texCoord[0] = new TexCoord2f(0.05f, 0.90f);
texCoord[1] = new TexCoord2f(0.25f, 0.10f);
texCoord[2] | |