Hi everybody,
I recently got mesmerized by this sketch found on openprocessing.org.
I wanted to tip my toe into p5 so I decided to try to adapt the code and here is my shot:
let x;
let t = 0;
let w = 255;
let m = 0;
let c;
function setup() {
createCanvas(255, 255);
}
function draw() {
t++;
background(0);
for (x = 0; x < w * w; x++) {
X = x % w + n();
Y = x / w + n();
c = 50 + (get(X, Y) >> 8 & w);
set(X, Y, color(c, c, c*2));
}
updatePixels();
}
function n(){
return noise((x % w / 0.99), (x / w / 0.99), (t / 0.99 + m++ % 2)) * w - w/2;
}
Although the code is pretty identical to the exemple from openprocessing, I only could get a cloud of noise when running it, without the elegant smoke behaviour.
I’m quite familiar with Java but much less with JS, so maybe I’m forgetting something obvious here…
Anyway I think some code is missing to reproduce the exemple, so I’m asking for your wise guidance.
Thank you
after a quick look in your noise function you are dividing by 0.99 whereas the source code is dividing by 99. there may be other things but that’s probably worth changing.
so this
return noise((x % w / 0.99), (x / w / 0.99), (t / 0.99 + m++ % 2)) * w - w/2;
should probably be this
return noise(x % w / 99, x / w / 99, t / 99 + m++ % 2) * w - w/2;
Processing main site has tutorial on pixels and how to access them. Commands are slightly different (Java) but it all applies to p5.js too https://processing.org/tutorials/pixels/
let x = 0;
let t = 0;
let w = 255;
let m = 0;
function setup() {
createCanvas(w, w);
pixelDensity(1);
}
function draw() {
t++;
background(0);
loadPixels();
for (x = 0; ++x < w * w;) {
X = x % w + n();
Y = x / w + n();
index = (X + Y * w) * 4;
c = 50 + pixels[index + 1] & w;
pixels[index + 0] = c;
pixels[index + 1] = c;
pixels[index + 2] = c * 2;
pixels[index + 3] = 255;
}
updatePixels();
}
function n() {
return Math.round(noise((x % w / 99), (x / w / 99), (t / 99 + m++ % 2)) * w - w / 2);
}
Here the map() method iterates over the array [...Array(s).keys()] and calls a function i => (i % w) on each of its element .
In other words:
[...Array(s).keys()] is similar to [0, 1, 2, ...s]
for each i in [0, 1, 2, ...s] the function makes the conversion (i % w)
So, to answer your question, each element in the final array is not a function but the result of that function. They are mapped (already transformed) in order to avoid redundant calculations in the draw() function.
On a side note posx and posy can be merged into one single array:
const w = 255; //width of canvas
const n = w*w; //total number of points
const pos = [...Array(n*2).keys()].map(i => (i & 1 ? Math.floor(i/(w<<1)): (i-(i>>1))%w) )
for (let i = 0; i < n*2; i+=2) {
x = i
y = i+1
...
}
Unlike before, pos now contains both the x and y positions (one after the other) in a single array. Same thing can be done for arrays a and b.
JS already provides a much more simplified method for such cases:
We can replace the whole thing like this:
const W = 255, S = W * W, K = 99, F = 30,
posX = Array.from({ length: S }, (v, i) => i % W),
posY = Array.from({ length: S }, (v, i) => i / W),
a = Array.from(posX, x => x / K),
b = Array.from(posY, y => y / K);
console.log(posX);
console.log(posY);
console.log(a);
console.log(b);
The excerpt above can be pasted on any browser console btW.
P.S.: Since those 4 arrays store numerical values only, we can use typed arrays for them instead:
const W = 255, S = W * W, K = 99, F = 30,
posX = Uint8Array.from({ length: S }, (v, i) => i % W),
posY = Float32Array.from({ length: S }, (v, i) => i / W),
a = Float32Array.from(posX, x => x / K),
b = Float32Array.from(posY, y => y / K);
console.log(posX);
console.log(posY);
console.log(a);
console.log(b);
I know, and I recently started to use typed arrays as well (d3.js ‘sketches’ are full of them) but for some reason I find [...Array(s).keys()] to be more readable. That’s a bad habit I guess.