November 93 - QD3D
QD3D
Jonathan A Hess
Special effects created by high end computer graphics hardware awe almost everyone.
Jurassic Park is a recent and widely seen example. Less theatrical applications are
just as worthy of 3d graphics, and many even require the third dimension. Examples
include medical imaging, molecular modeling, scientific data visualization, and
visualization of detailed information hierarchies. This article briefly describes an
architecture for interactive 3d applications, discusses implementation issues and
suggestions for that architecture, and describes the Qd3d library that serves as the
foundation for such an architecture.
Elements of an interactive 3d application
Figure 1 represents key components of 3d applications and the types of information
passed between those components. The user drives the hierarchy from the top by
interacting with the view window, view controller, and model editing tools. Visual
feedback to the user is provided by the 3d renderer at the bottom. The view window
sequences update events and sends "draw yourself" commands to the application
specific model. The view controller is responsible for manipulating the viewing
parameters of the three dimensional scene including viewer position and viewer
direction. The view controller may also manipulate viewing parameters to act as an
animator for movie recording.
At the center of any 3d application is the organization of the data being modeled.
Examples of application specific models include simple geometry information
describing a building, a kinetic simulation of a human gymnast, a vector field
interpolation of engineering data, and etc. There are three key things to remember
regarding the application specific model. First, application code is responsible for
saving, organizing, and retrieving the essence of the model. Second, application code
breaks the draw yourself message down into the 3d drawing primitives recognized by
the 3d renderer. Third, to decrease module cross coupling the model rendering code
rarely concerns itself with the 3d viewing parameters.
Separating the lighting model, model editing tools, and view controller elements from
the model itself is important from a flexibility and maintainability standpoint. By
keeping the lighting model separate, it becomes feasible to have a default high-speed
lighting model that can be swapped out with a slower but more realistic lighting model.
The model need only tag different elements with attributes such as "sand," "copper," or
"red." These attributes are then passed to the lighting model which in turn checks
viewing parameters and calculates a suitable RGB color.
Even more critical is the flexibility required for the editing tools used for model
manipulation. Editing tools often interface to real devices such as the Z Mouse from
Multipoint Technology Corporation [Multi93] and the Mattel Power Glove [Glove93].
Alternatively, editing tools may interface to virtual 3d control devices such as the
triad mouse [NiO86], or a virtual sphere controller [Chen93]. Editing tools may also
take advantage of application specific conditions. For example, if a 3d object's
movement is restricted to a plane, 2d desktop mouse movement can directly be mapped
to that plane. Query tools such as "tell me the name of the object I'm pointing at" or
"what is the height value at this point on the surface" also qualify as editing tools.
Finally, the current editing tool must easily switch between different tools similar to
how a draw program lets users switch between translation and rotation operations.
Only by separating editing tool code from the model can these manipulation
requirements be met.
At the bottom of Figure 1 lies the 3d renderer. The renderer is responsible for
creating the image resulting from the primitives called out by the model "draw
yourself" code. Editing tools and the view controller also use the renderer to provide
3d manipulation feedback. Finally, the renderer maintains and manipulates the
viewing parameters under direction from the view controller.
Key to the 3d application framework of Figure 1 is the lack of specifics and
constraints. Swapping out different elements of the architecture, such as the lighting
model, has already been discussed. In addition, the lighting model, the model editing
tools, and the view controller are optional. When working entirely with wireframes,
there is little need for a lighting model. If the model is static, there is no need to
provide editing tools. And, if the application is a "fly through" visual explorer, the
application is the view controller. Also, the diagram does not preclude multiple view
windows from sharing a single application model. Simultaneously viewing a model
from multiple directions helps with understanding and manipulation issues. Another
consideration is that multiple hardware input devices could feed into the system at
once. Finally, nothing prevents this 3d application framework from being built on top
of favorite application frameworks such as MacApp, the Think Class Library (TCL), or
Bedrock. For example, "viewing window" could be an item in a MacApp or TCL view
hierarchy.
Where do Qd3d, 3dPane, and SmartPane fit in?
The application structure in Figure 1 describes interactive 3d applications as opposed
to photo-realistic but largely static applications. As a result, a polygon based renderer
provides an appropriate foundation for the figure. Qd3d is such a renderer.
Qd3d has Macintosh roots reaching back to the Fall of 1988. After existing as an in
house development tool, Qd3d went commercial in the Spring of 1992 with version
1.2. Since that time, individuals and institutions have used Qd3d in applications such
as sports medicine, geology, molecular modeling, information sciences, robotics, and
scientific visualization. The most recent version, 2.1, was released in September
1993 and features support for the Cyberscope stereoscopic viewer from Simsalabim
Systems.
Qd3d Overview
Qd3d is a collection of classes and routines that provide a robust set of features for 3d
polygonal rendering. Primitives include point marking, line drawing, polygon framing
and filling, and text placement. Except for text placement, these primitives are defined
in color constant and color varying varieties. Color constant primitives use the
present GrafPort's foreground color and color varying primitives allow the association
of individual colors to each vertex of the primitive. During quality renderings, color
varying primitives smoothly blend color between the vertices. Polygons filled with
such a color blending are referred to as Gouraud shaded polygons.
Similar to QuickDraw's rendering of 2d primitives through the GrafPort pointed to by
"thePort," Qd3d sends its 3d primitives through "the3dPort." Unlike QuickDraw's
thePort structure pointer, the3dPort is an object pointer of type CQd3dPort. As a
result, access to Qd3d viewing parameters, such as viewer location and viewing
direction, are cleanly wrapped in messages defined for the CQd3dPort class. In
addition, all aspects of 3d rendering can be specialized or augmented by subclassing,
overriding, and inheriting.
CQd3dPorts maintain six rendering options which affect the appearance of every
primitive. These rendering options dramatically modify rendering speed and quality
and are known as OnlyQD, Wireframe, UseZBuff, DepthCue, and clipping level. OnlyQD
controls whether Qd3d quickly renders color varying primitives as color constant.
Wireframe maps polygon fill primitives to polygon frame primitives. Clipping level
controls how accurately Qd3d clips primitives to the boundary of the viewing window.
The default clipping level clips primitives so they fit just within the view window. In
contrast, the drastic clipping level entirely skips primitives that cross the viewing
area. UseZBuff requires OnlyQD to be off and uses a "z-buffer" the same size as the
image for hidden surface removal. Finally, DepthCue causes distant primitive colors to
be blended with the scene background color but leaves primitives closer to the viewer
at their original color. This background color blending helps with depth perception.
The manipulation of these six rendering options allows the same model rendering code
to be used for quick OnlyQD previews and for final Gouraud-shaded z-buffered
renderings.
Text placement primitives render 2d text at the projection point of a 3d location. Text
rendering options and attributes include: left, right, and center justification; whether
the text honors depth cueing; automatic font scaling with respect to distance from the
viewer; whether text is removed if its area is greater than the projection area of a 3d
object; and whether all text should be skipped.
CQd3dPort supports parallel and perspective projections. The familiar perspective
projection renders close objects larger than more distant objects of the same size. In
contrast, parallel projections appear flat because objects of the same size are
rendered at the same size regardless of distance from the viewer. Parallel projections
appear unnatural but have engineering applications that perspective projections can
not support.
Qd3d also supports stereoscopic projections with the CStereo3dPort and
CCyberscope3dPort subclasses. Depth perception is a function of the visual cortex
comparing minor differences between left and right eye views. Unfortunately, the 2d
nature of CRT monitors strip 3d graphics of their depth information. This becomes
acute in scenes that are unfamiliar to users or when the refresh rate of view
reorientation is low. Using stereoscopic techniques restores depth perception by
creating and presenting different images to both the left and right eyes.
CStereo3dPort acts as a template for Qd3d stereoscopic projections and provides for
straight-eyed and cross-eyed side-by-side stereoscopic image pairs. Figure 2 is an
example of a cross-eyed side-by-side stereo image pair.
To view Figure 2, hold the images squarely to the line of sight. Look cross-eyed at the
image pair and four images will appear. Vary cross-eyedness so the two inner images
overlap. Concentrate on the center image until it becomes focused. Practice.
Side-by-side stereo images require no additional gadgets for viewing but beginners
find it difficult to fuse image pairs and such viewing causes eye strain and fatigue.
An economical, on the order of US $180, device to recombine stereo image pairs is
Simsalabim's Cyberscope [Sims93]. The Cyberscope is a hood velcroed to the front of a
regular computer monitor. Looking straight through the Cyberscope reveals the
monitor screen as before with the exception of a vertical divider to separate left and
right eye views. Looking down in the Cyberscope allows its front surfaced mirrors to
recombine left and right eye views rotated on the monitor into a stereoscopic image.
Advantages of the Cyberscope over other 3d viewing methods include no need to go
cross-eyed, full color, increased depth perception from rotated images being wider
than they are tall, and no flicker from shuttered LCD glasses. The CCyberscope3dPort
class, included with Qd3d, creates the rotated images as required for the Cyberscope.
3dPane and SmartPane
As Qd3d provides an application framework independent 3d renderer for the
architecture in Figure 1, 3dPane provides a view controller and view window for the
TCL. The C3dPane class marries the3dPort of Qd3d to the TCL CPane class. TCL
application developers override the Draw3dScene method for their application specific
drawing. C3dPolarControl provides a polar coordinate based view controller. With
C3dPolarControl a horizontal scroll bar controls longitudinal viewing position about
an object of interest and a vertical scroll bar controls the latitudinal viewing position.
The SmartPane library supplements the existing TCL Pane hierarchy with offscreen
image buffering that reduces flicker. SmartPane also adds animation support and
QuickTime movie recording of images.
Application 3d Models
This section briefly suggests and describes considerations for developing a class
hierarchy forming the application specific model of Figure 1. This section also
describes facilities present in Qd3d for supporting tight integration between the
application model and actual rendering.
Hedra
Many 3d objects are appropriately rendered as collections of polygons known as
polyhedra. A key feature of polyhedra is that many polygons often share the same
vertices. Taking advantage of this sharing allows polyhedra to be described by vertex
locations and a special list of polygons. The special list of polygons lists the polygons as
ordered lists of vertex indices. This representation of a polyhedron adds structure
when multiple polyhedra are involved, and it compresses the data used to represent the
polyhedron. Data is compressed because values for individual vertices are stored only
once and subsequently referenced by index in the polygon lists.
The idea of referencing vertices by index is important from a rendering performance
standpoint. Transformation and projection of a world coordinate point to screen
coordinates is computationally expensive. By using the vertex indexing scheme during
polyhedron rendering each vertex can be transformed and projected once into a cache
of screen coordinates. As each individual polygon is rendered the screen coordinates of
the associated vertices are looked up in the screen coordinate cache. Without this cache
rendering a polyhedron can result in approximately 4 to 6 times as many
transformation and projection operations as necessary.