We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProgramming Questions & HelpPrograms › Plasma Fractal
Page Index Toggle Pages: 1
Plasma Fractal (Read 1552 times)
Plasma Fractal
Mar 26th, 2010, 12:54pm
 
I'm just adapting a Java program I found on the net (thanks Justin Seyster for releasing into the public domain). The original program is here: http://www.ic.sunysb.edu/Stu/jseyster/plasma/

I've got it working, but it's drawing a grid over the fractal and I can't see why. Any suggestions welcome, thanks.

EDIT: Doesn't actually need the Buffer - can write the program without it. Doesn't fix the problem, though.

Code:
PGraphics Buffer;	//A buffer used to store the image

  void setup()
  {
    size(600, 600);
    noStroke();
    colorMode(RGB, 1.0, 1.0, 1.0);
    Buffer = createGraphics(width, height, P2D);
    drawPlasma(width, height);
  }
 
  void draw()
  {

   
  }

 float Displace(float num)
{
  float max = num / (float)(width + height) * 3;
  return random(0.5)* max;
}

//Returns a color based on a color value, c.
color ComputeColor(float c)
{
float Red = 0;
float Green = 0;
float Blue = 0;

if (c < 0.5)
{
Red = c * 2;
}
else
{
Red = (1.0 - c) * 2;
}

if (c >= 0.3f && c < 0.8f)
{
Green = (c - 0.3) * 2;
}
else if (c < 0.3)
{
Green = (0.3 - c) * 2;
}
else
{
Green = (1.3 - c) * 2;
}

if (c >= 0.5)
{
Blue = (c - 0.5) * 2;
}
else
{
Blue = (0.5 - c) * 2;
}

return color(Red, Green, Blue);
}

//This is something of a "helper function" to create an initial grid
//before the recursive function is called.
void drawPlasma(int w, int h)
{
float c1, c2, c3, c4;

//Assign the four corners of the intial grid random color values
//These will end up being the colors of the four corners of the applet.
c1 = random(0,1);
c2 = random(0,1);
c3 = random(0,1);
c4 = random(0,1);

DivideGrid(0, 0, w , h , c1, c2, c3, c4);
 image(Buffer, 0 ,0);
}

//This is the recursive function that implements the random midpoint
//displacement algorithm.  It will call itself until the grid pieces
//become smaller than one pixel.
void DivideGrid(float x, float y, float w, float h, float c1, float c2, float c3, float c4)
{
float Edge1, Edge2, Edge3, Edge4, Middle;
float newWidth = w / 2;
float newHeight = h / 2;

if (w > 2 || h > 2)
{
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 < 0)
{
Middle = 0;
}
else if (Middle > 1.0)
{
Middle = 1.0;
}

//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.
float c = (c1 + c2 + c3 + c4) / 4;
Buffer.beginDraw();
 Buffer.noStroke();
 Buffer.set((int)x, (int)y, ComputeColor(c));
Buffer.endDraw();
}
}

//Draw a new plasma fractal whenever the applet is clicked.
void mouseReleased()
{
drawPlasma(width, height);
 }
Re: Plasma Fractal
Reply #1 - Mar 26th, 2010, 1:34pm
 
In the DivideGrid method change the first if statement from

Code:
 if (w > 2 || h > 2) 



to

Code:
 if (w > 1 || h > 1) 



Smiley
Re: Plasma Fractal
Reply #2 - Mar 26th, 2010, 2:04pm
 
