]> gitweb.ps.run Git - cloth_sim/blob - Scripts/main.js
uv mapping, add texture to flag
[cloth_sim] / Scripts / main.js
1 \r
2 \r
3 function addLights(scene){\r
4   scene.add( new THREE.AmbientLight( 0x222222 ) );\r
5 \r
6   const light1 = new THREE.PointLight( 0xffffff, 1, 50 );\r
7   light1.position.set( 15, 1, 40 );\r
8   scene.add( light1 );\r
9 \r
10   const light2 = new THREE.PointLight( 0xffffff, 1, 50 );\r
11   light2.position.set( -15, 0, 40 );\r
12   scene.add( light2 );\r
13 \r
14   const light3 = new THREE.PointLight( 0xffffff, 1, 50 );\r
15   light3.position.set( 0, -1, 40 );\r
16   scene.add( light3 );\r
17 }\r
18 \r
19 /**\r
20  * setup THREE JS Scene, Camera and Renderer\r
21  */\r
22 function setup_scene(canvasSpace) {\r
23   const scene = new THREE.Scene();\r
24   const camera = new THREE.PerspectiveCamera(75, window.innerWidth / (window.innerHeight - canvasSpace), 0.1, 1000);\r
25   const renderer = new THREE.WebGLRenderer();\r
26   /** size canvas to leave some space for UI */\r
27   renderer.setSize(window.innerWidth, window.innerHeight - canvasSpace);\r
28   renderer.antialias = true;\r
29   /** embed canvas in HTML */\r
30   document.getElementById("threejscontainer").appendChild(renderer.domElement);\r
31 \r
32   /** add orbit controls */\r
33   const controls = new THREE.OrbitControls(camera, renderer.domElement);\r
34   controls.target.set(0, 0, 0);\r
35   controls.update();\r
36 \r
37   /** add scene background */\r
38   const loader = new THREE.TextureLoader();\r
39   const texture = loader.load(\r
40     'Textures/tears_of_steel_bridge_2k.jpg',\r
41     () => {\r
42       const rt = new THREE.WebGLCubeRenderTarget(texture.image.height);\r
43       rt.fromEquirectangularTexture(renderer, texture);\r
44       scene.background = rt;\r
45     });\r
46 \r
47   /** add flag pole */\r
48   const geometry = new THREE.CylinderGeometry( 0.02, 0.02, 5, 32 );\r
49   const material = new THREE.MeshStandardMaterial( {color: 0xffffff} );\r
50   const cylinder = new THREE.Mesh( geometry, material );\r
51   cylinder.position.set(-0.5, -2.25, 0);\r
52   scene.add( cylinder );\r
53 \r
54   /** add global light */\r
55   const directionalLight = new THREE.DirectionalLight(0xffffff, 1);\r
56   scene.add(directionalLight);\r
57 \r
58   /** position camera */\r
59   camera.position.z = 2;\r
60   addLights(scene);\r
61   return [scene, camera, renderer];\r
62 }\r
63 \r
64 /** call "init" when document is fully loaded */\r
65 document.body.onload = init;\r
66 \r
67 function init() {\r
68   let mousePos = new THREE.Vector2();\r
69   \r
70   /**\r
71    * Space left empty under canvas\r
72    * for UI elements\r
73    */\r
74   const canvasSpace = 200;\r
75 \r
76   /** Constant Frame Time */\r
77   const frameTime = 1000.0 / 200.0;\r
78 \r
79   /** Setup scene */\r
80   let [scene, camera, renderer] = setup_scene(canvasSpace);\r
81   \r
82   const loader = new THREE.TextureLoader();\r
83   //Red color: 0xC70039\r
84 \r
85   const cloth = new Cloth(1, 0.5, 20, 20);\r
86   const clothGeometry = cloth.generateGeometry();\r
87   const clothMaterial = new THREE.MeshStandardMaterial({ map: loader.load('Textures/hsrm.jpg'), color: 0xffffff, side: THREE.DoubleSide, flatShading: false});\r
88   //const clothMaterial = new THREE.MeshStandardMaterial({ color: 0xC70039, side: THREE.DoubleSide, flatShading: false });\r
89   const clothMesh = new THREE.Mesh(clothGeometry, clothMaterial);\r
90   scene.add(clothMesh);\r
91   \r
92   document.getElementById("windToggle").checked = options.wind;\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 }