Fatrat's BeOS Projects: Sparticles



Sparticles is a screensaver that displays trails of color based on a type of particle effect.

Current version: 0.51 -- 2002.10.07


Project notes...


2002.10.07 (v:0.51) -- Fixed a bug with DirectDraw rendering when in 32bpp mode.



2002.10.07 (v:0.50) -- Added blending mode, but it's sooooooooo slow :( When doing blending, we fall back into the BeOS drawing routines, which aren't as good as the DirectDraw ones, plus the blending slows things down considerably. Using B_OP_BLEND instead of B_OP_ALPHA, as it is more suited for the way that these sparks are drawn. Moved the config panel around a little to add the checkbox for blending mode, if I add any more options I'll have to go to a tabbed view...

Optimized the DirectDraw stuff futher, mostly by unrolling loops; also now doing a few memcpy()'s instead of a bunch of individual byte-by-byte accesses to draw to the framebuffer, much more efficient. Optimized and tweaked a couple of other things, but the DirectDraw is the big improvement performance wise.

My buddy Brian says that this saver compiles easily on PPC, I should have a PPC binary included soon...



2002.10.04 (v:0.40) -- Cleaned up the source code, it's included now; made some more optimizations, added some tweaks... lots of good stuff. I still want to add an optional blending mode, but I've done enough for this evening already ;) The Vect2D class that's included in the source has some extra functions that don't get used, but I left them in there thinking someone else might get some use out of them...



2002.09.24 (v: 0.32) -- Implemented DirectDraw, nice speed improvements for drawing. Also made a few minor optimizations in code, no noticeable speedups really.

Experimented with a few blurring algorithms, found some that are nice but too CPU hungry; going to consider some kind of anti-aliasing that would only have to look at the edges of the particle trails, but I may just skip the blur; it looks pretty good now... Blending is also a problem, turning on blending causes lots of slowdown...



2002.09.19 (v:0.30) -- Lots of optimizations and changes, the code is MUCH faster now; calculations take up much less time than drawing, so that's the next bottleneck to tackle. Also fixed the bug with the gravity slider not storing the right values between invocations of the module, adjusted the way particles are pushed back onto the screen if they drift off of the edges, some minor calculation errors, added code to skip calculations and drawing in a number of places where I could, moved multiplication and divisions out of loops into pre-calculated variables, cached values gotten from slow function calls like view->Bounds().Width() (yes, that's a relatively slow call... I was surprised...), and so on. Many variables tweaked.

One of the most interesting things I did is not in the public version - I created a number of little graphs across the top of the screen so that I could track time spent calculating vs. drawing, see how many particles were off-screen, etc. I also discovered the way-cool BStopWatch, which makes taking timing info from code segments very simple. The graphs helped me optimize a lot, as I could easily find sections of code that needed to be either simplified, or skipped when possible.

Anti-aliasing is something I would like to implement, and I tried a number of "cheats" to do it with the built-in blending, different drawing modes, etc. The best result would come from doing a per-pixel effect to blur and degenerate things, with an accumulation buffer... but that will be, I think, prohibitively slow. The MeltdownBlur screensaver does a very nice job of this, and shows that it *can* be done -- on my Pentium-III 700MHz laptop, I was seeing some very nice framerates, but I'm almost positive the use of DirectDraw to do the rendering is a big part of that (my old laptop didn't have DirectDraw capability, and the screensaver never worked at all...) And MeltdownBlur cheats IMO -- it changes the display resolution to 640x480 (and, I suspect, 8-bpp) to get more speed :P ... Anyway, it's something to work on; there's lots of code floating around from the demo scene and such, I just need to do some more research. One of the nifty fire-effect algorithms might work ok, and those tend to be fairly slick and fast... From my other screensaver-writing experience, I know I can probably get away with blitting from an off-screen buffer to draw everything and still maintain 30Hz on most machines.

I should be working on the Maestro-3 driver, but this screensaver idea has gotten under my skin and is much more fun to play with; programming in kernel land is no fun :P



2002.09.15 (v:0.20) -- I picked a name for this screensaver: "Sparticles" -- a combination of "sparks" (which was my original working name) and "particles." I think it fits :)

