Now that my AU Library is out (in beta, anyway) I thought I’d show how to write the noise blending code from an earlier post, but this time using the AU Library. Although I do a little more work in setup()
, the draw()
is much simpler, and the results are much nicer.
Here’s what’s changed:
- I replaced the 3D array of floats with a single
AUMultiField
object. - I replaced the first two lines of
draw()
(which were pretty messy) with simple calls to anAUStepper
object. - I replaced the call to
curve()
with a call to a per-pixelAUCurve
object. This means we move through the curves at a smooth, constant pace. - These changes mean that the noise fields and a couple of other variables no longer need to be global. The only globals are the
AUStepper
and theAUCurve
objects.
I could scrunch the code down even more by doing away with the AUMultiField
that holds the noise. After all, there’s really no reason to compute it and save it since it’s only used once. The expressions to get the noise could be rolled right into each AUCurve
constructor. But I think this is a little easier to follow, and it demonstrates how to use AUMultiField
to hold this kind of data, so I left it this way.
import AULibrary.*; // A little sketch to demonstrate the multiple noise field interpolation technique. // No guarantee or warranty of any kind. You may use and distribute this freely. // Andrew Glassner, September 16, 2014 AUStepper Stepper; // tracks our progress through the fields AUCurve[][] NoiseCurves; // one curve of noise per pixel void setup() { size(500, 500); AUMultiField noiseArrays; // list of noise fields int numFields = 4; // how many fields you want to use. Must be > 0 int cycleLength = 25; // number of frames to get from one field to another Stepper = new AUStepper(numFields, cycleLength); // create the stepper Stepper.setAllEases(AULibrary.EASE_LINEAR); noiseArrays = new AUMultiField(this, numFields, width, height); for (int n=0; n<numFields; n++) { // for each field n, for (int y=0; y<height; y++) { // look at all the pixels for (int x=0; x<width; x++) { float noiseX = (x*.02) + (n*width); // .02 was chosen by eye; it's float noiseY = (y*.02) + (n*height); // not too simple or busy noiseArrays.fields[n].z[y][x] = noise(noiseY, noiseX); // save this value } } } NoiseCurves = new AUCurve[height][width]; for (int y=0; y<height; y++) { // build a curve for each pixel for (int x=0; x<width; x++) { float[][] knots = new float[numFields][1]; // the data for this curve for (int n=0; n<numFields; n++) { // fill in with this curve's data knots[n][0] = noiseArrays.fields[n].z[y][x]; } NoiseCurves[y][x] = new AUCurve(knots, 1, true); // 1D geometry, closed curve } } } void draw() { Stepper.step(); float alfa = Stepper.getFullAlfa(); // how far we are into the curves loadPixels(); for (int y=0; y<height; y++) { for (int x=0; x<width; x++) { float v = NoiseCurves[y][x].getX(alfa); // get value from this curve pixels[(y*width)+x] = color(255 * v); // save noise value as a shade of gray } } updatePixels(); }