It's a creative coding example using the Turing Pattern.
The Turing Pattern on the window will scare you.
It's a creative coding animation work that creates weird image. The code is written in the 'Processing'.
I tried to make an animation with Turing Pattern. I used the Gray-Scott model. And change feed/kill parameters with 2D Perlin noise.
This code does not display any images on the screen but generates image files in frames directory. It may take a very long time to draw.
Reference book.
The 'Processing' example code.
Please feel free to use this example code under the terms of the GPL. To see other works based on my code is my pleasure. And my honor.
// Thru the Window. // @author @deconbatch // @version 0.1 // Processing 3.2.1 // 2018.09.02 /* main -------------------- */ void setup() { size(720, 720); colorMode(HSB, 360.0, 100.0, 100.0, 100.0); blendMode(DIFFERENCE); rectMode(CENTER); smooth(); noLoop(); noStroke(); } void draw() { int frameCntMax = 15 * 6; Ecosystem eco = new Ecosystem(frameCntMax); for (int frameCnt = 0; frameCnt < frameCntMax; ++frameCnt) { eco.setTime(frameCnt); eco.initSchale(); eco.plant(); eco.culture(); eco.observe(); saveFrame("frames/" + String.format("%04d", frameCnt) + ".png"); } exit(); } /* -------------------- */ public class Ecosystem { private Cell[][] cells; private float[][][] initVs; private float hueBase; private float cellSize; private int canvasW; private int canvasH; private int frameCntMax; private int frameCnt; Ecosystem(int frameCntMax) { this.frameCntMax = frameCntMax; frameCnt = 0; cellSize = 3.0; hueBase = random(360.0); canvasW = floor(width / cellSize); canvasH = floor(height / cellSize); cells = new Cell[canvasW][canvasH]; initVs = new float[2][canvasW][canvasH]; // constract cells for (int x = 0; x < canvasW; x++) { for (int y = 0; y < canvasH; y++) { cells[x][y] = new Cell(); initVs[0][x][y] = 0.14 * (x % 5); initVs[1][x][y] = 0.05 * (y % 10); cells[x][y].setU(initVs[0][x][y]); cells[x][y].setV(initVs[1][x][y]); } } // set neighbor cells for (int x = 0; x < canvasW; x++) { for (int y = 0; y < canvasH; y++) { cells[x][y].setNeighbor(new Cell[] { // 8 directions cells[max(x-1,0)][max(y-1,0)], cells[min(x+1,canvasW-1)][max(y-1,0)], cells[max(x-1,0)][min(y+1,canvasH-1)], cells[min(x+1,canvasW-1)][min(y+1,canvasH-1)], cells[x][max(y-1,0)], cells[x][min(y+1,canvasH-1)], cells[max(x-1,0)][y], cells[min(x+1,canvasW-1)][y] }); } } } public void setTime(int frameCnt) { this.frameCnt = frameCnt; } public void initSchale() { for (int x = 0; x < canvasW; x++) { for (int y = 0; y < canvasH; y++) { cells[x][y].setU(initVs[0][x][y]); cells[x][y].setV(initVs[1][x][y]); } } } public void plant() { float frameRate = sin(TWO_PI * map(frameCnt, 0, frameCntMax, 0.0, 1.0)); float easeRate = sin(TWO_PI * easeInOutCubic(map(frameCnt, 0, frameCntMax, 0.0, 1.0))); for (int x = 0; x < canvasW; x++) { for (int y = 0; y < canvasH; y++) { // change Gray-Scott model parameters with noise cells[x][y].setFeed(map(noise(x * 0.008 + easeRate * 0.1, y * 0.002 - frameRate * 0.1), 0.0, 1.0, 0.041, 0.118)); cells[x][y].setKill(map(noise(x * 0.002 - frameRate * 0.1, y * 0.008 + easeRate * 0.1), 0.0, 1.0, 0.056, 0.067)); } } } float easeInOutCubic(float t) { t *= 2.0; if (t < 1.0) { return pow(t, 3) / 2.0; } t -= 2.0; return (pow(t, 3) + 2.0) / 2.0; } public void culture() { int cultureTimeMax = 800; for (int cultureTime = 0; cultureTime < cultureTimeMax; cultureTime++) { for (int x = 0; x < canvasW; x++) { for (int y = 0; y < canvasH; y++) { cells[x][y].laplacian(); } } for (int x = 0; x < canvasW; x++) { for (int y = 0; y < canvasH; y++) { cells[x][y].react(); } } } } public void observe() { background(0.0, 0.0, 20.0, 100.0); for (int x = 0; x < canvasW; x++) { for (int y = 0; y < canvasH; y++) { fill( hueBase, 10.0, cells[x][y].getStandardU() * 100.0, 100.0 ); rect( x * cellSize, height - y * cellSize, cellSize, cellSize ); fill( hueBase, 40.0, cells[x][y].getStandardV() * 100.0, 100.0 ); rect( x * cellSize, height - y * cellSize, cellSize, cellSize ); } } } } /* Gray-Scott model -------------------- */ public class Cell { private float difU = 0.001; private float difV = 0.000238; private float dt = 1.0; private float dxPow = pow(0.085, 2); private float feed = 0.0; private float kill = 0.0; private float valU; private float valV; private float lapU; private float lapV; private Cell[] neighbor; Cell() { valU = 0.0; valV = 0.0; resetLaplacian(); } private void resetLaplacian() { lapU = 0.0; lapV = 0.0; } public void setFeed(float init) { feed = init; } public void setKill(float init) { kill = init; } public void setV(float init) { valV = init; } public void setU(float init) { valU = init; } public void setNeighbor(Cell[] pNeighbor) { neighbor = new Cell[pNeighbor.length]; for (int i = 0; i < pNeighbor.length; ++i) { neighbor[i] = pNeighbor[i]; } } public float getRawU() { return valU; } public float getRawV() { return valV; } public float getStandardU() { return constrain(valU, 0.0, 1.0); } public float getStandardV() { return constrain(valV, 0.0, 1.0); } public void laplacian() { float sumU = 0.0; float sumV = 0.0; for (int i = 0; i < neighbor.length; ++i) { sumU += neighbor[i].getRawU(); sumV += neighbor[i].getRawV(); } lapU = (sumU - valU * neighbor.length) / dxPow; lapV = (sumV - valV * neighbor.length) / dxPow; } public void react() { float reaction = valU * valV * valV; float inflow = feed * (1.0 - valU); float outflow = (feed + kill) * valV; valU += dt * (difU * lapU - reaction + inflow); valV += dt * (difV * lapV + reaction - outflow); resetLaplacian(); } } /* Copyright (C) 2018- deconbatch This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/> */