Multiple Mass-Spring system test

by PhilQ

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/109/three.min.js"></script>
<canvas id="c"></canvas>
<button id="btn">Stop</button>

SCSS

canvas {
	width: 500px;
	height: 700px;
	border: 1px solid #000;
}

JavaScript

var gravity = new THREE.Vector3(0, -9.80665, 0);
var wind = new THREE.Vector3(0, 0, 0);
var springs = [];
var pins = [];
var time = Date.now(), timeStep = 0;
var paused = true;

class Particle {
	constructor(idx, x, y, z, damping) {
		this.idx = idx;
		this.mass = 1;
		this.damping = damping;
		this.pinned = false;
		this.f = new THREE.Vector3();
		this.a = new THREE.Vector3();
		this.v = new THREE.Vector3();
		this.p = new THREE.Vector3().set(x, y, z);
		this.tmp = new THREE.Vector3();
	}
	
	update( dt ) {
		if ( ! this.pinned ) {
			this.f.set(0,0,0);

			if ( springs[ this.idx ] ) {
				// Per spring:
				for (var i = 0, n = springs[ this.idx ].length; i < n; ++i) {
					var spring = springs[ this.idx ][ i ];

					// Spring force
					this.tmp.subVectors( this.p, spring[0].p );
					var dist = this.tmp.length() - spring[3];
					this.f.add(
						this.tmp.normalize().multiplyScalar( dist * -spring[1] )
					);
					
					// Damping force
					this.f.add(
						this.tmp.copy( this.v ).multiplyScalar( -this.damping )
					);
				}
				//divide by n?
			}

			// Gravity force
			this.f.add(
				gravity.clone().multiplyScalar( this.mass )
			);

			// Wind force
			this.f.add(
				wind.clone().multiplyScalar( this.mass )
			);

			if (this.idx == 0) {
				//console.log(this.f);
			}
			this.a.copy( this.f ).multiplyScalar( 1/this.mass );
			if (this.idx == 0) {
				//console.log(this.a);
			}
			this.v.add( this.a.clone().multiplyScalar( dt ) );
			if (this.idx == 0) {
				//console.log(this.v);
			}
			this.p.add( this.v.clone().multiplyScalar( dt ) );
			if (this.idx == 0) {
				//console.log(this.p);
			}
		}
	}
};

var xSegs = 10, ySegs = 10, distW = 10, distH = 10;
var width = xSegs * distW;
var height = ySegs * distH;
var points = [];

var cnv, ctx;

var _p1, _p2;

function setSpring(x1, y1, x2, y2, k, damping) {
	var i1 = x1 + y1*(xSegs+1);
	var i2 = x2 + y2*(xSegs+1);
	if ( ! springs[ i1 ] ) {
		springs[ i1 ] = [];
	}
	if ( ! springs[ i2 ] ) {
		springs[...