home *** CD-ROM | disk | FTP | other *** search
- Notes on Animation
- 04/19/93 -med
-
-
- Image Animation:
-
- Full color animation requires fast operation of the code to be
- done flicker free. With the standard BGI driver, the speed of the
- PutImage and GetImage functions is not fast enough to properly
- perform the task. An XorPut method can be used to get the job
- done (see the Turbo Pascal BGIDemo), but the problem with that
- method is that as the object moves over a background, the object
- will change colors because of the xoring. The flicker is reduced
- with XorPut, but at the cost of the object colors being changed.
-
- For true full color animation, color shifts are not acceptable.
- That means an additional Mask step must be added to the process.
- To animate a full color object requires a four step procedure.
- First the background must be saved, then the background must be
- masked to black for all areas of the object that will appear on
- the screen. Next the object itself is drawn. Finally, to move the
- animation object, we restore the old image that we saved, then
- move to the new location and start the process all over again.
-
- In the BGI, this is done with four procedures:
-
- while true do
- begin
- GetImage() {get background}
- PutImage() {mask background}
- PutImage() {draw object}
- ---------- {wait for change}
- PutImage() {restore background}
- end;
-
- The problem with this is that the three PutImage routines take a
- lot of time and for anything other than very small objects,
- flicker is readily noticeable. This is especially caused by the
- extra step to mask the background. In a normal animation library
- package, the extra Mask step is included as a part of the object
- draw. This is done by having a foreground only drawing routine.
-
- The BGI256 driver provides this ability with a special PutImage
- command that allows for a foreground only PutImage.
-
- This reduces the number of steps down to three from four. That
- reduces the flicker somewhat, but not completely. It would be
- nice to reduce it further. It so happens that we can merge
- another of the steps into the object draw step.
-
- Before we draw the new object, we first must save the old
- background. It takes time to perform that action, and it must be
- done after we restored the old background from the previous
- object position. The longer we delay from restoring the old
- background to drawing the new object position, the more flicker
- we see. We need to minimize this time period.
-
- The simplest way to minimize the time period is to read the
- background as we are drawing the object. The standard BGI
- mechanism does not provide for this ability, however the BGI256
- driver has provided a hook to perform this function. A special
- WriteMode command can be given to tell the BGI256 driver to
- change the operation of the GetImage function.
-
- Ideally it would be desirable to have two pointers passed to the
- function so as to allow the read/write to occur to two separate
- places in memory. That is not possible if we are to keep within
- the calling convention of the standard BGI library. So instead,
- BGI256 uses the same pointer. What happens is that the object to
- be drawn is passed in the Image pointer, and the old screen image
- is passed back in the same memory when the drawing is finished.
- Actually, it is updated on the fly. Before each pixel is written,
- the background is read and saved to the image memory.
-
- We have now reduced the animation sequence down to two steps:
-
- while true do
- begin
- GetImage() {get background / put image}
- ---------- {wait for change}
- PutImage() {restore background}
- end;
-
- From an algorithm standpoint, we now have an optimal animation
- routine. The update time period is limited to how fast we can get
- the new image on the screen after restoring the old background.
- About the only thing that could be done to improve things is to
- make the basic GetImage/PutImage code faster. The BGI256 driver
- has code that is as fast as it can be given the design
- constraints. There are faster animation methods, but they require
- different techniques than is used with GetImage/PutImage.
-
- There is actually more code involved than is indicated above,
- particularly, two memory moves must be done which are not shown.
- However, these moves can be done outside the critical time
- window, so they do not play a part in the flicker process. See
- the ANISUB.PAS file for an example of implementing the BGIDEMO
- flying saucer using the new method. (The DEMO256.PAS program uses
- the ANISUB.PAS unit.)
-
- Additionally, a separate command must be given before the
- GetImage function to specify that a foreground only write is to
- be done while drawing the object. This is required because there
- is no way to specify the drawing mode in the GetImage function as
- there is in the PutImage function, so a special call to the
- SetWriteMode function must be made.
-
-
- For an example of the difference in animation, run the DEMO256
- program. Try it with the Borland VESA16 driver (DEMO256 0 4) then
- with the BGI256 driver (DEMO256 3 0). This assumes you have a
- super VGA display that is VESA compliant. Notice the substantial
- reduction in flicker when using the BGI256 animation method.
-
- You can see the saucer completely disappear and then reappear
- when using the standard BGI animation method. But there is only a
- slight flicker with the BGI256 animation method. Actually, the
- amount of flicker will depend on the speed of the computer and
- display.
-
- Ideally, flicker is eliminated by utilizing the integration
- capabilities of the brain. Flicker is eliminated by keeping the
- period of time that the object is off the display to a minimum.
- The off time should be less than 10ms, and the ratio should be
- better than 3:1. That is, if the image is off the screen for
- 10Ms, it should be on the screen for 30ms or more. The longer the
- on screen time, the less the flicker. However, it is important
- not keep the off screen time in mind as well. The object should
- not be off the screen for longer than 1/2 screen refresh time. At
- 60Hz, this is 1/120 second, or 8ms which we can round up to 10ms.
-
- There are some tricks that can be used to reduce the flicker
- further. Screens are generally painted from top to bottom. By
- observing where the object is in the screen, and keeping the
- update time to less than 1/2 the refresh rate, you can delay the
- object update until the refresh scan has just passed the point on
- the screen where the object is. This can effectively eliminate
- flicker because the object is never actually off the display.
-
- Unfortunately, for large objects that technique is not always
- possible. Consider on the best display card available, the Video
- Seven VRAM card which can update the display at full PC bus
- speed. If we operate in the 800x600x256 mode, a line is 800
- pixels long. It takes 1.5us to update each pixel if we use a
- MOVSB instruction. That comes out to 1.2ms to update a single
- scan line, or 720ms for the full screen. This is absolute best
- case. In actuality it is much slower because of code overhead.
- Especially if we are using a foreground write which cannot use
- the MOVSB type instruction.
-
- There are other mechanisms that can be used to reduce the
- flicker. some of them are subjective. By reducing the contrast
- ratio of the background to the object being displayed, flicker
- can be reduced. An ideal contrast ratio would be around 3:1.
- A gray or pastel background reduces the contrast to the object.
- ie avoid black backgrounds if you want to reduce flicker.
-
- Only update the object if it has moved. Movement causes flicker
- to be much less objectionable compared to an object that is being
- continually updated in the same location. Keep in mind that the
- update time will be affected by computer type and speed as well
- as the display card being used. An old XT with a VGA card would
- be a horrible combination. A 66MHz 486 with a Video7 VRAM card
- would be an ideal solution.
-
- On simpler displays, a trick could be used of drawing to a
- separate undisplayed video memory location, then switching the
- display pointer to the new location. Unfortunately with most
- SuperVGA boards the address requires more than then 16bit defined
- display start address, and most SuperVGA manufacturers
- implemented the extended display address bits in different ways
- (for those who even bothered to implement the extended
- addressing).
-
- Neither has VESA defined a BIOS call to set this value. The end
- result is that either a special display card specific call must
- be done, or the function must be ignored. Since keeping up with
- SuperVGA manufacturers is a nearly impossible task, most BGI
- designers have opted to ignore the paging feature in the SuperVGA
- modes. Since this action is not available, so we are stuck with
- using the other more difficult (time critical) methods.
-
- Warning: just because a display card claims to be fast, it does
- not make it fast for bitmap updates. As an example, the Diamond
- Stealth card is claimed to be speedy in Windows. For doing things
- like drawing windows with the special Windows software, it is
- indeed speedy, but for drawing bitmaps, it is still slower than
- the aging Video7 VRAM card which can transfer bitmaps at the
- speed of the CPU bus. There is an excellent video benchmark
- program available in the IBM forum on Compuserve called 3DBench
- from SuperScape. It will tell you how fast your display card and
- computer combination truly is. For reference purposes, my 33MHz
- 486 with a Video7 VRAM display card has a benchmark of 20.0
- frames per second.
-
-
- P.S. You may notice a difference between how the Borland VESA16
- driver and the BGI256 driver handle the saucer as it passes over
- the background. Specifically, the filled area of the saucer is
- transparent with the BGI256 driver, and is not transparent with
- the VESA16 driver. This is caused by the differences in the
- floodfill routines which is what is used to fill the area. The
- Borland floodfill is a simple fast fill algorithm which is very
- speedy for solid fills, but does not do well with complex fills.
- The BGI256 floodfill handles complex fills properly which is why
- the filled saucer area is transparent.
-
-
-
- Pixel Animation:
-
- There is no GetLine or GetEllipse function calls, but there is a
- GetPixel function call, so to create animated full color lines
- or elipses, you can use the modified GetPixel function and build
- your own line or ellipse routine. By using the Modified GetPixel
- instead of a GetPixel/PutPixel combination, you can reduce the
- animated linedraw time in half.
-
-
-
- Example ANIMATE program:
-
- See the program ANIMATE.PAS for an example of animated line,
- rectangle, and ellipse routines. The program draws the lines,
- ellipses, and rectangles while saving the background in an array.
-
- You can control the object by pressing the up/down/left/right
- arrow keys. To select a line, press "L" to select a rectangle,
- press "R", to select an ellipse, press "E". To change the control
- point that the arrows change, press "T". To change the color,
- press "C". Toe see the automatic demo, press "A". To change the
- speed of the automatic demo, press a number (0-9). To quit, press
- "Q" or ESCape.
-
-
- <eof>
-
-
-