Orginal source code here.
HTML Code:
//- Press and hold to explode layers
script.
window.canvasOptions = {
autoClear: true,
autoCompensate: false,
autoPushPop: true,
canvas: true,
centered: true,
desynchronized: false,
width: null,
height: null
};
CSS Code:
body {
cursor: pointer;
}
Java Script Code:
const points = [];
const outer = 150;
const inner = 120;
let sep = 0;
function setup() {
// https://www.cmu.edu/biolphys/deserno/pdf/sphere_equi.pdf
const N = 3800;
const r = 4;
const a = 4 * PI * r ** 2 / N;
const d = sqrt(a);
const MTheta = round(PI / d);
const dTheta = PI / MTheta;
const dPhi = a / dTheta;
let i = 0;
for(let m = 0; m < MTheta; m++) {
const theta = PI * (m + 0.5) / MTheta;
const MPhi = round(2 * PI * sin(theta) / dPhi);
for(let n = 0; n < MPhi; n++) {
const phi = 2 * PI * n / MPhi;
const point = new Vector(
sin(theta) * cos(phi),
sin(theta) * sin(phi),
cos(theta)
).mult(outer);
point.i = i++;
points.push(point);
}
}
}
function draw(e) {
// const timeDiff = e - _lastCanvasTime;
// const timeAdjust = map(timeDiff, 0, 1000 / 60, 0, 1);
const time = e * 0.001;
rotate(time * 0.1);
if(mouseDown) {
sep = lerp(sep, inner, 0.05);
}
else {
sep = lerp(sep, 0, 0.12);
}
lineCap('round');
const COLOR = hsl(0, 100, 50);
// const zx = 0.0125 * timeAdjust;
// const xy = 0.005 * timeAdjust;
// const yz = sin(time * 0.5) * 0.01 * timeAdjust;
// for(const p of points) {
// p.rotateZX(zx).rotateXY(xy).rotateYZ(yz);
const c = sin(time * 0.5) * 0.01;
for(const p of points) {
p.rotateZX(0.0125).rotateXY(0.005).rotateYZ(c);
//// p.rotateYZ(p.i / points.length * PI * 0.01);
// const [ _, __, ___ ] = [
// p.y / outer * PI * 0.01,
// p.z / outer * PI * 0.02,
// p.x / outer * PI * 0.03
// ];
// p.rotateZX(_).rotateXY(__).rotateYZ(___);
p.setMag3D(
map(
sin(time * 5 + p.i / points.length * TAU * 12),
-1, 1, inner, outer
)
);
}
points.sort((a, b) => b.z - a.z);
const pointRad = p => map(p.z, 100, -100, 3, 7);
const innerPoints = [];
const innerTest = Math.cos(Math.PI * 0.25) * inner - 7;
let i = 0;
push();
translate(-sep, -sep);
beginPath();
for(; i < points.length; i++) {
const p = toCamera(points[i]);
if(p.z < 0) {
break;
}
if(
abs(p.x) < innerTest &&
abs(p.y) < innerTest
) {
continue;
}
innerPoints.push(p);
circle(p, pointRad(p));
}
fill(COLOR);
translate(0, sep * 2);
beginPath();
for(const p of innerPoints) {
line(p);
}
stroke(COLOR, 2);
innerPoints.splice(0);
translate(sep, -sep);
beginPath();
circle(0, 0, inner);
fill(hsl(0, 0, 100));
translate(sep, -sep);
beginPath();
for(; i < points.length; i++) {
const p = toCamera(points[i]);
// const p2 = toCamera(points[i]._.div(outer).mult(inner));
const p2 = toCamera(points[i]._.limit3D(inner));
innerPoints.push([ p, p2 ]);
circle(p, pointRad(p));
line(p, p2);
}
fill(COLOR);
translate(0, sep * 2);
beginPath();
for(const [ p1, p2 ] of innerPoints) {
line(p1, p2);
}
stroke(COLOR, 3);
pop();
// fillStyle(COLOR_WHITE);
globalAlpha(ease.expo.in(sep / 100));
textAlign(TEXTALIGN_CENTER);
font('24px sans-serif');
const labels = [ 1, 4, 5, 2 ];
for(let i = 0; i < 5; i++) {
if(i !== 4) {
push();
rotate(-QUARTER_PI + HALF_PI * i);
fillText(labels[i], 0, -sep / inner * 100 - inner * 2);
pop();
}
else {
fillStyle(COLOR_BLACK);
fillText(3, 0, 0);
}
}
}
function toCamera(_v) {
const v = _v.copy();
const z = (v.z + 1000) * 0.001;
v.x /= z;
v.y /= z;
return v;
}
/* requestAnimationFrame */
0 Comments:
Post a Comment