Quark beat me to it, however I would like to suggest that you rearrange code vis
Quote:
void divideGrid(float x, float y, float w, float h, float c1, float c2, float c3, float c4)
{

 float newWidth = w / 2.0;
 float newHeight = h / 2.0;

 if (w < 1.0 || h < 1.0)
 {
   //The four corners of the grid piece will be averaged and drawn as a single pixel.
 
   float c = (c1 + c2 + c3 + c4) / 4.0;
   buffer.beginDraw();
   buffer.noStroke();
   buffer.set((int)x, (int)y, computeColor(c));
   buffer.endDraw();
 }
 else
 {
   float middle =(c1 + c2 + c3 + c4) / 4.0 + displace(newWidth + newHeight);      //Randomly displace the midpoint!
   float edge1 = (c1 + c2) / 2.0;      //Calculate the edges by averaging the two corners of each edge.
   float edge2 = (c2 + c3) / 2.0;
   float edge3 = (c3 + c4) / 2.0;
   float edge4 = (c4 + c1) / 2.0;

   //Make sure that the midpoint doesn't accidentally "randomly displaced" past the boundaries!
   if (middle <= 0)
   {
     middle = 0;
   }
   else if (middle > 1.0)
   {
     middle = 1.0;
   }

   //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);
 }

}
Smiley


Re: Plasma Fractal
Reply #3 - Mar 26th, 2010, 2:06pm
 
yours looks different to theirs, too regular. i think it's this in Displace()

return ((float)Math.random() - 0.5f) * max; // theirs
vs
return random(0.5)* max; // yours

yours would be closer as random(-.5, .5) * max;

