|
Comments
Did you read today's front page stories & breaking news?
SYS-CON.TV
|
General Java Real Time 3D Graphics: DirectX Libraries
Real Time 3D Graphics: DirectX Libraries
By: Mark Watson
Oct. 1, 1997 12:00 AM
The Java programming language and platform are revolutionizing the development and deployment of distributed software. I believe that the huge "twitch" game market (based on game consoles and PCs) will continue to grow, but the largest market growth eventually will be in distributed games and entertainment experiences. With steady improvements in runtime performance, Java is well positioned to be the language of choice for writing distributed entertainment software. JavaSoft has recently released the specification for the Java3D API that will provide a cross-platform solution to real-time 3D graphics. Microsoft has also released a beta API of Java bindings for their DirectX libraries. The Microsoft Java API for DirectX is specific to the Windows environment. This article demonstrates the relative ease of generating a simple 3D world using Java and the Direct3D retained-mode library. There is quite a bit of documentation that you must eventually read if you want to take maximum advantage of the DirectX/Direct3D libraries; however, we will introduce real-time 3D programming with a very simple and thoroughly explained example: two texture mapped cubes in orbit around a central point. You can navigate around the orbiting cubes. If you have programmed DirectX applications in C or C++, then you will have a pleasant surprise: it is much easier to use the Java API for DirectX (and programs are much shorter).
The DirectX libraries for Java can be downloaded for free from Microsoft's Web site (they are included with the Java SDK 2.0 but you will also want to download the 5 megabytes of DirectX and Direct3D documentation). The DirectX libraries include: In all, Microsoft supplies hundreds of pages of documentation. We will get you started quickly in this article; read the documentation after you have some fun with the example program and the documentation will be easier to understand. One of the more difficult aspects of generating any real-time 3D environments is generating 3D artwork (or models). the ZIP file for this article uses a simple cube model that you can apply to arbitrary texture files (BMP format files with image dimensions that are a power of two; e.g., 64x64, 128x256, etc.) We will primarily use Direct3DRM in this simple example. Direct3D uses a left-handed coordinate. By default, we look down the positive Z-axis (see Figure 1) away from the origin; here, the positive Z-axis points into the page. (This is a left-handed coordinate system.) For the example, we will place two rotating cubes (one predominately blue and the other brown) in orbit in the X-Z plane. We initially position ourselves at x=0, y=0 and z=-14 (looking by default down the positive Z-axis towards the origin x=y=z=0).
The structure of the example program is simple: Figure 2 shows the application window. The a' and z' keys move closer and further to the objects (in +Z direction) and the arrow keys rotate the camera' point of view. The u' and d' keys move the viewpoint up and down in the Y direction.
We will use the following Java classes (which are derived from the Microsoft "castle" and "viewer" sample programs) to implement the orbiting cube example:
If you have never used Microsoft's COM model or DirectX before, you need to learn a few new terms:
We access the native Windows libraries for the Direct3D retained mode through the interfaces for a few objects: There are other objects used in Direct3D (eventually, you should read the excellent Direct3D documentation that is included with the DirectX developers kit) that we do not use in this simple example (e.g., lights). The simple example shown in Listings 1 through 4 is derived from the more detailed Microsoft example programs "castle" and "viewer". Listing 1 shows the implementation of the SimData class. This class is a simple container for public data for: a vector, dir, for storing the viewing direction; the Direct3dRM object, d3drm, used to access basic retained mode functions; retained mode frames scene, camera, cube_frame_1, and cube_frame_2 for defining the scene, camera and rotating cube frames of reference; the device, dev, for handling the display destination; rx, ry, rz and rtheta for calculating changes in viewing angle/orientation; and keydown for keeping track of which keyboard keys are currently in a down state. Listing 2 shows the implementation of class AnimFrame. This class requires a finalize method for releasing reference counts on COM objects used in the example program. It is important to do this because unlike Java variables, COM reference counts affect objects outside of the Java virtual machine. The test class (Listing 4) creates an instance of AnimFrame after the application (or applet) frame is created (this order is required). The method AnimFrame.startDirect creates and returns an instance of class Animator (Listing 3) after initializing the retained mode COM objects and loading the cube objects from data files. The method startDirect creates a DirectDrawClipper object and sets the clip size (i.e., the 2D area inside which drawing operations are allowed) based on the size of the application window. The switch statement is used to determine the hardware color depth and to then set the correct texture map parameters. The class variable info (of type SimData) is used to store data that will be used by the Animator class (Listing 3); the second argument to the Animator class constructor is a reference to the instance info of class SimData, that is stored inside of the Animator class. All non-temporary data that AnimFrame.startDirect initializes is stored in SimData info. The frames info.cube_frame_1 and info.cube_frame_2 are created as children of the global scene frame that is stored in info.scene. Temporary objects Direct3dMeshBuilder builder is used to initialize the cube frames using data files contained in the ZIP file for this article. The viewport info.view is created from the display device, camera (viewing) frame and the size of the display device (a tiny 240 by 180 pixels in this example). Usually, frames are created with a fixed position, orientation and zero angular velocity; the position and orientation can be modified every time a new animation frame is rendered. The cube frames are unusual because they are initialized with non-zero angular velocity components so they appear to rotate like planets in orbit with a slight "wobble" about the vertical (in this case Y) axis. Efficiency note: all Java objects used in the example program are created before we start rendering frames in real time. Once the program starts (and you see the real-time graphics display), hopefully no new data is created in the Java heap (although method calls will allocate and deallocate stack space) so garbage collection should not slow down the example application once it is running. Listing 3 shows the implementation of the Animator class. Remember that the constructor for the Animator class is passed an instance of class SimData, which has all the Direct3D, retained mode objects required for the animation of the example scene. The class Animator implements the Runnable interface so it must create and initialize a work thread and define the method run which is automatically called when the work thread is started. The class constructor stores the SimData object reference in the variable win for later access by the method run. The constructor initializes the arrays x1, y1, z1, x2, y2 and z2 that are used to pre-compute the positions of the cubes as they rotate around the origin. The vectors dir, up and right are used to compute changes to the current viewing angles. The vector pos is used to calculate changes to the current viewing position. The method Animator.run calls the method Animator.Render to update moving objects (remember that the retained mode Direct3D libraries perform scene and moving object management for us automatically) and render a new frame in the current viewport. The method Animator.run also explicitly sets the positions of the two cube frames to move the cubes in orbits around the origin (x=y=z=0) using the pre-calculated values in the arrays x1, y1, z1, x2, y2 and z2. The method Animator.run then updates the viewport's viewing orientation and position (by changing the state of win.camera) based on any keyboard key-down events set in class test (Listing 4). Remember that the variable win.camera is a frame object that defines the current viewport's position and orientation in space. Listing 4 shows the implementation of the class test. This class simply defines an applet that holds instances of classes AnimFrame and Animator that are created in the method test.init. The old event model (pre JDK 1.1) is used (I followed the example program’s "castle" and "viewer") by implementing the methods keyUp and keyDown (these methods simply set the variable int anim.win.keydown to encode the keys that are currently pressed on the keyboard while the example applet is running). Running the example applet: The example can be run by unzipping the ZIP file for this article in any directory and running the applet with Microsoft's Java Virtual machine: jview test This example is simple, but if you take a few minutes to run the example and to carefully read the code, then the Microsoft DirectX/Direct3D documentation will be easier to understand. When you install the Java SDK 2.0, you will also see other interesting examples for using DirectSound and DirectInput. Java is a great language for writing distributed entertainment systems, so using Microsoft's Direct3D, Sun/JavaSoft's Java3D or a combination of VRML (Virtual Reality Modeling Language) and Java, is a winning combination. Have fun! Reader Feedback: Page 1 of 1
Latest Cloud Developer Stories
Subscribe to the World's Most Powerful Newsletters
Subscribe to Our Rss Feeds & Get Your SYS-CON News Live!
|
SYS-CON Featured Whitepapers
Most Read This Week
Breaking Cloud Computing News
|
|||||||||||||||||||||||||||||||||||||||||||||||||