Finding the 'Cat formula' during my pursuit of creative coding truth
How I discovered the 'Cat formula' in this creative coding.
It's a creative coding animation work made with the 'Processing'.
I found a 'Cat formula' when I was palying with the idea of @ozachou_g.
How to Build Discrete Universe
https://how-to-build-du-e.tumblr.com/
A cat formula.
X1 = (pow(sin(X0), 3) + cos(Y0)) * sin(T0);
Y1 = (cos(X0) + pow(sin(Y0), 3)) * cos(T0);
T1 = T0 + timeDiv
And I made an animation with this morphing (lerping) method.
A, B : morph from A shape to B shape
morph : from 1.0 to 0.0
shape = A * morph + B * (1 - morph)
The 'Processing' code example.
Please feel free to use this code under the terms of the GPL.
To see other works based on my code is my pleasure. And my honor.
// Morph the Cat.
// @author @deconbatch
// @version 0.1
// Processing 3.2.1
// 2018.11.11
void setup() {
size(720, 720);
colorMode(HSB, 360, 100, 100, 100);
blendMode(SUBTRACT);
smooth();
noLoop();
noStroke();
}
void draw() {
int frameCntMax = 15 * 6; // 15fps x 6s
int recurseCntMax = 2500;
float divRotate = random(0.01, 0.02) * rndSign();
float baseHue = random(360);
// cat shape
int phaseCntMax = 500; // must for cat! > 500
float phaseDiv = 1.0 / phaseCntMax;
float phaseDivInit = PI * 0.75 - phaseDiv * phaseCntMax;
// some shape
float paramSomX = random(0.1, 1.0);
float paramSomY = random(0.1, 1.0) * rndSign();
float paramSomT = random(0.5, 1.5);
translate(width / 2, height / 2);
rotate(PI * (0.25 - 0.49 * frameCntMax * divRotate)); // for upright cat
for (int frameCnt = 1; frameCnt <= frameCntMax; ++frameCnt) {
float easing = easeInOutCubic(map(frameCnt, 0, frameCntMax, 1.0, 0.0)); // animate factor
float timeDiv = phaseDivInit;
background((baseHue + 150) % 360, 5, 90, 100);
rotate(PI * divRotate * easing);
for (int phaseCnt = 0; phaseCnt < phaseCntMax; ++phaseCnt) {
float phaseRate = map(phaseCnt, 0, phaseCntMax, 0.0, 1.0);
timeDiv += PI * phaseDiv;
float prevCatX = 0.0;
float prevCatY = 0.0;
float prevCatT = 0.0;
float prevSomT = 0.0;
for (int recurseCnt = 0; recurseCnt < recurseCntMax; ++recurseCnt) {
// cat formula
float catX = (pow(sin(prevCatX), 3) + cos(prevCatY)) * sin(prevCatT);
float catY = (cos(prevCatX) + pow(sin(prevCatY), 3)) * cos(prevCatT);
// some shape formula
float somX = (sin(prevCatX) * paramSomX - cos(prevCatY) * paramSomY) + cos(prevSomT);
float somY = (cos(prevCatX) * paramSomX - sin(prevCatY) * paramSomY) + sin(prevSomT);
float x = catX * (1.0 - easing) + somX * easing;
float y = catY * (1.0 - easing) + somY * easing;
float catT = prevCatT + timeDiv;
float somT = prevSomT - (x + y) * paramSomT;
float eX = x * width * (0.35 + easing * 0.0);
float eY = y * height * (0.35 + easing * 0.0);
float eS = phaseRate;
fill(
(baseHue + phaseRate * 60.0) % 360,
40,
(1.0 - phaseRate) * 30.0,
100
);
ellipse(
eX,
eY,
eS,
eS
);
prevCatX = catX;
prevCatY = catY;
prevCatT = catT;
prevSomT = somT;
}
}
saveFrame("frames/" + String.format("%02d", frameCnt) + "00.png");
}
// for showing cat shape longer
for (int i = 0; i < 5; ++i) {
saveFrame("frames/99" + String.format("%02d", i) + ".png");
}
saveFrame("frames/0000.png"); // for Twitter thumbnail
exit();
}
/**
* easeInOutCubic easing function.
* @param t 0.0 - 1.0 : linear value.
* @return float 0.0 - 1.0 : eased value.
*/
private 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;
}
/**
* rndSign random sign maker.
* @return int +1 or -1 : random
*/
private int rndSign() {
int rndVal = ceil(random(-10, 10));
if (rndVal == 0) {
return -1;
} else {
return rndVal / abs(rndVal);
}
}
/*
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 "https://www.gnu.org/licences/"
*/
On-going status of morphing.



