23 let a = this.x - that.x;
\r
24 let b = this.y - that.y;
\r
25 return Math.sqrt(a * a + b * b)
\r
29 function vectorLength(a, b) {
\r
30 let v1 = new THREE.Vector3();
\r
31 v1.set(a.x, a.y, a.z);
\r
32 let v2 = new THREE.Vector3();
\r
33 v2.set(b.x, b.y, b.z);
\r
35 return v1.sub(v2).length();
\r
46 constructor(a, b, c, d) {
\r
60 constructor(vertices, index1, index2) {
\r
61 this.index1 = index1;
\r
62 this.index2 = index2;
\r
64 let length = vectorLength(vertices[index1], vertices[index2]);
\r
65 this.restLength = length;
\r
66 this.currentLength = length;
\r
73 geometry = new THREE.Geometry();
\r
79 createBasic(width, height, numPointsWidth, numPointsHeight) {
\r
83 let stepWidth = width / (numPointsWidth - 1);
\r
84 let stepHeight = height / (numPointsHeight - 1);
\r
86 for (let y = 0; y < numPointsHeight; y++) {
\r
87 for (let x = 0; x < numPointsWidth; x++) {
\r
89 new THREE.Vector3(x * stepWidth, height - y * stepHeight, 0)
\r
94 function getVertexIndex(x, y) {
\r
95 return y * numPointsWidth + x;
\r
98 for (let y = 0; y < numPointsHeight - 1; y++) {
\r
99 for (let x = 0; x < numPointsWidth - 1; x++) {
\r
100 let newFace = new Face(
\r
101 getVertexIndex(x, y),
\r
102 getVertexIndex(x, y + 1),
\r
103 getVertexIndex(x + 1, y),
\r
104 getVertexIndex(x + 1, y + 1),
\r
107 newFace.springs.push(new Spring(vertices, getVertexIndex(x, y), getVertexIndex(x + 1, y)));
\r
108 newFace.springs.push(new Spring(vertices, getVertexIndex(x, y), getVertexIndex(x, y + 1)));
\r
109 newFace.springs.push(new Spring(vertices, getVertexIndex(x, y), getVertexIndex(x + 1, y + 1)));
\r
110 newFace.springs.push(new Spring(vertices, getVertexIndex(x + 1, y), getVertexIndex(x, y + 1)));
\r
111 newFace.springs.push(new Spring(vertices, getVertexIndex(x + 1, y), getVertexIndex(x + 1, y + 1)));
\r
112 newFace.springs.push(new Spring(vertices, getVertexIndex(x, y + 1), getVertexIndex(x + 1, y + 1)));
\r
114 faces.push(newFace);
\r
118 this.createExplicit(vertices, faces);
\r
121 createExplicit(vertices, faces) {
\r
122 for (let i in vertices) {
\r
123 this.geometry.vertices.push(vertices[i]);
\r
124 this.vertexWeights.push(0);
\r
126 for (let i in faces) {
\r
127 let face = faces[i];
\r
129 this.faces.push(face);
\r
131 this.geometry.faces.push(new THREE.Face3(
\r
132 face.a, face.b, face.c
\r
134 this.geometry.faces.push(new THREE.Face3(
\r
135 face.c, face.b, face.d
\r
138 let xLength = vectorLength(this.geometry.vertices[face.b], this.geometry.vertices[face.a]);
\r
139 let yLength = vectorLength(this.geometry.vertices[face.c], this.geometry.vertices[face.a]);
\r
140 let weight = xLength * yLength / 2;
\r
142 xLength = vectorLength(this.geometry.vertices[face.b], this.geometry.vertices[face.d]);
\r
143 yLength = vectorLength(this.geometry.vertices[face.c], this.geometry.vertices[face.d]);
\r
144 weight += xLength * yLength / 2;
\r
146 this.vertexWeights[face.a] += weight / 4;
\r
147 this.vertexWeights[face.b] += weight / 4;
\r
148 this.vertexWeights[face.c] += weight / 4;
\r
149 this.vertexWeights[face.d] += weight / 4;
\r
152 this.geometry.computeBoundingSphere();
\r
155 createDebugMesh(scene) {
\r
156 function addLine(from, to, color) {
\r
157 let geometry = new THREE.Geometry();
\r
158 geometry.vertices.push(from);
\r
159 geometry.vertices.push(to);
\r
160 let material = new THREE.LineBasicMaterial( { color: color, linewidth: 10 } );
\r
161 let line = new THREE.Line(geometry, material);
\r
162 line.renderOrder = 1;
\r
165 function addPoint(point, color) {
\r
166 const geometry = new THREE.SphereGeometry( 0.05, 32, 32 );
\r
167 const material = new THREE.MeshBasicMaterial( { color: color } );
\r
168 const sphere = new THREE.Mesh( geometry, material );
\r
169 sphere.position.set(point.x, point.y, point.z);
\r
170 scene.add( sphere );
\r
173 let lineColor = 0x000000;
\r
174 let pointColor = 0xff00000;
\r
176 for (let i in this.faces) {
\r
177 let face = this.faces[i];
\r
178 addLine(this.geometry.vertices[face.a], this.geometry.vertices[face.b], lineColor);
\r
179 addLine(this.geometry.vertices[face.a], this.geometry.vertices[face.c], lineColor);
\r
180 addLine(this.geometry.vertices[face.a], this.geometry.vertices[face.d], lineColor);
\r
181 addLine(this.geometry.vertices[face.b], this.geometry.vertices[face.c], lineColor);
\r
182 addLine(this.geometry.vertices[face.b], this.geometry.vertices[face.d], lineColor);
\r
183 addLine(this.geometry.vertices[face.c], this.geometry.vertices[face.d], lineColor);
\r
185 addPoint(this.geometry.vertices[face.a], pointColor);
\r
186 addPoint(this.geometry.vertices[face.b], pointColor);
\r
187 addPoint(this.geometry.vertices[face.c], pointColor);
\r
188 addPoint(this.geometry.vertices[face.d], pointColor);
\r
193 let mousePos = new Point();
\r
195 const canvasSpace = 200;
\r
197 const scene = new THREE.Scene();
\r
198 const camera = new THREE.PerspectiveCamera(75, window.innerWidth / (window.innerHeight - canvasSpace), 0.1, 1000);
\r
200 const renderer = new THREE.WebGLRenderer();
\r
201 renderer.setSize(window.innerWidth, window.innerHeight - canvasSpace);
\r
202 document.getElementById("threejscontainer").appendChild(renderer.domElement);
\r
204 const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
\r
205 scene.add(directionalLight);
\r
207 let cloth = new Cloth();
\r
208 cloth.createBasic(10, 10, 5, 5);
\r
209 cloth.createDebugMesh(scene);
\r
211 const material = new THREE.MeshBasicMaterial({ color: 0x0000ff });
\r
212 const mesh = new THREE.Mesh(cloth.geometry, material);
\r
215 camera.position.y = 5;
\r
216 camera.position.z = 10;
\r
217 //camera.lookAt(new THREE.Vector3(1, 0, 0));
\r
219 function animate(dt) {
\r
220 requestAnimationFrame(animate);
\r
221 renderer.render(scene, camera);
\r
224 let canvas = document.getElementsByTagName("canvas")[0];
\r
225 let resize = function () {
\r
226 w = window.innerWidth;
\r
227 h = window.innerHeight - 200;
\r
231 window.onresize = resize;
\r
233 if (canvas.getContext) {
\r
234 animate(performance.now());
\r
236 canvas.onmousemove = (evt) => {
\r
237 mousePos.x = evt.clientX;
\r
238 mousePos.y = evt.clientY;
\r