Mike T. Henderson

I make interactive things.

Categories:


More Mike:

Rotating Particles with PerlinNoise

September 3, 2008

Continuing on with my previous post on scaling particles with PerlinNoise, I decided to take it a little further by playing with each particle's rotation in relation to the white and dark values in the PerlinNoise. This is another little trick I learned from Robert Hodgin's presentation at FlashBelt on how to simulate realistic motion on how objects reacted to wind.

When wind blows, it doesn't just blow all objects at the same speed, direction, and force, all in a straight line. There are many parameters that can alter the way one object moves from within a large group of objects.

While PerlinNoise does not simulate wind patterns, the sheer randomness it provides allows us the ability to fake an effect such as the way a field of grass blows in the breeze, or the way a group of leaves on a tree blow in the wind.

The below example takes an object from the library, duplicates it a set amount of times, and applies it to the stage at a random position. The basic logic of the rotation is; to scan the entire PerlinNoise bitmap and gather the minimum and maximum color numbers from all the pixels within that bitmap, the take the current pixel color directly beneath the particle and subtract it by the minimum color value. Then take that value divided by the maximum color value, and then multiply that value by 360.

import flash.display.BitmapData;
import flash.display.Graphics;
import flash.display.Sprite;
import flash.events.Event;
import flash.geom.Point;
 
/* ------------------------------------------------------------------------------------------------
// set up Perlin Noise Properties
--------------------------------------------------------------------------------------------- */
 
var perlinW:int = 600;
var perlinH:int = 250;
var baseX:int = 275;
var baseY:int = 275;
var octaves:int = 1;
var seed:int = Math.floor(Math.random()*100);
var stitch:Boolean = true;
var fractal:Boolean = true;
var grayScale:Boolean = true;
var channels:int = 1;
var xSpeed:int = 15;
var ySpeed:int = 15;
var tnodes:int = 200;
 
/* ------------------------------------------------------------------------------------------------
// set up min/max color vars
--------------------------------------------------------------------------------------------- */
 
var minColor:int = Number.MAX_VALUE;
var maxColor:int = 0;
var pixelData:int;
 
/* ------------------------------------------------------------------------------------------------
// create offset
--------------------------------------------------------------------------------------------- */
 
var point1:Point = new Point(0, 0);
var point2:Point = new Point(0, 0);
var offset:Array = [point1, point2];
 
/* ------------------------------------------------------------------------------------------------
// create bitmapData object
--------------------------------------------------------------------------------------------- */
 
var myBD:BitmapData = new BitmapData(perlinW, perlinH);
 
/* ------------------------------------------------------------------------------------------------
// run perlinNoise
--------------------------------------------------------------------------------------------- */
 
addEventListener(Event.ENTER_FRAME, onEnterFrame);
function onEnterFrame(e:Event) {
offset[0].x += int(xSpeed);
offset[0].y += int(ySpeed);
myBD.perlinNoise(baseX, baseY, octaves, seed, stitch, fractal, channels, grayScale, offset);
}
 
/* ------------------------------------------------------------------------------------------------
// get min/max pixel info
--------------------------------------------------------------------------------------------- */
 
function updateMinMaxPixel():void {
 
for (var i : int = 0;i < perlinW; i++) {
for (var j : int = 0;j < perlinH; j++) {
pixelData = int(myBD.getPixel(i, j));
minColor = int(Math.min(pixelData, minColor));
maxColor = int(Math.max(pixelData, maxColor));
}
}
 
}
 
/* ------------------------------------------------------------------------------------------------
// create nodes
--------------------------------------------------------------------------------------------- */
 
function addNodes():void {
 
updateMinMaxPixel();
 
var i:int = tnodes;
 
while (i > 0) {
 
// build node
var myNode:Ball = new Ball();
 
// position node
myNode.x = int(Math.random() * perlinW);
myNode.y = int(Math.random() * perlinH);
 
// try drawing into a bitmap data
myNode.addEventListener(Event.ENTER_FRAME, scaleNode);
 
addChild(myNode);
 
i --;
}
}
 
/* ------------------------------------------------------------------------------------------------
// update Node
--------------------------------------------------------------------------------------------- */
 
function scaleNode(e:Event):void {
 
// find pixel color under node
var curColor:int = myBD.getPixel(int(e.currentTarget.x), int(e.currentTarget.y));
 
// find rotation by taking the difference of current color - minColor and the maxColor
var Rotation:Number = Number((curColor - minColor) / maxColor);
 
// update properties
e.currentTarget.rotation = Number(Rotation * 360);
e.currentTarget.scaleX = curColor * .0000001;
e.currentTarget.scaleY = curColor * .0000001;
} addNodes();
2 Comments | Posted under BitmapData Bookmark and Share

2 Comments »

  1. [...] In my previous experiments using Perlin Noise to create random movement, I played around with adjusting the rotation and the scale of each particle by taking the current pixel color number beneath each node and gathering a percentage of that by the maximum color number in the Perlin Noise. [...]

    Pingback by Mike T. Henderson » Moving Particles with Perlin Noise V01 — 9/11/08 @ 12:47 am

  2. [...] interesting method. In previous posts I’ve experimented, using the number it returns, to scale, rotate, move, and in my last post, create a halftone [...]

    Pingback by Mike t. Henderson » Pointillism in AS3 with BitmapData — 2/13/09 @ 8:47 pm

Leave a comment