]> gitweb.ps.run Git - cloth_sim/blob - Scripts/main.js
add cloth-cloth collision
[cloth_sim] / Scripts / main.js
1 //import {  } from './cloth.js';\r
2 //import { OrbitControls } from './OrbitControls.js';\r
3 \r
4 function addLights(scene){\r
5   scene.add( new THREE.AmbientLight( 0x222222 ) );\r
6 \r
7   const light1 = new THREE.PointLight( 0xffffff, 1, 50 );\r
8   light1.position.set( 15, 1, 40 );\r
9   scene.add( light1 );\r
10 \r
11   const light2 = new THREE.PointLight( 0xffffff, 1, 50 );\r
12   light2.position.set( -15, 0, 40 );\r
13   scene.add( light2 );\r
14 \r
15   const light3 = new THREE.PointLight( 0xffffff, 1, 50 );\r
16   light3.position.set( 0, -1, 40 );\r
17   scene.add( light3 );\r
18 }\r
19 \r
20 /**\r
21  * setup THREE JS Scene, Camera and Renderer\r
22  */\r
23 function setup_scene(canvasSpace) {\r
24   const scene = new THREE.Scene();\r
25   const camera = new THREE.PerspectiveCamera(75, window.innerWidth / (window.innerHeight - canvasSpace), 0.1, 1000);\r
26   const renderer = new THREE.WebGLRenderer();\r
27   /** size canvas to leave some space for UI */\r
28   renderer.setSize(window.innerWidth, window.innerHeight - canvasSpace);\r
29   renderer.antialias = true;\r
30   /** embed canvas in HTML */\r
31   document.getElementById("threejscontainer").appendChild(renderer.domElement);\r
32 \r
33   /** add orbit controls */\r
34   const controls = new THREE.OrbitControls(camera, renderer.domElement);\r
35   controls.target.set(0, 0, 0);\r
36   controls.update();\r
37 \r
38   /** add scene background */\r
39   const loader = new THREE.TextureLoader();\r
40   const texture = loader.load(\r
41     'Textures/tears_of_steel_bridge_2k.jpg',\r
42     () => {\r
43       const rt = new THREE.WebGLCubeRenderTarget(texture.image.height);\r
44       rt.fromEquirectangularTexture(renderer, texture);\r
45       scene.background = rt;\r
46     });\r
47 \r
48   /** add flag pole */\r
49   const geometry = new THREE.CylinderGeometry( 0.02, 0.02, 5, 32 );\r
50   const material = new THREE.MeshStandardMaterial( {color: 0xffffff} );\r
51   const cylinder = new THREE.Mesh( geometry, material );\r
52   cylinder.position.set(-0.5, -2.25, 0);\r
53   scene.add( cylinder );\r
54 \r
55   /** add global light */\r
56   const directionalLight = new THREE.DirectionalLight(0xffffff, 1);\r
57   scene.add(directionalLight);\r
58 \r
59   /** position camera */\r
60   camera.position.z = 2;\r
61   addLights(scene);\r
62   return [scene, camera, renderer];\r
63 }\r
64 \r
65 /** call "init" when document is fully loaded */\r
66 document.body.onload = init;\r
67 \r
68 function init() {\r
69   let mousePos = new THREE.Vector2();\r
70   \r
71   /**\r
72    * Space left empty under canvas\r
73    * for UI elements\r
74    */\r
75   const canvasSpace = 200;\r
76 \r
77   /** Constant Frame Time */\r
78   const frameTime = 1000.0 / 200.0;\r
79 \r
80   /** Setup scene */\r
81   let [scene, camera, renderer] = setup_scene(canvasSpace);\r
82   \r
83   //const loader = new THREE.TextureLoader();\r
84   //Red color: 0xC70039\r
85 \r
86   const cloth = new Cloth(1, 0.5, 20, 20);\r
87   const clothGeometry = cloth.generateGeometry();\r
88   //const clothMaterial = new THREE.MeshStandardMaterial({ map: loader.load('Textures/DeutschlandFlagge.jpg'), color: 0xffffff, side: THREE.DoubleSide, flatShading: false});\r
89   const clothMaterial = new THREE.MeshStandardMaterial({ color: 0xC70039, side: THREE.DoubleSide, flatShading: false });\r
90   const clothMesh = new THREE.Mesh(clothGeometry, clothMaterial);\r
91   scene.add(clothMesh);\r
92   \r
93   document.getElementById("windToggle").onchange = (e) => {\r
94     options.wind = e.target.checked;\r
95   };\r
96 \r
97   let raycaster = new THREE.Raycaster();\r
98   let intersects;\r
99   let rightMousePressed;\r
100   /**\r
101    * function called every frame\r
102    * @param {number} dt - time passed since last frame in ms\r
103    */\r
104   function animate(dt) {\r
105     cloth.simulate(dt / 1000);\r
106 \r
107     cloth.updateGeometry(clothGeometry);\r
108     \r
109     raycaster.setFromCamera( new THREE.Vector2((mousePos.x / w) * 2 - 1, ((h - mousePos.y) / h) * 2 - 1), camera );\r
110 \r
111     // intersects = raycaster.intersectObject( mesh );\r
112 \r
113     // if ( intersects.length > 0 && rightMousePressed) {\r
114     //   // Cloth mouse interaction\r
115     // }\r
116     setTimeout(() => {\r
117       animate(frameTime);\r
118     }, frameTime);\r
119     renderer.render(scene, camera);\r
120   }\r
121 \r
122 \r
123   /** add callback for window resize */\r
124   let canvas = document.getElementsByTagName("canvas")[0];\r
125   let w = window.innerWidth;\r
126   let h = window.innerHeight - canvasSpace;\r
127   let resize = function () {\r
128     w = window.innerWidth;\r
129     h = window.innerHeight - canvasSpace;\r
130     canvas.width = w;\r
131     canvas.height = h;\r
132   }\r
133   window.onresize = resize;\r
134   resize();\r
135 \r
136   /**\r
137    * if canvas has been successfully initialized\r
138    * start rendering\r
139    */\r
140   if (canvas.getContext) {\r
141     animate(performance.now());\r
142   }\r
143 \r
144   \r
145 \r
146   /** add mouse move callback */\r
147   canvas.onmousemove = (evt) => {\r
148     mousePos.x = evt.clientX;\r
149     mousePos.y = evt.clientY;\r
150 \r
151     //cloth.mouseMove(calculateMousePosToWorld(evt));\r
152   };\r
153 \r
154   /**\r
155    * Prevent context menu while blowing wind\r
156    */\r
157   canvas.addEventListener('contextmenu', function(evt) { \r
158     evt.preventDefault();\r
159   }, false);\r
160 \r
161 \r
162   canvas.onmousedown = (evt) => {\r
163 \r
164     // Check mouse click\r
165     rightMousePressed = evt.button == 2;\r
166     \r
167     if(intersects.length > 0 && evt.button == 0){\r
168       //cloth.mousePress(intersects);\r
169     } \r
170   }\r
171   \r
172   canvas.onmouseup = (evt) => {\r
173     //cloth.mouseRelease();\r
174     rightMousePressed = false;\r
175   }\r
176 \r
177   function calculateMousePosToWorld(evt){\r
178     var vec = new THREE.Vector3(); // create once and reuse\r
179     var pos = new THREE.Vector3(); // create once and reuse\r
180 \r
181     vec.set(\r
182       ( evt.clientX / window.innerWidth ) * 2 - 1,\r
183     - ( evt.clientY / window.innerHeight ) * 2 + 1,\r
184       0.5 );\r
185 \r
186     vec.unproject( camera );\r
187 \r
188     vec.sub( camera.position ).normalize();\r
189 \r
190     var distance = - camera.position.z / vec.z;\r
191 \r
192     pos.copy( camera.position ).add( vec.multiplyScalar( distance ) );\r
193     return pos;\r
194   }\r
195 }