The following is a selected excerpt of Chapter 14 from Killer Game Programming in Java (ISBN 0-596-00730-2) published by O'Reilly.
I'll summarize the main elements of Java 3D in this chapter, leaving program examples aside for the moment. Then, I'll examine Java 3D's suitability for games programming by considering the criticisms leveled against it.Java 3D
The Java 3D API provides a collection of high-level constructs for creating, rendering, and manipulating a 3D scene graph composed of geometry, materials, lights, sounds, and more. Java 3D was developed by Sun Microsystems, and the most recent stable release is Version 1.3.1.
TIP: There is a Version 1.3.2, but it's a bug fix release under review as I write this in December 2004. For example, a rarely occurring bug with the J3DTimer class has been fixed.
By the time you read this, Version 1.3.2 will have been finalized (an FCS release will be available).
There are two Java 3D variants: one implemented on top of OpenGL, and the other above DirectX Graphics. OpenGL is a popular software API for writing 3D (and 2D) graphics applications across a wide range of hardware and operating systems (http://www.opengl.org/). It's a low-level API based around a graphics pipeline for pixel and vertex manipulation.
TIP: Prior to the 1.3.2 bug fix release, a programmer had to choose whether to download the OpenGL version of Java 3D or the DirectX implementation since they were offered as separate installers. With Version 1.3.2 (build 7 and later), both versions are in a single download.
DirectX Graphics supports a traditional graphics pipeline, describing all geometry in terms of vertices and pixels. It's part of DirectX, a collection of related gaming modules aimed at MS Windows ( http://www.microsoft.com/directx). The other DirectX APIs support 3D audio, networking, input device integration, multimedia, and installation management.DirectX or OpenGL?
Often, the debate about which version of Java 3D is better is a debate about the relative merits of DirectX Graphics and OpenGL.
In most technical areas, DirectX Graphics and OpenGL are almost equivalent since both are based on the same graphics pipeline architecture and ideas flow between the two. The most significant differences between the two APIs are unrelated to their functionality. OpenGL is ported to a wide range of platforms and OSs, and DirectX is limited to PCs running Windows and the Xbox. DirectX is controlled by Microsoft alone, and the OpenGL Architecture Review Board (ARB) allows input from many partners.
The Direct X Graphics version of Java 3D is only available for Windows, where some users report that it's marginally faster than the OpenGL implementation. However, I've never noticed any difference when I've tried both systems.
The future seems brightest for the OpenGL version, which is the main focus of the current "bug fix" release of Java 3D, Version 1.3.2. I'll use the stable OpenGL version (1.3.1) in the rest of this book. It can be downloaded from http://java.sun.com/products/java-media/3D/, together with ample documentation and a long tutorial.
The Scene Graph
TIP: The FCS release of Version 1.3.2 will be available by the time you read this. You can obtain it from https://java3d.dev.java.net/.
Java 3D uses a scene graph to organize and manage a 3D application. The underlying graphics pipeline is hidden, replaced by a tree-like structure built from nodes representing 3D models, lights, sounds, the background, the camera, and many other scene elements.
The nodes are typed, the main division being between Group and Leaf nodes. A Group node is one with child nodes, grouping the children so operations such as translations, rotations, and scaling can be applied en masse. Leaf nodes are the leaves of the graph (did you guess that?), which often represent the visible things in the scene such as the models, but may be nontangible entities, such as lighting and sounds. Additionally, a Leaf node (e.g., for a 3D shape) may have node components , specifying color, reflectivity, and other attributes of the leaf.
The scene graph can contain behaviors , nodes holding code that can affect other nodes in the graph at runtime. Typical behavior nodes move shapes, detect and respond to shape collisions, and cycle lighting from day to night.
Scene graph is used, rather than scene tree, because it's possible for nodes to be shared (i.e., have more than one parent).
Before looking at a real Java 3D scene graph, Figure 14-1 shows how the scene graph idea can be applied to defining the contents of an office.
|Figure 14-1. Scene graph for an office|
The office Group node is the parent of Leaf nodes representing a desk and two chairs. Each Leaf utilizes geometry (shape) and color node components, and the chair geometry information is shared. This sharing means that both chairs will have the same shape but will be colored differently.
The choice of symbols in Figure 14-1 comes from a standard symbol set (shown in Figure 14-2), used in all of this book's Java 3D scene graph diagrams. I'll explain the VirtualUniverse and Locale nodes and the Reference relationship in due course.Some Java 3D scene graph nodes
The Java 3D API can be viewed as a set of classes that subclass the Group and Leaf nodes in various ways. The Leaf class is subclassed to define different kinds of 3D shapes and environmental nodes (i.e., nodes representing lighting, sounds, and behaviors).
|Figure 14-2. Scene graph symbols|
The main shape class is called Shape3D, which uses two node components to define its geometry and appearance; these classes are called Geometry and Appearance.
The Group class supports basic node positioning and orientation for its children and is subclassed to extend those operations. For instance, BranchGroup allows children to be added or removed from the graph at runtime; TransformGroup permits the position and orientation of its children to be changed.The HelloUniverse scene graph
The standard first example for Java 3D programmers is HelloUniverse. (It appears in Chapter 1 of Sun's Java 3D tutorial.) It displays a rotating colored cube, as in Figure 14-3.
The scene graph for this application is given in Figure 14-4.
VirtualUniverse is the top node in every scene graph and represents the virtual world space and its coordinate system. Locale acts as the scene graph's location in the virtual world. Below the Locale node are two subgraphs—the left branch is the content branch graph, holding program-specific content such as geometry, lighting, textures, and the world's background. The content branch graph differs significantly from one application to another.
The ColorCube is composed from a Shape3D node and associated Geometry and Appearance components. Its rotation is carried out by a Behavior node, which affects the TransformGroup parent of the ColorCube's shape.
|Figure 14-3. A rotating colored cube|
|Figure 14-4. Scene graph for HelloUniverse|
The righthand branch below Locale is the view branch graph, which specifies the users' position, orientation, and perspective as they look into the virtual world from the physical world (e.g., from in front of a monitor). The ViewPlatform node stores the viewer's position in the virtual world; the View node states how to turn what the viewer sees into a physical world image (e.g., a 2D picture on the monitor). The Canvas3D node is a Java GUI component that allows the 2D image to be placed inside a Java application or applet.
The VirtualUniverse, Locale, and view branch graph often have the same structure across different applications since most programs use a single Locale and view the virtual world as a 2D image on a monitor. For these applications, the relevant nodes can be created with Java 3D's SimpleUniverse utility class, relieving the programmer much graph construction work.
Java 3D Strengths
The core strengths of Java 3D are its scene graph, its performance, collection of unique features, the fact that it's Java and can call upon an enormous number of support packages and APIs, and its extensive documentation and examples.The Scene Graph
The scene graph has two main advantages: it simplifies 3D programming and accelerates the resulting code. The scene graph hides low-level 3D graphics elements and allows the programmer to manage and organize a 3D scene. A scene graph supports many complex graphical elements.
At the Java 3D implementation level, the scene graph is used to group shapes with common properties, carry out view culling, occlusion culling, level of detail selection, execution culling, and behavior pruning, all optimizations that must be coded directly by the programmer in lower-level APIs. Java 3D utilizes Java's multithreading to carry out parallel graph traversal and rendering, both useful optimizations.Performance
Java 3D is designed with performance in mind, which it achieves at the high level by scene graph optimizations and at the low level by being built on top of OpenGL or DirectX Graphics.
Some programmer-specified scene graph optimizations are available through capability bits, which state what operations can/cannot be carried out at runtime (e.g., prohibiting a shape from moving). Java 3D also permits the programmer to bypass the scene graph, either totally by means of an immediate mode, or partially via the mixed mode. Immediate mode gives the programmer greater control over rendering and scene management, but it isn't often required. Retained mode programs only use the scene graph API. All the examples in this book employ retained mode.Unique Features
Java 3D's view model separates the virtual and physical worlds through the ViewPlatform and View nodes. This makes it straightforward to reconfigure an application to utilize many output devices, from a monitor, to stereo glasses, to CAVEs.
Virtual world behavior is coded with Behavior nodes in the scene graph and is triggered by events. Among other things, this offers a different style of animation based on responding to events instead of the usual update redraw/cycle you've seen in all my 2D games programs.
The core Java 3D API package, javax.media.j3d, supports basic polygons and triangles within a scene graph; the com.sun.j3d packages add a range of utility classes including ColorCube and SimpleUniverse, mouse and keyboard navigation behaviors, audio device handling, and loaders for several 3D file formats.
Geometry compression is possible, often reducing size by an order of magnitude. When this is combined with Java's NIO and networking, it facilitates the ready transfer of large quantities of data between applications such as multiplayer games.
Java 3D allows 2D and 3D audio output, ambient and spatialized sound. Unfortunately, the sound system has bugs. Consequently, spatialized sound isn't available by default in Java 3D 1.3.2. Version 1.4 may offer a JOALMixer class instead, i.e., a JOAL-based audio device. JOAL is a Java binding for a 3D audio API called OpenAL, which is supported by many sound cards.Java Integration
Java 3D is Java and offers object orientation (classes, inheritance, polymorphism), threads, exception handling, and more. Java 3D can easily make use of other Java APIs, such as JMF and JAI. The Java Media Framework (JMF) includes mechanisms for playing audio and video segments and can be extended to support new forms or audio and video (http://java.sun.com/products/java-media/jmf). Java Advanced Imaging (JAI) provides many advanced image processing features, including over 100 imaging operators, tiling of large images, network-based capabilities, and the means to add new image processing features (http://java.sun.com/products/java-media/jai).Documentation and Examples
The Java 3D distribution comes with about 40 small to medium examples. They're a great help but somewhat lacking in documentation. Fortunately, more resources are online. Sun's Java 3D tutorial is available at http://java.sun.com/products/java-media/3D/collateral/. The tutorial is a good introduction to Java 3D but can confuse beginners. Ben Moxon has a good introductory Java 3D tutorial based around getting a MilkShape 3D figure to move over a hilly terrain (http://www.newview.co.uk/e/tutorials/java3d/index.jsp) and is called The Little Purple Dude Walks.
I recommend three Java 3D textbooks as supplemental reading:
The Walsh and Gehringer text is an excellent overview, using code snippets rather than pages of listings. It complements the Java 3D tutorial.
The Selman book is more advanced. For the games enthusiast, Selman describes a Doom-like world, utilizing first-person perspective keyboard navigation and scene creation from a 2D map. The world contains bookcases, pools of water, flaming torches, and animated guards.
Terrazas is involved in VR research and business, so there's a heavy slant in the 3D part of his book toward less common topics such as sensors, head tracking, and a bit on CAVEs. There's an example combining Java 3D and JMF to create a streaming 3D chat room.
Criticisms of Java 3D for Games Programming
The misconceptions and complaints about Java 3D closely match those used against Java, which we discussed in Chapter 1:
- Java 3D is too slow for games programming.
- Java 3D is too high-level.
- Java 3D isn't supported on games consoles, so why bother using it?
- No one uses Java 3D to write real games.
- Sun Microsystems isn't interested in supporting Java 3D.
This claim comes with almost no evidence. Jacob Marner did the only serious test (2002). Marner carried out comparative performance tests on OpenGL and Java 3D versions of the same 3D noninteractive space of randomly positioned, scaled and rotated boxes. He used the C++ and GL4Java bindings for OpenGL, and used Version 1.3.0 beta 1 of Java 3D. His master's thesis, Evaluating Java for Game Development, can be obtained from http://www.rolemaker.dk/articles/evaljava/.
The C++ version was fastest, the GL4Java implementation a little slower, and Java 3D about 2.5 times slower. However, the slowdown was due to a performance bug in that version of Java 3D and a poorly optimized scene graph. The timings haven't been repeated with the latest version of Java 3D or with more recent Java bindings to OpenGL such as JOGL or LWJGL.
Marner's code highlights some striking differences between Java 3D and OpenGL. The C++ and GL4Java programs are of comparable sizes (about 10 classes and 30 pages of code with documentation), but the Java 3D application is smaller (5 classes and 11 pages). Marner comments on the complexity of the OpenGL code, which requires a kd-tree data structure, a culling algorithm around the view frustum, and preprocessing vertex operations. All of these capabilities are built into Java 3D, so they didn't need to be implemented in the Java 3D application. In the GL4Java source, the optimized view frustum algorithm is hard to understand but is responsible for an order of magnitude speedup over the simpler version.
The OpenGL applications could have been considerable faster if extensions available on the graphics card were employed.
Another outcome of Marner's work is that it shows a negligible overhead for JNI: GL4Java uses JNI to interface Java to OpenGL, and its performance is slightly less than the C++ binding.Java 3D is slow because Java is slow
Java 3D performance is often equated with Java performance: the myth of Java's slowness somehow demonstrates the slowness of Java 3D. Since Java 3D relies on OpenGL or DirectX for rendering, much of the graphics processing speed of Java 3D is independent of Java.
History suggests that performance will become a less important consideration as the base speed of hardware keeps increasing. Many successful games rely less on special effects, more on gaming characterization and story. Of course, games will always need performance, but the real bottleneck will not be the platform but the network as multiplayer games begin to dominate.
Performance should be considered alongside issues such as code complexity, productivity, maintainability, and portability. These criteria strongly influence a move toward higher-level APIs, as typified by Java 3D.Java 3D Is Too High-Level
Java 3D's scene graph is often considered an unreasonable overhead, especially by programmers with experience in OpenGL or DirectX. Though Java 3D's scene graph does introduce some overhead, this overhead should be compared to the optimizations that comes along. These can be implemented in a low-level API by an experienced programmer but at what cost in time and maintainability?
Most large OpenGL and DirectX applications need a data structure like a scene graph to manage code complexity, so the scene graph versus no scene graph argument is often invalid.
A powerful, high-level, and flexible 3D graphics API needs a scene graph and a way to access the graphics pipeline efficiently. These mechanisms are aimed at different levels in 3D graphics programming, sometimes called the entity level and the rendering level . An application's entity level requires a data structure for organizing the scene objects, and the rendering level handles light mapping, shadows, radiosity, vertex shading, and so on. Great games are designed at the entity level, in terms of game play, characters, scenarios, and story elements. The look and feel of a great game, the light and dark, the atmosphere, is created at the rendering level.
Though Java 3D has highly developed tools for entity level programming, its deficit is at the rendering level. For example, the current version of Java 3D cannot perform vertex and pixel shading. Part of this is due to the desire to support Java 3D portability across OpenGL and DirectX, preventing it from making assumptions about which low-level features are present. Nevertheless, it is possible to achieve some striking rendering effects in Java 3D by employing multi-textures. The next major Java 3D release, Version 1.4, is scheduled to support two shader languages (Cg and GLSL); a beta version is due out in the middle of 2005.
The high-level nature of the scene graph makes Java 3D code harder to tune for speed unlike programs using OpenGL or DirectX directly. However, a programmer does have the option of moving to Java 3D's mixed or immediate modes.
Hiding low-level graphics API makes programming code around bugs harder in the APIs or the drivers.Lack of Console Support
The lack of a console implementation for Java 3D is a serious problem, but if Java and OpenGL are available on a game machine, then Java 3D should be readily portable. The Game Cube already uses OpenGL.
Linux for the PlayStation 2 includes OpenGL support (http://playstation2-linux.com/projects/openglstuff/). There's an old alpha version of an OpenGL for the PlayStation 2, implemented by DataPlus (http://www.dataplus.co.jp/OpenGL4ps2.html). However, the future for OpenGL on consoles and other small devices is probably OpenGL ES, a subset of OpenGL (http://www.khronos.org/opengles/).
A Java binding is being developed for OpenGL ES, managed by JSR 239 (http://www.jcp.org/en/jsr/detail?id=239). A JSR is a Sun-sanctioned process for defining a new Java API. Much of the work is derived from JSR 231, which will be based on JOGL and/or LWJGL (both are explained in the section "Java Bindings to OpenGL"). JSR 239 is scheduled to be finished early in 2005.
No Real Java 3D Games
Java 3D has been employed in relatively few games, but they include bestsellers and award winners. I mentioned the commercial games in Chapter 1.
- Law and Order II by Legacy Interactive (http://www.lawandordergame.com/index2.htm).
- Pernica by Starfire Research (http://www.starfireresearch.com/pernica/pernica.html).
- Cosm by Navtools, Inc. (http://www.cosm-game.com/).
- Roboforge by Liquid Edge Games (http://www.roboforge.com).
- FlyingGuns (http://www.flyingguns.com/).
- CazaPool3D (http://cazapool3d.sourceforge.net/cazapooljws/Pool.html).
- Out Of Space (http://www.geocities.com/Psionic1981).
- Cassos (http://www.la-cfd.com/cassos/english/index.php). Racing monkeys, with a dragon.
- Immediate Mode Interactive (http://www.imilabs.com/) has built several impressive game demos with Java 3D over the years, including Java 3D Grand Prix (a racing game), JAMID (a first-person shooter in the Quake mold), and Underworld Assault (a two-person fighting game). Pictures and videos of these games can be found at the web site.
- The Virtual Fishtank (http://www.virtualfishtank.com/main.html). A distributed simulation of a 24,000-gallon aquarium rendered to 13 large projection screens and running on 15 networked machines. The fish migrate from server to server as they swim from screen to screen. It was shown at the Boston Museum of Science and the St. Louis Science Center to teach children about emergent self-organizing behavior in decentralized rule-based systems.
- DALiWorld (http://www.dalilab.com/). Another distributed aquatic virtual world inhabited by autonomous artificial life.
The "Other Sites" page at j3d.org (http://www.j3d.org/sites.html) is a good source for Java 3D examples and includes games and demos sections with many links.
The Java Games Factory (JGF), http://grexengine.com/sections/externalgames/, places its games into 2D and 3D categories, with the 3D examples further subdivided by the 3D API being used, such as Java 3D, JOGL, and LWJGL.
The third year Computer Graphics course in the Computer Science Department of the University of Applied Sciences in Biel, Switzerland, maintains a site of student projects using Java 3D (http://www.hta-bi.bfh.ch/~swc/DemoJ3D/). Several of them have been games, including Battleship3D-Net (networked Battleships), Billard-3D (pool), Glymp3D (role playing action), JBomba (based on Bomberman), and TriChess (3D networked chess).
A good strategy for finding Java 3D games and source code is to visit SourceForge ( http://sourceforge.net/search/) and FreshMeat.com (http://freshmeat.net/) and search for keywords such as "Java," "3d," and "game."
Two very exciting Java 3D projects, which aren't really games:
Project Looking Glass (https://lg3d.dev.java.net/)
A prototype 3D desktop offering rotating, transparent windows, multiple desktop workspaces, and an API for developing applications. It received much attention at JavaOne in 2004.