Update index.html
Browse files- index.html +345 -19
index.html
CHANGED
@@ -1,19 +1,345 @@
|
|
1 |
-
<!
|
2 |
-
<html>
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
</
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html lang="en">
|
3 |
+
<head>
|
4 |
+
<meta charset="UTF-8">
|
5 |
+
<meta name="viewport" content="width=device-width,user-scalable=0">
|
6 |
+
<title>Cloth | three.js exsamples</title>
|
7 |
+
<link rel="stylesheet" href="./common/css/sanitize.css">
|
8 |
+
<style>
|
9 |
+
html, body {
|
10 |
+
padding: 0;
|
11 |
+
margin: 0;
|
12 |
+
font-family: Helvetica, Arial, sans-serif;
|
13 |
+
font-weight: 400;
|
14 |
+
font-size: 14px;
|
15 |
+
line-height: 1.8em;
|
16 |
+
color: #333;
|
17 |
+
background-color: #fff;
|
18 |
+
}
|
19 |
+
</style>
|
20 |
+
</head>
|
21 |
+
<body>
|
22 |
+
<div id="js_box"></div>
|
23 |
+
<script src="./common/js/three.js"></script>
|
24 |
+
<script>/******/ (function(modules) { // webpackBootstrap
|
25 |
+
/******/ // The module cache
|
26 |
+
/******/ var installedModules = {};
|
27 |
+
|
28 |
+
/******/ // The require function
|
29 |
+
/******/ function __webpack_require__(moduleId) {
|
30 |
+
|
31 |
+
/******/ // Check if module is in cache
|
32 |
+
/******/ if(installedModules[moduleId])
|
33 |
+
/******/ return installedModules[moduleId].exports;
|
34 |
+
|
35 |
+
/******/ // Create a new module (and put it into the cache)
|
36 |
+
/******/ var module = installedModules[moduleId] = {
|
37 |
+
/******/ exports: {},
|
38 |
+
/******/ id: moduleId,
|
39 |
+
/******/ loaded: false
|
40 |
+
/******/ };
|
41 |
+
|
42 |
+
/******/ // Execute the module function
|
43 |
+
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
44 |
+
|
45 |
+
/******/ // Flag the module as loaded
|
46 |
+
/******/ module.loaded = true;
|
47 |
+
|
48 |
+
/******/ // Return the exports of the module
|
49 |
+
/******/ return module.exports;
|
50 |
+
/******/ }
|
51 |
+
|
52 |
+
|
53 |
+
/******/ // expose the modules object (__webpack_modules__)
|
54 |
+
/******/ __webpack_require__.m = modules;
|
55 |
+
|
56 |
+
/******/ // expose the module cache
|
57 |
+
/******/ __webpack_require__.c = installedModules;
|
58 |
+
|
59 |
+
/******/ // __webpack_public_path__
|
60 |
+
/******/ __webpack_require__.p = "";
|
61 |
+
|
62 |
+
/******/ // Load entry module and return exports
|
63 |
+
/******/ return __webpack_require__(0);
|
64 |
+
/******/ })
|
65 |
+
/************************************************************************/
|
66 |
+
/******/ ([
|
67 |
+
/* 0 */
|
68 |
+
/***/ function(module, exports, __webpack_require__) {
|
69 |
+
|
70 |
+
module.exports = __webpack_require__(2);
|
71 |
+
|
72 |
+
|
73 |
+
/***/ },
|
74 |
+
/* 1 */
|
75 |
+
/***/ function(module, exports) {
|
76 |
+
|
77 |
+
"use strict";
|
78 |
+
|
79 |
+
Object.defineProperty(exports, "__esModule", {
|
80 |
+
value: true
|
81 |
+
});
|
82 |
+
|
83 |
+
var _createClass = function () {
|
84 |
+
function defineProperties(target, props) {
|
85 |
+
for (var i = 0; i < props.length; i++) {
|
86 |
+
var descriptor = props[i];descriptor.enumerable = descriptor.enumerable || false;descriptor.configurable = true;if ("value" in descriptor) descriptor.writable = true;Object.defineProperty(target, descriptor.key, descriptor);
|
87 |
+
}
|
88 |
+
}return function (Constructor, protoProps, staticProps) {
|
89 |
+
if (protoProps) defineProperties(Constructor.prototype, protoProps);if (staticProps) defineProperties(Constructor, staticProps);return Constructor;
|
90 |
+
};
|
91 |
+
}();
|
92 |
+
|
93 |
+
function _classCallCheck(instance, Constructor) {
|
94 |
+
if (!(instance instanceof Constructor)) {
|
95 |
+
throw new TypeError("Cannot call a class as a function");
|
96 |
+
}
|
97 |
+
}
|
98 |
+
|
99 |
+
/**
|
100 |
+
* 新しいClothオブジェクトを作成する。
|
101 |
+
* @class 風の揺らめきをシミュレーションする布クラス
|
102 |
+
* @params {Number} segmentX X軸の分割数
|
103 |
+
* @params {Number} segmentY Y軸の分割数
|
104 |
+
* @params {Number} distance 分割した頂点間の距離
|
105 |
+
* @params {Function} paramFunc パラメトリック曲面の計算式の関数
|
106 |
+
*/
|
107 |
+
|
108 |
+
var Cloth = function () {
|
109 |
+
function Cloth(segmentX, segmentY, distance, paramFunc) {
|
110 |
+
_classCallCheck(this, Cloth);
|
111 |
+
|
112 |
+
this.segmentX = segmentX;
|
113 |
+
this.segmentY = segmentY;
|
114 |
+
this.distance = distance;
|
115 |
+
this.paramFunc = paramFunc;
|
116 |
+
this.geometry = new THREE.ParametricGeometry(this.paramFunc, this.segmentX, this.segmentY);
|
117 |
+
this.windForce = new THREE.Vector3(0, 0, 0);
|
118 |
+
this.tmpForce = new THREE.Vector3();
|
119 |
+
this.lastTime = null;
|
120 |
+
this.particles = [];
|
121 |
+
this.constrains = [];
|
122 |
+
var u, v;
|
123 |
+
for (v = 0; v <= this.segmentY; v++) {
|
124 |
+
for (u = 0; u <= this.segmentX; u++) {
|
125 |
+
this.particles.push(new ClothParticle(u / this.segmentX, v / this.segmentY, 0, 0.1, this.paramFunc));
|
126 |
+
}
|
127 |
+
}
|
128 |
+
for (v = 0; v < this.segmentY; v++) {
|
129 |
+
for (u = 0; u < this.segmentX; u++) {
|
130 |
+
this.constrains.push([this.particles[this.getIndex_(u, v)], this.particles[this.getIndex_(u, v + 1)], this.distance]);
|
131 |
+
this.constrains.push([this.particles[this.getIndex_(u, v)], this.particles[this.getIndex_(u + 1, v)], this.distance]);
|
132 |
+
}
|
133 |
+
}
|
134 |
+
for (u = this.segmentX, v = 0; v < this.segmentY; v++) {
|
135 |
+
this.constrains.push([this.particles[this.getIndex_(u, v)], this.particles[this.getIndex_(u, v + 1)], this.distance]);
|
136 |
+
}
|
137 |
+
for (v = this.segmentY, u = 0; u < this.segmentX; u++) {
|
138 |
+
this.constrains.push([this.particles[this.getIndex_(u, v)], this.particles[this.getIndex_(u + 1, v)], this.distance]);
|
139 |
+
}
|
140 |
+
}
|
141 |
+
|
142 |
+
_createClass(Cloth, [{
|
143 |
+
key: "getGeometry",
|
144 |
+
value: function getGeometry() {
|
145 |
+
return this.geometry;
|
146 |
+
}
|
147 |
+
}, {
|
148 |
+
key: "windSimulate",
|
149 |
+
value: function windSimulate(time) {
|
150 |
+
if (!this.lastTime) {
|
151 |
+
this.lastTime = time;
|
152 |
+
return;
|
153 |
+
}
|
154 |
+
this.windForce.set(Math.sin(time / 2000), Math.cos(time / 3000), Math.sin(time / 1000)).normalize().multiplyScalar(200);
|
155 |
+
var i = 0,
|
156 |
+
max;
|
157 |
+
for (i = 0, max = this.particles.length; i < max; i = i + 1) {
|
158 |
+
this.geometry.vertices[i].copy(this.particles[i].position);
|
159 |
+
}
|
160 |
+
this.geometry.computeFaceNormals();
|
161 |
+
this.geometry.computeVertexNormals();
|
162 |
+
this.geometry.normalsNeedUpdate = true;
|
163 |
+
this.geometry.verticesNeedUpdate = true;
|
164 |
+
var faces = this.geometry.faces;
|
165 |
+
for (i = 0, max = faces.length; i < max; i = i + 1) {
|
166 |
+
this.tmpForce.copy(faces[i].normal).normalize().multiplyScalar(faces[i].normal.dot(this.windForce));
|
167 |
+
this.particles[faces[i].a].addForce(this.tmpForce);
|
168 |
+
this.particles[faces[i].b].addForce(this.tmpForce);
|
169 |
+
this.particles[faces[i].c].addForce(this.tmpForce);
|
170 |
+
}
|
171 |
+
for (i = 0, max = this.particles.length; i < max; i = i + 1) {
|
172 |
+
this.particles[i].addForce(new THREE.Vector3(0, -(981 * 1.4), 0).multiplyScalar(0.1));
|
173 |
+
this.particles[i].integrate(18 / 1000 * (18 / 1000));
|
174 |
+
}
|
175 |
+
for (i = 0, max = this.constrains.length; i < max; i = i + 1) {
|
176 |
+
this.satisifyConstrains_(this.constrains[i][0], this.constrains[i][1], this.constrains[i][2]);
|
177 |
+
}
|
178 |
+
for (i = 0, max = this.particles.length; i < max; i = i + 1) {
|
179 |
+
if (i % (this.segmentX + 1) == 0) {
|
180 |
+
this.particles[i].position.copy(this.particles[i].original);
|
181 |
+
this.particles[i].previous.copy(this.particles[i].original);
|
182 |
+
}
|
183 |
+
}
|
184 |
+
}
|
185 |
+
}, {
|
186 |
+
key: "getIndex_",
|
187 |
+
value: function getIndex_(u, v) {
|
188 |
+
return u + v * (this.segmentX + 1);
|
189 |
+
}
|
190 |
+
}, {
|
191 |
+
key: "satisifyConstrains_",
|
192 |
+
value: function satisifyConstrains_(p1, p2, distance) {
|
193 |
+
var diff = new THREE.Vector3();
|
194 |
+
diff.subVectors(p2.position, p1.position);
|
195 |
+
var currentDist = diff.length();
|
196 |
+
if (currentDist == 0) return;
|
197 |
+
var correction = diff.multiplyScalar(1 - distance / currentDist);
|
198 |
+
var correctionHalf = correction.multiplyScalar(0.5);
|
199 |
+
p1.position.add(correctionHalf);
|
200 |
+
p2.position.sub(correctionHalf);
|
201 |
+
}
|
202 |
+
}]);
|
203 |
+
|
204 |
+
return Cloth;
|
205 |
+
}();
|
206 |
+
|
207 |
+
/**
|
208 |
+
* 新しいClothParticleオブジェクトを作成する。
|
209 |
+
* @class 風の揺らめきに反応する各頂点のクラス
|
210 |
+
* @params {Number} x X座標
|
211 |
+
* @params {Number} y Y座標
|
212 |
+
* @params {Number} z Z座標
|
213 |
+
* @params {Number} mass
|
214 |
+
* @params {Function} paramFunc パラメトリック曲面の計算式の関数
|
215 |
+
*/
|
216 |
+
|
217 |
+
exports.default = Cloth;
|
218 |
+
|
219 |
+
var ClothParticle = exports.ClothParticle = function () {
|
220 |
+
function ClothParticle(x, y, z, mass, paramFunc) {
|
221 |
+
_classCallCheck(this, ClothParticle);
|
222 |
+
|
223 |
+
this.position = paramFunc(x, y);
|
224 |
+
this.previous = paramFunc(x, y);
|
225 |
+
this.original = paramFunc(x, y);
|
226 |
+
this.mass = 1 / mass;
|
227 |
+
this.vector = new THREE.Vector3(0, 0, 0);
|
228 |
+
this.tmp = new THREE.Vector3();
|
229 |
+
this.tmp2 = new THREE.Vector3();
|
230 |
+
}
|
231 |
+
|
232 |
+
_createClass(ClothParticle, [{
|
233 |
+
key: "addForce",
|
234 |
+
value: function addForce(force) {
|
235 |
+
this.vector.add(this.tmp2.copy(force).multiplyScalar(this.mass));
|
236 |
+
}
|
237 |
+
}, {
|
238 |
+
key: "integrate",
|
239 |
+
value: function integrate(timesq) {
|
240 |
+
var newPos = this.tmp.subVectors(this.position, this.previous);
|
241 |
+
newPos.multiplyScalar(0.95).add(this.position);
|
242 |
+
newPos.add(this.vector.multiplyScalar(timesq));
|
243 |
+
this.tmp = this.previous;
|
244 |
+
this.previous = this.position;
|
245 |
+
this.position = newPos;
|
246 |
+
this.vector.set(0, 0, 0);
|
247 |
+
}
|
248 |
+
}]);
|
249 |
+
|
250 |
+
return ClothParticle;
|
251 |
+
}();
|
252 |
+
|
253 |
+
/***/ },
|
254 |
+
/* 2 */
|
255 |
+
/***/ function(module, exports, __webpack_require__) {
|
256 |
+
|
257 |
+
"use strict";
|
258 |
+
|
259 |
+
var _Cloth = __webpack_require__(1);
|
260 |
+
|
261 |
+
var _Cloth2 = _interopRequireDefault(_Cloth);
|
262 |
+
|
263 |
+
function _interopRequireDefault(obj) {
|
264 |
+
return obj && obj.__esModule ? obj : { default: obj };
|
265 |
+
}
|
266 |
+
|
267 |
+
var DISTANCE = 25; // 旗を分割した頂点間の距離
|
268 |
+
var SEGMENTS_X = 10; // 旗のX軸の分割数
|
269 |
+
var SEGMENTS_Y = 10; // 旗のY軸の分割数
|
270 |
+
var WIDTH = DISTANCE * SEGMENTS_X; // 旗の横幅
|
271 |
+
var HEIGHT = DISTANCE * SEGMENTS_Y; // 旗の縦幅
|
272 |
+
|
273 |
+
// レンダラー
|
274 |
+
var renderer = new THREE.WebGLRenderer({ antialias: true });
|
275 |
+
renderer.setSize(800, 600);
|
276 |
+
renderer.setClearColor(0x000000);
|
277 |
+
document.getElementById("js_box").appendChild(renderer.domElement);
|
278 |
+
|
279 |
+
// シーン
|
280 |
+
var scene = new THREE.Scene();
|
281 |
+
scene.fog = new THREE.Fog(0x000000, 500, 5000);
|
282 |
+
|
283 |
+
// カメラ
|
284 |
+
var camera = new THREE.PerspectiveCamera(30, 800 / 600, 1, 5000);
|
285 |
+
camera.position.z = 1500;
|
286 |
+
scene.add(camera);
|
287 |
+
|
288 |
+
// 光源
|
289 |
+
var light = new THREE.DirectionalLight(0xffffff, 2);
|
290 |
+
light.position.set(50, 200, 100);
|
291 |
+
light.castShadow = false;
|
292 |
+
scene.add(light);
|
293 |
+
scene.add(new THREE.AmbientLight(0x333333));
|
294 |
+
|
295 |
+
// 星条旗
|
296 |
+
var loader = new THREE.TextureLoader();
|
297 |
+
var clothTexture = loader.load("texture/cloth.png");
|
298 |
+
clothTexture.wrapS = THREE.RepeatWrapping;
|
299 |
+
clothTexture.wrapT = THREE.RepeatWrapping;
|
300 |
+
clothTexture.anisotropy = 16;
|
301 |
+
var clothMaterial = new THREE.MeshPhongMaterial({ specular: 0x000000, map: clothTexture, side: THREE.DoubleSide });
|
302 |
+
var cloth = new _Cloth2.default(SEGMENTS_X, SEGMENTS_Y, DISTANCE, function (u, v) {
|
303 |
+
var x = (u - 0.5) * DISTANCE * SEGMENTS_X;
|
304 |
+
var y = (v + 0.5) * DISTANCE * SEGMENTS_Y;
|
305 |
+
var z = 0;
|
306 |
+
return new THREE.Vector3(x, y, z);
|
307 |
+
});
|
308 |
+
var clothMeth = new THREE.Mesh(cloth.getGeometry(), clothMaterial);
|
309 |
+
clothMeth.position.set(WIDTH / 2, -HEIGHT / 2, 0);
|
310 |
+
scene.add(clothMeth);
|
311 |
+
|
312 |
+
// ポール
|
313 |
+
var poleGeometry = new THREE.CylinderGeometry(5, 5, 500, 10, 0, true);
|
314 |
+
var poleMaterial = new THREE.MeshPhongMaterial({ color: 0x999999, specular: 0xffffff });
|
315 |
+
var poleMesh = new THREE.Mesh(poleGeometry, poleMaterial);
|
316 |
+
poleMesh.position.x = 0;
|
317 |
+
poleMesh.position.y = 0;
|
318 |
+
scene.add(poleMesh);
|
319 |
+
|
320 |
+
// 月面
|
321 |
+
loader = new THREE.TextureLoader();
|
322 |
+
var groundTexture = loader.load("texture/grand.jpg");
|
323 |
+
groundTexture.wrapS = THREE.RepeatWrapping;
|
324 |
+
groundTexture.wrapT = THREE.RepeatWrapping;
|
325 |
+
groundTexture.repeat.set(25, 25);
|
326 |
+
groundTexture.anisotropy = 16;
|
327 |
+
var groundMaterial = new THREE.MeshPhongMaterial({ color: 0x999999, specular: 0x000000, map: groundTexture });
|
328 |
+
var groundMesh = new THREE.Mesh(new THREE.PlaneBufferGeometry(20000, 20000), groundMaterial);
|
329 |
+
groundMesh.position.y = -250;
|
330 |
+
groundMesh.rotation.x = -Math.PI / 2;
|
331 |
+
scene.add(groundMesh);
|
332 |
+
|
333 |
+
// アニメーション
|
334 |
+
function animate() {
|
335 |
+
requestAnimationFrame(animate);
|
336 |
+
cloth.windSimulate(Date.now());
|
337 |
+
camera.lookAt(scene.position);
|
338 |
+
renderer.render(scene, camera);
|
339 |
+
}
|
340 |
+
animate();
|
341 |
+
|
342 |
+
/***/ }
|
343 |
+
/******/ ]);</script>
|
344 |
+
</body>
|
345 |
+
</html>
|