cosell@bbn.com (Bernie Cosell) (02/16/89)
I confess that I'm a creature left over from the days of the point-plotting scopes. One of the neat things about doing animation on those scopes was that it mostly came for free (by contrast: doing a STABLE single frame was a pain, 'cause you had to keep regenerating the display!). Can anyone give me any tricks or tips for doing simple animation in the modern world of bitmapped displays? I've checked Foley&VanDam and Newman&Sproull and they seem only to mention screen-flipping. Is there nothing simpler? For example, I was writing a little program to explore the properties of compound pendulums. That seemed simple enough, but then I realized: on a point-plotting scope it would all work more-or-less like magic. I'd just plot the position of the bob and the fading phosphors would give me enough of a "tail" so that I could see the pattern of where it was and where it had come from. In fact, the impression of depth you could get essentially for free was pretty spectacular. The best I was able to come up with for THIS guy (although I don't have it working yet) is to use my system's color table. What I'll do is have a "current color" and I'll go and pump points into the bitmap with THAT color until a little timer goes off. THEN: I bump the "current color". *and* diddle the color mapping table so that "current" is now the brightest color, "current-1" (the previous current color) is just a bit more faded, and so on around the palette. Seems like a kludge, but it might work! Am I missing some set of simple tricks? Are there any reference books that talk about doing this sort of thing? Thanks! __ / ) Bernie Cosell /--< _ __ __ o _ BBN Sys & Tech, Cambridge, MA 02238 /___/_(<_/ (_/) )_(_(<_ cosell@bbn.com
sfisher@abingdon.SGI.COM (Scott Fisher) (02/17/89)
In article <36049@bbn.COM>, cosell@bbn.com (Bernie Cosell) writes: > I confess that I'm a creature left over from the days of the point-plotting > scopes. One of the neat things about doing animation on those scopes was > that it mostly came for free (by contrast: doing a STABLE single frame was a > pain, 'cause you had to keep regenerating the display!). Can anyone give me > any tricks or tips for doing simple animation in the modern world of > bitmapped displays? I've checked Foley&VanDam and Newman&Sproull and they > seem only to mention screen-flipping. Is there nothing simpler? > > For example, I was writing a little program to explore the properties of > compound pendulums. That seemed simple enough, but then I realized: on a > point-plotting scope it would all work more-or-less like magic. I'd just > plot the position of the bob and the fading phosphors would give me enough of > a "tail" so that I could see the pattern of where it was and where it had > come from. In fact, the impression of depth you could get essentially for > free was pretty spectacular. The best I was able to come up with for THIS > guy (although I don't have it working yet) is to use my system's color table. > What I'll do is have a "current color" and I'll go and pump points into the > bitmap with THAT color until a little timer goes off. THEN: I bump the > "current color". *and* diddle the color mapping table so that "current" is > now the brightest color, "current-1" (the previous current color) is just a > bit more faded, and so on around the palette. Seems like a kludge, but it > might work! > > Am I missing some set of simple tricks? Are there any reference books that > talk about doing this sort of thing? Thanks! Color map animation is one way to give the illusion of movement, but it's complicated. It is faster, as long as you can remember to reload your color maps between retrace--most systems give you a way to specify this. If you've ever seen a demo of a program that swapped color maps in the middle of a retrace instead of between them, you know why this is a good idea. The modern approach to animation is, as you say, to clear the screen, draw an image, clear the screen, draw the new image, etc. There are a couple of alternative "tricks," but not necessarily simple, and limited in application. One thing you might consider for your pendulum application is whether your system does transformations faster than it fills the framebuffer, or vice-versa. If you're animating over a solid-colored background, you might find it faster to do something like this. (Note: this does the simplest possible thing to manage an x translation so that you can see what is going on. It's also limited to the 2D case for the sake of simplicity, and of course it's a fragment, not a whole program.) . . . /* first clear the screen to black */ color(BLACK); clear(); centerpoint = 1200; /* now draw a circle moving R-L; circf draws a filled circle at x, y, radius */ while (centerpoint > 100) { color (WHITE); /* next thing drawn is WHITE */ circf (centerpoint, 130.0, 65.0); color (BLACK); /* effectively erases circle */ circf (centerpoint, 130.0, 65.0); centerpoint = centerpoint - 1; } . . . The advantage to this approach is that what you see is a white circle moving across a black background, one pixel farther to the left with each iteration of the while loop. The idea here is that you blank out ONLY the pixels that you have drawn in the preceding image. Obviously, for your pendulum, you'd need to calculate x and y coordinates for each iteration as well as simulating the rate you want, but you know that... The problem with this is that it shortcuts such niceties as double-buffering, complex image backgounds, texture-mapped images behind the thing you're animating, etc. But this one does fill the fewest pixels on any given scene. Obviously in such a simple example, there is no real performance benefit to be gained by erasing the object from the preceding scene before moving it. But if you're working in a system that is fill-rate limited and you have a number of polygons to draw over a solid-colored background, sometimes you can save a few cycles by drawing only the pixels that interest you and leaving the rest of the screen alone. If you're doing a fairly complex image transformation on the object you're drawing (rather than this ultra-simplistic way to do an x translate), the time you save in drawing pixels might get lost in the time it takes to calculate the transformation matrix. On the other hand, it might be the difference between realistic "tactile" response and a clunky video-game feel. Only your CPU knows for sure... BTW, the "correct" way to do this is more like this: . . . /* be sure to enable double-buffering in your init. */ /* by convention, all drawing is done in the "back" */ /* buffer, the "front" is visible, and swapbuffers */ /* exchanges the position (in our GL, anyway) */ /* first clear the screen to black */ color(BLACK); clear(); centerpoint = 1200; /* now draw a circle moving R-L; circf draws a filled circle at x, y, radius stored in array 'coords' */ while (centerpoint > 100) { color (BLACK); clear(); /* erase the screen before drawing */ color (WHITE); /* next thing drawn is WHITE */ circf (centerpoint, 130.0, 65.0); centerpoint = centerpoint - 1; swapbuffers(); /* after you've drawn the scene */ } . . . This does draw the entire screen (well, window) each time you do the while loop, but it does the drawing in the back buffer while the front buffer is visible (etc.). Note also that the examples here are gedankencode--that is, they're taken from an example that works but modified to demonstrate the point here, and I haven't compiled (much less run, much less benchmarked) either one of them (though I have run the program on which the second example is based & it looks very smooth). If you yank them and stuff them into your code, don't sue us if they don't work the way you expected!:-)