(or you could just use theirs, Math.random should work in processing.
Re: Plasma Fractal
Reply #4 - Mar 26th, 2010, 2:44pm
 
Yep...that does it....thanks a lot for your help.

I still don't understand why it drew a grid of squares....I would have just thought it would look more "blocky"...
Re: Plasma Fractal
Reply #5 - Mar 26th, 2010, 2:51pm
 
Just posting the "finished" program here so anyone else who wants to can use it......
(Now that it works in Processing I'm going to adapt it for my own purposes).

Code:
// Adapted for Processing from "Plasma Fractal" - Written January, 2002 by Justin Seyster (thanks for releasing into public domain, Justin).

void setup()
{
   size(600, 600);
   noStroke();
   colorMode(RGB, 1.0, 1.0, 1.0);
   drawPlasma(width, height);
}
 
void draw()
{

}

float displace(float num)
{
 float max = num / (float)(width + height) * 3;
 return random(-0.5, 0.5)* max;
}

//Returns a color based on a color value, c.
color computeColor(float c)
{
 float Red = 0;
 float Green = 0;
 float Blue = 0;

 if (c < 0.5)
 {
   Red = c * 2;
 }
 else
 {
   Red = (1.0 - c) * 2;
 }
 if (c >= 0.3 && c < 0.8)
 {
   Green = (c - 0.3) * 2;
 }
 else if (c < 0.3)
 {
    Green = (0.3 - c) * 2;
 }
 else
 {
    Green = (1.3 - c) * 2;
 }

 if (c >= 0.5)
 {
    Blue = (c - 0.5) * 2;
 }
 else
 {
    Blue = (0.5 - c) * 2;
 }

  return color(Red, Green, Blue);
}

//This is something of a "helper function" to create an initial grid
//before the recursive function is called.
void drawPlasma(float w, float h)
{
  float c1, c2, c3, c4;

  //Assign the four corners of the intial grid random color values
  //These will end up being the colors of the four corners of the applet.
  c1 = random(0,1);
  c2 = random(0,1);
  c3 = random(0,1);
  c4 = random(0,1);
  divideGrid(0.0, 0.0, w , h , c1, c2, c3, c4);
}

//This is the recursive function that implements the random midpoint
//displacement algorithm.  It will call itself until the grid pieces
//become smaller than one pixel.
void divideGrid(float x, float y, float w, float h, float c1, float c2, float c3, float c4)
{

  float newWidth = w / 2.0;
  float newHeight = h / 2.0;

  if (w < 1.0 || h < 1.0)
  {
    //The four corners of the grid piece will be averaged and drawn as a single pixel.
    float c = (c1 + c2 + c3 + c4) / 4.0;
    set((int)x, (int)y, computeColor(c));
  }
  else
  {
    float middle =(c1 + c2 + c3 + c4) / 4.0 + displace(newWidth + newHeight); //Randomly displace the midpoint!
    float edge1 = (c1 + c2) / 2.0; //Calculate the edges by averaging the two corners of each edge.
    float edge2 = (c2 + c3) / 2.0;
    float edge3 = (c3 + c4) / 2.0;
    float edge4 = (c4 + c1) / 2.0;

    //Make sure that the midpoint doesn't accidentally "randomly displaced" past the boundaries!
    if (middle <= 0)
    {
middle = 0;
    }
    else if (middle > 1.0)
    {
middle = 1.0;
    }

    //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);
  }
}

//Draw a new plasma fractal whenever the applet is clicked.
void mouseReleased()
{
   drawPlasma(width, height);
}
Re: Plasma Fractal
Reply #6 - Mar 26th, 2010, 11:25pm
 
Pretty cool Smiley
To save clicking the mouse you could do something like
Code:

void draw()
{
 if (frameCount % 13 == 0)
 drawPlasma(width, height);
}


I tried other variants in calculating the edge, in divideGrid instead of dividing by 2 try sqrt(3) or PHI. ( 1 + sqrt(5)/2 ). You might want to bump up the displacement to make the look a bit less spartan using PHI in place of 2.

For a funky quilt look try
Code:

    float edge1 = (c1 + c2)  / sqrt(3);
    float edge2 = (c2 + c3)  / 2;
    float edge3 = (c3 + c4) / 2;
    float edge4 = (c4 + c1)  / sqrt(3);


This is a lot of fun you can even try randomizing the divisor to get some random/emergent structure (Mr Sierpinksi is never too far away).
Code:
     
    float edge1 = (c1 + c2)/ random(sqrt(2), 2);
    float edge2 = (c2 + c3) / random(sqrt(2), 2);
    float edge3 = (c3 + c4) / random(sqrt(2), 2);
    float edge4 = (c4 + c1)/ random(sqrt(2), 2);

Re: Plasma Fractal
Reply #7 - Mar 27th, 2010, 6:18am
 
That's pretty cool....

You can also control the "graininess" (vs. smoothness) of the fractal by changing the divisor here:

float max = num / (float)(width + height) * 3 <--- change this number.

I put a final int GRAIN=3; at the start of the sketch and changed this to:

float max = num / (float)(width + height) * GRAIN;

1-2 gives a very smooth fractal.....10 is very grainy....100 is really grainy...
Re: Plasma Fractal
Reply #8 - Mar 27th, 2010, 1:14pm
 
I added a little gui stuff using G4P, and put the sketch on openProcessing:
http://www.openprocessing.org/visuals/?visualID=8528 It won't run in the browser, though - is this a known problem with G4P
Re: Plasma Fractal
Reply #9 - Mar 27th, 2010, 2:20pm
 
I wonder could it have anything to to with the font being in a different jar Quark will know Wink.
You could try replacing loadFont(name) with createFont(name, size)?
Anyway the downloaded version works ok for me in the ide.  As an aside do you think that there might be some mileage in using bitwise operations to manipulate the color, according the Ira Greenberg book it should be more efficient?
Re: Plasma Fractal
Reply #10 - Mar 27th, 2010, 2:59pm
 
Yes....should be faster... Though the fractals generate pretty much instantly on my machine....so I'm too lazy to implement it (I have done it in other programs, though).

The Java console indicates that it is the gui components that are causing the problem....even though they are inside the zip file I uploaded. Well, I don't know why it doesn't work. I tried doing the font thing the other way but it didn't help.
Re: Plasma Fractal
Reply #11 - Mar 27th, 2010, 4:02pm
 
Works on openProcessing with the gui now. I had the library file in a "code" folder in the sketch directory...but Cedric helped me to install the library properly in this thread: http://processing.org/discourse/yabb2/num_1269728210.html#5
Page Index Toggle Pages: 1