abouttreesummaryrefslogcommitdiff
diff options
context:
space:
mode:
authorPatrick Schönberger2021-02-06 12:48:25 +0100
committerPatrick Schönberger2021-02-06 12:48:25 +0100
commit999a549825d3de0b53e2922462ed1e120e176ec2 (patch)
treeb1ed24d49f362a5a35e96c9c61122355f85f7f64
parent19d9f67e228e9925958489574339448bb608c9db (diff)
downloadcloth_sim-999a549825d3de0b53e2922462ed1e120e176ec2.tar.gz
cloth_sim-999a549825d3de0b53e2922462ed1e120e176ec2.zip
simulate
-rw-r--r--Scripts/cloth.js90
-rw-r--r--Scripts/main.js4
-rw-r--r--Textures/DeutschlandFlagge.jpgbin0 -> 4333 bytes
3 files changed, 83 insertions, 11 deletions
diff --git a/Scripts/cloth.js b/Scripts/cloth.js
index db07ac3..0c4f02c 100644
--- a/Scripts/cloth.js
+++ b/Scripts/cloth.js
@@ -1,14 +1,35 @@
+const DAMPING = 0.03;
+const DRAG = 1 - DAMPING;
const MASS = 0.1;
+const GRAVITY = new THREE.Vector3(0, -9.81 * MASS, 0);
+const K = 1;
+
+let tmpCorrection;
class Constraint {
- constructor(p1, p2, distance) {
+ constructor(p1, p2, restDist) {
this.p1 = p1;
this.p2 = p2;
- this.distance = distance;
+ this.restDist = restDist;
+ }
+
+ satisfy() {
+ const diff = this.p2.position.clone().sub(this.p1.position);
+ const currentDist = diff.length();
+ if (currentDist == 0) return;
+ if (currentDist <= this.restDist) return;
+ const correction = diff.multiplyScalar(1 - (this.restDist / currentDist));
+ correction.multiplyScalar(K);
+ tmpCorrection = correction;
+ const correctionHalf = correction.multiplyScalar(0.5);
+ this.p1.position.add(correctionHalf);
+ this.p2.position.sub(correctionHalf);
}
}
class Particle {
+ movable = true;
+
constructor(x, y, z, mass) {
this.position = new THREE.Vector3(x, y, z);
this.previous = new THREE.Vector3(x, y, z);
@@ -16,10 +37,23 @@ class Particle {
this.mass = mass;
}
addForce(force) {
-
+ this.acceleration.add(
+ force.clone().multiplyScalar(1/this.mass)
+ );
}
verlet(dt) {
-
+ // verlet algorithm
+ // next position = 2 * current Position - previous position + acceleration * (passed time)^2
+ // acceleration (dv/dt) = F(net)
+ const nextPosition = this.position.clone().sub(this.previous);
+ nextPosition.multiplyScalar(DRAG);
+ nextPosition.add(this.position);
+ nextPosition.add(this.acceleration.multiplyScalar(dt*dt));
+
+ this.previous = this.position;
+ this.position = nextPosition;
+
+ this.acceleration.set(0, 0, 0);
}
}
@@ -29,6 +63,7 @@ class Cloth {
this.height = height;
this.numPointsWidth = numPointsWidth;
this.numPointsHeight = numPointsHeight;
+ this.windFactor = new THREE.Vector3(0.5, 0.2, 0.2);
/**
* distance between two vertices horizontally/vertically
@@ -55,6 +90,10 @@ class Cloth {
}
}
+ this.particles[this.getVertexIndex(0, 0)].movable = false;
+ this.particles[this.getVertexIndex(0, numPointsHeight-1)].movable = false;
+ this.particles[this.getVertexIndex(numPointsWidth-1, 0)].movable = false;
+
const REST_DIST_X = width / (numPointsWidth-1);
const REST_DIST_Y = height / (numPointsHeight-1);
@@ -71,7 +110,7 @@ class Cloth {
REST_DIST_X
));
}
- if (x < numPointsWidth-1) {
+ if (y < numPointsHeight-1) {
this.constraints.push(new Constraint(
this.particles[this.getVertexIndex(x, y)],
this.particles[this.getVertexIndex(x, y+1)],
@@ -126,13 +165,44 @@ class Cloth {
return geometry;
}
updateGeometry(geometry) {
-
- }
- satisfyConstraints() {
-
+ const positions = geometry.attributes.position.array;
+ for (let i in this.particles) {
+ let p = this.particles[i];
+ if (p.movable) {
+ positions[i*3+0] = p.position.x;
+ positions[i*3+1] = p.position.y;
+ positions[i*3+2] = p.position.z;
+ } else {
+ p.position = p.previous;
+ }
+ }
+ geometry.attributes.position.needsUpdate = true;
+ geometry.computeBoundingSphere();
+ geometry.computeVertexNormals();
}
- simulate() {
+ simulate(dt) {
+ let now = performance.now();
+ for (let particle of this.particles) {
+ let vertex = particle.position;
+ let fWind = new THREE.Vector3(
+ this.windFactor.x * (Math.sin(vertex.x * vertex.y * now)+1),
+ this.windFactor.y * Math.cos(vertex.z * now),
+ this.windFactor.z * Math.sin(Math.cos(5 * vertex.x * vertex.y * vertex.z))
+ );
+ // normalize then multiply?
+ particle.addForce(fWind);
+ // calculate wind with normal?
+
+ particle.addForce(GRAVITY);
+
+ particle.verlet(dt);
+ }
+
+ for (let constraint of this.constraints) {
+ constraint.satisfy();
+ }
+ //console.log(tmpCorrection);
}
/**
* helper function to calculate index of vertex
diff --git a/Scripts/main.js b/Scripts/main.js
index d54aa9f..3353f4d 100644
--- a/Scripts/main.js
+++ b/Scripts/main.js
@@ -98,7 +98,9 @@ function init() {
* @param {number} dt - time passed since last frame in ms
*/
function animate(dt) {
- // simulate cloth
+ cloth.simulate(dt / 1000);
+
+ cloth.updateGeometry(clothGeometry);
raycaster.setFromCamera( new THREE.Vector2((mousePos.x / w) * 2 - 1, ((h - mousePos.y) / h) * 2 - 1), camera );
diff --git a/Textures/DeutschlandFlagge.jpg b/Textures/DeutschlandFlagge.jpg
new file mode 100644
index 0000000..09e63ab
--- /dev/null
+++ b/Textures/DeutschlandFlagge.jpg
Binary files differ