xxxxxxxxxx
265
// important fixes & improvements:
// desired length is now a property of nodes, not of connections so they cant be vaiable
// sources for next steps:
// - merel boers!!
// - willy morry <3
let stitchdist = 5; // this is kinda dumb and easy to fix but im lazy so stitch distance gets multiplied with scale so if u want an actual stitch distance of 2mm on scale 4 u need to set stitchdist to 5
let embroideryScale = 4;
let stems = [];
let leaves = [];
let flowers = [];
let pullstepdiv = 0.5; //how much to divide the steps taken each frame
let maxLeafSize = 20;
let growthFalloff = 0.50;
let branchingFalloff = 0.05;
let rootChance = 0.1;
let leafCount = 7;
let upDraft = -1;
let stemLength = 20;
let horSpread = 10;
// saving/downloading stuff:
let coords = [];
let paused = false;
class Stem {
constructor(x, y, links, growChance, branchDir, isRoot=false){
this.pos = createVector(x,y);
this.links = links;
this.id = stems.length;
this.growChance = growChance;
this.branchDir = branchDir;
this.isRoot = isRoot;
this.restLength = stemLength;
this.externalPull = createVector(0,0);
this.flowers = [];
this.leaves = [];
for(let i=0; i<this.links.length; i++){
stems[this.links[i]].links.push(this.id);
}
}
drawLinks(){
for(let i=0;i<this.links.length;i++){
line(this.pos.x, this.pos.y, stems[this.links[i]].pos.x, stems[this.links[i]].pos.y);
}
}
pushPull(){
let move = createVector(0,0);
let linkcount = this.links.length + 1;
if(this.isRoot){
return;
}
for(let i=0;i<this.links.length;i++){
let p = createVector( stems[this.links[i]].pos.x, stems[this.links[i]].pos.y );
move.add( p5.Vector.mult(
p5.Vector.sub(this.pos, p), // the vector towards the linked node
(this.restLength / p5.Vector.dist(this.pos, p)) - 1.0 ) // how close the current lengh is to the rest length
);
}
move.div(linkcount*pullstepdiv)
this.pos.add(move);
this.pos.add(this.branchDir);
}
grow(){
// split this up into different chances for stem leaf and flower
// grow stem?
if(random() < this.growChance * branchingFalloff**(this.links.length-1)) {
stems.push(new Stem(
this.pos.x,
this.pos.y,
[this.id],
growthFalloff * this.growChance,
createVector( (random() - 0.5) * (this.links.length - 0.9) * horSpread, -1.0 ).setMag(0.5)
));
}
//or leaf
else if (false){
}
//or flower
else if (false){
}
}
}
class Leaf {
constructor(stemId, angle, leafSize){
}
getSun(){
// figure out how much sun falls on the leaf and grow or shrink accordingly
// also change angle and put a pull on the connected stem to reach more light
return;
}
}
class Flower {
constructor(stemId, flowertype, angle, leafSize){
}
getPull(){
// move somewhere for some reason. lol.
// i think this is where i want all the weird shit to happen based on different flower types etc
}
}
class Root extends Stem {
constructor(x,y,links){
super(x,y,links);
}
}
function setup() {
createCanvas(500, 500);
//saving stuff
createButton('pause/play').mousePressed(() => {paused = !paused }).position(20,height + 20);
createButton('download csv').mousePressed(saveCSV).position(120,height + 20);
stems.push(new Stem(
width/2,
height-10,
[],
rootChance,
createVector(0,0.1),
true));
}
function draw() {
if(paused){
return
}
background(255);
// stems[0].pos = createVector(mouseX,mouseY);
for(let i=0;i<stems.length;i++){
stems[i].grow();
}
for(let i=1;i<stems.length;i++){
stems[i].pushPull();
}
for(let i=0;i<stems.length;i++){
point(stems[i].pos.x,stems[i].pos.y);
stems[i].drawLinks();
}
text('nodes: ' + stems.length, 10, 25);
text('draw time: ' + int(deltaTime) + ' ms', 10, 35)
line(20,height-10,width-20,height-10)
}
//------------------------------------------------//
//----------EXPORTING FUNCTIONS-------------------//
//------------------------------------------------//
function getEmbroidery(startId) {
pushStitch(startId);
if(stems[stems[startId].links[1]] instanceof Leaf){
for(let i=1;i<stems[startId].links.length-1; i++){
pushStitch(stems[startId].links[i])
pushStitch(stems[startId].links[i+1])
pushStitch(startId);
}
return
}
for(let i=0; i<stems[startId].links.length; i++){
if(!stems[startId].isRoot && i==0){
continue
}
if(stems[stems[startId].links[i]] instanceof Stem){
getEmbroidery(stems[startId].links[i]);
}
pushStitch(startId);
}
}
function pushStitch(index){
let jump = p5.Vector.sub(stems[index].pos, coords[coords.length-1]);
if(jump.mag() < 1){ return }
let tc = []
for(let i=stitchdist; i < jump.mag(); i+=stitchdist){
tc.push(
p5.Vector.add(coords[coords.length-1],
p5.Vector.mult(jump, i/jump.mag())
)
);
}
coords.push(tc, stems[index].pos);
}
function saveCSV(){
coords = [];
for(let i=0;i<stems.length;i++){
if(stems[i].isRoot){
coords.push(stems[i].pos);
getEmbroidery(i);
}
}
let table = new p5.Table();
table.addColumn('x');
table.addColumn('y');
for(let i=20; i<(width-20); i+= stitchdist){
let newRow = table.addRow();
newRow.setNum('x', round(i * embroideryScale));
newRow.setNum('y', round((height-10) * embroideryScale) );
}
for(let i=0;i<coords.length;i++){
let newRow = table.addRow();
newRow.setNum('x', round(coords[i].x * embroideryScale));
newRow.setNum('y', round(coords[i].y * embroideryScale));
}
saveTable(table,'fg1-2.csv')
}