< Zurück | Inhalt | Weiter >

2.1 Learning 3D graphics programming

Given the enormous variety of teaching and learning styles, there probably is no best way of teaching 3D graphics programming. I learned 3D graphics programming by experimenting. I wrote my first 3D graphics program about 10 years ago. It was written in C and ran on my venerable Intel 80386 with a whole 256 KB of RAM! Needless to say, it didn’t use Java 3D or OpenGL. The program was a modified port of a simple BASIC program that I "borrowed" from a simple little BASIC programming book. I later ported the program to run on Solaris using the GKS rendering API. The program was a very simple wire frame 3D model viewer and editor. You could load 3D shapes described using ASCII text files and then display them on screen. You could also interactively rotate the shapes about one axis. Times have certainly changed.

The interesting thing about my first 3D effort is that I built upon my general programming knowledge and some simple 2D rendering techniques, such as drawing a line to the screen. That’s what we’ll do here. In this chapter, we will turn the clock back 10 years and build some sections of that program all over again, this time using Java, Java 2D, and some of the Java 3D utilities. This should remove some of the mystery from the operations performed by 3D graphics libraries like Java 3D and OpenGL. At the end of the day, we are simply converting from 3D coordinates to 2D coordinates and drawing a bunch of points and lines. We can use the source code as a basis for introducing the basics of 3D graphics programming and highlight some of the fundamental operations that a graphics library such as Java 3D provides.

By looking at the example, you’ll see the additional operations that a real graphics API provides, and that our homegrown, primitive API does not.

To begin, look at the output from a simple Java 3D program and compare it with the test−bed application MyJava3D. Figure 2.1 was rendered by a simple Java 3D program (the LoaderTest example), which loads a

Lightwave OBJ file and renders it to the screen. Figure 2.2 was rendered in MyJava3D using AWT 2D graphics routines to draw the lines that compose the shape.


Figure 2.1 Output of a simple Java 3D application (LoaderTest)


Figure 2.2 Output rendered by MyJava3D—a wire frame version of the same hand used for figure 2.1

The Java3D−rendered image is certainly superior. I’ll compare the two images in detail later in this chapter. However, the wire frame version (just lines) that was rendered using MyJava3D is also useful.

Note how the triangular surfaces that compose the 3D model are visible in figure 2.2. The model is composed of hundreds of points, each positioned in 3D space. In addition, lines are drawn to connect the points, to form triangular surfaces. The illusion of a solid 3D shape in figure 2.1 has now been revealed—what appeared to be a solid shape is in fact a hollow skin. The skin of the shape is described using hundred of points, which are then drawn as solid triangles. Java 3D filled the interior of the triangles while MyJava3D merely drew the outer lines of each triangle.

Consider the simplest series of operations that must take place to convert the 3D model data into a rendered image:

1. Load the 3D points that compose the vertices (corners) of each triangle. The vertices are indexed so they can be referenced by index later.

2. Load the connectivity information for the triangles. For example, a triangle might connect vertices 2, 5, and 7. The actual vertex information will be referenced using the information and indices established in step 1.

3. Perform some sort of mathematical conversion between the 3D coordinates for each vertex and the 2D coordinates used for the pixels on the screen. This conversion should take into account the position of the viewer of the scene as well as perspective.

4. Draw each triangle in turn using a 2D graphics context, but instead of using the 3D coordinates loaded in step 1, use the 2D coordinates that were calculated in step 3.

5. Display the image.

That’s it.

Steps 1, 2, 4, and 5 should be straightforward. Steps 1 and 2 involve some relatively simple file I/O, while steps 4 and 5 use Java’s AWT 2D graphics functions to draw a simple line into the screen. Step 3 is where much of the work takes place that qualifies this as a 3D application.

In fact, in the MyJava3D example application, we cheat and use some of the Java 3D data structures. This allows us to use the existing Lightwave OBJ loader provided with Java 3D to avoid doing the tiresome file I/O ourselves. It also provides useful data structures for describing 3D points, objects to be rendered, and so on.