|
//
//CLASS
//ExLinearFog - illustrate use of linear fog
//
//LESSON
//Add an LinearFog node to apply fog of varying thickness.
//
//SEE ALSO
//ExExponentialFog
//
//AUTHOR
//David R. Nadeau / San Diego Supercomputer Center
//
import java.applet.Applet;
import java.awt.AWTEvent;
import java.awt.BorderLayout;
import java.awt.CheckboxMenuItem;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Frame;
import java.awt.Menu;
import java.awt.MenuBar;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.File;
import java.util.Enumeration;
import java.util.EventListener;
import javax.media.j3d.AmbientLight;
import javax.media.j3d.Appearance;
import javax.media.j3d.Background;
import javax.media.j3d.Behavior;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Canvas3D;
import javax.media.j3d.DirectionalLight;
import javax.media.j3d.Fog;
import javax.media.j3d.GeometryArray;
import javax.media.j3d.Group;
import javax.media.j3d.IndexedQuadArray;
import javax.media.j3d.IndexedTriangleStripArray;
import javax.media.j3d.Light;
import javax.media.j3d.LinearFog;
import javax.media.j3d.Link;
import javax.media.j3d.Material;
import javax.media.j3d.Shape3D;
import javax.media.j3d.SharedGroup;
import javax.media.j3d.Texture;
import javax.media.j3d.TextureAttributes;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.media.j3d.WakeupCriterion;
import javax.media.j3d.WakeupOnAWTEvent;
import javax.media.j3d.WakeupOnElapsedFrames;
import javax.media.j3d.WakeupOr;
import javax.vecmath.Color3f;
import javax.vecmath.Matrix4d;
import javax.vecmath.Point3d;
import javax.vecmath.Point3f;
import javax.vecmath.Vector3d;
import javax.vecmath.Vector3f;
import com.sun.j3d.utils.geometry.Primitive;
import com.sun.j3d.utils.image.TextureLoader;
import com.sun.j3d.utils.universe.PlatformGeometry;
import com.sun.j3d.utils.universe.SimpleUniverse;
import com.sun.j3d.utils.universe.Viewer;
import com.sun.j3d.utils.universe.ViewingPlatform;
public class ExLinearFog extends Java3DFrame {
//--------------------------------------------------------------
// SCENE CONTENT
//--------------------------------------------------------------
//
// Nodes (updated via menu)
//
private LinearFog fog = null;
private Background background = null;
//
// Build scene
//
public Group buildScene() {
// Get the current color
Color3f color = (Color3f) colors[currentColor].value;
float front = ((Float) fronts[currentFront].value).floatValue();
float back = ((Float) backs[currentBack].value).floatValue();
// Turn off the example headlight
setHeadlightEnable(false);
// Default to walk navigation
setNavigationType(Walk);
// Create the scene group
Group scene = new Group();
// BEGIN EXAMPLE TOPIC
// Create influencing bounds
BoundingSphere worldBounds = new BoundingSphere(new Point3d(0.0, 0.0,
0.0), // Center
1000.0); // Extent
// Set the fog color, front & back distances, and
// its influencing bounds
fog = new LinearFog();
fog.setColor(color);
fog.setFrontDistance(front);
fog.setBackDistance(back);
fog.setCapability(Fog.ALLOW_COLOR_WRITE);
fog.setCapability(LinearFog.ALLOW_DISTANCE_WRITE);
fog.setInfluencingBounds(worldBounds);
scene.addChild(fog);
// END EXAMPLE TOPIC
// Set the background color and its application bounds
// Usually, the background color should match the fog color
// or the results look odd.
background = new Background();
background.setColor(color);
background.setApplicationBounds(worldBounds);
background.setCapability(Background.ALLOW_COLOR_WRITE);
scene.addChild(background);
// Build foreground geometry
scene.addChild(new ColumnScene(this));
return scene;
}
//--------------------------------------------------------------
// USER INTERFACE
//--------------------------------------------------------------
//
// Main
//
public static void main(String[] args) {
ExLinearFog ex = new ExLinearFog();
ex.initialize(args);
ex.buildUniverse();
ex.showFrame();
}
// Coupled background and fog color
private boolean coupledBackgroundOnOff = true;
private CheckboxMenuItem coupledBackgroundOnOffMenu = null;
// Color menu choices
private NameValue[] colors = { new NameValue("White", White),
new NameValue("Gray", Gray), new NameValue("Dark Gray", DarkGray),
new NameValue("Black", Black), new NameValue("Red", Red),
new NameValue("Dark Red", DarkRed), new NameValue("Green", Green),
new NameValue("Dark Green", DarkGreen),
new NameValue("Blue", Blue), new NameValue("Dark Blue", DarkBlue), };
private int currentColor = 0;
private int currentBackgroundColor = currentColor;
private CheckboxMenu colorMenu;
private CheckboxMenu backgroundColorMenu;
// Front distance menu choices
private NameValue[] fronts = {
new NameValue("At front (0.0)", new Float(0.0f)),
new NameValue("Near distance (2.0)", new Float(2.0f)),
new NameValue("Mid distance (12.0)", new Float(12.0f)),
new NameValue("Far distance (22.0)", new Float(22.0f)), };
private int currentFront = 0;
private CheckboxMenu frontMenu;
// Back distance menu choices
private NameValue[] backs = {
new NameValue("At front (0.0)", new Float(0.0f)),
new NameValue("Near distance (2.0)", new Float(2.0f)),
new NameValue("Mid distance (12.0)", new Float(12.0f)),
new NameValue("Far distance (22.0)", new Float(22.0f)), };
private int currentBack = 3;
private CheckboxMenu backMenu;
//
// Initialize the GUI (application and applet)
//
public void initialize(String[] args) {
// Initialize the window, menubar, etc.
super.initialize(args);
exampleFrame.setTitle("Java 3D LinearFog Example");
//
// Add a menubar menu to change node parameters
// Coupled background color
// Background color -->
// Fog color -->
// Fog front distance -->
// Fog back distance -->
//
Menu m = new Menu("LinearFog");
coupledBackgroundOnOffMenu = new CheckboxMenuItem(
"Couple background color", coupledBackgroundOnOff);
coupledBackgroundOnOffMenu.addItemListener(this);
m.add(coupledBackgroundOnOffMenu);
backgroundColorMenu = new CheckboxMenu("Background color", colors,
currentBackgroundColor, this);
m.add(backgroundColorMenu);
backgroundColorMenu.setEnabled(!coupledBackgroundOnOff);
colorMenu = new CheckboxMenu("Fog color", colors, currentColor, this);
m.add(colorMenu);
frontMenu = new CheckboxMenu("Fog front distance", fronts,
currentFront, this);
m.add(frontMenu);
backMenu = new CheckboxMenu("Fog back distance", backs, currentBack,
this);
m.add(backMenu);
exampleMenuBar.add(m);
}
//
// Handle checkboxes and menu choices
//
public void checkboxChanged(CheckboxMenu menu, int check) {
if (menu == backgroundColorMenu) {
// Change the background color
currentBackgroundColor = check;
Color3f color = (Color3f) colors[check].value;
background.setColor(color);
return;
}
if (menu == colorMenu) {
// Change the fog color
currentColor = check;
Color3f color = (Color3f) colors[check].value;
fog.setColor(color);
// If background is coupled, set the background color
if (coupledBackgroundOnOff) {
currentBackgroundColor = currentColor;
backgroundColorMenu.setCurrent(check);
background.setColor(color);
}
return;
}
if (menu == frontMenu) {
// Change the fog front distance
currentFront = check;
float front = ((Float) fronts[currentFront].value).floatValue();
fog.setFrontDistance(front);
return;
}
if (menu == backMenu) {
// Change the fog back distance
currentBack = check;
float back = ((Float) backs[currentBack].value).floatValue();
fog.setBackDistance(back);
return;
}
// Handle all other checkboxes
super.checkboxChanged(menu, check);
}
public void itemStateChanged(ItemEvent event) {
Object src = event.getSource();
// Check if it is the coupled background choice
if (src == coupledBackgroundOnOffMenu) {
coupledBackgroundOnOff = coupledBackgroundOnOffMenu.getState();
if (coupledBackgroundOnOff) {
currentBackgroundColor = currentColor;
backgroundColorMenu.setCurrent(currentColor);
Color3f color = (Color3f) colors[currentColor].value;
background.setColor(color);
backgroundColorMenu.setEnabled(false);
} else {
backgroundColorMenu.setEnabled(true);
}
}
// Handle all other checkboxes
super.itemStateChanged(event);
}
}
//
//CLASS
//ColumnScene - shapes and lights for a scene with gothic columns
//
//DESCRIPTION
//This class builds a scene containing a stone floor, a set of
//marble columns, plus appropriate lighting. The scene is used in
//several of the examples to provide content to affect with lights,
//background colors and images, and so forth.
//
//SEE ALSO
//ExExponentialFog
//ExLinearFog
//
//AUTHOR
//David R. Nadeau / San Diego Supercomputer Center
//
class ColumnScene extends Group {
//--------------------------------------------------------------
// SCENE CONTENT
//--------------------------------------------------------------
// Construction parameters
private final static float ColumnHeight = 3.0f;
private final static float ColumnRadius = 0.2f;
private final static float ColumnDepthSpacing = 6.0f;
private final static float ColumnSideOffset = 1.0f;
private final static int NumberOfColumns = 4;
private final static float WalkwayWidth = 3.0f;
private final static float WalkwayDepth = ((float) NumberOfColumns - 1)
* ColumnDepthSpacing + 4.0f * WalkwayWidth;
private final static float LawnWidth = 4.0f * WalkwayWidth;
private final static float LawnDepth = WalkwayDepth;
private Texture columnTex = null;
//
// Build a single column in a shared group
//
private SharedGroup buildSharedColumn() {
Appearance columnApp = new Appearance();
Material columnMat = new Material();
columnMat.setAmbientColor(0.6f, 0.6f, 0.6f);
columnMat.setDiffuseColor(1.0f, 1.0f, 1.0f);
columnMat.setSpecularColor(0.0f, 0.0f, 0.0f);
columnApp.setMaterial(columnMat);
TextureAttributes columnTexAtt = new TextureAttributes();
columnTexAtt.setTextureMode(TextureAttributes.MODULATE);
columnTexAtt.setPerspectiveCorrectionMode(TextureAttributes.NICEST);
columnApp.setTextureAttributes(columnTexAtt);
if (columnTex != null)
columnApp.setTexture(columnTex);
GothicColumn columnShape = new GothicColumn(ColumnHeight, // height
ColumnRadius, // radius
GothicColumn.BUILD_TOP, // flags
columnApp); // appearance
// BEGIN EXAMPLE TOPIC
// Build a shared group to hold the column shape
SharedGroup column = new SharedGroup();
column.addChild(columnShape);
// END EXAMPLE TOPIC
return column;
}
//
// Used a column in a shared group and link to it
// several times to build a double row of columns
//
private Group buildColumns(SharedGroup column) {
Group group = new Group();
// Place columns
float x = -ColumnSideOffset;
float y = -1.6f;
float z = ColumnDepthSpacing;
float xSpacing = 2.0f * ColumnSideOffset;
float zSpacing = -ColumnDepthSpacing;
// BEGIN EXAMPLE TOPIC
Vector3f trans = new Vector3f();
Transform3D tr = new Transform3D();
TransformGroup tg;
for (int i = 0; i < NumberOfColumns; i++) {
// Left link
trans.set(x, y, z);
tr.set(trans);
tg = new TransformGroup(tr);
tg.addChild(new Link(column));
group.addChild(tg);
// Right link
trans.set(x + xSpacing, y, z);
tr.set(trans);
tg = new TransformGroup(tr);
tg.addChild(new Link(column));
group.addChild(tg);
z += zSpacing;
}
// END EXAMPLE TOPIC
return group;
}
//
// Build a scene containing multiple columns
//
public ColumnScene(Component observer) {
BoundingSphere worldBounds = new BoundingSphere(new Point3d(0.0, 0.0,
0.0), // Center
1000.0); // Extent
// Add a few lights
AmbientLight ambient = new AmbientLight();
ambient.setEnable(true);
ambient.setColor(new Color3f(0.2f, 0.2f, 0.2f));
ambient.setInfluencingBounds(worldBounds);
addChild(ambient);
DirectionalLight dir1 = new DirectionalLight();
dir1.setEnable(true);
dir1.setColor(new Color3f(1.0f, 1.0f, 1.0f));
dir1.setDirection(new Vector3f(0.8f, -0.35f, 0.5f));
dir1.setInfluencingBounds(worldBounds);
addChild(dir1);
DirectionalLight dir2 = new DirectionalLight();
dir2.setEnable(true);
dir2.setColor(new Color3f(0.75f, 0.75f, 1.0f));
dir2.setDirection(new Vector3f(-0.7f, -0.35f, -0.5f));
dir2.setInfluencingBounds(worldBounds);
addChild(dir2);
// Load textures
TextureLoader texLoader = new TextureLoader("grass06.jpg", observer);
Texture grassTex = texLoader.getTexture();
if (grassTex == null)
System.err.println("Cannot load grass06.jpg texture");
else {
grassTex.setBoundaryModeS(Texture.WRAP);
grassTex.setBoundaryModeT(Texture.WRAP);
grassTex.setMinFilter(Texture.NICEST);
grassTex.setMagFilter(Texture.NICEST);
grassTex.setMipMapMode(Texture.BASE_LEVEL);
grassTex.setEnable(true);
}
texLoader = new TextureLoader("marble10.jpg", observer);
Texture walkTex = texLoader.getTexture();
if (walkTex == null)
System.err.println("Cannot load marble10.jpg texture");
else {
walkTex.setBoundaryModeS(Texture.WRAP);
walkTex.setBoundaryModeT(Texture.WRAP);
walkTex.setMinFilter(Texture.NICEST);
walkTex.setMagFilter(Texture.NICEST);
walkTex.setMipMapMode(Texture.BASE_LEVEL);
walkTex.setEnable(true);
}
texLoader = new TextureLoader("granite07rev.jpg", observer);
columnTex = texLoader.getTexture();
if (columnTex == null)
System.err.println("Cannot load granite07rev.jpg texture");
else {
columnTex.setBoundaryModeS(Texture.WRAP);
columnTex.setBoundaryModeT(Texture.WRAP);
columnTex.setMinFilter(Texture.NICEST);
columnTex.setMagFilter(Texture.NICEST);
columnTex.setMipMapMode(Texture.BASE_LEVEL);
columnTex.setEnable(true);
}
//
// Build the ground
// +-----+---+-----+
// | | | |
// | G | W | G |
// | | | |
// +-----+---+-----+
//
// where "G" is grass, and "W" is a walkway between columns
//
Vector3f trans = new Vector3f();
Transform3D tr = new Transform3D();
TransformGroup tg;
// Walkway appearance
Appearance walkApp = new Appearance();
Material walkMat = new Material();
walkMat.setAmbientColor(0.5f, 0.5f, 0.5f);
walkMat.setDiffuseColor(1.0f, 1.0f, 1.0f);
walkMat.setSpecularColor(0.0f, 0.0f, 0.0f);
walkApp.setMaterial(walkMat);
TextureAttributes walkTexAtt = new TextureAttributes();
walkTexAtt.setTextureMode(TextureAttributes.MODULATE);
walkTexAtt.setPerspectiveCorrectionMode(TextureAttributes.NICEST);
tr.setIdentity();
tr.setScale(new Vector3d(1.0, 6.0, 1.0));
walkTexAtt.setTextureTransform(tr);
walkApp.setTextureAttributes(walkTexAtt);
if (walkTex != null)
walkApp.setTexture(walkTex);
// Grass appearance
Appearance grassApp = new Appearance();
Material grassMat = new Material();
grassMat.setAmbientColor(0.5f, 0.5f, 0.5f);
grassMat.setDiffuseColor(1.0f, 1.0f, 1.0f);
grassMat.setSpecularColor(0.0f, 0.0f, 0.0f);
grassApp.setMaterial(grassMat);
TextureAttributes grassTexAtt = new TextureAttributes();
grassTexAtt.setTextureMode(TextureAttributes.MODULATE);
grassTexAtt.setPerspectiveCorrectionMode(TextureAttributes.NICEST);
tr.setIdentity();
tr.setScale(new Vector3d(2.0, 8.0, 1.0));
grassTexAtt.setTextureTransform(tr);
grassApp.setTextureAttributes(grassTexAtt);
if (grassTex != null)
grassApp.setTexture(grassTex);
// Left grass
trans.set(-LawnWidth / 2.0f - WalkwayWidth / 2.0f, -1.6f, 0.0f);
tr.set(trans);
tg = new TransformGroup(tr);
ElevationGrid grass1 = new ElevationGrid(2, // X dimension
2, // Z dimension
LawnWidth, // X spacing
LawnDepth, // Z spacing
grassApp); // appearance
tg.addChild(grass1);
addChild(tg);
// Right grass
trans.set(LawnWidth / 2.0f + WalkwayWidth / 2.0f, -1.6f, 0.0f);
tr.set(trans);
tg = new TransformGroup(tr);
ElevationGrid grass2 = new ElevationGrid(2, // X dimension
2, // Z dimension
LawnWidth, // X spacing
LawnDepth, // Z spacing
grassApp); // appearance
tg.addChild(grass2);
addChild(tg);
// Walkway
trans.set(0.0f, -1.6f, 0.0f);
tr.set(trans);
tg = new TransformGroup(tr);
ElevationGrid walk = new ElevationGrid(2, // X dimension
2, // Z dimension
WalkwayWidth, // X spacing
WalkwayDepth, // Z spacing
walkApp); // appearance
tg.addChild(walk);
addChild(tg);
//
// Build several columns on the floor
//
SharedGroup column = buildSharedColumn();
Group columns = buildColumns(column);
addChild(columns);
}
}
//
//CLASS
//GothicColumn - Gothic-style column used in example scenes
//
//DESCRIPTION
//This class builds a Gothic-column architectural column.
//
//SEE ALSO
//?
//
//AUTHOR
//David R. Nadeau / San Diego Supercomputer Center
//
//
class GothicColumn extends Primitive {
//
// Construction Flags
//
public final static int BUILD_TAPERED_CROWN = 0x1;
public final static int BUILD_TOP = 0x2;
public final static int BUILD_BOTTOM = 0x4;
//
// 3D nodes
//
private Appearance mainAppearance = null;
//
// Construct a column
//
public GothicColumn(float height, float radius, Appearance app) {
this(height, radius, 0, app);
}
public GothicColumn(float height, float radius, int flags, Appearance app) {
mainAppearance = app;
// Compute sizes and positions based upon the
// desired main column radius
// Base box
float baseWidth = 2.7f * radius;
float baseDepth = baseWidth;
float baseHeight = 0.75f * radius / 2.0f;
// Base box #2
float base2Width = 0.8f * baseWidth;
float base2Depth = base2Width;
float base2Height = baseHeight / 2.0f;
// Tapered crown
float crownWidth1 = 2.0f * 0.707f * radius;
float crownDepth1 = crownWidth1;
float crownWidth2 = 1.0f * base2Width;
float crownDepth2 = 1.0f * base2Depth;
float crownHeight = 2.0f * baseHeight;
// Box above tapered crown
float crown2Width = 1.1f * base2Width;
float crown2Depth = 1.1f * base2Depth;
float crown2Height = base2Height;
// Final crown box
float crown3Width = 1.1f * baseWidth;
float crown3Depth = 1.1f * baseDepth;
float crown3Height = baseHeight;
|