diff options
| author | Patrick Schönberger | 2021-01-06 10:24:10 +0100 |
|---|---|---|
| committer | Patrick Schönberger | 2021-01-06 10:24:10 +0100 |
| commit | 4079007a1ed290280e228b93432129c4a262dae9 (patch) | |
| tree | 433d70d5776a3a8bf3fdecd9ea38ef4cb8e70239 /Scripts | |
| parent | f3d7f6c46c59cd98eb64a079301b872ca2a6a2f3 (diff) | |
| download | cloth_sim-4079007a1ed290280e228b93432129c4a262dae9.tar.gz cloth_sim-4079007a1ed290280e228b93432129c4a262dae9.zip | |
reorganize code into separate files
Diffstat (limited to 'Scripts')
| -rw-r--r-- | Scripts/main.js | 301 |
1 files changed, 11 insertions, 290 deletions
diff --git a/Scripts/main.js b/Scripts/main.js index 4d7ac7c..a0387ac 100644 --- a/Scripts/main.js +++ b/Scripts/main.js @@ -1,3 +1,6 @@ +import { Face, Spring, Cloth } from './cloth.js';
+
+
class Point {
constructor(x, y) {
this.x = x;
@@ -25,296 +28,11 @@ class Point { }
}
-/**
- * Convenience Function for calculating the distance between two vectors
- * because THREE JS Vector functions mutate variables
- * @param {Vector3} a - Vector A
- * @param {Vector3} b - Vector B
- */
-function vectorLength(a, b) {
- let v1 = new THREE.Vector3();
- v1.set(a.x, a.y, a.z);
- let v2 = new THREE.Vector3();
- v2.set(b.x, b.y, b.z);
-
- return v1.sub(v2).length();
-}
-
-/**
- * Class representing a quad face
- * Each face consists of two triangular mesh faces
- * containts four indices for determining vertices
- * and six springs, one between each of the vertices
- */
-class Face {
- a;
- b;
- c;
- d;
-
- springs = [];
-
- constructor(a, b, c, d) {
- this.a = a;
- this.b = b;
- this.c = c;
- this.d = d;
- }
-}
-
-/**
- * Class representing a single spring
- * has a current and resting length
- * and indices to the two connected vertices
- */
-class Spring {
- restLength;
- currentLength;
- index1;
- index2;
-
-
- /**
- * set vertex indices
- * and calculate inital length based on the
- * vertex positions
- * @param {Array of Vector3} vertices
- * @param {number} index1
- * @param {number} index2
- */
- constructor(vertices, index1, index2) {
- this.index1 = index1;
- this.index2 = index2;
-
- let length = vectorLength(vertices[index1], vertices[index2]);
- this.restLength = length;
- this.currentLength = length;
- }
-}
-
-/**
- * Class representing a single piece of cloth
- * contains THREE JS geometry,
- * logically represented by an array of adjacent faces
- * and vertex weights which are accessed by the same
- * indices as the vertices in the Mesh
- */
-class Cloth {
- VertexWeight = 1;
-
- geometry = new THREE.Geometry();
-
- faces = [];
-
- vertexWeights = [];
-
-
- /**
- * creates a rectangular piece of cloth
- * takes the size of the cloth
- * and the number of vertices it should be composed of
- * @param {number} width - width of the cloth
- * @param {number} height - height of the cloth
- * @param {number} numPointsWidth - number of vertices in horizontal direction
- * @param {number} numPointsHeight - number of vertices in vertical direction
- */
- createBasic(width, height, numPointsWidth, numPointsHeight) {
- /** resulting vertices and faces */
- let vertices = [];
- let faces = [];
-
- /**
- * distance between two vertices horizontally/vertically
- * divide by the number of points minus one
- * because there are (n - 1) lines between n vertices
- */
- let stepWidth = width / (numPointsWidth - 1);
- let stepHeight = height / (numPointsHeight - 1);
-
- /**
- * iterate over the number of vertices in x/y axis
- * and add a new Vector3 to "vertices"
- */
- for (let y = 0; y < numPointsHeight; y++) {
- for (let x = 0; x < numPointsWidth; x++) {
- vertices.push(
- new THREE.Vector3(x * stepWidth, height - y * stepHeight, 0)
- );
- }
- }
-
- /**
- * helper function to calculate index of vertex
- * in "vertices" array based on its x and y positions
- * in the mesh
- * @param {number} x - x index of vertex
- * @param {number} y - y index of vertex
- */
- function getVertexIndex(x, y) {
- return y * numPointsWidth + x;
- }
-
- /**
- * generate faces based on 4 vertices
- * and 6 springs each
- */
- for (let y = 0; y < numPointsHeight - 1; y++) {
- for (let x = 0; x < numPointsWidth - 1; x++) {
- let newFace = new Face(
- getVertexIndex(x, y),
- getVertexIndex(x, y + 1),
- getVertexIndex(x + 1, y),
- getVertexIndex(x + 1, y + 1),
- );
-
- newFace.springs.push(new Spring(vertices, getVertexIndex(x, y), getVertexIndex(x + 1, y)));
- newFace.springs.push(new Spring(vertices, getVertexIndex(x, y), getVertexIndex(x, y + 1)));
- newFace.springs.push(new Spring(vertices, getVertexIndex(x, y), getVertexIndex(x + 1, y + 1)));
- newFace.springs.push(new Spring(vertices, getVertexIndex(x + 1, y), getVertexIndex(x, y + 1)));
- newFace.springs.push(new Spring(vertices, getVertexIndex(x + 1, y), getVertexIndex(x + 1, y + 1)));
- newFace.springs.push(new Spring(vertices, getVertexIndex(x, y + 1), getVertexIndex(x + 1, y + 1)));
-
- faces.push(newFace);
- }
- }
-
- /**
- * call createExplicit
- * with generated vertices and faces
- */
- this.createExplicit(vertices, faces);
- }
-
- /**
- * Generate THREE JS Geometry
- * (list of vertices and list of indices representing triangles)
- * and calculate the weight of each face and split it between
- * surrounding vertices
- * @param {Array of Vector3} vertices
- * @param {Array of Face} faces
- */
- createExplicit(vertices, faces) {
- /**
- * Copy vertices and initialize vertex weights to 0
- */
- for (let i in vertices) {
- this.geometry.vertices.push(vertices[i]);
- this.vertexWeights.push(0);
- }
- /**
- * copy faces,
- * generate two triangles per face,
- * calculate weight of face as its area
- * and split between the 4 vertices
- */
- for (let i in faces) {
- let face = faces[i];
-
- /** copy faces to class member */
- this.faces.push(face);
-
- /** generate triangles */
- this.geometry.faces.push(new THREE.Face3(
- face.a, face.b, face.c
- ));
- this.geometry.faces.push(new THREE.Face3(
- face.c, face.b, face.d
- ));
-
- /**
- * calculate area of face as combined area of
- * its two composing triangles
- */
- let xLength = vectorLength(this.geometry.vertices[face.b], this.geometry.vertices[face.a]);
- let yLength = vectorLength(this.geometry.vertices[face.c], this.geometry.vertices[face.a]);
- let weight = xLength * yLength / 2;
-
- xLength = vectorLength(this.geometry.vertices[face.b], this.geometry.vertices[face.d]);
- yLength = vectorLength(this.geometry.vertices[face.c], this.geometry.vertices[face.d]);
- weight += xLength * yLength / 2;
-
- /**
- * split weight equally between four surrounding vertices
- */
- this.vertexWeights[face.a] += weight / 4;
- this.vertexWeights[face.b] += weight / 4;
- this.vertexWeights[face.c] += weight / 4;
- this.vertexWeights[face.d] += weight / 4;
- }
-
- /**
- * let THREE JS compute bounding sphere around generated mesh
- * needed for View Frustum Culling internally
- */
- this.geometry.computeBoundingSphere();
- }
-
- /**
- * generate a debug mesh for visualizing
- * vertices and springs of the cloth
- * and add it to scene for rendering
- * @param {Scene} scene - Scene to add Debug Mesh to
- */
- createDebugMesh(scene) {
- /**
- * helper function to generate a single line
- * between two Vertices with a given color
- * @param {Vector3} from
- * @param {Vector3} to
- * @param {number} color
- */
- function addLine(from, to, color) {
- let geometry = new THREE.Geometry();
- geometry.vertices.push(from);
- geometry.vertices.push(to);
- let material = new THREE.LineBasicMaterial( { color: color, linewidth: 10 } );
- let line = new THREE.Line(geometry, material);
- line.renderOrder = 1;
- scene.add(line);
- }
- /**
- * helper function to generate a small sphere
- * at a given Vertex Position with color
- * @param {Vector3} point
- * @param {number} color
- */
- function addPoint(point, color) {
- const geometry = new THREE.SphereGeometry( 0.05, 32, 32 );
- const material = new THREE.MeshBasicMaterial( { color: color } );
- const sphere = new THREE.Mesh( geometry, material );
- sphere.position.set(point.x, point.y, point.z);
- scene.add( sphere );
- }
-
- let lineColor = 0x000000;
- let pointColor = 0xff00000;
-
- /**
- * generate one line for each of the 6 springs
- * and one point for each of the 4 vertices
- * for all of the faces
- */
- for (let i in this.faces) {
- let face = this.faces[i];
- addLine(this.geometry.vertices[face.a], this.geometry.vertices[face.b], lineColor);
- addLine(this.geometry.vertices[face.a], this.geometry.vertices[face.c], lineColor);
- addLine(this.geometry.vertices[face.a], this.geometry.vertices[face.d], lineColor);
- addLine(this.geometry.vertices[face.b], this.geometry.vertices[face.c], lineColor);
- addLine(this.geometry.vertices[face.b], this.geometry.vertices[face.d], lineColor);
- addLine(this.geometry.vertices[face.c], this.geometry.vertices[face.d], lineColor);
-
- addPoint(this.geometry.vertices[face.a], pointColor);
- addPoint(this.geometry.vertices[face.b], pointColor);
- addPoint(this.geometry.vertices[face.c], pointColor);
- addPoint(this.geometry.vertices[face.d], pointColor);
- }
- }
-}
/**
* setup THREE JS Scene, Camera and Renderer
*/
-function setup_scene() {
+function setup_scene(canvasSpace) {
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / (window.innerHeight - canvasSpace), 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
@@ -331,9 +49,12 @@ function setup_scene() { camera.position.y = 5;
camera.position.z = 10;
- return [scene, camera];
+ return [scene, camera, renderer];
}
+/** call "init" when document is fully loaded */
+document.body.onload = init;
+
function init() {
let mousePos = new Point();
@@ -344,7 +65,7 @@ function init() { const canvasSpace = 200;
/** Setup scene */
- let [scene, camera] = setup_scene();
+ let [scene, camera, renderer] = setup_scene(canvasSpace);
/** setup cloth and generate debug mesh */
let cloth = new Cloth();
@@ -367,8 +88,8 @@ function init() { /** add callback for window resize */
let canvas = document.getElementsByTagName("canvas")[0];
let resize = function () {
- w = window.innerWidth;
- h = window.innerHeight - 200;
+ let w = window.innerWidth;
+ let h = window.innerHeight - 200;
canvas.width = w;
canvas.height = h;
}
|
