The Gray Scott model eye is gently watching over you.
Gray Scott model in 3D!
It's a creative coding artwork with the reaction-diffusion.
The 3D modeling eyeball is watching you!
Why are you in fear and trembling?
It has been watching over you with a warm heart. ;)
This uneven surface is made with a Gray Scott model. It'll take a long time to draw.
The 'Processing' example code.
This code does not display any images on the screen but generates image files in frames directory. You can make an animation with these files.
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.
// Every Breath You Take. // @author @deconbatch // @version 0.1 // Processing 3.2.1 // 2018.10.06 void setup() { size(720, 720, P3D); colorMode(HSB, 360, 100, 100, 100); smooth(8); sphereDetail(30); noLoop(); noStroke(); } void draw() { int frameCntMax = 15 * 6; float hueBase = random(360.0); Ecosystem eco = new Ecosystem(frameCntMax, hueBase); translate(0.0, 0.0, 0.0); ambientLight(0.0, 0.0, 15.0); lightFalloff(1.0, 0.001, 0.0); pointLight(0.0, 0.0, 100.0, 100.0, 100.0, 500.0); for (int frameCnt = 0; frameCnt < frameCntMax; ++frameCnt) { float frameIdx = map(frameCnt, 0, frameCntMax, 6.0, -6.0); float sigmoid = ((1.0 / (1.0 + exp(frameIdx)))); camera(map(sin(TWO_PI * sigmoid), 0.0, 1.0, 0.0, 200.0), map(sin(PI * sigmoid), 0.0, 1.0, 0.0, -300.0), 1600, 0, 0, 0, 1, 0, 0); blendMode(BLEND); background(0.0, 0.0, 0.0, 100.0); backdrop(hueBase); eco.setTime(frameCnt); eco.initSchale(); eco.plant(); eco.culture(); eco.observe(); blendMode(SCREEN); pupil(hueBase, sigmoid); saveFrame("frames/" + String.format("%04d", frameCnt) + ".png"); } exit(); } private void backdrop(float hueBase) { pushMatrix(); rotateZ(radians(15)); translate(0, 0, -800); for (int i = 0; i < 20; ++i) { fill( hueBase, 60, map(i, 0, 20, 40.0, 0.0), 100 ); rect( -2500.0, map(i, 0, 20, -1800.0, 2500.0), 5000.0, 500.0 ); } popMatrix(); } private void pupil(float hueBase, float sigmoid) { pushMatrix(); translate(0.0, 0.0, 500.0); for (float i = 0.0; i < 100.0; i += 10.0) { translate(-3.0, 0.0, 0.0); fill( (hueBase + i * 0.6) % 360.0, 40.0, map(i, 0.0, 100.0, 20.0, 0.0), 100.0 ); sphere((10.0 + i * 2.0) * pow((sigmoid - 0.5) * 2.0, 4)); } popMatrix(); } /* -------------------- */ 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; private int cultureTimeMax; Ecosystem(int frameCntMax, float hueBase) { this.frameCntMax = frameCntMax; this.hueBase = hueBase; frameCnt = 0; cultureTimeMax = 0; cellSize = 8.0; canvasW = floor(width * 2.0 / cellSize); canvasH = floor(height * 2.0 / 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] = random(0.5, 1.0); initVs[1][x][y] = random(0.0, 0.5); 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 frameIdx = map(frameCnt, 0, frameCntMax, 0.0, -6.0); float sigmoid = ((1.0 / (1.0 + exp(frameIdx)))); float easeRate = sin(PI * sigmoid); for (int x = 0; x < canvasW; x++) { for (int y = 0; y < canvasH; y++) { cells[x][y].setFeed(map(noise(x * 0.1 + easeRate * 0.08, y * 0.2 - easeRate * 0.08), 0.0, 1.0, 0.05, 0.10 )); cells[x][y].setKill(map(noise(x * 0.2 - easeRate * 0.08, y * 0.1 + easeRate * 0.08), 0.0, 1.0, 0.056, 0.0665 )); } } cultureTimeMax = floor( 40 + 1500 * pow( 1.0 - abs(cos(PI * map(frameCnt, 0, frameCntMax, 0.0, 1.0))), 2) ); } public void culture() { 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() { DrawCell drawCellU = new DrawCellU(); DrawCell drawCellV = new DrawCellV(); float radiusEllipse = 700.0; float frameIdx = sin(PI * map(frameCnt, 0, frameCntMax, 0.0, 1.0)); float idoStart = max(0.25, frameIdx); float divIdo = 0.8; // outer skin for (float ido = 32 - idoStart * 8.0; ido <= 140; ido += divIdo) { // Y biotissue( radiusEllipse - frameIdx * cellSize, ido, divIdo, drawCellU ); } // inner skin for (float ido = 10 + idoStart * 18.0; ido <= 120; ido += divIdo) { // Y biotissue( radiusEllipse + frameIdx * cellSize, ido, divIdo, drawCellV ); } } private void biotissue(float radiusEllipse, float ido, float divIdo, DrawCell drawCell) { float radianIdo = radians(ido); float divKdo = 180 / max(160 / divIdo * sin(radianIdo), 1.0); for (float kdo = 0; kdo < 360; kdo += divKdo) { // Z float radianKdo = radians(kdo); float locateX = radiusEllipse * cos(radianKdo) * sin(radianIdo); float locateY = radiusEllipse * sin(radianKdo) * sin(radianIdo); float locateZ = radiusEllipse * cos(radianIdo); pushMatrix(); translate(locateX, locateY, locateZ); rotateZ(radianKdo); // must be this order Z -> Y rotateY(radianIdo); // not real 3D but 3D sphere -> 2D flat square mapping int cellX = floor((radiusEllipse + locateX) / cellSize); int cellY = floor((radiusEllipse + locateY) / cellSize); drawCell.withSphere(hueBase, cells[cellX][cellY]); popMatrix(); } } // to use polymorphism in drawing cells private abstract class DrawCell { abstract void withSphere(float hueBase, Cell cells); } private class DrawCellU extends DrawCell { DrawCellU() { super(); } public void withSphere(float hueBase, Cell cells) { float sizeU = (cells.getStandardU() * 10.0) * cellSize; float hueApply = (30.0 + hueBase + cells.getStandardU() * 60.0) % 360.0; fill( hueApply, 20.0, 100.0, 100.0 ); sphere(sizeU); } } private class DrawCellV extends DrawCell { DrawCellV() { super(); } public void withSphere(float hueBase, Cell cells) { float sizeV = (cells.getStandardV() * 6.0) * cellSize; float hueApply = (hueBase + cells.getStandardV() * 60.0) % 360.0; fill( hueApply, 30.0, 70.0, 100.0 ); sphere(sizeV); } } } /* 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/> */
Yet another example images.
This is scary and you should post this on LiveLeak, but it is down now. So you have to go for some LiveLeak-like sites. Anyway, here I found a post for help: 11 Best LiveLeak Alternatives