-
-
Notifications
You must be signed in to change notification settings - Fork 8
/
sim_0.js
121 lines (97 loc) · 2.64 KB
/
sim_0.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
class Particle {
constructor(posX, posY, velX, velY) {
this.posX = posX;
this.posY = posY;
this.prevX = posX;
this.prevY = posY;
this.velX = velX;
this.velY = velY;
}
}
class Simulator {
constructor(width, height, numParticles) {
this.running = false;
this.width = width;
this.height = height;
this.gravX = 0;
this.gravY = 0.1;
this.particles = [];
this.addParticles(numParticles);
}
start() { this.running = true; }
pause() { this.running = false; }
resize(width, height) {
this.width = width;
this.height = height;
}
addParticles(count) {
for (let i = 0; i < count; i++) {
const posX = Math.random() * this.width;
const posY = Math.random() * this.height;
const velX = Math.random() * 2 - 1;
const velY = Math.random() * 2 - 1;
this.particles.push(new Particle(posX, posY, velX, velY));
}
}
draw(ctx) {
ctx.save();
ctx.translate(-2.5, -2.5);
ctx.fillStyle = "#0066FF";
for (let p of this.particles) {
ctx.fillRect(p.posX, p.posY, 5, 5);
}
ctx.restore();
}
// Algorithm 1: Simulation step
update(dt = 1) {
if (!this.running) {
return;
}
for (let p of this.particles) {
// apply gravity
p.velX += this.gravX * dt;
p.velY += this.gravY * dt;
}
this.applyViscosity(dt);
for (let p of this.particles) {
// save previous position
p.prevX = p.posX;
p.prevY = p.posY;
// advance to predicted position
p.posX += p.velX * dt;
p.posY += p.velY * dt;
}
this.adjustSprings(dt);
this.applySpringDisplacements(dt);
this.doubleDensityRelaxation(dt);
this.resolveCollisions(dt);
for (let p of this.particles) {
// use previous position to calculate new velocity
p.velX = (p.posX - p.prevX) / dt;
p.velY = (p.posY - p.prevY) / dt;
}
}
doubleDensityRelaxation(dt) { }
applySpringDisplacements(dt) { }
adjustSprings(dt) { }
applyViscosity(dt) { }
resolveCollisions(dt) {
const boundaryMul = .5; // Soft boundary
const boundaryMinX = 5;
const boundaryMaxX = this.width - 5;
const boundaryMinY = 5;
const boundaryMaxY = this.height - 5;
for (let p of this.particles) {
if (p.posX < boundaryMinX) {
p.posX += boundaryMul * (boundaryMinX - p.posX);
} else if (p.posX > boundaryMaxX) {
p.posX += boundaryMul * (boundaryMaxX - p.posX);
}
if (p.posY < boundaryMinY) {
p.posY += boundaryMul * (boundaryMinY - p.posY);
} else if (p.posY > boundaryMaxY) {
p.posY += boundaryMul * (boundaryMaxY - p.posY);
}
}
}
}