xxxxxxxxxx
288
// require https://cdn.jsdelivr.net/npm/tweakpane@3.0.7/dist/tweakpane.min.js
// require https://cdn.jsdelivr.net/npm/p5@latest/lib/p5.min.js
const pane = new Tweakpane.Pane();
const SHOULD_SAVE = true;
// constants
const FR = SHOULD_SAVE ? 10 : 30;
const CANVAS_WIDTH = 960;
const CANVAS_HEIGHT = 540;
const START_X = CANVAS_WIDTH * 1.2; // * 0.75;
let xPos = 0;
const PARAMS = {
bgColor: "#FFF",
lineColor: "#FF7878",
endColor: "#A3E000",
// shape
diameter: CANVAS_WIDTH/3,
margin: 10,
angle: 30,
circlePoints: 60,
strokeWeight: 0.4,
curveVertex: true,
// anim
speed: 0.3,
seed: 315,
moveSpeed: 2,
barrierStart: 0.3,
barrierEnd: 0.7,
// diam noise
useDiameterNoise: true,
dNoiseAmplitude: 1.5,
dNoiseFrequency: 0.004,
// shape noise
useShapeNoise: true,
sNoiseAmplitude: 0.4,
sNoiseFrequency: 0.08,
// main
isDebug: false,
};
// global variables that are needed
let cutCount = 0;
let sphere_counter = 0;
let cnv = null;
function setup() {
cnv = createCanvas(CANVAS_WIDTH, CANVAS_HEIGHT);
noFill();
frameRate(FR)
pane.addInput(PARAMS,"isDebug");
// add parameters
const f1 = pane.addFolder({
title: 'Base Shape',
expanded: false,
});
f1.addInput(PARAMS, "bgColor", {
view: 'color',
});
f1.addInput(PARAMS, "lineColor", {
view: 'color',
});
f1.addInput(PARAMS, "diameter", {
min: 0,
max: CANVAS_WIDTH,
});
f1.addInput(PARAMS, "margin", {
min: 2,
max: 100,
});
f1.addInput(PARAMS, "angle", {
min: 0,
max: 45,
});
f1.addInput(PARAMS, "circlePoints", {
step: 1,
min: 0,
max: 100,
});
f1.addInput(PARAMS, "strokeWeight", {
min: 0,
max: 2,
});
f1.addInput(PARAMS, "curveVertex");
const f2 = pane.addFolder({
title: 'Animation',
expanded: false,
});
f2.addInput(PARAMS, "speed", {
min: 0,
max: 3,
});
f2.addInput(PARAMS, "seed", {
step: 1,
min: 0,
max: 999,
});
f2.addInput(PARAMS, "moveSpeed", {
min: 0,
max: 10,
});
const f5 = pane.addFolder({
title: 'Environment',
expanded: false,
});
f5.addInput(PARAMS, "barrierStart", {
min: 0,
max: 1,
});
f5.addInput(PARAMS, "barrierEnd", {
min: 0,
max: 1,
});
const f3 = pane.addFolder({
title: 'Diameter Noise',
expanded: false,
});
f3.addInput(PARAMS, "useDiameterNoise");
f3.addInput(PARAMS, "dNoiseAmplitude", {
min: 0,
max: 10,
});
f3.addInput(PARAMS, "dNoiseFrequency", {
step: 0.001,
min: 0,
max: 0.05,
});
const f4 = pane.addFolder({
title: 'Shape Noise',
expanded: false,
});
f4.addInput(PARAMS, "useShapeNoise");
f4.addInput(PARAMS, "sNoiseAmplitude", {
min: 0,
max: 1,
});
f4.addInput(PARAMS, "sNoiseFrequency", {
step: 0.001,
min: 0,
max: 0.1,
});
adjustValues();
pane.on("change", adjustValues);
}
function adjustValues () {
cutCount = int(PARAMS.diameter / PARAMS.margin);
strokeWeight(PARAMS.strokeWeight);
noiseSeed(PARAMS.seed);
}
function draw() {
background(PARAMS.bgColor);
drawBG();
push();
const colorStart = color(PARAMS.lineColor);
const colorEnd = color(PARAMS.endColor);
xPos -= PARAMS.moveSpeed
if( xPos + START_X + PARAMS.diameter <= 0 ){
SHOULD_SAVE && noLoop();
xPos = width - START_X + PARAMS.diameter;
}
const tX = sphere_counter * PARAMS.speed;
const p_now = tX / PARAMS.margin;
if( tX > PARAMS.margin ){
sphere_counter = 0;
}
translate( xPos, 0 )
translate(START_X - PARAMS.diameter/2 - PARAMS.margin/2,height/2);
for (let i = 0; i < cutCount; i++){
const p = lerp( i/cutCount, (i+1)/cutCount, p_now);
const sliceCut = lerp(0, PARAMS.diameter, p);
const radius = sqrt( PARAMS.diameter * sliceCut - pow(sliceCut,2) );
const h = radius * 2;
const d = radius * 2 * cos(radians(90-PARAMS.angle));
translate( PARAMS.margin, 0 );
const dn = PARAMS.useDiameterNoise ? noise( PARAMS.dNoiseFrequency * frameCount, p ) * PARAMS.dNoiseAmplitude : 1;
const sliceXVal = PARAMS.margin * i + START_X + xPos - d*2;
const lerpPoint = map(sliceXVal, width*PARAMS.barrierEnd, width*PARAMS.barrierStart, 0, 1, true);
const ringColor = lerpColor( colorStart, colorEnd, lerpPoint );
stroke(ringColor);
const tCirclePoints = floor( lerp( 7,PARAMS.circlePoints,1-lerpPoint ) )
// draw circle
beginShape();
for( let c = 0; c <= tCirclePoints; c++ ){
let x = sin( c/tCirclePoints * TWO_PI ) * d/2 * dn;
let y = cos( c/tCirclePoints * TWO_PI ) * h/2 * dn;
if( PARAMS.useShapeNoise ){
const n2 = sin( p * PI ) * PARAMS.sNoiseAmplitude * ( noise( frameCount * 0.01, PARAMS.sNoiseFrequency * c ) - 0.5 );
x += n2 * d;
y += n2 * h;
}
x += tX;
/*
if( PARAMS.curveVertex ){
curveVertex( x, y );
}else{
vertex( x, y );
}
*/
if( lerpPoint < 0.3 ){
curveVertex( x, y );
}else{
vertex( x, y );
}
}
endShape(CLOSE);
}
sphere_counter++;
pop();
if( PARAMS.isDebug ){
push();
stroke("blue")
line( width*PARAMS.barrierStart, 0,width*PARAMS.barrierStart, height );
line( width*PARAMS.barrierEnd, 0,width*PARAMS.barrierEnd, height );
pop();
}
if( SHOULD_SAVE ){
let count = ( "000" + frameCount).slice(-4);
save(cnv, `Scene_02-${count}.jpg`);
}
}
const drawBG = () => {
push();
stroke( PARAMS.lineColor );
for( let i = 0; i < ( width / PARAMS.margin ); i++ ){
translate( PARAMS.margin, 0 );
line( 0,0,0,height );
}
pop();
// draw object
push();
noStroke();
fill( "#FFF6" );
rect( 0,0, width * PARAMS.barrierStart, height );
stroke("#6666")
line( width * PARAMS.barrierStart,0,width * PARAMS.barrierStart,height )
pop();
}