xxxxxxxxxx
204
// running on a 1000x1000 canvas = 10x10cm thing
let stDist = 4;
let embroideryScale = 3;
let forceSeed = 0; // set 0 to not force the seed
let seed = 0;
let noiseamp = 10;
let steps = 4230;
let noiseres = 0.008;
let trunkWidth = 40;
let offset;
let noiseTime = 0;
let paused = false;
let sprCoords;
let xStep = trunkWidth/steps;
let linemode = true;
function setup() {
createCanvas(500, 500);
pixelDensity(2)
background(220);
offset = {x:width/2 - trunkWidth/2,y:height/2}
createButton('new noise texture').mousePressed(() => {if(forceSeed!=0){seed = forceSeed} else{ seed = round(random()*10000)} print(seed); noiseSeed(seed) }).position(10,height + 60);
createButton('lines/points').mousePressed(() => {linemode = !linemode }).position(135,height + 60);
createButton('pause/play').mousePressed(() => {paused = !paused }).position(250,height + 60);
createButton('download csv').mousePressed(saveCSV).position(350,height + 60);
slider = createSlider(0, 0.1,0.02,0.001);
slider.position(10, height + 10);
slider.size(380);
slider2 = createSlider(0, 100,17);
slider2.position(10, height + 30);
slider2.size(380);
}
function showField(){
// so here we wanna make it generate intereseting fields that are actually kinda tree like.
// visualize field:
for(let x=10;x<width;x+=15){
for(let y=10;y<height;y+=15){
let dir = sampleField(x,y,'noise')
line(x,y,x+dir.x,y+dir.y);
}
}
}
function sampleField(x,y,fieldtype){
//perlin normal
if(fieldtype=='noise'){
return {
x: (noise(x*noiseres, y*noiseres,noiseTime*0.0003) -0.5) * noiseamp,
y: (noise(x*noiseres+100, y*noiseres,noiseTime*0.0003) -0.5) * noiseamp
}
}
//fractional brownian motion perlin noise (put oct count at end of string)
if(fieldtype.substring(0, 3)=='fbm'){
let value = {x:0,y:0}
for(let i=1;i<int(fieldtype[3])+1;i++){
value = {
x: value.x + (1/(1+i))* (noise(x*noiseres*i, y*noiseres*i,noiseTime*0.0003) - 0.5) * noiseamp,
y: value.y + (1/(1+i))* (noise(x*noiseres*i+100, y*noiseres*i,noiseTime*0.0003) - 0.5) * noiseamp
}
}
return value
}
//image texture (placeholder)
if(fieldtype=='img'){
return {
x: 0,
y: 0
}
}
}
function growIt(){
let coords = [{x:offset.x, y:offset.y}];
let tadjust = 0;
beginShape();
vertex(coords[0].x,coords[0].y)
for(let t=1;t<steps;t++){
let period = 0.02
let fieldtype = 'fbm8';
let fieldval;
if(t%((2/period)*PI) > (1/period)*PI){
fieldtype = 'noise';
}
if(t%((1/period)*PI)>(0.5/period)*PI && tadjust < t-1){
tadjust += 2
fieldval = sampleField(coords[t-tadjust].x, coords[t-tadjust].y, fieldtype);
fieldval = {x:-1*fieldval.x, y:-1*fieldval.y};
}
else{
tadjust = 0;
fieldval = sampleField(coords[t-1].x, coords[t-1].y, fieldtype);
}
coords.push({
x: coords[t-1].x + xStep + (0.8*abs(sin(period* t))**2 + 0.2) * fieldval.x,
y: coords[t-1].y + 3 * cos(period* t) + (0.8*abs(sin(period* t))**2 + 0.2) * fieldval.y
})
}
//spread stitches
sprCoords = [{x:round(coords[0].x*2), y:round(coords[0].y*2)}];
let a=0
for(let t=1;t<steps;t++){
//calculate distance w pythagoras bc im a dumb idiot
let aDist = sqrt((coords[t].x-coords[a].x)**2 + (coords[t].y-coords[a].y)**2);
if(aDist>stDist){
sprCoords.push({x:round(coords[t].x*embroideryScale), y:round(coords[t].y*embroideryScale)});
a=t;
if(linemode){
vertex( sprCoords[sprCoords.length-1].x/embroideryScale, sprCoords[sprCoords.length-1].y/embroideryScale );
} else {
point( sprCoords[sprCoords.length-1].x/embroideryScale, sprCoords[sprCoords.length-1].y/embroideryScale );
}
}
}
endShape()
line(width/2-100,height/2,width/2+100,height/2);
}
function draw(){
if(!paused){
noiseTime += deltaTime;
}
background(255)
noiseamp = slider2.value();
noiseres = slider.value();
growIt();
// showField();
// noLoop();
}
function saveCSV(){
let table = new p5.Table();
table.addColumn('x');
table.addColumn('y');
for(let i=0;i<100*embroideryScale-trunkWidth/embroideryScale;i+=25*embroideryScale){
let newRow = table.addRow();
newRow.setNum('x', round(i));
newRow.setNum('y', 0);
}
for(let i=0;i<sprCoords.length;i++){
let newRow = table.addRow();
newRow.setNum('x', sprCoords[i].x - round(150*embroideryScale));
newRow.setNum('y', sprCoords[i].y - round(250*embroideryScale));
}
for(let i=0;i<100*embroideryScale-trunkWidth/embroideryScale;i+=25*embroideryScale){
let newRow = table.addRow();
newRow.setNum('x', round(200+trunkWidth/embroideryScale+i));
newRow.setNum('y', 0);
}
saveTable(table,'sintree.csv')
}