-\r
- newFace.springs.push(new Spring(vertices, getVertexIndex(x, y), getVertexIndex(x + 1, y))); // oben\r
- newFace.springs.push(new Spring(vertices, getVertexIndex(x, y), getVertexIndex(x, y + 1))); // links\r
- newFace.springs.push(new Spring(vertices, getVertexIndex(x, y), getVertexIndex(x + 1, y + 1))); // oben links -> unten rechts diagonal\r
- newFace.springs.push(new Spring(vertices, getVertexIndex(x + 1, y), getVertexIndex(x, y + 1))); // oben rechts -> unten links diagonal\r
- newFace.springs.push(new Spring(vertices, getVertexIndex(x + 1, y), getVertexIndex(x + 1, y + 1))); // rechts\r
- newFace.springs.push(new Spring(vertices, getVertexIndex(x, y + 1), getVertexIndex(x + 1, y + 1))); // unten\r
-\r
- faces.push(newFace);\r
- }\r
- }\r
-\r
- /**\r
- * call createExplicit\r
- * with generated vertices and faces\r
- */\r
- this.createExplicit(vertices, faces);\r
-\r
- /**\r
- * hand cloth from left and right upper corners\r
- */\r
- this.vertexRigidness[0] = true;\r
- this.vertexRigidness[numPointsWidth-1] = true;\r
- }\r
-\r
- /**\r
- * Generate THREE JS Geometry\r
- * (list of vertices and list of indices representing triangles)\r
- * and calculate the weight of each face and split it between\r
- * surrounding vertices\r
- * @param {Array<Vector3>} vertices \r
- * @param {Array<Face>} faces \r
- */\r
- createExplicit(vertices, faces) {\r
-\r
- /**\r
- * Copy vertices and initialize vertex weights to 0\r
- */\r
- for (let i in vertices) {\r
- this.geometry.vertices.push(vertices[i].clone());\r
- this.previousPositions.push(vertices[i].clone());\r
- // this.geometry.vertices.push(vertices[i]);\r
- // this.previousPositions.push(vertices[i]);\r
- this.vertexWeights.push(0);\r
- this.vertexRigidness.push(false);\r
- }\r
- /**\r
- * copy faces,\r
- * generate two triangles per face,\r
- * calculate weight of face as its area\r
- * and split between the 4 vertices\r
- */\r
- for (let i in faces) {\r
- let face = faces[i];\r
-\r
- /** copy faces to class member */\r
- this.faces.push(face);\r
-\r
- /** generate triangles */\r
- this.geometry.faces.push(new THREE.Face3(\r
- face.a, face.b, face.c\r
- ));\r
- this.geometry.faces.push(new THREE.Face3(\r
- face.c, face.b, face.d\r
- ));\r
-\r
- /**\r
- * calculate area of face as combined area of\r
- * its two composing triangles\r
- */\r
- let xLength = vectorLength(this.geometry.vertices[face.b], this.geometry.vertices[face.a]);\r
- let yLength = vectorLength(this.geometry.vertices[face.c], this.geometry.vertices[face.a]);\r
- let weight = xLength * yLength / 2;\r
-\r
- xLength = vectorLength(this.geometry.vertices[face.b], this.geometry.vertices[face.d]);\r
- yLength = vectorLength(this.geometry.vertices[face.c], this.geometry.vertices[face.d]);\r
- weight += xLength * yLength / 2;\r
-\r
- /**\r
- * split weight equally between four surrounding vertices\r
- */\r
- this.vertexWeights[face.a] += weight / 4;\r
- this.vertexWeights[face.b] += weight / 4;\r
- this.vertexWeights[face.c] += weight / 4;\r
- this.vertexWeights[face.d] += weight / 4;\r
- }\r
-\r
- /**\r
- * let THREE JS compute bounding sphere around generated mesh\r
- * needed for View Frustum Culling internally\r
- */\r
- this.geometry.computeBoundingSphere();\r
- this.geometry.computeFaceNormals();\r
- }\r
-\r
- /**\r
- * generate a debug mesh for visualizing\r
- * vertices and springs of the cloth\r
- * and add it to scene for rendering\r
- * @param {Scene} scene - Scene to add Debug Mesh to\r
- */\r
- createDebugMesh(scene) {\r
- /**\r
- * helper function to generate a single line\r
- * between two Vertices with a given color\r
- * @param {Vector3} from \r
- * @param {Vector3} to \r
- * @param {number} color \r
- */\r
- function addLine(from, to, color) {\r
- let geometry = new THREE.Geometry();\r
- geometry.vertices.push(from);\r
- geometry.vertices.push(to);\r
- let material = new THREE.LineBasicMaterial({ color: color, linewidth: 10 });\r
- let line = new THREE.Line(geometry, material);\r
- line.renderOrder = 1;\r
- scene.add(line);\r
- }\r
- /**\r
- * helper function to generate a small sphere\r
- * at a given Vertex Position with color\r
- * @param {Vector3} point \r
- * @param {number} color \r
- */\r
- function addPoint(point, color) {\r
- const geometry = new THREE.SphereGeometry(0.05, 32, 32);\r
- const material = new THREE.MeshBasicMaterial({ color: color });\r
- const sphere = new THREE.Mesh(geometry, material);\r
- sphere.position.set(point.x, point.y, point.z);\r
- scene.add(sphere);\r
- }\r
-\r
- let lineColor = 0x000000;\r
- let pointColor = 0xff00000;\r
-\r
- /**\r
- * generate one line for each of the 6 springs\r
- * and one point for each of the 4 vertices\r
- * for all of the faces\r
- */\r
- for (let i in this.faces) {\r
- let face = this.faces[i];\r
- addLine(this.geometry.vertices[face.a], this.geometry.vertices[face.b], lineColor);\r
- addLine(this.geometry.vertices[face.a], this.geometry.vertices[face.c], lineColor);\r
- addLine(this.geometry.vertices[face.a], this.geometry.vertices[face.d], lineColor);\r
- addLine(this.geometry.vertices[face.b], this.geometry.vertices[face.c], lineColor);\r
- addLine(this.geometry.vertices[face.b], this.geometry.vertices[face.d], lineColor);\r
- addLine(this.geometry.vertices[face.c], this.geometry.vertices[face.d], lineColor);\r
-\r
- addPoint(this.geometry.vertices[face.a], pointColor);\r
- addPoint(this.geometry.vertices[face.b], pointColor);\r
- addPoint(this.geometry.vertices[face.c], pointColor);\r
- addPoint(this.geometry.vertices[face.d], pointColor);\r
- }\r
- }\r
-\r
- previousPositions = [];\r
- time = 0;\r
- /**\r
- * \r
- * @param {number} dt time in seconds since last frame\r
- */\r
- simulate(dt) {\r
- for (let i in this.geometry.vertices) {\r
- let acceleration = this.getAcceleration(i, dt);\r
-\r
- //acceleration.clampLength(0, 10);\r
-\r
- if (Math.abs(acceleration.length()) <= 10e-4) {\r
- acceleration.set(0, 0, 0);\r
- }\r
- \r
- let currentPosition = this.verlet(this.geometry.vertices[i].clone(), this.previousPositions[i].clone(), acceleration, dt);\r
- //let currentPosition = this.euler(this.geometry.vertices[i], acceleration, dt);\r
- \r
- this.previousPositions[i].copy(this.geometry.vertices[i]);\r
- this.geometry.vertices[i].copy(currentPosition);\r
- }\r
- //console.log(this.getAcceleration(1, dt));\r
- \r
- this.time += dt;\r
-\r
- for (let face of this.faces) {\r
- for (let spring of face.springs) {\r
- spring.update(this.geometry.vertices);\r