This section outlines the techniques for creating animated scenes within the following topics:
backbuffer | |
Enables drawing in the back buffer. | |
blink | |
Changes the color map entry at a selectable rate. | |
cyclemap | |
Cycles between color maps at a specified rate. | |
doublebuffer | |
Sets the display mode to double buffer mode. | |
frontbuffer | |
Enables drawing in the front buffer. | |
getbuffer | |
Finds out which buffers are enabled for drawing. | |
getdisplaymode | |
Returns the current display mode. | |
gsync | |
Waits for the next vertical retrace period. | |
singlebuffer | |
Sets the display mode to single buffer mode. | |
swapbuffers | |
Exchanges the front and back buffers. | |
swapinterval | |
Defines the minimum time between buffer swaps. |
Animated objects on the screen are created by using a technique called double buffering.
For smooth motion, the system displays a completely drawn image for a certain time (for instance, a few 60ths of a second), then presents the next frame, also completely drawn, during the next time period, and so on.
Double buffering provides this capability. The system's standard bitplanes are divided into two halves, only one of which is displayed. Drawing is typically done into the other, invisible half. When the drawing is complete, the buffers are swapped. The previously invisible buffer (now containing the next frame) becomes visible, and the previously visible buffer becomes invisible and available for drawing the following frame.
The currently visible buffer is the front buffer and the invisible, drawing buffer is the back buffer. Double buffering works in either RGB mode or color map mode.
In double buffer mode, your program addresses frame buffer memory as if it were two buffers, only one of which is available for drawing or for display at a time.
In single buffer mode, a program addresses frame buffer memory as a single buffer whose pixels are always visible. By default, the system is in single buffer mode. Whatever you draw into the bitplanes is immediately visible on the screen. For static drawings, this is acceptable, but it does not provide smooth animated motion. If you try to animate a drawing in single buffer mode, you can see a visible flicker in all but the simplest drawing operations.
The following subroutines enable you to create animated scenes.
The doublebuffer subroutine sets the display mode to double buffer mode. It does not take effect until you call the gconfig subroutine. In double buffer mode, the bitplanes are partitioned into two groups, the front bitplanes and the back bitplanes. Double buffer mode displays only the front bitplanes. Drawing routines normally update only the back bitplanes; the frontbuffer and backbuffer subroutines can override the default. The gconfig subroutine sets the value for the frontbuffer subroutine to False and the backbuffer subroutine to True in double buffer mode. The syntax follows:
void doublebuffer()
No matter what you are doing, the display hardware in the system constantly reads the contents of the visible buffer (the front buffer in double buffer mode), and displays those results on the screen. On a standard monitor, the electron guns sweep from the top of the screen to the bottom, refreshing all pixels, 60 times each second. If the graphics hardware changes the contents of the visible frame buffer, the next time the refresh hardware reads a changed pixel, the new value is drawn instead of the old one.
After sweeping out the entire frame, the guns are reset to the top of the screen again, and this takes a short period of time. This time period is called the vertical retrace, and during this period (much shorter than 60th of a second), nothing can change on the screen. The swapbuffers subroutine exchanges the front and back buffers in double buffer mode during the next vertical retrace. The system waits for the vertical retrace so that the currently displayed buffer is completely drawn.
If it did not wait for the vertical retrace, a frame would be drawn partly from one buffer, and partly from another, causing a serious visual disturbance. Because vertical retraces occur every 60th of a second on the standard monitor, the swapbuffers subroutine can block the running process for up to that long. (The default monitor is refreshed 60 times per second. Other options can have other retrace periods.)
Once an image is fully drawn in the back buffer, the swapbuffers subroutine displays it. This subroutine is ignored in single buffer mode.
Note: A caution is in order for double buffered programs. Suppose you are writing a flight simulator that draws each frame, and then swaps the buffers. Suppose it runs at a certain rate (say 60 frames per second). As you modify the program to increase the complexity of the scene, eventually you reach a point where the drawing cannot be completed in a 60th of a second.
At this point, because the swapbuffers subroutine must wait for a vertical retrace, the frame rate suddenly drops to 30 per second; that is, adding the last polygon cuts the performance in half. There is no smooth degradation. Similarly, as more geometry is added, the rate drops to 20 per second, 15 per second, and so on. Properly tuning such a program can be tricky if smooth motion is required. The swapinterval subroutine helps adjust the timing between buffer swaps. Read the discussion on the swapinterval subroutine for further information.
void swapbuffers()
The gconfig subroutine sets the modes that you have requested. You must call the gconfig subroutine for the doublebuffer, multimap, overlay, underlay, onemap, RGBmode, cmode, and singlebuffer subroutines to take effect.
After a call to the gconfig subroutine, the writemask and color attributes are no longer defined. The contents of the color map do not change. The syntax follows:
void gconfig()
In single buffer mode, the system simultaneously updates and displays the image data in the active bitplanes; consequently, incomplete or changing pictures can appear on the screen. The singlebuffer subroutine does not take effect until the gconfig subroutine is called. Single buffer mode is the default. The syntax follows:
void singlebuffer()
Sometimes in double buffer mode, it is useful to be able to write the same thing into both buffers at once. For example, suppose an animated image has both a fixed part and a changing part. The fixed part needs to be drawn only once, but into both buffers. It is most easily done by enabling the front buffer (as well as the back buffer) for writing, drawing the image, and then disabling the front buffer. The animation then proceeds by drawing the changing part of the image using the usual double buffering techniques.
A frontbuffer subroutine setting of True enables simultaneous updating of (or writing into) the front while the rear buffer is being updated. Its parameter is a 32-bit integer value. The gconfig subroutine sets the value of the frontbuffer subroutine to False. This subroutine is useful only in double buffer mode. The syntax follows:
void frontbuffer(Int32 bool)
It is sometimes convenient to update both the front and the back buffers, or to update the front buffer instead of the back. The backbuffer subroutine enables updating in the back buffer. Its parameter is a 32-bit integer value. When the value of the parameter is True, the default, the back buffer is enabled for writing. When the value of the parameter is False, the back buffer is not enabled for writing.
The gconfig subroutine sets the value of the backbuffer subroutine to True. The syntax follows:
void backbuffer(Int32 bool)
The getbuffer subroutine indicates which buffer or buffers are enabled for writing in double buffer mode. The values returned can be compared to the values of MSINGLE, MPROJECTION, and MVIEWING to determine the current mode. The back buffer is enabled by default. Other returned values indicate that the front buffer or both buffers are enabled. The getbuffer subroutine returns zero if neither buffer is enabled or if the system is not in double buffer mode. The syntax follows:
Int32 getbuffer()
The swapinterval subroutine defines a minimum time between buffer swaps. For example, a swap interval of 5 refreshes the screen at least five times between execution of successive calls to the swapbuffers subroutine.
The swapinterval subroutine is typically used when you want to show frames at a constant rate, but the images vary in complexity. To achieve a constant rate, the swap interval is set to be long enough that even the most complex frame can be drawn in that time. If a simple frame is drawn, the user's process simply blocks and waits until the swap interval is used up. The default interval is 1.
The swapinterval subroutine is valid only in double buffer mode. The syntax follows:
void swapinterval(Int16 interval)
The getdisplaymode subroutine returns the current display mode. The values returned can be compared to the values of MSINGLE, MPROJECTION, and MVIEWING to determine the current mode. The syntax follows:
Int32 getdisplaymode()
DMRGB | Indicates RGB single buffer mode. |
DMRGBDOUBLE | Indicates RGB double buffer mode. |
DMSINGLE | Indicates color map single buffer mode. |
DMDOUBLE | Indicates color map double buffer mode. |
The gsync subroutine waits for the next vertical retrace. Because this subroutine does not return until vertical retrace begins, the calling process is effectively blocked until that time.
This subroutine is useful for pacing the drawing when in single buffer mode. If the amount of drawing to be done is small, this subroutine can be used to achieve a limited amount of smooth animation in single buffer mode. For high-quality, smooth animation, double buffer mode together with the swapbuffers subroutine should be used. The syntax follows:
void gsync()