Static virtual worlds are, well, boring. Once the "golly" effect wears off, users begin to expect (and demand) more. You've already learned the basic techniques necessary to model a virtual world. This month I'll show you how to wow 'em. I'm going to teach you how to implement two basic geometric transformations -- translation and rotation -- and how to build them into a simple user interface for your virtual world. As a bonus, I'll show you how to add the illusion of depth to views of our model. (2,400 words)
Before I present new material, I'd like to briefly review the two topics I covered last month -- building a computer model and displaying it on the computer screen.
We learned we could build a skeletal copy of a real-world object composed solely of line segments, which allows us to capture the essential information about each object's shape -- the coordinates and the edges. We simply record the coordinates of each line segment's begin and end points in a table, embed that table in a program, and voilà, we have a model of the world inside a computer.
Once we've transformed the world into a computer model, we naturally want to view the scene the model represents. Last month I described one way to transform the model into something that could be viewed on a computer screen. We took the model data, discarded one dimension (the z coordinate, which represents depth), scaled the resulting data (so that it fit on the computer screen), and drew a line for each line segment described by the data. These steps allowed us to create what is called a wire-frame view of the model. We use this term because every object in the view looks like it is made only of wire -- that is, only the edges are visible.
If you'd like more detail on either of these topics, see last month's column 3D computer graphics, Part 1.
Changing the world
The applets I presented last month fell short in a number of areas. In particular, they were static. Although the applets were good at displaying an object, the user couldn't interact with the object or the portal's view of the object. To see the object in another position or orientation, the user would have to calculate the new coordinates of the corners by hand (a tedious, not to mention error-prone set of operations), and then edit and recompile the source code. Of course, this approach assumes that your average run-of-the-mill user could actually perform these tasks!
As it turns out, many of the things a user might want to do to a shape (for example, rotate the shape) are easily described arithmetically. And you guessed it -- computers are great at arithmetic.
Before I proceed, let me step aside for one brief moment and define position and orientation as they pertain to our three-dimensional model of the world.
Position versus orientation
An object's position is its location relative to some point of reference (in our case, that point is the origin). If the object's location relative to that point doesn't change, we say that the object hasn't changed position. Figure 1 illustrates what I mean. The two squares at A have the same position, while the two squares at B do not.
Figure 1: Position versus orientation
An object's orientation is harder to define, but easy to illustrate. So let me dispense with the words and show you what orientation is. Take another look at Figure 1. The two squares at B have the same orientation, while the two squares at A do not. That was simple, wasn't it?
Now let's consider two very basic transformations that computers happen to do well: translations and rotations.
The simplest transformation -- Translation
Translation involves changing the position of an object by moving (or translating) every point that comprises the object by the same amount in the same direction. Because each point is moved the same way, a translation affects an object's position, not its orientation.
In order to better understand what translation does, let's look at what happens in two dimensions. Figure 2 depicts a square in the translation process. Notice that all four corners of the square move, and they move by the same amount in the same direction.
Figure 2: Translating an object
As you've probably guessed, translating points is exactly the sort of thing that computers are good at. We just need to tell them how to do it. I can feel some of you starting to squirm. For those of you who are uncomfortable with mathematics, the road is about to become a bit bumpy. But hang in there and we'll get back to the basics shortly.
We can represent a coordinate like this:
When we translate an object, we move each of that object's coordinates along a vector given by:
The result is a new set of coordinates, each of which has been moved by the same amount in the same direction:
That wasn't so bad. And to top it off, you don't even have to create the class to perform such a translation. I've created one for you. Translation.java will do the trick.
Taking the world out for a spin -- Rotation
Rotation involves changing the orientation (and often the position) of an object by moving every point that comprises the object in a circular motion.
Once again, let's consider first what happens in two dimensions. Figure 3 depicts a square as it's being rotated around a point, which is represented by the black dot. Notice that the object's position and its orientation change.
Figure 3: Rotating an object
It's time to drop into math mode once more, so hang on.
Consider a three-dimensional object floating in space. Assume we want to rotate this object around a line going through the origin. The resulting operation is
where the matrix M has the following form:
The constants a, b, and c are components of the unit vector describing the direction of the line through the origin. The final constant, alpha ( ), specifies the angle of rotation.
Once again, I've supplied a class that performs such a rotation -- Rotation.java.
Gaining a new perspective
While we're at it, let's embellish the presentation of our model a little bit by adding perspective. Perspective is an artistic technique used to represent three-dimensional objects and depth relationships on a two-dimensional surface like a computer screen. Because the isometric projection we did last month simply discarded the z coordinate, our scene appeared flat -- that is, it lacked the illusion of depth.
Consider the illustration in Figure 4. The colored bar represents the computer screen (the portal), and the colored circle represents your eye (the black dot represents your pupil). Imagine that the model consists of two arrows, identical in every respect except for their distance from the portal (and your eye). We all know intuitively that the farther away an object is from us, the smaller it appears. The illustration shows how this happens.
Figure 4: Understanding perspective
Adding perspective to a view is simply a matter of scaling the height (and width) of each object by the distance the object is from the screen. In the following equation, x is the height of the object and z is its distance from the screen. The value z' is the distance the eye is from the screen, and x' is the apparent height of the object on the screen:
The Java connection
Now that we've covered the theory, I can describe the building blocks that make this whole endeavor possible. I am, of course, speaking of the Java classes.
We'll begin with the classes to model the world, then we'll look at the classes that display and manipulate the model of the world.
Classes for modeling a world
Despite its simplicity, the Scene class is a very important building block. It provides the scaffolding (the support), which the other classes depend upon. Functionally, it acts as a container for the objects that make up the world.
A scene contains pieces of scenery. There are two types of scenery. The most basic kind is a simple list of coordinates. The coordinates specify the begin and end points of a set of line segments linked end-to-end. It is represented by an instance of the Vector class, each element of which holds a coordinate. This simple representation, while fine for wire-frame models, has a number of limitations -- the most important of which is a lack of surface information (location, texture, color, and so on). The Scenery interface addresses this shortcoming.
The Scenery interface forms the basis for more complex pieces of scenery. Pieces of scenery that implement the Scenery interface define complete surfaces. An example is class TriangleShape. The TriangleShape class represents flat, triangular surfaces. It provides a convenient building block that you can use to design much more complex objects.
All scenery is ultimately a collection of coordinate data. The Coordinates class encapsulates coordinate data.
Classes for displaying and manipulating the model
A portal is a window into a scene. It is responsible for transforming the model into something viewable. A portal has great latitude in how it does this transformation and how much detail it includes. Like the portals in this and the last column, a portal can simply display a wire-frame view of the model. On the other hand, a portal can shade, texture, and smooth the image and add any number of enhancements. In future columns, I'll examine some of those enhancements, such as shading and texture mapping.
An abstract Portal class implements basic portal functionality. It is a subtype of class Canvas. Actual portals should be subclasses of class Portal and should implement any of the functionality specific to their needs. The Port class is one such class.
Transformations cause changes to the world. A transformation is represented by an instance of interface Transformation. I've supplied two implementations of the Transformation interface: class Translation and class Rotation.
A day at the beach
If you've stuck with me this far, you deserve a reward. I think a trip to the beach is in order. And with this beach you don't even have to ask your boss for time off. Okay, okay, so it's only a virtual beach, but at least the sand won't burn your feet! Before you turn over to toast your backside, take some time to peruse the code that builds the model.
Figure 5: Lounging on the beach
But wait. That's not all. This applet is interactive. The portal responds to the arrow keys. Pressing an arrow key causes the scene to rotate about the center of the portal in the appropriate direction. If you hold down the Shift key while pressing an arrow key, the scene will move in the appropriate direction. Give it a try.
Note to Solaris users: Unfortunately, on systems running Solaris with Netscape, the arrow keys don't generate events, so the model will not change orientation.
Note to Windows 95 users: If the arrow keys don't appear to work, click on the applet and try again. It seems that the applet occasionally loses input focus (and therefore never receives any further keyboard events). Clicking on the window restores the focus.
Next month we continue our explorations, this time focusing on surfaces, lighting, and shading. I'll see you then.
About the author
Todd Sundsted (email@example.com) has been writing programs since computers became available in desktop models. Though originally interested in building distributed object applications in C++, Todd moved to the Java programming language when Java became the obvious choice for that sort of thing. Todd is co-author of the Java Language API SuperBible, now in bookstores everywhere. In addition to writing, Todd is president of Etcee, which offers Java-centric training, mentoring, and consulting.
Previous How-To Java articles
Original URL: http://www.javaworld.com/javaworld/jw-06-1997/jw-06-howto.html
Last modified: Friday, May 16, 1997