Nothing communicates an idea better than a picture. It's the defining principle behind the popularity of Microsoft Windows and other graphical environments. Not long ago, though, you might recall serious debate over whether Windows would ever meet the performance demands of a graphical user interface. Much of the trepidation resulted, no doubt, from the tremendous freedom of MS-DOS programs to directly access video hardware. However, faster CPUs, accelerated video adapters, local bus connections, multimedia, and a mature Graphical Display Interface (GDI) have since conspired in favor of Windows.
These changes pose significant opportunities in 3-D modeling software development. Three-dimensional modeling has become increasingly important over time because it mimics elements in the real world. This article focuses on simple strategies for 3-D modeling. The accompanying source code was compiled and linked with the Microsoft C/C++ Optimizing Compiler Version 7.0 and Microsoft Windows 3.1 Software Developer Kit (SDK). Every effort has been made to ensure compatibility with other compilers. Compile instructions are provided in comments at the top of each listing. The bitmaps were created with Microsoft Paintbrush.
This article barely scratches the surface of 3-D graphics. Rendering, shading, ray tracing, and texture mapping get a more thorough treatment from the references in the bibliography. This article will present a building block for such advanced features.
Do not confuse 3-D modeling with Windows metafiles. A metafile is a binary-encoded collection of GDI function calls. You create one by sending the output from various GDI function calls to a special device context. A recorded metafile can be played back by passing its associated resource handle to PlayMetaFile. The resulting picture may look three-dimensional but it's just a two-dimensional facade.
Microsoft Windows derives its characteristic look and feel primarily from raster-based or bitmapped graphics technology. Most fonts, controls, and icons are nothing more than bitmaps two-dimensional blocks of pixels that appear three-dimensional due to varying color gradients. Bitmaps look great but generally experience some kind of image distortion when rotated, stretched, or scaled onto devices of varying resolutions. To address such deficiencies Microsoft incorporated so-called TrueType font technology into Windows 3.1. TrueType is a form of vector-based graphics, in which images are constructed with individual graphical primitives such as lines, points, rectangles, ellipses, and curves rather than bitmaps. Vector graphics are scalable, require less memory than bitmaps, and enable us to model three-dimensional objects with relative ease.
The Windows GDI does not contain explicit support for 3-D modeling, but it is not difficult to build a suitable framework atop existing primitive functions. Nearly any 3-D object can be drawn with a set of interconnected points or vertices. For example, a simple cube has eight vertices (one for each corner) while the General Dynamics F16 Falcon aircraft in 3D.C in Listing 1 (along with the files in Listing 2 and Listing 3) contains literally hundreds of vertices. Of course, a collection of points is worthless without some frame of reference, so they are placed in a domain called the World Coordinate System (WCS). You can change the object's orientation in WCS by multiplying each vertex by a series of transformation matrices. There are distinct transformation matrices for rotation, reflection, shearing, scaling, and translation operations, respectively.
Try to imagine yourself floating in space around a motionless object. As you change position, each WCS vertex is transformed with respect to an Eye Coordinate System (ECS) that emanates from your eye and points toward the object (Figure 1) . To complicate matters even more, the resulting ECS vertices must be transformed from three-dimensional to two-dimensional screen coordinates (SCS) before the object can be displayed. Once these screen positions are known, you can connect-the-dots to produce a transparent wireframe model, or use filled polygons for a more realistic solid model (Figure 2) . Three-dimensional objects are drawn one surface at a time, so vertices are generally grouped in that order.
Hidden-surface removal is one of the more complicated and computation-in-tensive facets of 3-D modeling. The most popular method of hidden-surface removal is called backplane elimination. Basically, it involves computing whether a normal (perpendicular) vector emanating from a given surface points away from or toward the viewer's line of sight. Those surfaces facing away from the viewer cannot be seen and, therefore, need not be drawn. It does have its drawbacks, too. Objects with irregular or overlapping surfaces will not be drawn properly. One quick-and-dirty solution is to sort the surfaces in terms of decreasing distance from the viewer (ECS z-coordinate). Surfaces lying farther away from the viewer are drawn first and subsequently masked by closer surfaces. Depth sorting has its flaws but performance-conscious applications usually don't mind.
3D.C (Listing 1) supports both wireframe and solid models. It first creates a window with horizontal and vertical scroll bars, and uses SetScrollRange to lock the thumb between 0 and 360 degrees. Depressing the scroll bars changes the angular position of the viewer relative to the object. This is especially convenient because the viewer's position is given in spherical coordinates (distance, theta, phi). All measurements are given in device units. The F16 object "database" has been optimized to keep code size to a minimum.
3D.C calls DrawObject whenever the viewer depresses the scroll bars or resizes the window. DrawObject determines the center point of the window and creates a compatible work bitmap. Using an intermediate bitmap prevents the flashing effects that occur while drawing straight to a display context. DrawObject also precalculates sine and cosine values for global variables theta and phi. These values are needed when f16.vertex.world vertices are transformed to f16.vertex.eye vertices and, finally, to f16.vertex.screen coordinates. DrawObject clears the work bitmap and loops through each surface in the f16.info array. For solid models, DrawObject performs a depth sort on the f16.vertex.eye vertices, removes hidden surfaces with backplane elimination, selects a brush color from f16.info.brushColor, and calls Polygon; otherwise, it calls PolyLine for a wire-frame surface. DrawObject then updates the client area with the completed work bitmap and deletes unused resources.
Floating-point computations incur a considerable amount of overhead even with a math coprocessor installed but you can improve performance significantly by substituting fixed-point integers for floating-point numbers. Fixed-point integers incorporate both the whole and fractional components of floating-point numbers but can be manipulated in single arithmetic operations, such as IMUL and IDIV. For example, it is possible to represent the floating-point number 12.345 with integer 12345 by shifting the decimal place three positions. There are certain problems with this technique, as well. Integers can only represent so many digits before overflowing, so you must strike a balance between the scale and precision of the 3-D model.
NASA's Jet Propulsion Laboratories unveiled a computer-generated film several months ago that depicted the surface topography of some distant planet. JPL had downloaded countless bits of radar imaging data from a distant probe into three Cray super computers and rendered the surreal landscape frame-by-frame over the course of three solid weeks. The resulting bitmaps were finally transferred to videotape and made available for public consumption. There's a lesson hiding behind this madness. Even though real-time 3-D graphics were out of the question, JPL eventually got what it paid for by blending vector and raster technologies.
Adams, Lee. 1986. High-Performance CAD Graphics in C. Blue Ridge Summit, PA: Windcrest/Tab.
Microsoft Corp. 1991. Microsoft Windows Multimedia Authoring and Tools Guide. Redmond, WA: Microsoft Press.
Microsoft Corp. 1991. Microsoft Windows Multimedia Programmer's Reference. Redmond, WA: Microsoft Press.
Microsoft Corp. 1991. Microsoft Windows Multimedia Programmer's Workbook. Redmond, WA: Microsoft Press.
Park, Chan S. 1985. Interactive Microcomputer Graphics. Reading, MA: Addison-Wesley Publishing Company.
Petzold, Charles. 1990. Programming Windows. Redmond, WA: Microsoft Press.
Wilton, Richard. 1987. Programmer's Guide to PC & PS/2 Video Systems. Redmond, WA: Microsoft Press.