I was doing some cleanup of my computer the other day and I stumbled on some nice projects I did over the years. Some of it may be interesting to someone so I decided to post them on the blog. These projects are AS IS, meaning they were made a long time ago and were mostly conversions from other programming languages to RealBasic without going deep into the math myself. If you want to know more on how it works, I suggest you dive into some articles on the InterWeb.
I’ll try to give credit to the original coder if i can find it back. If you are the coder, please mail me and I’ll add it to the article.
From some of the projects I even saved the original article, but unfortunately not the website were I found it.
The plasma generator uses a recursive algorithm known as random midpoint displacement. The algorithm begins with a rectangular grid that has four points, one at each corner. These corners are each randomly assigned a color value.
Now, five new points are added to the grid. One point is added to each edge that has a color value in-between the color value of the two corners connected to the edge (i.e., it is the average value of those two corners). The fifth point is placed in the center, or midpoint, of the grid. It is the average of the original four corners.
This is where the algorithm gets its name. The midpoint is randomly displaced. That is to say, some random value is chosen, and the color value is shifted by the value. The range of possible random numbers is made to be proportional to the size of the square. A large square may have its midpoint displaced a great deal, and a small square can not have its midpoint displaced by more than a little bit.
Adding the five extra points divided the original rectangle into four similar rectangles of one fourth the area. The algorithm is repeated for each of these new squares, yielding a total of sixteen squares. The process can be repeated recursively as necessary. In this case, it is repeated until each rectangle is less than the size of a single pixel. At that point, the recursion ends, and the pixel is drawn.
A great deal of the magic has to do with the selection of colors. Every color value is a number from zero to one. What the algorithm does is create a field of smoothly changing color values. A function converts these color values to colors so that the color values from zero to one flow smoothly between colors, creating the plasma effect.
This plasma fractal has been colored to show you what color value each pixel was assigned. All black means a color value of 0.0 and all white is a color value of 1.0. The chart on the right illustrates how each color value is converted to a color. The chart to the right shows all the colors from the first chart broken into their red, green and blue components.
Most of all this is done by the recursive function DivideGrid:
Private Sub DivideGrid(ByVal x As Single, ByVal y As Single, ByVal width As Single, ByVal height As Single, ByVal c1 As Single, ByVal c2 As Single, ByVal c3 As Single, ByVal c4 As Single) Dim Edge1, Edge2, Edge3, Edge4, Middle As Single Dim newWidth As Single = width / 2 Dim newHeight As Single = height / 2 If width > 1 Or height > 1 Then Middle = (c1 + c2 + c3 + c4) / 4 + Displace(newWidth + newHeight) 'Randomly displace the midpoint! Edge1 = (c1 + c2) / 2 'Calculate the edges by averaging the two corners of each edge. Edge2 = (c2 + c3) / 2 Edge3 = (c3 + c4) / 2 Edge4 = (c4 + c1) / 2 'Make sure that the midpoint doesn't accidentally "randomly displaced" past the boundaries! If Middle 1.0 Then Middle = 1.0 End If 'Do the operation over again for each of the four new grids. DivideGrid(x, y, newWidth, newHeight, c1, Edge1, Middle, Edge4) DivideGrid(x + newWidth, y, newWidth, newHeight, Edge1, c2, Edge2, Middle) DivideGrid(x + newWidth, y + newHeight, newWidth, newHeight, Middle, Edge2, c3, Edge3) DivideGrid(x, y + newHeight, newWidth, newHeight, Edge4, Middle, Edge3, c4) Else 'This is the "base case," where each grid piece is less than the size of a pixel. 'The four corners of the grid piece will be averaged and drawn as a single pixel. Dim c As Single = (c1 + c2 + c3 + c4) / 4 rgbBuffer.pixel(x,y) = ComputeColor(c) End If End Sub
The RealBasic source code and a compiled example can be downloaded from: http://www.gorgeousapps.com/ABPlasma.zip