Bill Hsu 
		
		YaBB Newbies
		 
		Offline 
		
		
		Posts: 9
		
		
		
		
 
	 
	
		
			
				Re: generating random blobs  
				Reply #6 -  May 8th , 2009, 11:19pm 
			 
			
				
	  
			 
		
		
			[Ok, let's see if I can fake out the forum software...] The code is at the end of this post. Press any key to generate some blobs. Press again to generate new blobs.  makeBlob() is the blob generator function. The input parameters are the approximate center of the blob, the diameter, a parameter to control how blob-like or noisy the result is, and a parameter to very roughly control the density. I've tried to make this fairly efficient; I haven't looked into using lots of metaballs instead, but I think this might be faster. I'm using the blobs in a project where I do a lot of pixel hacking, so I write straight into the pixel array.  Two sets of blobs are displayed. The bottom shows the blobs without trimming the circular border; if that's what you need, great, but I think it makes the splatters look unnatural. I use a hack-y scaling function to trim the borders; that's the top. Because it's just Perlin noise with thresholds, sometimes you get more than one blob. And the density control is very approximate. I suppose I could look into segmenting or parameterizing the blobs better, but I think this is workable for what I need. Hope this is interesting to someone. Comments appreciated! Bill // Random Blob Generation // by Bill Hsu // Uses Perlin noise with threshold to generate blobs // at specified center and radius // Kludge-y scaling kernel to trim borders int bgCol = 0; int fgCol = color(255, 255, 255); PGraphics pg; void setup() {   size(200, 400);   pg = createGraphics(200, 400, P3D);   pg.beginDraw();   pg.background(bgCol);   pg.noStroke();   pg.endDraw();   image(pg, 0, 0);   pg.loadPixels(); } void draw() { } void keyPressed() {      pg.beginDraw();   pg.background(bgCol);   makeBlob(width/2, width/2, width/2, .05, .25);   pg.endDraw();   image(pg, 0, 0); } void makeBlob(int midX, int midY, // (x,y) coordinates of center               int side, // length of a side, or diameter of blob               float noiseMult, // position multiplier .02-.25                                // very blobby to very noisy               float percentDev) // percent deviation .005-.5                                 // very sparse to very dense {   float xoff = random(10);   float yoff = random(10);      float baseLevel = noise(midX*noiseMult + xoff, midY*noiseMult + yoff);   float pixelScaleBoundary = 40.; // start scaling 40 pixels from circle edge   for (int i=midX-side/2; i<midX+side/2; i++) {     for (int j=midY-side/2; j<midY+side/2; j++) {       float radius = sqrt((i - midX) * (i - midX) + (j - midY) * (j - midY));       float diffRad = radius - side/2.;       if (diffRad >= 0.)         continue;       float newNoise = noise(i*noiseMult + xoff,j*noiseMult + yoff);              // "fade out" if too close to circular boundary       float fudgeFactor = -diffRad / pixelScaleBoundary;       if (fudgeFactor > 1.)         fudgeFactor = 1.;       float newRatio = newNoise / baseLevel;       // bound base noise level if original is too low       if (baseLevel < .25) {         newRatio = newNoise * 4.;       }       // draw blob       if (newRatio > 1 && newRatio < (1. + percentDev * fudgeFactor)) {         pg.pixels[j*width + i] = fgCol;       }       else if (newRatio < 1. && newRatio > (1. - percentDev * fudgeFactor)) {         pg.pixels[j*width + i] = fgCol;       }              // draw blob without boundary scaling for comparison       if (newRatio > (1.-percentDev) && newRatio < (1. + percentDev)) {         pg.pixels[(j+height/2)*width + i] = fgCol;       }     }   } }