Added various colors; fixed the trails so that they draw tail-to-nose (when drawing nose-to-tail, you could see some artifacts of the final squares being drawn when the trails were all bunched up); added a timer so that each spark will die-out (gracefully - it fades away) after a certain amount of time and generate a new spark; added a separate function to init sparks, and made it so that they always start somewhere off of the screen (10% outside the border); The size of the squares to draw the trails is now scaled to the screen size that everything is being displayd on - so the preview actually looks like what you're going to see, and not an oversized-block version. Set the "tick" size (i.e., delay between drawing frames) to 33333us, or about 1/30th of a second (a decent framerate, if nothing else is sucking up all your CPU cycles.)

Copied over the controls from Kablooie and just changed some things to make them work as controls for this saver; made configs store/restore between invocations. Added check to see if settings had changed, and if they do, it re-inits everything and wipes the screen (useful for the config view, otherwise there were cases where half-drawn spark trails were left around when the trail length was tweaked.

The interaction scale is interesting, since the nrepulsion effects are so much more interesting than then the attraction ones; so the scale is effectively divided in half, the left side being repulsion with a very high value at the far left, while the right side of the slider is attraction, which is a very small value even at its maximum. This isn't working exactly right for some reason, still looking into why - sometimes the gravity stored between invocations is not restored properly :/ It seems to only happen when the slider is way on the left-side of the scale, but I can't see why that would cause any trouble from the code... :/

Going to package things up and put it on BeBits tonight, need to write a Readme and do all that fun stuff. I need to clean up the source code considerably before I'll be comfortable publishing it, I'm sure that there's a LOT of optimization I can do :)




2002.09.15 (v:0.10) -- This screensaver is the result of an idea I was tossing around in one of my math classes this week. I originally set out to make something similar to a screensaver that's in the Xscreensaver package, where a bunch of little balls move about a 2D space based on some formula for attraction and replusion from eachother; the size of the balls shows how much "pull" they had on the other objects (i.e., mass if you're using a model similar to gravitation, charge if you're working on something like electron/proton interactions.) All kinds of nifty orbits and curves arise out of this, depending on which properties and how many balls are in the system. (There was also an optional fixed-point in the middle of the screen that wobbled and attracted the balls to keep them moving around.)

I went about implementing something like this starting with Newton's universal law of gravitation, Fg = (G)*( (m1 * m2) / (r^2) ), and then playing around with some of the variables and part of the formula to come up with a system that did neat things and looked cool. Key to this formula is the fact that force is determined by an inverse relation to distance, i.e., 1/r^2 (where r is the distance between two particles), so that they only cause changes to eachother's heading and speed when they are close enough, further varied by their "mass." Each particle has a vector to determine direction and speed, and working with vectors allowed for making the movements very smooth. A little heavy on calculations (lots of multiplies, divides and a few square-roots on floating point numbers), but nothing a modern PC can't handle easlily, and not too heavy computationally for a screensaver IMO.

I noticed that the particles tended to form little black-holes of sorts, where two would get stuck together, and slowly attract the others until all of the particles were piled up in a couple of clumps. Tweaking a minimum and maximum velocity, as well as some other factors in the general formula to determine how strongly each is attracted to the others, I managed to get around that, and then decided to try making the attraction force between particles actually be a repulsion - i.e., as they skittered around, they would veer away from one another; the effect is very cool to watch :) Then I added some fading trails behind the particles, and the result closely resembles fish lazily swimming around, or comets in some grand celestial simulation, depending on the length of the trails.

One of the things I added to keep things looking more fluid and less contrived is the way particles heading out-of-bounds are handled. Instead of just bouncing the direction vector to point away from the boundry a particle had crossed, a vector directing the particle back to the center of the screen is applied for as long as the particle is out-of-range. This causes them to gracefully curve back towards the playfield (usually offscreen), and not have a sharp "bounce" in their path when they bump into the edges.

I'm really happy with the way things are looking... now I need to clean up the code a little, add some color variations (at the moment, everything is in shades of purple, because that looked cool), and add in some controls to manipluate aspects such as the number of particles, trail length, etc. I'm thinking that a slider to control the attractive/repulsive force will be nifty, allowing one to have them either gravitate towards eachother, or repel other particles as they approach.

I have the calculations working off of a system that's independent of the screen size, and the positions for drawing are all scaled into the current size of the screen; the problem I have here is determining how large the "points" for drawing the particles should be, as this needs to vary with the screen size; something to mess with as I polish things I suppose.

There's a function in the code to show a "map" of the attraction/repulsion forces, by coloring squares in a grid in the background based on the total force affecting the center of each square in the grid. It looks extremely cool, but slows down things by too much to include in a public release, so I'll probably stick with a black background.




Back to the main projects page


Email me with comments, etc. --> fatrat@fat-rat.com