/*******************************************************************************
* Copyright (C) 2001 Daniel Selman
*
* First distributed with the book "Java 3D Programming" by Daniel Selman and
* published by Manning Publications. http://manning.com/selman
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, version 2.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* The license can be found on the WWW at: http://www.fsf.org/copyleft/gpl.html
*
* Or by writing to: Free Software Foundation, Inc., 59 Temple Place - Suite
* 330, Boston, MA 02111-1307, USA.
*
* Authors can be contacted at: Daniel Selman: daniel@selman.org
*
* If you make changes you think others would like, please contact one of the
* authors or someone at the www.j3d.org web site.
******************************************************************************/
import java.applet.Applet;
import javax.media.j3d.Alpha;
import javax.media.j3d.Appearance;
import javax.media.j3d.Background;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.DirectionalLight;
import javax.media.j3d.Material;
import javax.media.j3d.PositionInterpolator;
import javax.media.j3d.Texture;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.vecmath.Color3f;
import javax.vecmath.Point3d;
import javax.vecmath.Vector3f;
import com.sun.j3d.utils.geometry.Primitive;
import com.sun.j3d.utils.geometry.Sphere;
import com.sun.j3d.utils.image.TextureLoader;
import com.sun.j3d.utils.universe.SimpleUniverse;
/*
* This example builds a simple Java 3D Application using the SUN utility
* classes: MainFrame and SimpleUniverse. The example displays a moving sphere,
* in front of a background image. It uses a texture image and one light to
* increase the visual impact of the scene.
*/
public class SimpleTest extends Applet {
/*
* Create a simple Java 3D environment containing: a sphere (geometry), a
* light,background geometry with an applied texture, and a behavior that
* will move the sphere along the X-axis.
*/
public SimpleTest() {
// create the SimpleUniverse class that will
// encapsulate the scene that we are building.
// SimpleUniverse is a helper class (utility)
// from SUN that is included with the core Java 3D
// distribution.
SimpleUniverse u = new SimpleUniverse();
// create a BranchGroup. A BranchGroup is a node in
// a Tree data structure that can have child nodes
BranchGroup bgRoot = new BranchGroup();
// create the Background node and add it to the SimpleUniverse
u.addBranchGraph(createBackground());
// create the behaviors to move the geometry along the X-axis.
// The behavior is added as a child of the bgRoot node.
// Anything add as a child of the tg node will be effected by the
// behvior (will be moved along the X-axis).
TransformGroup tg = createBehaviors(bgRoot);
// add the Sphere geometry as a child of the tg
// so that it will be moved along the X-axis.
tg.addChild(createSceneGraph());
// because the sphere was added at the 0,0,0 coordinate
// and by default the viewer is also located at 0,0,0
// we have to move the viewer back a little so that
// she can see the scene.
u.getViewingPlatform().setNominalViewingTransform();
// add a light to the root BranchGroup to illuminate the scene
addLights(bgRoot);
// finally wire everything together by adding the root
// BranchGroup to the SimpleUniverse
u.addBranchGraph(bgRoot);
}
/*
* Create the geometry for the scene. In this case we simply create a Sphere
* (a built-in Java 3D primitive).
*/
public BranchGroup createSceneGraph() {
// create a parent BranchGroup node for the Sphere
BranchGroup bg = new BranchGroup();
// create an Appearance for the Sphere.
// The Appearance object controls various rendering
// options for the Sphere geometry.
Appearance app = new Appearance();
// assign a Material to the Appearance. For the Sphere
// to respond to the light in the scene it must have a Material.
// Assign some colors to the Material and a shininess setting
// that controls how reflective the surface is to lighting.
Color3f objColor = new Color3f(0.8f, 0.2f, 1.0f);
Color3f black = new Color3f(0.0f, 0.0f, 0.0f);
app.setMaterial(new Material(objColor, black, objColor, black, 80.0f));
// create a Sphere with a radius of 0.1
// and associate the Appearance that we described.
// the option GENERATE_NORMALS is required to ensure that the
// Sphere responds correctly to lighting.
Sphere sphere = new Sphere(0.1f, Primitive.GENERATE_NORMALS, app);
// add the sphere to the BranchGroup to wire
// it into the scene.
bg.addChild(sphere);
return bg;
}
/*
* Add a directional light to the BranchGroup.
*/
public void addLights(BranchGroup bg) {
// create the color for the light
Color3f color = new Color3f(1.0f, 1.0f, 0.0f);
// create a vector that describes the direction that
// the light is shining.
Vector3f direction = new Vector3f(-1.0f, -1.0f, -1.0f);
// create the directional light with the color and direction
DirectionalLight light = new DirectionalLight(color, direction);
// set the volume of influence of the light.
// Only objects within the Influencing Bounds
// will be illuminated.
light.setInfluencingBounds(getBoundingSphere());
// add the light to the BranchGroup
bg.addChild(light);
}
/*
* Create some Background geometry to use as a backdrop for the application.
* Here we create a Sphere that will enclose the entire scene and apply a
* texture image onto the inside of the Sphere to serve as a graphical
* backdrop for the scene.
*/
public BranchGroup createBackground() {
// create a parent BranchGroup for the Background
BranchGroup backgroundGroup = new BranchGroup();
// create a new Background node
Background back = new Background();
// set the range of influence of the background
back.setApplicationBounds(getBoundingSphere());
// create a BranchGroup that will hold
// our Sphere geometry
BranchGroup bgGeometry = new BranchGroup();
// create an appearance for the Sphere
Appearance app = new Appearance();
// load a texture image using the Java 3D texture loader
Texture tex = new TextureLoader("back.jpg", this).getTexture();
// apply the texture to the Appearance
app.setTexture(tex);
// create the Sphere geometry with radius 1.0
// we tell the Sphere to generate texture coordinates
// to enable the texture image to be rendered
// and because we are *inside* the Sphere we have to generate
// Normal coordinates inwards or the Sphere will not be visible.
Sphere sphere = new Sphere(1.0f, Primitive.GENERATE_TEXTURE_COORDS
| Primitive.GENERATE_NORMALS_INWARD, app);
// start wiring everything together
// add the Sphere to its parent BranchGroup
bgGeometry.addChild(sphere);
// assign the BranchGroup to the Background as geometry.
back.setGeometry(bgGeometry);
// add the Background node to its parent BranchGroup
backgroundGroup.addChild(back);
return backgroundGroup;
}
/*
* Create a behavior to move child nodes along the X-axis. The behavior is
* added to the BranchGroup bg, whereas any nodes added to the returned
* TransformGroup will be effected by the behavior.
*/
public TransformGroup createBehaviors(BranchGroup bg) {
// create a TransformGroup.
//
// A TransformGroup is a Group node (can have children)
// and contains a Transform3D member.
//
// The Transform3D member contains a 4x4 transformation matrix
// that is applied during rendering to all the TransformGroup's
// child nodes. The 4x4 matrix can describe:
// scaling, translation and rotation in one neat package!
// enable the TRANSFORM_WRITE capability so that
// our behavior code can modify it at runtime
TransformGroup objTrans = new TransformGroup();
objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
// create a new Transform3D that will describe
// the direction we want to move.
Transform3D xAxis = new Transform3D();
// create an Alpha object.
// The Alpha object describes a function against time.
// The Alpha will output a value that ranges between 0 and 1
// using the time parameters (in milliseconds).
Alpha xAlpha = new Alpha(-1, Alpha.DECREASING_ENABLE
| Alpha.INCREASING_ENABLE, 1000, 1000, 5000, 1000, 1000, 10000,
2000, 4000);
// create a PositionInterpolator
// The PositionInterpolator will modify the translation components
// of a TransformGroup's Transform3D (objTrans) based on the output
// from the Alpha. In this case the movement will range from
// -0.8 along the X-axis with Alpha=0 to X=0.8 when Alpha=1.
PositionInterpolator posInt = new PositionInterpolator(xAlpha,
objTrans, xAxis, -0.8f, 0.8f);
// set the range of influence of the PositionInterpolator
posInt.setSchedulingBounds(getBoundingSphere());
// wire the PositionInterpolator into its parent
// TransformGroup. Just like rendering nodes behaviors
// must be added to the scenegraph.
objTrans.addChild(posInt);
// add the TransformGroup to its parent BranchGroup
bg.addChild(objTrans);
// we return the TransformGroup with the
// behavior attached so that we can add nodes to it
// (which will be effected by the PositionInterpolator).
return objTrans;
}
/*
* Return a BoundingSphere that describes the volume of the scene.
*/
BoundingSphere getBoundingSphere() {
return new BoundingSphere(new Point3d(0.0, 0.0, 0.0), 200.0);
}
/*
* main entry point for the Application.
*/
public static void main(String[] args) {
SimpleTest simpleTest = new SimpleTest();
}
}
|