xxxxxxxxxx
288
let world;
let dt = 0.05;
let N = 1200;
let G = 10;
let id = 0;
let img;
let colors;
function preload() {
img = loadImage('test.jpg');
colors = loadJSON('test.json');
}
class World {
constructor() {
this.objects = [];
this.g_constraints = [];
this.constraints = [];
}
show() {
for(let el of this.objects) {
el.show();
}
}
show_c() {
for(let el of this.constraints) {
el.show();
}
for(let el of this.g_constraints) {
el.show();
}
}
add(el) {
this.objects.push(el);
}
add_gc(el) {
this.g_constraints.push(el);
}
add_c(c) {
this.constraints.push(c);
}
update() {
for(let el of this.objects) {
let f = createVector(0, G); // Gravity
el.update(f);
}
for(let i = 0; i < 2; ++i) {
// Global Constraints
// Local constraints
for(let c of this.constraints) {
c.constraint();
}
for(let el of this.objects) {
if(el.p.x < 0) el.p.x = 0 + random() * 2;
if(el.p.x > 400) el.p.x = 400 - random() * 2;
if(el.p.y < 0 ) el.p.y = 0 + random() * 2;
if(el.p.y > 400) el.p.y = 400 - random() * 2;
// for(let c of this.g_constraints) {
// c.constraint(el);
// }
}
}
}
}
class MassPoint {
constructor(x, y, r=8, m=1) {
this.p = createVector(x, y);
this.pp = this.p.copy();
this.m = 1.0;
this.r = r;
this.r2 = r*r;
// this.c = [100, 0, 0];
// this.getColor();
this.id = id;
this.c = colors[this.id]
id += 1;
}
getColor() {
let i = int(this.p.x);
let j = int(this.p.y);
this.c[0] = img.pixels[j*4*400 + i*4];
this.c[1] = img.pixels[j*4*400 + i*4 + 1];
this.c[2] = img.pixels[j*4*400 + i*4 + 2];
}
getPosition() {
return this.p;
}
setPosition(p) {
this.p = p;
}
update(F) {
F.mult(dt * dt / this.m);
let temp = this.p.copy()
this.p.mult(2).sub(this.pp).add(F);
this.pp = temp;
}
show() {
// console.log(this.p)
// this.getColor();
fill(this.c[0], this.c[1], this.c[2])
circle(this.p.x, this.p.y, this.r * 1.5);
}
}
class WallC {
constructor(x1, y1, x2, y2) {
this.e1 = createVector(x1, y1);
this.e2 = createVector(x2, y2);
this.e = p5.Vector.sub(this.e2, this.e1);
this.l = this.e.mag();
this.dir = p5.Vector.normalize(this.e);
}
constraint(p) {
let proj = p5.Vector.mult(this.dir, p5.Vector.dot(p5.Vector.sub(p.p, this.e1), this.dir)).add(this.e1);
let d = p5.Vector.sub(p.p, proj);
// line(p.p.x, p.p.y, proj.x + this.e1.x, proj.y + this.e1.y);
if(d.mag() <= 10) {
let pp1 = p5.Vector.sub(this.e1, p.p);
let pp2 = p5.Vector.sub(this.e2, p.p);
if(p5.Vector.dot(pp1, pp2) < pp1.mag() * pp2.mag() / sqrt(2)) {
// stroke("blue")
// proj.add(this.e1)
// strokeWeight(1)
// line(p.p.x, p.p.y, p.p.x + d.x, p.p.y + d.y);
// point(proj.x + 5*d.x, proj.y + 5*d.y)
// p.setPosition(d.normalize().mult(5));
d.normalize().mult(10);
proj.add(d)
p.setPosition(proj);
}
}
}
show() {
// strokeWeight(8)
// stroke("red");
// line(this.e1.x, this.e1.y, this.e2.x, this.e2.y);
}
}
class StickC {
constructor(p1, p2, l) {
this.p1 = p1;
this.p2 = p2;
this.l = l;
this.l2 = l*l;
}
get_dir() {
return p5.Vector.sub(this.p2.p, this.p1.p).normalize();
}
show() {
strokeWeight(1);
stroke("purple")
line(this.p1.p.x, this.p1.p.y, this.p2.p.x, this.p2.p.y);
}
constraint() {
let delta = p5.Vector.sub(this.p2.p, this.p1.p);
delta.mult(this.l2 / (delta.magSq() + this.l2) - 0.5);
this.p1.p.sub(delta);
this.p2.p.add(delta);
}
}
class PointPointC {
constructor(p1, p2) {
this.p1 = p1;
this.p2 = p2;
}
constraint() {
let d = p5.Vector.sub(this.p2.p, this.p1.p);
if(this.p1.r2 + this.p2.r2 > d.magSq()) { // Intersection
// console.log("intersection")
d.div(10);
this.p1.p.sub(d);
this.p2.p.add(d);
}
}
show(){}
}
class StickStickC {
constructor(s1, s2) {
this.s1 = s1;
this.s2 = s2;
}
constraint() {
// Compute projection vector for s1.p1 and s1.p2 to s2
let p1 = this.s1.p1.p;
let p2 = this.s1.p2.p;
let q1 = this.s2.p1.p;
let q2 = this.s2.p2.p
let dir = this.s2.get_dir();
// handle orthogonal case?
let proj1 = p5.Vector.mult(dir, p5.Vector.dot(p5.Vector.sub(p1, q1), dir));
let orth1 = p5.Vector.sub(p1, q1).sub(proj1)
let proj2 = p5.Vector.mult(dir, p5.Vector.dot(p5.Vector.sub(p2, q1), dir));
let orth2 = p5.Vector.sub(p2, q1).sub(proj2)
line(orth1.x + proj1.x + q1.x, orth1.y + proj1.y + q1.y, proj1.x + q1.x, proj1.y + q1.y)
line(orth2.x + proj2.x + q1.x, orth2.y + proj2.y + q1.y, proj2.x + q1.x, proj2.y + q1.y)
// console.log(proj1.heading(), proj2.heading())
if(abs(orth1.heading() - orth2.heading()) >= 0.0001) {
console.log("crossed")
if(orth1.magSq() < orth2.magSq()) {
orth1.normalize();
orth1.mult(0.4)
this.s1.p1.p.sub(orth1);
this.s1.p2.p.sub(orth1);
this.s2.p1.p.add(orth1);
this.s2.p2.p.add(orth1)
} else {
orth2.normalize();
orth2.mult(0.4)
this.s1.p1.p.sub(orth2);
this.s1.p2.p.sub(orth2);
this.s2.p1.p.add(orth2);
this.s2.p2.p.add(orth2)
}
}
strokeWeight(2);
stroke("blue")
// line(p1.x, p1.y, proj1.x + q1.x, proj1.y + q1.y)
// line(p2.x, p2.y, proj2.x + q1.x, proj2.y + q1.y)
}
show() {
}
}
let points = [];
function setup() {
createCanvas(400, 400);
img.loadPixels();
world = new World();
randomSeed(1);
// Walls
world.add_gc(new WallC(0, 400, 400, 400));
world.add_gc(new WallC(0, 0, 400, 0));
world.add_gc(new WallC(0, 0, 0, 400));
world.add_gc(new WallC(400, 0, 400, 400));
}
function draw() {
background(0);
if(points.length < N) {
for(let i = 0; i < 1; ++i) {
let m = new MassPoint(350 + 30 * random(), 20 * random());
world.add(m);
points.push(m);
for(let j = 0; j < points.length; ++j) {
world.add_c(new PointPointC(m, points[j]));
}
}
} else {
console.log("finished")
}
world.update();
world.show();
world.show_c();
// image(img, 0, 0);
}
// function mousePressed() {
// let json = {};
// for(let ol of world.objects) {
// ol.getColor();
// json[ol.id] = ol.c;
// }
// saveJSON(json, 'test.json');
// }