xxxxxxxxxx
404
// made by owloats :D
let maxdist = 25;
let defaultA = new p5.Vector(0, 200, 0);
let Iters = 3;
let doVerlet = true;
let sim = false;
const TSPEED = 0.001;
const BorderPin = true;
let PPoint = function()
{
this.pos = createVector(0, 0, 0);
this.prevPos = createVector(0, 0, 0);
this.k = createVector(0, 0, 0);
this.lerpT = 0.01;
this.pinPos = null;
this.verlet = function(dt)
{
this.prevPos = p5.Vector.lerp(this.prevPos, this.pos, this.lerpT);
let temp = this.pos;
this.pos = p5.Vector.add(this.pos, p5.Vector.add(p5.Vector.sub(this.pos, this.prevPos), p5.Vector.mult(this.k, dt * dt)));
this.prevPos = temp;
this.k.set(0, 0, 0);
};
};
let PLineAdder = function()
{
this.lastPoint = null;
this.detectDist = 1;
this.input = function(InVec)
{
if (this.lastPoint === null)
{
this.lastPoint = createVector();
this.lastPoint.set(InVec);
return true;
}
if ((distSq(InVec, this.lastPoint) > (this.detectDist*this.detectDist)))
{
this.lastPoint.set(InVec);
return true;
}
return false;
};
this.clear = function()
{
lastPoint = null;
};
}
let PConstraint = function()
{
this.i0 = 0;
this.i1 = 0;
this.dist = 0;
this.bias = 0.5;
this.bakeDist = function(x1, x2)
{
this.dist = p5.Vector.dist(x1, x2);
};
this.enforce = function(x1, x2)
{
let delta = p5.Vector.sub(x2, x1);
let deltaLen = sqrt(p5.Vector.dot(delta, delta));
if (deltaLen <= 0)
return;
let diff = (deltaLen - this.dist) / deltaLen;
x1.add(p5.Vector.mult(delta, (this.bias) * diff));
x2.sub(p5.Vector.mult(delta, (1.0-this.bias) * diff));
};
};
let Constraints = [];
let Points = [];
let Constraints_B = [];
let Points_B = [];
let pwindowWidth = 0;
let pwindowHeight = 0;
let Mouse = null;
let TrueMouse = null;
let lineAdder = null;
let IdxlastGrabbedPoint = -1;
let MouseConstraint = null;
//let EraseButton = null;
const Border = 20;
let SimBlend = 0;
function SetButtonPos()
{
//EraseButton.position(0, 0);
}
function distSq(a, b)
{
return sq(a.x - b.x) + sq(a.y - b.y);// + sq(a.z - b.z);
}
function TryResizeCanvas()
{
if (pwindowWidth != windowWidth || pwindowHeight != windowHeight)
{
resizeCanvas(windowWidth, windowHeight);
pwindowWidth = windowWidth;
pwindowHeight = windowHeight;
SetButtonPos();
}
}
function makeConstraint(a, b)
{
let c = new PConstraint();
c.i0 = a;
c.i1 = b;
c.bakeDist(Points[a].pos, Points[b].pos);
Constraints.push(c);
}
function FindClosestPoint(P, IgnoreIndex = -1)
{
let bdist = Number.MAX_VALUE;
let index = -1;
for (let i = 0; i < Points.length; i++)
{
if (i === IgnoreIndex) continue;
const d = distSq(Points[i].pos, P);
if (d < bdist)
{
bdist = d;
index = i;
}
}
return index;
}
function InBorder(In)
{
const xD = abs(In.x - (width / 2));
const yD = abs(In.y - (height / 2));
return xD >= ((width - Border*2) / 2) || yD >= ((height - Border*2) / 2);
}
function addPoint(In)
{
let p = new PPoint();
p.pos.set(In);
p.prevPos.set(In);
Points.push(p);
if (BorderPin && InBorder(In))
{
p.pinPos = createVector(In.x, In.y);
}
if (Points.length === 1)
return;
for (let i = 0; i < Points.length - 1; i++)
{
if ( distSq(Points[i].pos, In) < (2*sq(maxdist)))
{
makeConstraint(i, Points.length - 1);
}
}
}
function setup()
{
createCanvas(windowWidth, windowHeight)
frameRate(60);
pwindowWidth = windowWidth;
pwindowHeight = windowHeight;
Constraints = [];
Points = [];
MouseConstraint = new PConstraint();
Mouse = createVector(0, 0);
TrueMouse = createVector(0, 0);
lineAdder = new PLineAdder();
lineAdder.detectDist = maxdist;
lastAddedPoint = -1;
//EraseButton = createButton('Erase');
//EraseButton.mousePressed(ResetSim);
SetButtonPos();
}
function draw()
{
TryResizeCanvas();
TrueMouse.set(mouseX, mouseY);
let mLoop = true;
for (let _ = 0; _ < 8 && mLoop; _++)
{
if (mouseIsPressed && !sim)
{
let mVDelta = p5.Vector.sub(TrueMouse, Mouse);
mVDelta.limit(maxdist / 4);
Mouse.add(mVDelta);
}
else
{
Mouse.set(TrueMouse);
}
TickMouseLogic();
if (sim)
{
mLoop = false;
}
else
{
if (distSq(TrueMouse, Mouse) < sq(maxdist / 4))
{
mLoop = false;
}
}
}
const dt = 1/60;//deltaTime / 1000.0;
const t = millis() * TSPEED;
if (sim && doVerlet)
for (let i = 0; i < Points.length; i++)
{
Points[i].k.add(defaultA);
Points[i].verlet(dt);
}
background(0, 0,0,150);
fill(0, 0,0,150);
rect(Border, Border, width - Border*2, height - Border*2);
if (sim)
stroke(255, 255, 255);
else
stroke(255, 0, 0);
const simblendspeed = 4;
if (sim)
{
SimBlend = lerp(SimBlend, 0, dt * simblendspeed);
}
else
{
SimBlend = lerp(SimBlend, 1, dt * simblendspeed);
}
for (let i = Constraints.length - 1; i >= 0; i--)
{
const c = Constraints[i];
const x1 = Points[c.i0].pos;
const x2 = Points[c.i1].pos;
const p = i / Constraints.length;
const ip = 1 - p;
const r = 255*(0.5+ip);
const g = 255*sin(t*ip)*ip;
const b = 255*ip*cos(t*ip);
const r2 = lerp(r, 255, SimBlend);
const g2 = lerp(g, 255, SimBlend);
const b2 = lerp(b, 255, SimBlend);
stroke(r2, g2, b2);
strokeWeight(1);
line(x1.x, x1.y, x2.x, x2.y);
}
if (mouseIsPressed)
circle(Mouse.x, Mouse.y, 10);
const tsize = 16;
const buffer = 0;
fill(255, 255, 255);
textSize(tsize);
if (sim)
text("<SPACE>: Play Mode", buffer, height - buffer);
else
text("<SPACE>: Edit Mode", buffer, height - buffer);
text("<E>: Erase", width - 128, height - buffer);
}
function TickMouseLogic()
{
if (sim)
{
if (mouseIsPressed && IdxlastGrabbedPoint == -1 && Points.length > 0)
{
IdxlastGrabbedPoint = FindClosestPoint(Mouse);
MouseConstraint.bias = 0.025;
MouseConstraint.i0 = IdxlastGrabbedPoint;
MouseConstraint.bakeDist(Mouse, Points[IdxlastGrabbedPoint].pos);
}
else if (!mouseIsPressed && IdxlastGrabbedPoint != -1)
{
IdxlastGrabbedPoint = -1;
}
}
else
{
if (mouseIsPressed)
{
if (lineAdder.input(Mouse))
{
addPoint(Mouse);
lastAddedPoint = Points.length - 1;
}
}
else
{
if (lastAddedPoint != - 1 && InBorder(Mouse))
{
let closest = FindClosestPoint(Mouse, lastAddedPoint);
if (closest != -1)
addPoint(Mouse, closest);
}
lastAddedPoint = -1;
lineAdder.clear();
}
}
if (sim)
{
if (Constraints.length > 0)
{
for (let iter = 0; iter < Iters; iter++)
{
if (IdxlastGrabbedPoint != -1)
{
MouseConstraint.enforce(Points[IdxlastGrabbedPoint].pos, createVector(Mouse.x, Mouse.y));
}
for (let cIdx = 0; cIdx < Constraints.length; cIdx++)
{
const c = Constraints[cIdx];
let x1 = Points[c.i0].pos;
let x2 = Points[c.i1].pos;
c.enforce(x1, x2);
}
for (let pIdx = 0; pIdx < Points.length; pIdx++)
{
let p = Points[pIdx];
if (p.pinPos != null)
{
p.pos.set(p.pinPos);
continue;
}
if (p.pos.x < Border)
p.pos.x = Border;
else if (p.pos.x > width - Border)
p.pos.x = width - Border;
if (p.pos.y < Border)
p.pos.y = Border;
else if (p.pos.y > height - Border)
p.pos.y = height - Border;
}
}
}
}
}
function keyPressed()
{
// http://keycode.info/
if (keyCode === 32) // space
{
sim = !sim;
}
if (keyCode === 69)
{
ResetSim();
}
}
function ResetSim()
{
Points = [];
Constraints = [];
sim = false;
}