Java 3D Programming by Daniel Selman - HTML preview

PLEASE NOTE: This is an HTML preview only and some elements such as links or page numbers may be incorrect.
Download the book in PDF, ePub, Kindle for a complete version.

CHAPTER 3

Getting started, Hello Java 3D!

3.1 Installation

3.2 Your first Java 3D application

3.3 Exercises for the reader

3.4 Summary

Now the fun begins. It’s time to begin conquering the Java 3D development environment, setting ourselves up for serious Java 3D fun in the chapters to come. I’ll introduce a realistic Java 3D application to test your configuration, and allow you to experiment with some of the features described in later chapters. You’ll look

at a simple Java 3D example, SimpleTest, that illustrates building an AWT-based Java 3D application. The SimpleTest example uses the Sun utility classes MainFrame and SimpleUniverse (included with your Java 3D distribution) to hide some of the complexities that we will be delving into in the chapters to come.

3.1 Installation

Our first step, obviously, is to install everything we need for Java 3D development. Refer to appendix B and the bibliography for useful sources of information or additional help.

3.1.1 Java 2 SDK

Check the Sun web site (http://java.sun.com)  and download the latest release. Java 2 SDK 1.3.1 (JDK 1.3.1) is the latest release at the time of print. You can also find it at http://www.javasoft.com/j2se/1.3/.  Remove all previous versions of the SDK, JDK, or JRE prior to installing the new SDK. After installation launch the Java plug-in control applet from the Windows Control Panel and set the Java Runtime Environment (JRE) to the newly installed SDK location. This will enable running Java 3D applets using the Java 2 plug-in.

3.1.2 Java 3D 1.2 JDK

Download the latest release of the Java 3D SDK at http://www.javasoft.com/products/java-media/3D/index.html.   The OpenGL version of Java 3D has historically been more stable and ahead of the DirectX release in terms of features. At the time of print the latest release is Java 3D 1.2.1. You should install Java 3D into the same directory as the Java 2 SDK, typically c:\jdk1.3.  This will ensure that all your Java 2 demo applications are installed into the same place.

You can then use REGEDIT to edit the Windows registry to remove all references to the JRE installation directory (which is also installed when you install the SDK). Replace all occurrences of c:\program files\javasoft\jre\1.3\… with the SDK installation location, usually c:\jdk1.3\jre\…  This will enable running the Java 3D demos from the command line, and ensure that only one Java 2 runtime environment is installed on your machine.

–––––––––––––––––––––––––––––––

IMPORTANT

Do not run REGEDIT unless you are an experienced Windows user and familiar with editing the registry. It is not strictly necessary to remove all references to the JRE install location.

–––––––––––––––––––––––––––––––

Test your Java 3D installation by running the HelloUniverse Java 3D demo. First run from the command line by going to the relevant installation directory and then typing:

java HelloUniverse

You can test the Java 2 plug-in installation by double-clicking the HelloUniverse_plug-in.html file. Your web browser should launch, the Java 2 plug-in window will appear, and the HelloUniverse applet should start.

Once the tests are running you can safely delete the c:\program files\javasoft directory.

3.1.3 Documentation

Java 3D programming involves general Java programming, high-performance programming, 3D graphics algorithms, 2D graphics programming, UI design, and many other issues. A good reference library or collection of electronic bookmarks will save you a lot of time and help you to avoid some of the pitfalls that have befallen your predecessors.

Though far from exhaustive, the list of references which follows should give you some indication of fruitful areas to start researching.

  • Java 2 SDK JavaDoc and reference books—Java 2 is a complex technology. If you are going to write good Java 3D code you are going to require the latest Java 2 documentation and some good reference books.
  • Swing reference book—If you are developing an application that uses Swing (JFC) for the UI you will want to get a good Swing reference book. These weighty tomes can save you a lot of time during development. A good place to start is Swing by Mathew Robinson and Pavel Vorobiev (http://www.manning.com/Robinson/index.html).
  • Java 3D JavaDoc—Of course you should ensure that you download the latest API documentation for Java 3D.
  • Sun collateral Java 3D tutorial—The free Java 3D tutorial from Sun makes a good reference for many introductory topics and for those that like a structured tutorial style book to get started. Find it at http://www.javasoft.com/products/java-media/3D/collateral/.
  • J3D.ORG—You should check the J3D.ORG web site (http://www.j3d.org/)  for FAQs and free example code. Many of the questions and problems that you run into have been faced and answered by other Java 3D users. Many answers are posted on the J3D.ORG web site or in the interest email list archives. J3D.ORG also contains useful utility code, tutorials, and examples that have been contributed by the active Java 3D community.
  • Java 3D interest email list—You should subscribe to this excellent forum (http://archives.java.sun.com/archives/java3d-interest.html) for asking fellow developers questions. Before posting your questions, take the time to search the archives for similar questions and answers.
  • Java 3D user interface reference—Building Java 3D User Interfaces by Jon Barrilleaux from Manning Publications will be very useful if you are building a complex 3D user interface. Jon answers many of the questions you will run into as you try to use 3D overlays, and presents solutions for the common UI requirements. For more information, surf to http://www.manning.com/Barrilleaux/index.html . There are several other Java 3D books coming into print—check the J3D.ORG web site for the latest information.
  • 3D graphics reference books—If you are new to 3D graphics in general, you may want to pick up a good textbook on the subject. A good reference will cover the general aspects of 3D projections, transformation matrices, clipping, lighting, and rendering. Computer Graphics: Principles and Practice in C by James D. Foley, et al. (Addison-Wesley, 1995) is considered by many to be the bible of computer-generated 3D graphics. Many other useful books are reviewed in appendix B.
  • OpenGL reference books—There is considerable overlap between Java 3D and OpenGL. A good OpenGL reference will give you a greater understanding for what is going on under the covers and allow you to use Java 3D to the fullest. An OpenGL reference can also be useful when you need to extrapolate from the Java 3D documentation and infer the behavior of more advanced operations. The OpenGL “Red Book” is an excellent reference and is also available online at http://ask.ii.uib.no/ebt-bin/nph-dweb/dynaweb/SGI_Developer/OpenGL_PG/.   Some general OpenGL related links have been compiled at the OpenGL FAQ and Troubleshooting Guide at http://www.frii.com/~martz/oglfaq/gettingstarted.htm.

3.1.4 Java 2 development environment (optional)

Every developer has their favorite programmer’s editor, and an increasing number of Integrated Development Environments (IDEs) are available that support Java 2. They range from free to expensive, and have a wide variety of features. Some of the more popular IDEs for Java 2 development are:

All the examples for this book were built using Kawa. Unfortunately, after Allaire was acquired by Macromedia, development of Kawa was discontinued.

3.1.5 Performance analysis tools (optional)

As you formalize your designs and requirements it is often helpful to drop into a performance measurement tool to see where your code is spending its time. Two popular commercial tools for Java optimization are:

You can also use the free (but harder to interpret) performance measurement capabilities of the Java 2 JVM. See the documentation for the java –Xprof argument for details.

3.1.6 Java class decompiler (optional)

When things get really sticky and you can’t understand what Java 3D is doing it can be useful to decompile the Java 3D class files. You will need to decompress the Java 3D JAR files and extract the class files prior to decompling them. A popular (and free) decompiler is JAD (JAva Decompiler). Find it at http://www.geocities.com/SiliconValley/Bridge/8617/jad.html.

3.2 Your first Java 3D application

The SimpleTest example (figure 3.1) is intended to build upon the HelloUniverse example that comes with the Java 3D distribution. I’ve attempted to expand upon HelloUniverse by documenting the relationships between the various constructs used in the example and showcasing some of the features of Java 3D that enable you to build fairly complex applications with very little code. This example is 280 lines (less than 100 without comments) and illustrates some fairly complex functionality:

img13.png

Figure 3.1 The SimpleTest example. One hundred lines of Java code give you an animated scene, including a graphical textured background with directional lighting

  • Background geometry, in this case the scene is placed within a Sphere.
  • Textured geometry, an image is applied to the inside of the background Sphere to give the illusion of a distant skyline.
  • Lighting, a single directional light is created to provide depth cues through rendering.
  • Geometry, a second smaller Sphere is placed within the scene.
  • Appearance, the smaller Sphere has an Appearance and Material associated with it that interacts with the directional light to produce a shaded, colored effect.
  • Animation, a PositionInterpolator behavior is attached to the smaller Sphere to move it left and right using a complex time function (Alpha).

For instructions on running the examples that accompany the book please refer to appendix A.

To produce a comparable example using basic OpenGL would require many hundreds of lines of code. You can quickly see the benefits of a Java 3D’s higher-level of scene description—the scenegraph.

 From SimpleTest.java

import java.applet.Applet;

import javax.media.j3d.*;

import javax.vecmath.*;

import com.sun.j3d.utils.geometry.*;

import com.sun.j3d.utils.universe.*;

import com.sun.j3d.utils.image.TextureLoader;

 

/*

 * 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 added as a child of the tg node will be effected by the

// behavior (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 );v

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

 }

}

3.3 Exercises for the reader

When you run the example, I would encourage you to make some changes and see their effects. For example:

Colors and lighting

See how the color of the Material and the color of the directional light interact to produce the actual rendered color. Sophisticated lighting equations are at work to combine the effects of both at runtime. Try changing the shininess parameter to (80.0f) to increase or decrease the apparent shininess of the smaller Sphere.

Try removing the setMaterial call and see how rendering is affected.

Animation parameters