xxxxxxxxxx
242
class BezierCurve {
constructor(anchorX1, anchorY1, weightX1, weightY1, anchorX2, anchorY2, weightX2, weightY2) {
this.aX = anchorX1
this.aY = anchorY1
this.bX = weightX1
this.bY = weightY1
this.cX = anchorX2
this.cY = anchorY2
this.dX = weightX2
this.dY = weightY2
}
quadraticCurve(p1x, p1y, p2x, p2y, p3x, p3y, t) {
let lx1 = lerp(p1x, p2x, t);
let ly1 = lerp(p1y, p2y, t);
let lx2 = lerp(p2x, p3x, t);
let ly2 = lerp(p2y, p3y, t);
let ox = lerp(lx1, lx2, t);
let oy = lerp(ly1, ly2, t);
return { x : ox, y : oy }
}
cubicCurve(p1x, p1y, p2x, p2y, p3x, p3y, p4x, p4y, t) {
let p1 = this.quadraticCurve(p1x, p1y, p2x, p2y, p3x, p3y, t);
let p2 = this.quadraticCurve(p2x, p2y, p3x, p3y, p4x, p4y, t);
let ox = lerp(p1.x, p2.x, t);
let oy = lerp(p1.y, p2.y, t);
return { x : ox, y : oy }
}
check(t) {
return this.cubicCurve(
this.aX, this.aY,
this.bX, this.bY,
this.cX, this.cY,
this.dX, this.dY, t
)
}
draw(res = 1) {
let lastX = this.aX;
let lastY = this.aY;
for (let i = 0; i <= 1+1/res; i += 1/res) {
let newP = this.check(i);
line(lastX, lastY, newP.x, newP.y)
lastX = newP.x;
lastY = newP.y;
}
}
show() {
line(this.aX, this.aY, this.bX, this.bY)
circle(this.aX, this.aY, 10)
circle(this.bX, this.bY, 8)
line(this.cX, this.cY, this.dX, this.dY)
circle(this.cX, this.cY, 8)
circle(this.dX, this.dY, 10)
}
}
class bezierPath {
constructor() {
this.path = []
this.locked = false;
}
add(b) {
this.path.push(b);
}
editor(mousex, mousey) {
if (!this.locked && mouseIsPressed) {
let out = { b: 0, p: -1 }
for (let b = 0; b < this.path.length; b++) {
let i = this.path[b]
if (dist(mouseX, mouseY, i.aX, i.aY) < 12) {
out.b = b
out.p = 0;
break;
} else if (dist(mouseX, mouseY, i.bX, i.bY) < 12) {
out.b = b
out.p = 1;
break;
} else if (dist(mouseX, mouseY, i.cX, i.cY) < 12) {
out.b = b
out.p = 2;
break;
} else if (dist(mouseX, mouseY, i.dX, i.dY) < 12) {
out.b = b
out.p = 3;
break;
}
}
if (out.p != -1) {
this.locked = out;
}
} else {
if (!mouseIsPressed) {
this.locked = false;
} else {
let a = this.path[this.locked.b]
let b = -1;
let c = -1;
if (this.locked.b+1 < this.path.length) {
b = this.path[this.locked.b+1]
}
if (this.locked.b-1 >= 0) {
c = this.path[this.locked.b-1]
}
let delX
let delY
switch (this.locked.p) {
case 0:
delX = a.bX - a.aX;
delY = a.bY - a.aY;
a.aX = mouseX
a.aY = mouseY
a.bX = a.aX + delX
a.bY = a.aY + delY
if (c != -1) {
c.dX = mouseX;
c.dY = mouseY
}
break;
case 1:
delX = a.bX - a.aX;
delY = a.bY - a.aY;
a.bX = mouseX
a.bY = mouseY
if (c != -1) {
c.cX = a.aX - delX;
c.cY = a.aY - delY;
}
break;
case 2:
delX = a.cX - a.dX;
delY = a.cY - a.dY;
a.cX = mouseX
a.cY = mouseY
if (b != -1) {
b.bX = a.dX - delX;
b.bY = a.dY - delY;
}
break;
case 3:
delX = a.cX - a.dX;
delY = a.cY - a.dY;
a.dX = mouseX
a.dY = mouseY
a.cX = a.dX + delX
a.cY = a.dY + delY
if (b != -1) {
b.aX = mouseX;
b.aY = mouseY
b.bX = a.dX - delX;
b.bY = a.dY - delY;
}
break;
}
}
}
}
show() {
for (let i of this.path) {
i.show()
}
}
draw(res = 1) {
for (let i of this.path) {
i.draw(res)
}
}
check(t) {
let a = floor(t * this.path.length)
let test = map(t, a/this.path.length, a/this.path.length+1/this.path.length, 0, 1)
return this.path[a].check(test)
}
}
let bezierManager;
let animSpeed;
function setup() {
createCanvas(600, 450);
animSpeed = createSlider(0.0001, 0.01, 0.01, 0.0001)
bezierManager = new bezierPath();
for (let i = 0; i < 1; i++) {
let bez = new BezierCurve(random(width), random(height), random(width), random(height), random(width), random(height), random(width), random(height))
bezierManager.add(bez)
}
}
function keyPressed() {
if (keyCode == SHIFT) {
let last = bezierManager.path[bezierManager.path.length-1]
let delX = last.dX - last.cX
let delY = last.dY - last.cY
let bez = new BezierCurve(last.dX, last.dY, last.dX + delX, last.dY + delY, mouseX + delX, mouseY + delY, mouseX, mouseY)
bezierManager.add(bez)
}
}
let anim =0
function draw() {
background(220);
bezierManager.editor()
bezierManager.draw(40)
if (!keyIsDown(32)) {
bezierManager.show()
}
anim = anim + animSpeed.value()//sin(millis() / 1000) / 2 + 0.5
let a = bezierManager.check(anim % 1)
circle(a.x, a.y, 6)
text(str(anim),16,16)
}