[ create a new paste ] login | about

Link: http://codepad.org/crMEQ2DD    [ raw code | fork ]

C++, pasted on Jun 12:
var bitmapData:BitmapData = new BitmapData(100, 100, false, 0xFFFFFF);

var noises:Vector.<Number> noises = PerlinNoise.getNoise(100, 100, 3, 7, 0.6, 20);
			
for (var x:int = 0; x < width; x++) 
{
	for (var y:int = 0; y < height - 10; y++) 
	{
		var noise:Number = noises[x + y * width];
		
		if (noise > 0.4 && noise < 0.6)
		{
			bitmapData.setPixel(x, y + 10, 0xFFFFFF);
		}
		
		if (noise > 0.8 && noise < 1.0)
		{
			bitmapData.setPixel(x, y + 10, 0x0000FF);
		}
		
		if (noise > 0.0 && noise < 0.2 && y >= 70)
		{
			bitmapData.setPixel(x, y + 10, 0xFF0000);
		}
	}
}

var bmp:Bitmap = new Bitmap(bitmapData);
			
bmp.scaleX = 6.0;
bmp.scaleY = 6.0;

addChild(bmp);

public final class Rand
{
	static private var _seed:uint;
	
	public function set seed(val:uint):void
	{
		if (val != 0)
		{
			_seed = val;
		}
		else
		{
			_seed = uint(Math.random() * uint.MAX_VALUE);
		}
	}
	
	public function get seed():uint
	{
		return _seed;
	}
	
	public function nextInt(min:int, max:int):int
	{
		_seed = 214013 * _seed + 2531011;
		return min + (_seed ^ (_seed >> 15)) % (max - min + 1);
	}
	public function nextNumber(min:Number, max:Number):Number
	{
		_seed = 214013 * _seed + 2531011;
		return min + (_seed >>> 16) * (1.0 / 65535.0) * (max - min);
	}
}

public final class PerlinNoise
{
	private static var _rand:Rand = new Rand();
	
	public static function randomize(seed:uint):void
	{
		_rand.seed = seed;
	}
	
	public static function getNoise(width:int, height:int,
		startOctave:int, endOctave:int, persistence:Number, smoothAmount:Number):Vector.<Number>
	{
		var valueNoiseMap:Vector.<Number> = new Vector.<Number>(width * height);

		var cellSize:Number = width / Math.pow(2, endOctave);

		var integerX:int = Math.floor((width - 1) / cellSize);
		var integerY:int = Math.floor((height - 1) / cellSize);
		
		var octaveSize:Number = Math.pow(2, endOctave + 1) - Math.pow(2, endOctave) + 1;
		
		var nodeCount:int = (integerY + 1) * octaveSize + integerX + 2;
						
		var randomTree:Vector.<Number> = new Vector.<Number>(nodeCount);
		
		for (var i:int = 0; i < randomTree.length; ++i)
		{
			randomTree[i] = _rand.nextNumber(0.0, 0.9);
		}
		
		for(var y:int = 0; y < height; ++y)
		{
			for(var x:int = 0; x < width; ++x)
			{
				valueNoiseMap[y * width + x] = 0;
				
				for (var i:int = startOctave; i <= endOctave; ++i)
				{
					var cellSize:Number = width / Math.pow(2, i);

					var integerX:int = Math.floor(x / cellSize);
					var integerY:int = Math.floor(y / cellSize);

					var fractionalX:Number = (x - integerX * cellSize) / cellSize;
					var fractionalY:Number = (y - integerY * cellSize) / cellSize;
					
					var octaveSize:Number = Math.pow(2, i + 1) - Math.pow(2, i) + 1;
					
					var i1 = interpolate(randomTree[integerY * octaveSize + integerX],
										 randomTree[integerY * octaveSize + integerX + 1],
										 fractionalX);
										 
					var i2 = interpolate(randomTree[(integerY + 1) * octaveSize + integerX],
										 randomTree[(integerY + 1) * octaveSize + integerX + 1],
										 fractionalX);

					valueNoiseMap[y * width + x] +=
						interpolate(i1 , i2 , fractionalY) * Math.pow(persistence, i - startOctave);
				}
			}
		}

		smooth(width, height, valueNoiseMap, smoothAmount);

		normalize(width, height, valueNoiseMap, 0, 1);

		return valueNoiseMap;
	}

	private static function smooth(width:int, height:int, noise:Vector.<Number>, amount:int):void
	{
		for (var i:int = 0; i < amount; ++i)
		{
			for (var y:int = 0; y < height; ++y)
			{
				for(var x:int = 0; x < width; ++x)
				{
					var xMinus1:int = x == 0 ? width - 1 : x - 1;
					var yMinus1:int = y == 0 ? height - 1 : y - 1;
					var xPlus1:int = (x + 1) % width;
					var yPlus1:int = (y + 1) % height;
					
					var corners:Number = (noise[yMinus1 * width + xMinus1] + 
								   noise[yMinus1 * width + xPlus1] + 
								   noise[yPlus1 * width + xPlus1] + 
								   noise[yPlus1 * width + xMinus1]) / 16.0;
								   
					var sides:Number = (noise[y * width + xMinus1] + 
										noise[y * width + xPlus1] + 
										noise[yMinus1 * width + x] + 
										noise[yPlus1 * width + x]) / 8.0;
								   
					var center:Number = noise[y * width + x] / 4.0;
					
					noise[y * width + x] = corners + sides + center;
				}
			}
		}
	}

	private static function normalize(width:int, height:int,
		noise:Vector.<Number>, minimum:Number, maximum:Number):void
	{
		var min:Number = Number.MAX_VALUE;
		var max:Number = -Number.MAX_VALUE;

		// Calculate min and max range used to normalize with
		for (var y:int = 0; y < height; ++y)
		{
			for(var x:int = 0; x < width; ++x)
			{
				min = Math.min(min, noise[y * width + x]);
				max = Math.max(max, noise[y * width + x]);
			}
		}

		// Normalize the range to 0 to 1
		for (var y:int = 0; y < height; ++y)
		{
			for(var x:int = 0; x < width; ++x)
			{
				noise[y * width + x] = (noise[y * width + x] - min) / (max - min) * (maximum - minimum) + minimum;
			}
		}
	}

	private static function interpolate(a:Number, b:Number, x:int)
	{
		var ft:Number = x * 3.1415927;
		var f:Number = (1.0 - Math.cos(ft)) * 0.5;
		return a * (1.0 - f) + b * f;
	}
}


Create a new paste based on this one


Comments: